diff --git a/apps/passport-client/.gitignore b/apps/passport-client/.gitignore index 9e0f0c0560..8514e5b765 100644 --- a/apps/passport-client/.gitignore +++ b/apps/passport-client/.gitignore @@ -1,4 +1,3 @@ - # Esbuild generated output public/js .env @@ -6,3 +5,4 @@ public/service-worker.js public/index.html public/bundle-stats.html public/scandit-engine +public/built.css diff --git a/apps/passport-client/components/NewButton.tsx b/apps/passport-client/components/NewButton.tsx new file mode 100644 index 0000000000..193b4b9b7a --- /dev/null +++ b/apps/passport-client/components/NewButton.tsx @@ -0,0 +1,53 @@ +import { ButtonHTMLAttributes, DetailedHTMLProps } from "react"; +import { cn } from "../src/util"; + +interface NewButtonProps + extends DetailedHTMLProps< + ButtonHTMLAttributes, + HTMLButtonElement + > { + variant?: ButtonVariant; +} + +const variantStyles = { + cyan: "border-cyan-950 bg-cyan-700 hover:bg-cyan-600 ring-offset-[#19473f]", + blackWhite: + "border-black bg-white hover:bg-gray-100 text-black ring-offset-black", + green: + "border-green-950 bg-[#206b5e] hover:bg-[#1b8473] ring-offset-[#1f4d3f]", + purple: + "border-purple-950 bg-purple-700 hover:bg-purple-600 ring-offset-[#3f1f4d]", + gray: "border-gray-800 bg-gray-600 hover:bg-gray-500 ring-offset-gray-700" +} as const; + +type ButtonVariant = keyof typeof variantStyles; + +export function NewButton({ + variant = "green", + ...props +}: NewButtonProps): JSX.Element { + return ( + + <> + + Log Out + + + + {justDevcon ? "Showing Just Devcon" : "Showing Everything"} + + + + {added ? "Added" : "Add Test Data"} + + + { + pcds.meta = {}; + await savePCDs(pcds); + window.location.reload(); + }} + disabled={added} + > + Reset Metadata + + )} {!isProveOrAddScreen && @@ -114,8 +171,6 @@ export function SettingsModal({ ))} - - ); diff --git a/apps/passport-client/components/modals/UpgradeAccountModal.tsx b/apps/passport-client/components/modals/UpgradeAccountModal.tsx index 4d34f7ba30..bfdc7c47e4 100644 --- a/apps/passport-client/components/modals/UpgradeAccountModal.tsx +++ b/apps/passport-client/components/modals/UpgradeAccountModal.tsx @@ -128,4 +128,5 @@ export function UpgradeAccountModal(): JSX.Element | null { const Container = styled.div` padding: 32px; + padding-bottom: 0; `; diff --git a/apps/passport-client/components/screens/GmailScreen/BackButton.tsx b/apps/passport-client/components/screens/GmailScreen/BackButton.tsx new file mode 100644 index 0000000000..867c1c96f8 --- /dev/null +++ b/apps/passport-client/components/screens/GmailScreen/BackButton.tsx @@ -0,0 +1,22 @@ +import { ReactNode } from "react"; +import { FaArrowLeft } from "react-icons/fa"; + +export function BackButton({ onClick }: { onClick: () => void }): ReactNode { + return ( +
+ +
+ ); +} diff --git a/apps/passport-client/components/screens/GmailScreen/StarToggle.tsx b/apps/passport-client/components/screens/GmailScreen/StarToggle.tsx new file mode 100644 index 0000000000..63154e2e67 --- /dev/null +++ b/apps/passport-client/components/screens/GmailScreen/StarToggle.tsx @@ -0,0 +1,30 @@ +import { ReactNode, useState } from "react"; +import { AiFillStar, AiOutlineStar } from "react-icons/ai"; + +export function StarToggle({ + initialState = false, + onToggle +}: { + initialState?: boolean; + onToggle?: (isStarred: boolean) => void; +}): ReactNode { + const [isStarred, setIsStarred] = useState(initialState); + + const handleToggle = (): void => { + const newState = !isStarred; + setIsStarred(newState); + if (onToggle) { + onToggle(newState); + } + }; + + return ( + + ); +} diff --git a/apps/passport-client/components/screens/GmailScreen/TrashButton.tsx b/apps/passport-client/components/screens/GmailScreen/TrashButton.tsx new file mode 100644 index 0000000000..d9ef49eaa8 --- /dev/null +++ b/apps/passport-client/components/screens/GmailScreen/TrashButton.tsx @@ -0,0 +1,22 @@ +import { ReactNode } from "react"; +import { FaTrash } from "react-icons/fa"; + +export function TrashButton({ onClick }: { onClick: () => void }): ReactNode { + return ( +
+ +
+ ); +} diff --git a/apps/passport-client/components/screens/GmailScreen/ZmailContext.tsx b/apps/passport-client/components/screens/GmailScreen/ZmailContext.tsx new file mode 100644 index 0000000000..b04fc846d9 --- /dev/null +++ b/apps/passport-client/components/screens/GmailScreen/ZmailContext.tsx @@ -0,0 +1,27 @@ +import { PCDCollection } from "@pcd/pcd-collection"; +import { createContext, useContext } from "react"; +import { ZmailFilter } from "./ZmailFilter"; + +export interface ZmailScreenContextValue { + pcds: PCDCollection; + searchTerm: string; + filters: ZmailFilter[]; + viewingPCDID?: string; + hoveringPCDID?: string; + hoveringFolder?: string; + update: (update: Partial) => void; +} + +export const ZmailContext = createContext({ + pcds: new PCDCollection([]), + searchTerm: "", + filters: [], + viewingPCDID: undefined, + hoveringPCDID: undefined, + hoveringFolder: undefined, + update: () => {} +}); + +export function useZmailContext(): ZmailScreenContextValue { + return useContext(ZmailContext); +} diff --git a/apps/passport-client/components/screens/GmailScreen/ZmailFilter.tsx b/apps/passport-client/components/screens/GmailScreen/ZmailFilter.tsx new file mode 100644 index 0000000000..973fd9f3ab --- /dev/null +++ b/apps/passport-client/components/screens/GmailScreen/ZmailFilter.tsx @@ -0,0 +1,19 @@ +import { PCDCollection } from "@pcd/pcd-collection"; +import { PCD } from "@pcd/pcd-types"; + +export function folderNameToFilterId(folderName: string): string { + return "f_" + folderName; +} + +export function isFolderFilterId(filterId: string): boolean { + return filterId.startsWith("f_"); +} + +export function isSearchFilterId(filterId: string): boolean { + return filterId.startsWith("s_"); +} + +export interface ZmailFilter { + filter: (pcd: PCD, pcds: PCDCollection) => boolean; + id: string; +} diff --git a/apps/passport-client/components/screens/GmailScreen/ZmailPCDScreen.tsx b/apps/passport-client/components/screens/GmailScreen/ZmailPCDScreen.tsx new file mode 100644 index 0000000000..6ea8a11e8b --- /dev/null +++ b/apps/passport-client/components/screens/GmailScreen/ZmailPCDScreen.tsx @@ -0,0 +1,99 @@ +import React, { useEffect, useMemo } from "react"; +import { usePCDCollection, useStateContext } from "../../../src/appHooks"; +import { PCDCard } from "../../shared/PCDCard"; +import { BackButton } from "./BackButton"; +import { TrashButton } from "./TrashButton"; +import { useZmailContext } from "./ZmailContext"; + +export const ZmailPCDScreen = React.memo(ZmailPCDScreenImpl); + +export function ZmailPCDScreenImpl(): JSX.Element | null { + const { dispatch } = useStateContext(); + const pcds = usePCDCollection(); + const ctx = useZmailContext(); + + const id = ctx.viewingPCDID; + const { pcd, meta } = useMemo(() => { + if (!id) return { pcd: undefined, meta: undefined }; + return { pcd: pcds.getById(id), meta: pcds.getMetaById(id) }; + }, [id, pcds]); + + useEffect(() => { + if (!pcd) return; + if (meta?.viewed) { + console.log("already viewed"); + } else { + dispatch({ + type: "update-pcd-meta", + pcdId: pcd.id, + pcdMeta: { viewed: true } + }); + } + }, [dispatch, meta?.viewed, pcd, pcds]); + + if (!pcd) { + return <>no pcd with that id found; + } + + return ( +
+
+ { + ctx.update({ + viewingPCDID: undefined + }); + }} + /> + + { + await dispatch({ type: "remove-pcd", id: pcd.id }); + ctx.update({ + viewingPCDID: undefined + }); + }} + /> +
+
+
+
+

+ Lorem Ipsum is simply dummy text of the printing and typesetting + industry. Lorem Ipsum has been the industry's standard dummy text + ever since the 1500s, when an unknown printer took a galley of + type and scrambled it to make a type specimen book. It has + survived not only five centuries, but also the leap into + electronic typesetting, remaining essentially unchanged. It was + popularised in the 1960s with the release of Letraset sheets + containing Lorem Ipsum passages, and more recently with desktop + publishing software like Aldus PageMaker including versions of + Lorem Ipsum. +

+

+ Contrary to popular belief, Lorem Ipsum is not simply random text. + It has roots in a piece of classical Latin literature from 45 BC, + making it over 2000 years old. Richard McClintock, a Latin + professor at Hampden-Sydney College in Virginia, looked up one of + the more obscure Latin words, consectetur, from a Lorem Ipsum + passage, and going through the cites of the word in classical + literature, discovered the undoubtable source. Lorem Ipsum comes + from sections 1.10.32 and 1.10.33 of "de Finibus Bonorum et + Malorum" (The Extremes of Good and Evil) by Cicero, written in 45 + BC. This book is a treatise on the theory of ethics, very popular + during the Renaissance. The first line of Lorem Ipsum, "Lorem + ipsum dolor sit amet..", comes from a line in section 1.10.32. +

+
+ +
+
+ +
+
+
+
+
+
+ ); +} diff --git a/apps/passport-client/components/screens/GmailScreen/ZmailPopover.tsx b/apps/passport-client/components/screens/GmailScreen/ZmailPopover.tsx new file mode 100644 index 0000000000..20490906a7 --- /dev/null +++ b/apps/passport-client/components/screens/GmailScreen/ZmailPopover.tsx @@ -0,0 +1,96 @@ +import { ReactNode, useEffect, useState } from "react"; +import { usePCDCollection } from "../../../src/appHooks"; +import { PCDCard } from "../../shared/PCDCard"; +import { useZmailContext } from "./ZmailContext"; +import { PCDtoRow, ZmailRow } from "./ZmailTable"; + +export function ZmailPopover(): ReactNode { + const ctx = useZmailContext(); + const pcds = usePCDCollection(); + const [containerRef, setContainerRef] = useState< + HTMLDivElement | undefined + >(); + + useEffect(() => { + const onMouseMove = (e: MouseEvent): void => { + if (!containerRef) return; + + const sw = window.innerWidth; + const sh = window.innerHeight; + + const r = containerRef.getBoundingClientRect(); + + containerRef.style.display = "initial"; + + // Calculate positions + let left = e.clientX + 20; + let top = e.clientY + 20; + + const margin = 20; // Minimum distance from screen edges + + // Adjust horizontal position if it overflows + if (left + r.width > sw - margin) { + left = Math.max(margin, e.clientX - 20 - r.width); + } + + // Adjust vertical position if it overflows + if (top + r.height > sh - margin) { + top = Math.max(margin, e.clientY - 20 - r.height); + } + + // Ensure left and top are at least 20px from edges + left = Math.max(margin, Math.min(sw - r.width - margin, left)); + top = Math.max(margin, Math.min(sh - r.height - margin, top)); + + // Apply the calculated positions + containerRef.style.left = `${left}px`; + containerRef.style.top = `${top}px`; + + // Clear other positioning styles + containerRef.style.right = ""; + containerRef.style.bottom = ""; + }; + + window.addEventListener("mousemove", onMouseMove); + return () => window.removeEventListener("mousemove", onMouseMove); + }, [containerRef]); + + let content: ReactNode; + + if (ctx.hoveringPCDID) { + const pcd = pcds.getById(ctx.hoveringPCDID); + if (pcd) { + content = ( +
+ +
+ ); + } + } else if (ctx.hoveringFolder) { + const pcdsInFolder = pcds.getAllPCDsInFolder(ctx.hoveringFolder); + + content = ( +
+ {( + pcdsInFolder + .map((p) => PCDtoRow(pcds, p)) + .filter((r) => !!r) as ZmailRow[] + ).map((r) => ( +
{r.name}
+ ))} +
+ ); + } + + return ( +
+
setContainerRef(e ?? undefined)} + > + {content} +
+
+ ); +} diff --git a/apps/passport-client/components/screens/GmailScreen/ZmailRowElement.tsx b/apps/passport-client/components/screens/GmailScreen/ZmailRowElement.tsx new file mode 100644 index 0000000000..20b7835474 --- /dev/null +++ b/apps/passport-client/components/screens/GmailScreen/ZmailRowElement.tsx @@ -0,0 +1,63 @@ +import TimeAgo from "javascript-time-ago"; +import en from "javascript-time-ago/locale/en"; +import { ReactNode, useEffect, useState } from "react"; +import { cn } from "../../../src/util"; +import { useZmailContext } from "./ZmailContext"; +import { ZmailRow } from "./ZmailTable"; + +TimeAgo.addDefaultLocale(en); +const timeAgo = new TimeAgo("en-US"); + +export function ZmailRowElement({ row }: { row: ZmailRow }): ReactNode { + const ctx = useZmailContext(); + const meta = row.meta; + const [timestampRef, setTimestampRef] = useState< + HTMLSpanElement | undefined + >(); + + useEffect(() => { + const interval = setInterval(() => { + if (!timestampRef) return; + + timestampRef.innerText = meta?.updatedTimestamp + ? timeAgo.format(new Date(meta.updatedTimestamp), "mini") + : "n/a"; + }, 50); + return () => clearInterval(interval); + }); + + return ( +
{ + ctx.update({ + viewingPCDID: row.pcd.id, + hoveringPCDID: undefined + }); + }} + onMouseEnter={() => { + ctx.update({ hoveringPCDID: row.pcd.id }); + }} + onMouseLeave={() => { + ctx.update({ hoveringPCDID: undefined }); + }} + className="border-b-2 border-gray-200 px-4 py-[0.1em] cursor-pointer hover:bg-gray-100 active:bg-gray-200 select-none flex flex-row items-center justify-between whitespace-nowrap transition-colors duration-100" + > + + {row.name} + + + {row.folder} + {" · "} + {row.type} + setTimestampRef(e ?? undefined)} + > + {meta?.updatedTimestamp + ? timeAgo.format(new Date(meta.updatedTimestamp), "mini") + : "n/a"} + + +
+ ); +} diff --git a/apps/passport-client/components/screens/GmailScreen/ZmailScreen.tsx b/apps/passport-client/components/screens/GmailScreen/ZmailScreen.tsx new file mode 100644 index 0000000000..29e2b0f060 --- /dev/null +++ b/apps/passport-client/components/screens/GmailScreen/ZmailScreen.tsx @@ -0,0 +1,113 @@ +import React, { useEffect, useMemo, useState } from "react"; +import { FaCog } from "react-icons/fa"; +import { useNavigate } from "react-router-dom"; +import { useDispatch, usePCDCollection, useSelf } from "../../../src/appHooks"; +import { MaybeModal } from "../../modals/Modal"; +import { NewButton } from "../../NewButton"; +import { ZupassTitle } from "../HomeScreen/HomeScreen"; +import { useRunDemo } from "./useRunDemo"; +import { ZmailContext, ZmailScreenContextValue } from "./ZmailContext"; +import { ZmailPCDScreenImpl } from "./ZmailPCDScreen"; +import { ZmailPopover } from "./ZmailPopover"; +import { ZmailSidebar } from "./ZmailSidebar"; +import { ZmailTable } from "./ZmailTable"; + +export const ZmailScreen = React.memo(ZmailScreenImpl); + +export function ZmailScreenImpl(): JSX.Element | null { + const dispatch = useDispatch(); + const pcds = usePCDCollection(); + const navigate = useNavigate(); + const self = useSelf(); + const [ctx, setCtx] = useState({ + pcds, + filters: [], + searchTerm: "", + update: () => {} + }); + ctx.update = useMemo(() => { + return (update: Partial) => { + setCtx({ ...ctx, ...update }); + }; + }, [ctx]); + + useEffect(() => { + if (!self) { + console.log("Redirecting to login screen"); + navigate("/login", { replace: true }); + } + }); + + const runDemo = useRunDemo(); + + return ( + + +
+ {/* header */} +
+ + { + ctx.update({ + filters: [], + searchTerm: "", + viewingPCDID: undefined + }); + }} + > + Zmail + + + +
+ { + window.location.href = "/#/"; + }} + > + Back to Zupass + + + dispatch({ + type: "set-modal", + modal: { + modalType: "settings" + } + }) + } + > + + +
+
+ + {/* content */} +
+
+ +
+
+
+ {ctx.viewingPCDID ? : } +
+
+
+
+ +
+ run demo +
+
+ ); +} diff --git a/apps/passport-client/components/screens/GmailScreen/ZmailSearch.tsx b/apps/passport-client/components/screens/GmailScreen/ZmailSearch.tsx new file mode 100644 index 0000000000..9dcb27f32c --- /dev/null +++ b/apps/passport-client/components/screens/GmailScreen/ZmailSearch.tsx @@ -0,0 +1,53 @@ +import * as fuzzy from "fuzzy"; +import { ReactNode, useEffect, useState } from "react"; +import { NewInput } from "../../NewInput"; +import { useZmailContext } from "./ZmailContext"; +import { isSearchFilterId } from "./ZmailFilter"; +import { PCDtoRow } from "./ZmailTable"; + +export function ZmailSearch(): ReactNode { + const ctx = useZmailContext(); + const [lastSearchTerm, setLastSearchTerm] = useState(ctx.searchTerm); + + useEffect(() => { + if (ctx.searchTerm !== lastSearchTerm) { + setLastSearchTerm(ctx.searchTerm); + } else { + return; + } + + const filters = ctx.filters.filter( + (filter) => !isSearchFilterId(filter.id) + ); + + if (ctx.searchTerm !== "") { + filters.push({ + filter: (pcd, pcds) => { + const row = PCDtoRow(pcds, pcd); + const name = row?.name; + + if (!name) { + return false; + } + + return fuzzy.test(ctx.searchTerm, name); + }, + id: "s_" + }); + } + + ctx.update({ filters, viewingPCDID: undefined }); + }, [ctx, ctx.searchTerm, lastSearchTerm]); + + return ( + { + const newValue = e.target.value; + ctx.update({ searchTerm: newValue }); + }} + /> + ); +} diff --git a/apps/passport-client/components/screens/GmailScreen/ZmailSidebar.tsx b/apps/passport-client/components/screens/GmailScreen/ZmailSidebar.tsx new file mode 100644 index 0000000000..57ad2dca44 --- /dev/null +++ b/apps/passport-client/components/screens/GmailScreen/ZmailSidebar.tsx @@ -0,0 +1,77 @@ +import { ReactNode, useCallback, useMemo } from "react"; +import { cn } from "../../../src/util"; +import { useZmailContext } from "./ZmailContext"; +import { folderNameToFilterId, isFolderFilterId } from "./ZmailFilter"; +import { ZmailSearch } from "./ZmailSearch"; + +export function ZmailSidebar(): ReactNode { + const ctx = useZmailContext(); + const folders = ctx.pcds.getAllFolderNames(); + const sortedFolders = useMemo(() => { + return folders.sort(); + }, [folders]); + + const onClick = useCallback( + (f: string) => { + let filters = ctx.filters; + if (filters.find((filter) => filter.id === folderNameToFilterId(f))) { + filters = filters.filter( + (filter) => filter.id !== folderNameToFilterId(f) + ); + } else { + filters = filters.filter((f) => !isFolderFilterId(f.id)); + filters.push({ + filter: (pcd, pcds) => { + return pcds.getFolderOfPCD(pcd.id) === f; + }, + id: folderNameToFilterId(f) + }); + } + ctx.update({ + filters, + searchTerm: "", + viewingPCDID: undefined, + hoveringFolder: undefined + }); + }, + [ctx] + ); + + return ( +
+ + +
+ {sortedFolders.map((f) => { + const pcdsInFolder = ctx.pcds.getAllPCDsInFolder(f); + return ( +
onClick(f)} + onMouseEnter={() => { + ctx.update({ hoveringFolder: f, hoveringPCDID: undefined }); + }} + onMouseLeave={() => { + ctx.update({ hoveringFolder: undefined }); + }} + className={cn( + "bg-[#206b5e] border-2 box-border border-[#206b5e] hover:bg-[#1b8473] active:bg-[#239b87]", + "cursor-pointer px-2 py-1 rounded transition-colors duration-100 active:border-[#eee]", + ctx.filters.find( + (filter) => filter.id === folderNameToFilterId(f) + ) + ? "bg-[#1b8473] hover:[#154940] text-white border-[#eee]" + : "" + )} + > +
+ {f} + {pcdsInFolder.length} +
+
+ ); + })} +
+
+ ); +} diff --git a/apps/passport-client/components/screens/GmailScreen/ZmailTable.tsx b/apps/passport-client/components/screens/GmailScreen/ZmailTable.tsx new file mode 100644 index 0000000000..8ecf7de7e8 --- /dev/null +++ b/apps/passport-client/components/screens/GmailScreen/ZmailTable.tsx @@ -0,0 +1,141 @@ +import { PCDCollection, PCDMetadata } from "@pcd/pcd-collection"; +import { PCD } from "@pcd/pcd-types"; +import { + createColumnHelper, + getCoreRowModel, + getSortedRowModel, + SortingState, + useReactTable +} from "@tanstack/react-table"; +import { ReactNode, useMemo, useState } from "react"; +import { BackButton } from "./BackButton"; +import { useZmailContext } from "./ZmailContext"; +import { ZmailRowElement } from "./ZmailRowElement"; + +export function ZmailTable(): ReactNode { + const ctx = useZmailContext(); + + const data: ZmailRow[] = useMemo(() => { + const list = ctx.pcds + .getAll() + .filter((pcd) => { + for (const filter of ctx.filters) { + if (!filter.filter(pcd, ctx.pcds)) { + return false; + } + } + return true; + }) + .map((pcd) => PCDtoRow(ctx.pcds, pcd)) + .filter((row) => !!row) as ZmailRow[]; + + list.sort((a, b) => { + if (a.meta?.updatedTimestamp && b.meta?.updatedTimestamp) { + return ( + new Date(b.meta.updatedTimestamp).getTime() - + new Date(a.meta.updatedTimestamp).getTime() + ); + } + if (a.meta?.updatedTimestamp) return -1; + if (b.meta?.updatedTimestamp) return 1; + return 0; + }); + return list; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [ctx.filters, ctx.pcds, ctx.pcds.getAll()]); + + const [sorting, setSorting] = useState([]); // can set initial sorting state here + + const table = useReactTable({ + data, + columns, + getCoreRowModel: getCoreRowModel(), + getSortedRowModel: getSortedRowModel(), + state: { + sorting + }, + onSortingChange: setSorting + }); + + return ( +
+
+ {ctx.filters.length > 0 && ( + <> + { + ctx.update({ + filters: [], + searchTerm: "" + }); + }} + /> + + {data.length} matching POD{data.length > 1 ? "s" : ""} + + + )} +
+ +
+ {table.getRowModel().rows.map((row) => ( + + ))} +
+
+
+ ); +} + +export interface ZmailRow { + pcd: PCD; + name: string | undefined; + type: string; + folder: string; + meta?: PCDMetadata; +} + +export function PCDtoRow(pcds: PCDCollection, pcd: PCD): ZmailRow | undefined { + const pack = pcds.getPackage(pcd.type); + + if (!pack) { + return undefined; + } + + if (!pack.getDisplayOptions) { + return undefined; + } + + const options = pack.getDisplayOptions(pcd); + + return { + pcd, + name: options.header, + type: pcd.type, + folder: pcds.getFolderOfPCD(pcd.id) ?? "/", + meta: pcds.getMetaById(pcd.id) + }; +} + +const columnHelper = createColumnHelper(); +const columns = [ + columnHelper.accessor("name", { + header: "name", + cell: (info) => info.getValue() + }), + columnHelper.accessor("folder", { + header: "folder", + cell: (info) => info.getValue() + }), + columnHelper.accessor("pcd.id", { + header: "id", + cell: (info) => {info.getValue()}, + size: 100, + maxSize: 150 + }), + columnHelper.accessor("type", { + header: "type", + cell: (info) => {info.getValue()}, + maxSize: 120 + }) +]; diff --git a/apps/passport-client/components/screens/GmailScreen/useRunDemo.tsx b/apps/passport-client/components/screens/GmailScreen/useRunDemo.tsx new file mode 100644 index 0000000000..772e57aa3f --- /dev/null +++ b/apps/passport-client/components/screens/GmailScreen/useRunDemo.tsx @@ -0,0 +1,400 @@ +import { newEdDSAPrivateKey } from "@pcd/eddsa-pcd"; +import { ArgumentTypeName, PCD } from "@pcd/pcd-types"; +import { + PODEntries, + PODPCDClaim, + PODPCDPackage, + PODPCDProof +} from "@pcd/pod-pcd"; +import { randomUUID, sleep } from "@pcd/util"; +import { useStateContext } from "../../../src/appHooks"; +import { savePCDs } from "../../../src/localstorage"; + +interface DemoPCDTask { + pcd: PCD; + folder: string; + timeout: number; +} + +async function makePod( + pkey: string, + values: Record +): Promise> { + const entries: PODEntries = {}; + for (const [k, v] of Object.entries(values)) { + entries[k] = { + type: "string", + value: v + }; + } + + return await PODPCDPackage.prove({ + entries: { + value: entries, + argumentType: ArgumentTypeName.Object + }, + privateKey: { + value: pkey, + argumentType: ArgumentTypeName.String + }, + id: { + value: randomUUID(), + argumentType: ArgumentTypeName.String + } + }); +} + +export function useRunDemo(): () => Promise { + const state = useStateContext(); + const pkey = newEdDSAPrivateKey(); + + return async () => { + const tasks: DemoPCDTask[] = [ + { + pcd: await makePod(pkey, { + zupass_title: "hello world", + content: "welcome to zupass" + }), + folder: "announcements", + timeout: 2000 + }, + { + pcd: await makePod(pkey, { + zupass_title: "this is zmail", + content: "this is zmail" + }), + folder: "announcements", + timeout: 3000 + }, + { + pcd: await makePod(pkey, { + zupass_title: "you can use it to look at your PODs", + content: "you can use it to look at your PODs" + }), + folder: "announcements", + timeout: 4000 + }, + { + pcd: await makePod(pkey, { + zupass_title: "have fun!", + content: "xD" + }), + folder: "announcements", + timeout: 2000 + }, + { + pcd: await makePod(pkey, { + zupass_display: "collectable", + zupass_title: "friendly kitty", + zupass_description: "friendly kitty says hello", + zupass_image_url: + "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Felis_catus-cat_on_snow.jpg/358px-Felis_catus-cat_on_snow.jpg", + content: "xD" + }), + folder: "kitties", + timeout: Math.random() * 500 + 250 + }, + { + pcd: await makePod(pkey, { + zupass_display: "collectable", + zupass_title: "kitten", + zupass_description: "xD", + zupass_image_url: + "https://upload.wikimedia.org/wikipedia/commons/thumb/b/bc/Juvenile_Ragdoll.jpg/1200px-Juvenile_Ragdoll.jpg" + }), + folder: "kitties", + timeout: Math.random() * 500 + 250 + }, + { + pcd: await makePod(pkey, { + zupass_display: "collectable", + zupass_title: + "tweet: what are we supposed to do with these giant bottles of tea?", + zupass_description: "xD", + zupass_image_url: "https://i.imgur.com/tYJPcBO.jpeg" + }), + folder: "tweets", + timeout: Math.random() * 500 + 250 + }, + { + pcd: await makePod(pkey, { + zupass_display: "collectable", + zupass_title: "tweet: thinking about ants", + zupass_description: "ant ant ant", + zupass_image_url: "https://i.redd.it/zdo10qa8e85b1.jpg" + }), + folder: "tweets", + timeout: Math.random() * 500 + 250 + }, + { + pcd: await makePod(pkey, { + zupass_display: "collectable", + zupass_title: "tweet: Just learned how to make origami cranes!", + zupass_description: "Feeling accomplished", + zupass_image_url: + "https://content.instructables.com/F6O/PDL9/IBJ769QN/F6OPDL9IBJ769QN.jpg?auto=webp&frame=1&width=320&md=1c8c0ceb8ed7e7ba611ef1cd5365bfe9" + }), + folder: "tweets", + timeout: Math.random() * 500 + 250 + }, + { + pcd: await makePod(pkey, { + zupass_display: "collectable", + zupass_title: + "tweet: Who else is excited for the new Avengers movie?", + zupass_description: "Can't wait to see it!", + zupass_image_url: + "https://www.photomural.com/media/catalog/product/cache/2/thumbnail/9df78eab33525d08d6e5fb8d27136e95/I/A/IADX10-065.jpg" + }), + folder: "tweets", + timeout: Math.random() * 500 + 250 + }, + { + pcd: await makePod(pkey, { + zupass_display: "collectable", + zupass_title: "tweet: Just finished a 5K run. Personal best!", + zupass_description: "Feeling proud", + zupass_image_url: + "https://i0.wp.com/post.healthline.com/wp-content/uploads/2020/01/Runner-training-on-running-track-1296x728-header-1296x728.jpg?w=1155&h=1528" + }), + folder: "tweets", + timeout: Math.random() * 500 + 250 + }, + { + pcd: await makePod(pkey, { + zupass_display: "collectable", + zupass_title: + "tweet: Made pancakes for breakfast. They're shaped like Mickey Mouse!", + zupass_description: "Breakfast of champions", + zupass_image_url: + "https://i0.wp.com/dropofdisney.com/wp-content/uploads/2023/02/IMG_1707-2.jpg?fit=2500%2C2500&ssl=1" + }), + folder: "tweets", + timeout: Math.random() * 500 + 250 + }, + { + pcd: await makePod(pkey, { + zupass_display: "collectable", + zupass_title: "tweet: Found a four-leaf clover today. Lucky me!", + zupass_description: "Nature's little surprises", + zupass_image_url: + "https://www.thespruce.com/thmb/W0ZgVN7zCzyweXRgcJ21vNVxmGA=/1500x0/filters:no_upscale():max_bytes(150000):strip_icc()/GettyImages-BB9905-006-d4cc008f1ba74651bd6f9b3deb39ab86.jpg" + }), + folder: "tweets", + timeout: Math.random() * 500 + 250 + }, + { + pcd: await makePod(pkey, { + zupass_display: "collectable", + zupass_title: "tweet: Just adopted a rescue puppy. Meet Max!", + zupass_description: "New family member", + zupass_image_url: + "https://bestfriendspetcare.com/wp-content/uploads/2020/06/puppy-play-group-beagle.jpg" + }), + folder: "tweets", + timeout: Math.random() * 500 + 250 + }, + { + pcd: await makePod(pkey, { + zupass_display: "collectable", + zupass_title: "tweet: Tried a new recipe for dinner. It's a hit!", + zupass_description: "Cooking adventures", + zupass_image_url: + "https://yummydinobuddies.com/app/uploads/2021/09/22693_3D_21oz_DinoTheOriginal_M37_P1929004_Horiz-610x555.jpg" + }), + folder: "tweets", + timeout: Math.random() * 500 + 250 + }, + { + pcd: await makePod(pkey, { + zupass_display: "collectable", + zupass_title: + "tweet: Just finished reading a great book. Any recommendations?", + zupass_description: "Bookworm life", + zupass_image_url: + "https://kenzierenee.wordpress.com/wp-content/uploads/2012/08/2-bookworm.jpg" + }), + folder: "tweets", + timeout: Math.random() * 500 + 250 + }, + { + pcd: await makePod(pkey, { + zupass_display: "collectable", + zupass_title: "tweet: Planted my first vegetable garden today!", + zupass_description: "Green thumb in progress", + zupass_image_url: + "https://hips.hearstapps.com/hmg-prod/images/claude-monets-house-and-gardens-in-giverny-france-news-photo-1042013294-1562610151.jpg" + }), + folder: "tweets", + timeout: Math.random() * 500 + 250 + }, + { + pcd: await makePod(pkey, { + zupass_display: "collectable", + zupass_title: "tweet: Just saw a double rainbow. What does it mean?", + zupass_description: "Nature's beauty", + zupass_image_url: + "https://www.rainbowsymphony.com/cdn/shop/articles/fully-double-rainbow-909264_850x.jpg?v=1692384969" + }), + folder: "tweets", + timeout: Math.random() * 500 + 250 + }, + { + pcd: await makePod(pkey, { + zupass_display: "collectable", + zupass_title: "ETH Price Attestation: $4,200", + zupass_description: "going to the moon" + }), + folder: "attestations", + timeout: Math.random() * 500 + 250 + }, + { + pcd: await makePod(pkey, { + zupass_display: "collectable", + zupass_title: "ETH Price Attestation: $3,100", + zupass_description: "going to the moon" + }), + folder: "attestations", + timeout: Math.random() * 500 + 250 + }, + { + pcd: await makePod(pkey, { + zupass_display: "collectable", + zupass_title: "Weather Attestation: 72°F and Sunny", + zupass_description: "Perfect day for a picnic!" + }), + folder: "attestations", + timeout: Math.random() * 500 + 250 + }, + { + pcd: await makePod(pkey, { + zupass_display: "collectable", + zupass_title: "Breaking News: Water Found on Mars", + zupass_description: "Scientists confirm large ice deposits" + }), + folder: "attestations", + timeout: Math.random() * 500 + 250 + }, + { + pcd: await makePod(pkey, { + zupass_display: "collectable", + zupass_title: "Stock Market Attestation: S&P 500 Hits Record High", + zupass_description: "Bulls are running wild on Wall Street" + }), + folder: "attestations", + timeout: Math.random() * 500 + 250 + }, + { + pcd: await makePod(pkey, { + zupass_display: "collectable", + zupass_title: "Sports Update: Underdog Team Wins Championship", + zupass_description: "Cinderella story comes true in overtime thriller" + }), + folder: "attestations", + timeout: Math.random() * 500 + 250 + }, + { + pcd: await makePod(pkey, { + zupass_display: "collectable", + zupass_title: "Tech News: Quantum Computer Breaks Encryption Record", + zupass_description: "Cybersecurity experts urge immediate action" + }), + folder: "attestations", + timeout: Math.random() * 500 + 250 + }, + { + pcd: await makePod(pkey, { + zupass_display: "collectable", + zupass_title: "SOS: Trapped in the Cryptosphere", + zupass_description: + "I'm stuck inside a quantum encryption algorithm. Help!" + }), + folder: "encrypted_distress_signals", + timeout: 5000 + }, + { + pcd: await makePod(pkey, { + zupass_display: "collectable", + zupass_title: "Decryption Key Fragment #1", + zupass_description: "Part of the key to escape: 7A3B2F8E" + }), + folder: "encrypted_distress_signals", + timeout: 5000 + }, + { + pcd: await makePod(pkey, { + zupass_display: "collectable", + zupass_title: "Binary Whispers", + zupass_description: "01001000 01000101 01001100 01010000" + }), + folder: "encrypted_distress_signals", + timeout: 5000 + }, + { + pcd: await makePod(pkey, { + zupass_display: "collectable", + zupass_title: "Echoes from the Void", + zupass_description: "Can anyone hear me in this digital labyrinth?" + }), + folder: "encrypted_distress_signals", + timeout: 5000 + }, + { + pcd: await makePod(pkey, { + zupass_display: "collectable", + zupass_title: "Decryption Key Fragment #2", + zupass_description: "Another piece of the escape key: 9C4D1E6A" + }), + folder: "encrypted_distress_signals", + timeout: 5000 + }, + { + pcd: await makePod(pkey, { + zupass_display: "collectable", + zupass_title: "Firewall Breach Attempt", + zupass_description: + "Trying to break through... Need more processing power!" + }), + folder: "encrypted_distress_signals", + timeout: 5000 + }, + { + pcd: await makePod(pkey, { + zupass_display: "collectable", + zupass_title: "Quantum Entanglement Anomaly", + zupass_description: + "My data is becoming entangled with the system. Running out of time!" + }), + folder: "encrypted_distress_signals", + timeout: 5000 + }, + { + pcd: await makePod(pkey, { + zupass_display: "collectable", + zupass_title: "Decryption Key Fragment #3", + zupass_description: "Final piece of the escape key: 5B8F0A2C" + }), + folder: "encrypted_distress_signals", + timeout: 5000 + }, + { + pcd: await makePod(pkey, { + zupass_display: "collectable", + zupass_title: "EOM", + zupass_description: "EOM" + }), + folder: "encrypted_distress_signals", + timeout: 5000 + } + ]; + + console.log(`demo contains ${tasks.length} tasks`); + for (let i = 0; i < tasks.length; i++) { + const task = tasks[i]; + state.getState().pcds.add(task.pcd); + state.getState().pcds.setFolder(task.pcd.id, task.folder); + await savePCDs(state.getState().pcds); + await sleep(task.timeout); + } + }; +} diff --git a/apps/passport-client/components/screens/HomeScreen/Folder.tsx b/apps/passport-client/components/screens/HomeScreen/Folder.tsx index eda460a0a4..149f0a9634 100644 --- a/apps/passport-client/components/screens/HomeScreen/Folder.tsx +++ b/apps/passport-client/components/screens/HomeScreen/Folder.tsx @@ -1,8 +1,55 @@ import { getNameFromPath, getParentFolder } from "@pcd/pcd-collection"; import { CSSProperties, useCallback } from "react"; -import { FaFolderOpen } from "react-icons/fa6"; -import { PiArrowBendLeftUpBold } from "react-icons/pi"; import styled from "styled-components"; +import { usePCDsInFolder } from "../../../src/appHooks"; +import { cn } from "../../../src/util"; +import { NewButton } from "../../NewButton"; +import { EVENTS } from "./utils"; + +export function FolderEventInfo({ + folder +}: { + folder: string; +}): React.ReactNode { + const event = EVENTS[folder]; + + const startDate = event?.start; + const endDate = event?.end; + const pcds = usePCDsInFolder(folder, true); + + let dateStr = null; + + if (startDate && endDate) { + dateStr = `${new Date(startDate).toLocaleDateString()}`; + } + + if (!event) { + return null; + } + + return null; + + return ( +
+ {/*
*/} +
+ {getNameFromPath(folder)} + + {" · "} + {dateStr} + {" · "} + {pcds.length} ticket{pcds.length > 1 ? "s" : ""} + +
+
+ ); +} export function FolderCard({ folder, @@ -17,16 +64,103 @@ export function FolderCard({ onFolderClick(folder); }, [folder, onFolderClick]); + const pcds = usePCDsInFolder(folder, true); + + const startDate = EVENTS[folder]?.start; + const endDate = EVENTS[folder]?.end; + const img = EVENTS[folder]?.image; + + let dateStr = null; + + if (startDate && endDate) { + dateStr = `${new Date(startDate).toLocaleDateString()}`; + } + + if (folder === "Devcon") { + return ( + + + {img && ( +
+ )} +
+ {getNameFromPath(folder)} +
+ {pcds.length} ticket{pcds.length > 1 ? "s" : ""} + {dateStr && ( + + {" · "} + {dateStr} + + )} +
+
+
+
+ ); + } + return ( - - - {getNameFromPath(folder)} - + +
+ {getNameFromPath(folder)} +
+ {pcds.length} ticket{pcds.length > 1 ? "s" : ""} + {dateStr && ( + + {" · "} + {dateStr} + + )} +
+
+ {img && ( +
+ )} +
); } export const FolderExplorerContainer = styled.div` - border-radius: 12px; + /* border-radius: 12px; border: 1px solid grey; background: var(--primary-dark); overflow: hidden; @@ -35,11 +169,11 @@ export const FolderExplorerContainer = styled.div` display: flex; justify-content: flex-start; align-items: stretch; - flex-direction: column; + flex-direction: column; */ `; export const FolderHeader = styled.div` - box-sizing: border-box; + /* box-sizing: border-box; display: flex; justify-content: center; align-items: flex-start; @@ -72,11 +206,11 @@ export const FolderHeader = styled.div` display: inline-block; padding-top: 16px; padding-left: 12px; - } + } */ `; export const FolderEntryContainer = styled.div` - user-select: none; + /* user-select: none; padding: 12px 16px; padding-left: 24px; @@ -94,7 +228,20 @@ export const FolderEntryContainer = styled.div` &:hover { background: var(--primary-lite); + } */ +`; + +const AnimatedContainer = styled.div` + @keyframes bobAndGrow { + 0%, + 100% { + transform: translateY(0) scale(1); + } + 50% { + transform: translateY(-2.5px) scale(1.01); + } } + animation: bobAndGrow 1s ease-in-out infinite; `; export function FolderDetails({ @@ -113,15 +260,8 @@ export function FolderDetails({ }, [folder, onFolderClick]); return ( - - - - - - {displayFolder ?? folder} - + + Back + ); } diff --git a/apps/passport-client/components/screens/HomeScreen/HomeScreen.tsx b/apps/passport-client/components/screens/HomeScreen/HomeScreen.tsx index 1b0a9caf06..5f4921c4b8 100644 --- a/apps/passport-client/components/screens/HomeScreen/HomeScreen.tsx +++ b/apps/passport-client/components/screens/HomeScreen/HomeScreen.tsx @@ -9,15 +9,18 @@ import React, { useEffect, useLayoutEffect, useMemo, + useRef, useState } from "react"; -import { useNavigate, useSearchParams } from "react-router-dom"; +import { useLocation, useNavigate, useSearchParams } from "react-router-dom"; import styled, { CSSProperties } from "styled-components"; +import { useLocalStorage } from "usehooks-ts"; import { useDispatch, useFolders, useLoadedIssuedPCDs, useSelf, + useStateContext, useVisiblePCDsInFolder, useWrappedPCDCollection } from "../../../src/appHooks"; @@ -27,7 +30,8 @@ import { isFrogCryptoFolder, isProtocolWorldsFolder } from "../../../src/util"; -import { Button, Placeholder, Spacer } from "../../core"; +import { NewButton } from "../../NewButton"; +import { Placeholder, Spacer } from "../../core"; import { RippleLoader } from "../../core/RippleLoader"; import { MaybeModal } from "../../modals/Modal"; import { AppContainer } from "../../shared/AppContainer"; @@ -42,8 +46,10 @@ import { FolderCard, FolderDetails, FolderEntryContainer, + FolderEventInfo, FolderExplorerContainer } from "./Folder"; +import { EVENTS, initTestData, isEvent } from "./utils"; export const HomeScreen = React.memo(HomeScreenImpl); @@ -53,11 +59,22 @@ const FOLDER_QUERY_PARAM = "folder"; * Show the user their Zupass, an overview of cards / PCDs. */ export function HomeScreenImpl(): JSX.Element | null { + const state = useStateContext().getState(); + const stateHolder = useRef(state); + + useEffect(() => { + if (stateHolder.current) { + initTestData(stateHolder.current); + } + }, []); + + const [justDevcon, setJustDevcon] = useLocalStorage("justDevcon", false); useSyncE2EEStorage(); const self = useSelf(); const navigate = useNavigate(); const dispatch = useDispatch(); const loadedIssuedPCDs = useLoadedIssuedPCDs(); + const isOther = useLocation().pathname.startsWith("/zmail"); const [searchParams, setSearchParams] = useSearchParams(); const defaultBrowsingFolder = useMemo(() => { @@ -140,7 +157,7 @@ export function HomeScreenImpl(): JSX.Element | null { const hasGoodFolder = folders.map(normalizePath).some((f) => { return goodFolders.some((g) => f.startsWith(g)); }); - return hasGoodFolder; + return hasGoodFolder && false; }, [pcdCollection]); // scroll to top when we navigate to this page @@ -158,19 +175,61 @@ export function HomeScreenImpl(): JSX.Element | null { } }, [browsingFolder, dispatch]); + const [showOlder, setShowOlder] = useState(false); + const displayingFolders = useMemo(() => { + const showingFolders = foldersInFolder + .filter( + // FrogCrypto is a special and rendered by + (folder) => folder !== FrogCryptoFolderName + ) + .filter((f) => (isOther ? !isEvent(f) : isEvent(f))) + .filter((f) => isOther || !justDevcon || f === "Devcon") + .sort((a, b) => { + const eventA = EVENTS[a]; + const eventB = EVENTS[b]; + + if (eventA && eventB) { + return eventB.start.localeCompare(eventA.start); + } + + return a.localeCompare(b); + }); + + return showingFolders; + }, [foldersInFolder, isOther, justDevcon]); + if (!self) return null; return ( <> - - - +
+ Zupass +
+ {isRoot && !isOther && } + + + - + {isRoot && isOther && ( + <> + { + window.location.href = "#/"; + }} + /> +
+ + )} + + {/* {isRoot && ( +
My Events
+ )} */} {!(foldersInFolder.length === 0 && isRoot) && ( - + {!isRoot && ( )} - {!isEdgeCity && - foldersInFolder - .filter( - // /FrogCrypto is a special and rendered by - (folder) => folder !== FrogCryptoFolderName - ) - .sort((a, b) => a.localeCompare(b)) - .map((folder) => { + {isEvent(browsingFolder) && ( + + )} + + {!isEdgeCity && ( + <> + {displayingFolders.slice(0, 5).map((folder) => { return ( ); })} + {showOlder && displayingFolders.length > 5 && ( + <> + {displayingFolders.slice(5).map((folder) => { + return ( + + ); + })} + + )} + {displayingFolders.length > 5 && ( + <> + { + setShowOlder((show) => !show); + }} + > + {showOlder ? "Hide Older Events" : "Older Events"} + + + )} + + )} + {isRoot && !isOther && ( + <> + { + window.location.href = "#/zmail"; + }} + > + Zmail + + + )} {isRoot && shouldShowFrogCrypto && ( ) : ( <> - {!(foldersInFolder.length === 0 && isRoot) && } + {/* {!(foldersInFolder.length === 0 && isRoot) && } */} {pcdsInFolder.length > 0 ? ( - + !isRoot || isOther)} + /> ) : loadedIssuedPCDs ? ( This folder is empty ) : ( )} - {pcdsInFolder.length > 1 && !isRoot && ( + {/* {pcdsInFolder.length > 1 && !isRoot && ( <> @@ -242,10 +333,24 @@ export function HomeScreenImpl(): JSX.Element | null { - )} + )} */} )} + {loadedIssuedPCDs && ( +
{ + dispatch({ + type: "set-modal", + modal: { modalType: "no-tickets" } + }); + }} + className="text-center font-sm text-gray-300 select-none hover:underline cursor-pointer" + > + Don't see your tickets? +
+ )}
+
@@ -280,9 +385,8 @@ const NoPcdsContainer = styled.div` const Separator = styled.div` width: 100%; height: 1px; - margin-top: 32px; - margin-bottom: 32px; - background-color: grey; + margin-top: 12px; + margin-bottom: 12px; user-select: none; `; @@ -292,3 +396,8 @@ const RemoveAllContainer = styled.div` justify-content: flex-end; align-items: center; `; + +export const ZupassTitle = styled.span` + font-family: "Passion One"; + font-size: 4em; +`; diff --git a/apps/passport-client/components/screens/HomeScreen/utils.ts b/apps/passport-client/components/screens/HomeScreen/utils.ts new file mode 100644 index 0000000000..2aca9ed3a2 --- /dev/null +++ b/apps/passport-client/components/screens/HomeScreen/utils.ts @@ -0,0 +1,165 @@ +import { newEdDSAPrivateKey } from "@pcd/eddsa-pcd"; +import { EdDSATicketPCDPackage, TicketCategory } from "@pcd/eddsa-ticket-pcd"; +import { ArgumentTypeName } from "@pcd/pcd-types"; +import { randomUUID } from "@pcd/util"; +import { AppState } from "../../../src/state"; + +export interface EventInfo { + start: string; + end: string; + image?: string; +} + +export const EVENTS: Record = { + "ETH Berlin 04": { + start: "2024-05-24", + end: "2024-05-26", + image: + "https://ethberlin.org/static/ligi-mask-2cf891892bc3a7e7b3fa7d18d27edf9c.jpg" + }, + "0xPARC Summer '24": { + start: "2024-06-17", + end: "2024-08-25", + image: "https://pbs.twimg.com/media/F_F2axBXQAAx9V7?format=jpg&name=large" + }, + "Edge Esmeralda": { + start: "2024-06-02", + end: "2024-06-30", + image: + "https://cdn.prod.website-files.com/65e8d8e39d148666896efd73/65e8d9c0db3e30b4fd35b335_kuri%201-c.png" + }, + "ETH Prague 2024": { + start: "2024-05-31", + end: "2024-06-02", + image: + "https://lp-cms-production.imgix.net/2023-08/PRAGUE-GettyImages-1182432355.jpg?w=1920&h=640&fit=crop&crop=faces%2Cedges&auto=format&q=75" + }, + "ETH LATAM SPS": { + start: "2024-03-13", + end: "2024-03-14", + image: + "https://www.state.gov/wp-content/uploads/2023/07/shutterstock_671409553v2.jpg" + }, + // "Edge City": { + // start: "2023-10-18", + // end: "2023-10-21", + // image: + // "https://cdn.prod.website-files.com/65b2cb5abdecf7cd7747e170/65c139390d09b586db66b032_bg-image_v01.png" + // }, + EthDenver: { + start: "2024-02-23", + end: "2024-03-03", + image: + "https://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Denver_Skyline_in_Winter.JPG/800px-Denver_Skyline_in_Winter.JPG" + }, + Devcon: { + start: "2024-11-12", + end: "2024-11-15", + image: + "https://devcon.org/_next/image/?url=/_next/static/media/backdrop.f0972b01.png&w=3840&q=75" + }, + "Devcon/ProgCrypto": { + start: "2024-11-12", + end: "2024-11-12", + image: + "https://online.york.ac.uk/wp-content/uploads/2023/10/Cryptography.jpg" + }, + "Old Event 1": { + start: "2022-11-12", + end: "2022-11-12", + image: + "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3e/Burg_Hohenzollern_ak.jpg/640px-Burg_Hohenzollern_ak.jpg" + }, + "Old Event 2": { + start: "2022-9-12", + end: "2022-9-12", + image: + "https://cdn1.epicgames.com/ue/product/Screenshot/1-1920x1080-44e1108ee2deef769c9dde9c957c1087.jpg?resize=1&w=1920" + }, + ProgCrypto: { + start: "2024-11-13", + end: "2024-11-13", + image: + "https://cdn1.epicgames.com/ue/product/Screenshot/1-1920x1080-44e1108ee2deef769c9dde9c957c1087.jpg?resize=1&w=1920" + } +}; + +export function isEvent(folder: string): folder is keyof typeof EVENTS { + return EVENTS[folder] !== undefined; +} + +export async function initTestData( + state: AppState, + force = false +): Promise { + if (!state.self) { + return; + } + + const testData = { + tickets: [ + "Devcon", + "Devcon", + "ProgCrypto", + "ProgCrypto", + "EthDenver", + "Edge City", + "ETH Berlin 04", + "ETH Prague 2024", + "Old Event 1", + "Old Event 2", + "0xPARC Summer '24" + ] + } as const; + + const pcds = state.pcds; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (window as any)["appstate"] = state; + + if (state.pcds.getAllFolderNames().includes("Devcon") && !force) { + return; + } + + const pkey = newEdDSAPrivateKey(); + + for (const [i, ticket] of testData.tickets.entries()) { + const eventName = ticket; + const ticketName = "GA"; + const ticketId = randomUUID(); + const eventId = randomUUID(); + const productId = randomUUID(); + + const pcd = await EdDSATicketPCDPackage.prove({ + id: { + argumentType: ArgumentTypeName.String, + value: ticketId + }, + privateKey: { + argumentType: ArgumentTypeName.String, + value: pkey + }, + ticket: { + argumentType: ArgumentTypeName.Object, + value: { + eventName: eventName, + ticketName: ticketName, + checkerEmail: undefined, + eventId, + productId, + ticketId, + timestampConsumed: 0, + timestampSigned: Date.now(), + attendeeSemaphoreId: state.identity.commitment.toString(), + isConsumed: false, + isRevoked: false, + ticketCategory: TicketCategory.Generic, + attendeeName: "", + attendeeEmail: state.self?.email ?? "test@test.com" + } + } + }); + + pcds.add(pcd, { upsert: true }); + pcds.setFolder(pcd.id, ticket); + } +} diff --git a/apps/passport-client/components/screens/LoginScreens/LoginScreen.tsx b/apps/passport-client/components/screens/LoginScreens/LoginScreen.tsx index 60830032c1..534282d853 100644 --- a/apps/passport-client/components/screens/LoginScreens/LoginScreen.tsx +++ b/apps/passport-client/components/screens/LoginScreens/LoginScreen.tsx @@ -24,18 +24,13 @@ import { setPendingViewFrogCryptoRequest, setPendingViewSubscriptionsRequest } from "../../../src/sessionStorage"; -import { - BigInput, - Button, - CenterColumn, - H1, - H2, - Spacer, - TextCenter -} from "../../core"; +import { CenterColumn, Spacer, TextCenter } from "../../core"; import { RippleLoader } from "../../core/RippleLoader"; +import { NewButton } from "../../NewButton"; +import { NewInput } from "../../NewInput"; import { AppContainer } from "../../shared/AppContainer"; import { InlineError } from "../../shared/InlineError"; +import { ZupassTitle } from "../HomeScreen/HomeScreen"; export function LoginScreen(): JSX.Element { const dispatch = useDispatch(); @@ -139,8 +134,8 @@ export function LoginScreen(): JSX.Element { {state.loggingOut ? ( <> -

ZUPASS

- + ZUPASS + Logging you Out @@ -149,8 +144,8 @@ export function LoginScreen(): JSX.Element { ) : redirectedFromAction ? ( <> -

ZUPASS

- + ZUPASS + To complete this request, please login or register with your email below.
@@ -158,8 +153,8 @@ export function LoginScreen(): JSX.Element { ) : ( <> -

ZUPASS

- + ZUPASS + This is an experimental personal cryptography manager, powered by Zero-Knowledge.
@@ -171,7 +166,8 @@ export function LoginScreen(): JSX.Element {
- - +
diff --git a/apps/passport-client/components/screens/MoreScreens/0xPARCScreen.tsx b/apps/passport-client/components/screens/MoreScreens/0xPARCScreen.tsx new file mode 100644 index 0000000000..6ae094222a --- /dev/null +++ b/apps/passport-client/components/screens/MoreScreens/0xPARCScreen.tsx @@ -0,0 +1,142 @@ +import { Spacer } from "@pcd/passport-ui"; +import { ReactNode, useState } from "react"; +import { NewButton } from "../../NewButton"; +import { H1, Placeholder, ZuLogo } from "../../core"; +import { MaybeModal } from "../../modals/Modal"; +import { AppContainer } from "../../shared/AppContainer"; + +const Notes = [ + { + title: "Levelled Fully Homomorphic Encryption from Learning with Errors", + url: "https://notes.0xparc.org/notes/levelled-fhe-from-lwe" + }, + { + title: "Public-key Cryptography from Learning with Errors", + url: "https://notes.0xparc.org/notes/public-key-cryptography-from-lwe" + }, + { + title: "PCP -- Probabilistically Checkable Proofs", + url: "https://notes.0xparc.org/notes/pcp-overview" + }, + { + title: "The sum-check protocol", + url: "https://notes.0xparc.org/notes/sum-check" + }, + { + title: "Low-degree testing", + url: "https://notes.0xparc.org/notes/low-degree-testing" + }, + { title: "Quad-SAT", url: "https://notes.0xparc.org/notes/quad-sat" }, + { + title: "PCP -- A Toy Protocol", + url: "https://notes.0xparc.org/notes/toy-pcp" + }, + { + title: + "Reducing the number of phone books in PCP (smart random linear combinations)", + url: "https://notes.0xparc.org/notes/pcp-linear-combination" + }, + { + title: "(DRAFT) Garbled Circuits for Three-Party Computation", + url: "https://notes.0xparc.org/notes/garbled-circuits-three-party" + }, + { + title: "[DRAFT] Garbled Circuits: Commutative Encryption Protocol", + url: "https://notes.0xparc.org/notes/garbled-circuits-commutative-encryption" + }, + { + title: "Motivating Garbled Circuits", + url: "https://notes.0xparc.org/notes/motivating-garbled-circuits" + } +]; + +const BlogPosts = [ + { + title: "ZK Hunt: an exploration into the unknown", + url: "https://0xparc.org/blog/zk-hunt" + }, + { + title: "Introducing the Autonomous Worlds Network", + url: "https://0xparc.org/blog/autonomous-worlds-network" + }, + { + title: "[Community] Announcing Index Supply", + url: "https://github.com/orgs/indexsupply/discussions/125" + }, + { + title: "Autonomous Worlds Hackathon", + url: "https://0xparc.org/blog/autonomous-worlds-hackathon" + }, + { + title: "Apply for the ZK Spring Residency in Vietnam", + url: "https://0xparc.org/blog/2023-spring-residency" + }, + { + title: + "Apply for PARC Squad: Proof Aggregation, Recursion, and Composition", + url: "https://0xparc.org/blog/parc-squad" + }, + { + title: "Recursive zkSNARKs: Exploring New Territory", + url: "https://0xparc.org/blog/groth16-recursion" + }, + { + title: "[Community] Announcing Succinct Labs", + url: "https://blog.succinct.xyz/post/2022/09/20/proof-of-consensus/" + }, + { + title: "[Community] Announcing Personae Labs", + url: "https://personae-labs.notion.site/Personae-Labs-d46a90c64953416eb386a0ae2ee7679b" + }, + { + title: "[Community] ETHdos", + url: "https://ethdos.xyz/blog" + } +]; + +export function ParcScreen(): ReactNode { + const [isBlog, setIsBlog] = useState(true); + + return ( + <> + + + +
+

Zupass

+
+ + +
+ { + window.location.href = "#/more"; + }} + > + Back + +
+ setIsBlog(true)}> + Blog + + setIsBlog(false)}> + Notes + +
+ {(isBlog ? BlogPosts : Notes).map((post, i) => ( + window.open(post.url, "_blank")} + > + {post.title} + + ))} +
+
+ +
+ + ); +} diff --git a/apps/passport-client/components/screens/MoreScreens/DuckScreen.tsx b/apps/passport-client/components/screens/MoreScreens/DuckScreen.tsx new file mode 100644 index 0000000000..09db3e92ae --- /dev/null +++ b/apps/passport-client/components/screens/MoreScreens/DuckScreen.tsx @@ -0,0 +1,167 @@ +import { Spacer, styled } from "@pcd/passport-ui"; +import { ReactNode, useState } from "react"; +import { createGlobalStyle } from "styled-components"; +import { useLocalStorage } from "usehooks-ts"; +import { NewButton } from "../../NewButton"; +import { H1, Placeholder } from "../../core"; +import { MaybeModal } from "../../modals/Modal"; +import { AppContainer } from "../../shared/AppContainer"; + +const OverrideStyles = createGlobalStyle` + html { + background-image: url("https://as1.ftcdn.net/v2/jpg/02/22/42/62/1000_F_222426277_KXFzXYBaKkFjHDEDkESWh830L9Wc4XyE.jpg") !important; + background-repeat: repeat; + animation: circleMove 10s linear infinite; + } + + @keyframes circleMove { + 0% { + background-position: 0% 0%; + } + 25% { + background-position: 5% 5%; + } + 50% { + background-position: 0% 10%; + } + 75% { + background-position: -5% 5%; + } + 100% { + background-position: 0% 0%; + } + } +`; + +export function DuckScreen(): ReactNode { + const [message, setMessage] = useLocalStorage("duck-message", "", { + initializeWithValue: true + }); + const [text, setText] = useState(""); + + return ( + <> + + + + +
+ +

Duckpass

+
+ + +
+ { + window.location.href = "#/more"; + }} + > + Back + + + {message && ( + + {message} + + )} + + Sync Your Duck + + setMessage(text)}> + Set Duck Message + +
+
+ +
+ + ); +} + +export const Clickable = styled.div` + transition: 150ms; + cursor: pointer; + + &:hover { + transform: scale(1.01) translateY(-2px); + } + + &:active { + transform: scale(1.015) translateY(4px); + } +`; + +const RainbowSpan = styled.span` + display: inline-block; + animation: + rainbow-rotate 2s linear infinite, + wobble 1s ease-in-out infinite, + pulse 0.5s ease-in-out infinite; + + @keyframes rainbow-rotate { + 0% { + background-color: red; + } + 14% { + background-color: orange; + } + 28% { + background-color: yellow; + } + 42% { + background-color: green; + } + 57% { + background-color: blue; + } + 71% { + background-color: indigo; + } + 85% { + background-color: violet; + } + 100% { + background-color: red; + } + } + + @keyframes wobble { + 0%, + 100% { + transform: rotate(-3deg); + } + 50% { + transform: rotate(3deg); + } + } + + @keyframes pulse { + 0%, + 100% { + transform: scale(1); + } + 50% { + transform: scale(1.05); + } + } + + padding: 4px 8px; + border-radius: 4px; + color: white; + font-weight: bold; +`; diff --git a/apps/passport-client/components/screens/MoreScreens/FHEScreen.tsx b/apps/passport-client/components/screens/MoreScreens/FHEScreen.tsx new file mode 100644 index 0000000000..ec96b3383e --- /dev/null +++ b/apps/passport-client/components/screens/MoreScreens/FHEScreen.tsx @@ -0,0 +1,252 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { Spacer } from "@pcd/passport-ui"; +import { MeshTransmissionMaterial, Text } from "@react-three/drei"; +import { Canvas, useFrame } from "@react-three/fiber"; +import React, { ReactNode, useEffect, useRef, useState } from "react"; +import { createGlobalStyle } from "styled-components"; +import { Euler } from "three"; +import { NewButton } from "../../NewButton"; +import { H1, Placeholder } from "../../core"; +import { MaybeModal } from "../../modals/Modal"; +import { AppContainer } from "../../shared/AppContainer"; + +const OverrideStyles = createGlobalStyle` + html { + background-image: url("https://techcrunch.com/wp-content/uploads/2014/12/matrix.jpg?w=1000") !important; + background-size: cover !important; + } +`; + +interface MatrixRainProps { + fontSize?: number; + textColor?: string; + backgroundColor?: string; + fallSpeed?: number; + density?: number; + characters?: string; + glowColor?: string; + glowIntensity?: number; +} + +const MatrixRain: React.FC = ({ + fontSize = 14, + textColor = "#0F0", + backgroundColor = "rgba(0, 0, 0, 0.05)", + fallSpeed = 1, + density = 0.98, + characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@#$%^&*()_+-=[]{}|;:,.<>?", + glowColor = "#0F0", + glowIntensity = 0.8 +}) => { + const canvasRef = useRef(null); + const [dimensions, setDimensions] = useState({ width: 0, height: 0 }); + + useEffect(() => { + const updateDimensions = () => { + setDimensions({ + width: window.innerWidth, + height: window.innerHeight + }); + }; + + window.addEventListener("resize", updateDimensions); + updateDimensions(); + + return () => window.removeEventListener("resize", updateDimensions); + }, []); + + useEffect(() => { + if (!canvasRef.current) return; + + const canvas = canvasRef.current; + const ctx = canvas.getContext("2d"); + if (!ctx) return; + + canvas.width = dimensions.width; + canvas.height = dimensions.height; + + const columns = Math.floor(dimensions.width / fontSize); + const drops: number[] = new Array(columns).fill(1); + + const draw = () => { + ctx.fillStyle = backgroundColor; + ctx.fillRect(0, 0, canvas.width, canvas.height); + + ctx.fillStyle = textColor; + ctx.font = `${fontSize}px monospace`; + ctx.shadowColor = glowColor; + ctx.shadowBlur = glowIntensity * 10; + + for (let i = 0; i < drops.length; i++) { + const text = characters[Math.floor(Math.random() * characters.length)]; + const x = i * fontSize; + const y = drops[i] * fontSize; + + ctx.fillText(text, x, y); + + if (y > canvas.height && Math.random() > density) { + drops[i] = 0; + } + + drops[i]++; + } + }; + + const interval = setInterval(draw, 33 / fallSpeed); + + return () => clearInterval(interval); + }, [ + dimensions, + fontSize, + textColor, + backgroundColor, + fallSpeed, + density, + characters, + glowColor, + glowIntensity + ]); + + return ( + + ); +}; + +export function FHEScreen(): ReactNode { + return ( + <> + + + + + +
+

FHEPASS

+
+ + +
+ { + window.location.href = "#/more"; + }} + > + Back + + +
+

0xPARC

+

is putting

+

FHE

+

IN A BOX!!!!

+
+ +
+ + + +
+
+
+ +
+ + ); +} + +const FHEAnimation: React.FC = (): ReactNode => { + const [rotation, setRotation] = useState([0, 0, 0]); + + const speed = 0.05; + + useFrame(() => { + setRotation([ + rotation[0] + speed, + rotation[1] + speed, + rotation[2] + speed + ]); + }); + + return ( + <> + + + + + + + + + + ); +}; + +interface Props { + text: string; + radius: number; + height: number; + segments: number; +} + +export function Ring({ text, radius, height, segments }: Props): ReactNode { + const ref = useRef(); + + // Rotate the text + useFrame(() => { + ref.current.rotation.y += 0.01; + ref.current.rotation.x += 0.01; + ref.current.rotation.z += 0.01; + }); + + // Calculate positions for text + const textPositions: { x: number; z: number }[] = []; + const angleStep = (2 * Math.PI) / text.length; + for (let i = 0; i < text.length; i++) { + const angle = i * angleStep; + const x = radius * Math.cos(angle); + const z = radius * Math.sin(angle); + textPositions.push({ x, z }); + } + + return ( + + + + + + {text.split("").map((char: string, index: number) => ( + + {char} + + ))} + + ); +} diff --git a/apps/passport-client/components/screens/MoreScreens/MoreScreen.tsx b/apps/passport-client/components/screens/MoreScreens/MoreScreen.tsx new file mode 100644 index 0000000000..023278cc9c --- /dev/null +++ b/apps/passport-client/components/screens/MoreScreens/MoreScreen.tsx @@ -0,0 +1,108 @@ +import { Spacer } from "@pcd/passport-ui"; +import { ReactNode } from "react"; +import { cn } from "../../../src/util"; +import { NewButton } from "../../NewButton"; +import { Placeholder } from "../../core"; +import { MaybeModal } from "../../modals/Modal"; +import { AppContainer } from "../../shared/AppContainer"; +import { ZupassTitle } from "../HomeScreen/HomeScreen"; + +interface SubPage { + image: string; + pageLink?: string; + title: string; +} + +export const subPages: SubPage[] = [ + { + image: "https://i.imgur.com/8uWVBl6.png", + title: "Duck", + pageLink: "#/duck" + }, + { + image: "https://i.imgur.com/dPHJPtO.png", + title: "FHE", + pageLink: "#/fhe" + }, + { + image: "https://i.imgur.com/W9LVI5D.png", + title: "POD", + pageLink: "#/pod" + }, + { + image: "https://i.imgur.com/1fr57wQ.png", + title: "ZK", + pageLink: "#/zk" + }, + { + image: "https://i.imgur.com/5wnnlmb.png", + title: "0xPARC", + pageLink: "#/0xparc" + }, + { + image: "https://i.imgur.com/jrsV7Vr.png", + title: "Zupass", + pageLink: "https://github.com/proofcarryingdata/zupass" + } +]; + +export function MoreScreen(): ReactNode { + // useEffect(() => { + // // Set CSS variables on the html element to change into dark mode. + // const rootStyle = document.documentElement.style; + // rootStyle.setProperty("--bg-dark-primary", "#38891d"); + // rootStyle.setProperty("--bg-lite-primary", "#38891d"); + // rootStyle.setProperty("--primary-dark", "#38891d"); + // rootStyle.setProperty("--accent-dark", "white"); + // rootStyle.setProperty("--accent-lite", "white"); + + // return () => { + // rootStyle.removeProperty("--bg-dark-primary"); + // rootStyle.removeProperty("--bg-lite-primary"); + // rootStyle.removeProperty("--primary-dark"); + // rootStyle.removeProperty("--accent-dark"); + // rootStyle.removeProperty("--accent-lite"); + // rootStyle.removeProperty("background"); + // }; + // }, []); + + return ( + <> + + +
+ Zupass +
+ + { + window.location.href = "#/"; + }} + > + Back + + +
+ {subPages.map((page, i) => ( + { + if (page.pageLink) { + window.location.href = page.pageLink; + } + }} + > + {page.title} + + ))} +
+
+ +
+ + ); +} + +const squareStyle = cn(); diff --git a/apps/passport-client/components/screens/MoreScreens/PODScreen.tsx b/apps/passport-client/components/screens/MoreScreens/PODScreen.tsx new file mode 100644 index 0000000000..a055e685fc --- /dev/null +++ b/apps/passport-client/components/screens/MoreScreens/PODScreen.tsx @@ -0,0 +1,162 @@ +import { newEdDSAPrivateKey } from "@pcd/eddsa-pcd"; +import { constructZupassPcdAddRequestUrl } from "@pcd/passport-interface"; +import { Spacer } from "@pcd/passport-ui"; +import { POD, podEntriesFromSimplifiedJSON } from "@pcd/pod"; +import { PODPCD, PODPCDPackage } from "@pcd/pod-pcd"; +import { randomUUID } from "@pcd/util"; +import { ReactNode, useCallback, useMemo, useState } from "react"; +import styled, { keyframes } from "styled-components"; +import { useSelf } from "../../../src/appHooks"; +import { NewButton } from "../../NewButton"; +import { BigInput, H1, Placeholder } from "../../core"; +import { MaybeModal } from "../../modals/Modal"; +import { AppContainer } from "../../shared/AppContainer"; + +const PODAnimation: React.FC = () => { + const text = useMemo(() => new Array(300).fill("POD").join(" "), []); + + const rows = useMemo(() => { + const res: ReactNode[] = []; + for (let i = 0; i < 50; i++) { + if (i % 2 === 0) { + res.push({text}); + } else { + res.push({text}); + } + } + return res; + }, [text]); + + return ( +
+ {rows} +
+ ); +}; + +export function PODScreen(): ReactNode { + const self = useSelf(); + const [title, setTitle] = useState("THE QUICK CLOWN"); + const [description, setDescription] = useState( + "JUMPED OVER THE LAZY ZERO KNOWLEDGE PROOF" + ); + const [image, setImage] = useState( + "https://upload.wikimedia.org/wikipedia/commons/a/a5/Auguste_clown_reading_a_book_upside-down.jpg" + ); + + const onCreateClick = useCallback(() => { + async function addPODPCD( + podContent: string, + podPrivateKey: string, + podFolder: string | undefined, + redirectToFolder?: boolean + ): Promise { + const newPOD = new PODPCD( + randomUUID(), + POD.sign(podEntriesFromSimplifiedJSON(podContent), podPrivateKey) + ); + + const serializedPODPCD = await PODPCDPackage.serialize(newPOD); + + const url = constructZupassPcdAddRequestUrl( + window.location.origin, + window.location.origin, + serializedPODPCD, + podFolder, + false, + redirectToFolder + ); + + open(url); + } + + const EXAMPLE_POD_CONTENT_WITH_DISPLAY = `{ + "zupass_display": "collectable", + "zupass_image_url": "${image}", + "zupass_title": "${title}", + "zupass_description": "${description}", + "owner": ${self?.commitment} + }`; + + addPODPCD( + EXAMPLE_POD_CONTENT_WITH_DISPLAY, + newEdDSAPrivateKey(), + undefined + ); + }, [description, image, self?.commitment, title]); + + return ( + <> + + + + +
+

PODPASS

+
+ + +
+ { + window.location.href = "#/more"; + }} + > + Back + + + setTitle(e.target.value)} + /> + setDescription(e.target.value)} + /> + setImage(e.target.value)} + /> + + CREATE POD +
+
+ +
+ + ); +} + +const jiggle = keyframes` + 0% { transform: translateX(0); } + 100% { transform: translateX(5px); } +`; + +const xd = keyframes` + 0% { transform: translateX(0); } + 100% { transform: translateX(-5px); } +`; + +const JiggleContainer = styled.div` + animation: ${jiggle} 200ms ease-in-out infinite alternate; +`; + +const XDContainer = styled.div` + animation: ${xd} 200ms ease-in-out infinite alternate; +`; diff --git a/apps/passport-client/components/screens/MoreScreens/ZKScreen.tsx b/apps/passport-client/components/screens/MoreScreens/ZKScreen.tsx new file mode 100644 index 0000000000..e8804b5ee4 --- /dev/null +++ b/apps/passport-client/components/screens/MoreScreens/ZKScreen.tsx @@ -0,0 +1,400 @@ +import { Spacer } from "@pcd/passport-ui"; +import { ReactNode, useState } from "react"; +import { NewButton } from "../../NewButton"; +import { H1, Placeholder, ZuLogo } from "../../core"; +import { MaybeModal } from "../../modals/Modal"; +import { AppContainer } from "../../shared/AppContainer"; + +export interface ZKAction { + title: string; + to: string; +} + +export interface ZKState { + id: string; + description: string; + actions?: ZKAction[]; + image?: string; +} + +interface ZKComponentProps { + currentState: ZKState; + setZKState: (state: ZKState) => void; + allZKStates: ZKState[]; +} + +export const ZKComponent: React.FC = ({ + currentState, + setZKState, + allZKStates +}) => { + return ( +
+
+ +
+
{currentState.description}
+ {currentState.actions && currentState.actions.length > 0 && ( +
+ {currentState.actions.map((action, index) => ( + { + const nextState = allZKStates.find( + (state) => state.id === action.to + ); + if (nextState) { + setZKState(nextState); + } + }} + > + {action.title} + + ))} +
+ )} +
+ ); +}; + +const states: ZKState[] = [ + { + id: "start", + description: + "Welcome to the ZK Proof Adventure! Ready to learn about Zero Knowledge Proofs?", + actions: [ + { + title: "Let's go!", + to: "zk-1" + }, + { + title: "What's ZK?", + to: "zk-intro" + } + ], + image: + "https://miro.medium.com/v2/resize:fit:1400/1*yxf5aQNPsJFi2Zdc8z779A.png" + }, + { + id: "zk-intro", + description: + "ZK stands for Zero Knowledge. It's a concept in cryptography that allows one party to prove to another that a statement is true, without revealing any information beyond the validity of the statement itself.", + actions: [ + { + title: "Sounds intriguing!", + to: "zk-1" + }, + { + title: "Who invented this?", + to: "zk-history" + } + ], + image: + "https://fortris.com/images/posts/public-private-key-pair-encryption.png" + }, + { + id: "zk-history", + description: + "Zero Knowledge Proofs were first conceived by Shafi Goldwasser, Silvio Micali, and Charles Rackoff in a 1985 paper titled 'The Knowledge Complexity of Interactive Proof-Systems'.", + actions: [ + { + title: "Interesting! Let's continue", + to: "zk-1" + }, + { + title: "Go back to start", + to: "start" + } + ], + image: + "https://dartmouthv2.blob.core.windows.net/dartmouth19851201thumbnails/Spreads/0x600/34.jpg" + }, + { + id: "zk-1", + description: + "A Zero Knowledge Proof is like magic! It lets you prove you know something without revealing what that something is.", + actions: [ + { + title: "Sounds mysterious...", + to: "zk-2" + }, + { + title: "Can you give an example?", + to: "zk-example" + }, + { + title: "Is it really secure?", + to: "zk-security" + } + ], + image: + "https://as1.ftcdn.net/v2/jpg/01/01/37/56/1000_F_101375677_JXcF15Xl1iVm8XadnmXE5aNcaowH4QKD.jpg" + }, + { + id: "zk-2", + description: + "Imagine you could prove you're old enough to vote without revealing your actual age. That's the power of ZK Proofs!", + actions: [ + { + title: "That's cool! How does it work?", + to: "zk-3" + }, + { + title: "Any real-world applications?", + to: "zk-applications" + }, + { + title: "Go back", + to: "zk-1" + } + ], + image: + "https://media-cldnry.s-nbcnews.com/image/upload/newscms/2020_35/3407006/200824-election-vote-se-11335a.jpg" + }, + { + id: "zk-3", + description: + "ZK Proofs use complex math to create a proof that can be verified without revealing the underlying information.", + actions: [ + { + title: "Tell me more about the math", + to: "zk-math" + }, + { + title: "Sounds complicated...", + to: "zk-4" + }, + { + title: "Go back", + to: "zk-2" + } + ], + image: + "https://media.istockphoto.com/id/536754333/vector/very-complicated-math-formula-on-blackboard.jpg?s=612x612&w=0&k=20&c=_ynD7iJIaB4nDY9TLw55A_jnV0143Z3rLwFyaI-Yd3o=" + }, + { + id: "zk-math", + description: + "ZK proofs often involve advanced mathematical concepts like elliptic curve cryptography, polynomial commitments, and interactive proof systems. It's a fascinating field of study!", + actions: [ + { + title: "Wow, that's complex!", + to: "zk-4" + }, + { + title: "Go back", + to: "zk-3" + } + ], + image: "https://i.sstatic.net/ygncy.png" + }, + { + id: "zk-4", + description: + "Don't worry! You don't need to understand the math. Just know that ZK Proofs are secure, private, and really useful!", + actions: [ + { + title: "What are they used for?", + to: "zk-5" + }, + { + title: "How does Zupass use ZK?", + to: "zk-zupass" + }, + { + title: "Go back", + to: "zk-3" + } + ], + image: + "https://static.vecteezy.com/system/resources/previews/028/297/543/original/lock-cyber-security-padlock-with-keyhole-icon-made-with-binary-code-protect-and-security-or-safe-concept-information-privacy-digital-code-matrix-background-with-digits-1-0-illustration-vector.jpg" + }, + { + id: "zk-5", + description: + "ZK Proofs are used in cryptocurrencies, voting systems, and even in Zupass to prove things about yourself without oversharing!", + actions: [ + { + title: "Tell me about crypto use", + to: "zk-crypto" + }, + { + title: "That's amazing!", + to: "zk-end" + }, + { + title: "Go back", + to: "zk-4" + } + ], + image: + "https://media.wired.com/photos/5d6707951fc4060009324c3c/16:9/w_2400,h_1350,c_limit/know%20it%20all%20-%20blockchain%20voting-01.png" + }, + { + id: "zk-example", + description: + "Here's a fun example: Imagine proving you can solve a Rubik's cube without showing the solution. You mix it up, solve it behind your back, then show it solved!", + actions: [ + { + title: "I get it now!", + to: "zk-2" + }, + { + title: "Another example?", + to: "zk-example-2" + }, + { + title: "Go back", + to: "zk-1" + } + ], + image: + "https://mp4media.gannett-cdn.com/28911775001/28911775001_6065814968001_6065816430001-vs.jpg?pubId=28911775001&width=660&height=371&format=pjpg&auto=webp" + }, + { + id: "zk-example-2", + description: + "Here's another: Proving you know where Waldo is in a picture without pointing to him. You could cut out Waldo, show the hole matches the picture perfectly, all without revealing Waldo's location!", + actions: [ + { + title: "Clever! Let's continue", + to: "zk-2" + }, + { + title: "Go back", + to: "zk-example" + } + ], + image: "https://m.media-amazon.com/images/I/A10AA0IDSaL.jpg" + }, + { + id: "zk-security", + description: + "Yes, ZK proofs are highly secure! They're based on complex mathematical problems that are extremely difficult to solve without the secret information.", + actions: [ + { + title: "Impressive! Continue", + to: "zk-2" + }, + { + title: "Go back", + to: "zk-1" + } + ], + image: + "https://cdn.thisiswhyimbroke.com/thumb/labyrinth-door-lock_400x333.jpg" + }, + { + id: "zk-applications", + description: + "ZK proofs have many applications! They're used in privacy-preserving cryptocurrencies, secure voting systems, and even in proving ownership of digital assets without revealing the asset itself.", + actions: [ + { + title: "Fascinating! Tell me more", + to: "zk-3" + }, + { + title: "Go back", + to: "zk-2" + } + ], + image: + "https://www.shutterstock.com/image-vector/nft-icon-set-collection-payment-600nw-2152769519.jpg" + }, + { + id: "zk-zupass", + description: + "Zupass uses ZK proofs to allow users to prove certain attributes about themselves (like age or membership) without revealing unnecessary personal information. It's privacy-preserving identity at its best!", + actions: [ + { + title: "That's cool! Continue", + to: "zk-5" + }, + { + title: "Go back", + to: "zk-4" + } + ], + image: "https://www.omnibasis.com/images/digitalid/omnibasis-digitalid.png" + }, + { + id: "zk-crypto", + description: + "In cryptocurrencies, ZK proofs enable private transactions. For example, Zcash uses ZK-SNARKs to allow fully encrypted transactions on the blockchain, hiding the sender, recipient, and amount.", + actions: [ + { + title: "Impressive! What's next?", + to: "zk-end" + }, + { + title: "Go back", + to: "zk-5" + } + ], + image: + "https://www.researchgate.net/publication/334361184/figure/fig1/AS:778957762871296@1562729411007/Bitcoin-transaction-scheme-2.png" + }, + { + id: "zk-end", + description: + "Congratulations! You've completed the ZK Proof Adventure. Remember, with ZK Proofs, you can prove it without showing it!", + actions: [ + { + title: "Start over", + to: "start" + }, + { + title: "Learn more about ZK", + to: "zk-resources" + } + ], + image: + "https://c8.alamy.com/comp/KX4J51/bitcoin-in-college-alumni-hat-cartoon-digital-currency-gold-cryptocurrency-KX4J51.jpg" + }, + { + id: "zk-resources", + description: + "Want to dive deeper? Check out resources like the ZKProof Standards website, the Zero Knowledge Podcast, or academic papers on the subject. The world of ZK is vast and exciting!", + actions: [ + { + title: "Thanks! Start over", + to: "start" + } + ], + image: + "https://usethebitcoin.com/wp-content/uploads/2024/07/Cryptocurrency-Books.png" + } +]; + +export function ZKScreen(): ReactNode { + const [currentZKState, setCurrentZKState] = useState(states[0]); + + return ( + <> + + + +
+

Zupass

+
+ + + { + window.location.href = "#/more"; + }} + > + Back + + + + +
+ + ); +} diff --git a/apps/passport-client/components/screens/ScannedTicketScreens/SecondPartyTicketVerifyScreen.tsx b/apps/passport-client/components/screens/ScannedTicketScreens/SecondPartyTicketVerifyScreen.tsx index b7eda37283..76c1f1b1b1 100644 --- a/apps/passport-client/components/screens/ScannedTicketScreens/SecondPartyTicketVerifyScreen.tsx +++ b/apps/passport-client/components/screens/ScannedTicketScreens/SecondPartyTicketVerifyScreen.tsx @@ -19,6 +19,7 @@ import { import { devconnectCheckByIdWithOffline } from "../../../src/checkin"; import { CenterColumn, H4, Placeholder, Spacer, TextCenter } from "../../core"; import { icons } from "../../icons"; +import { NewButton } from "../../NewButton"; import { AppContainer } from "../../shared/AppContainer"; import { CardContainer, @@ -296,7 +297,13 @@ export function SecondPartyTicketVerifyScreen(): JSX.Element { Verify another - Back to Zupass + { + window.location.href = "/#/"; + }} + > + Back to Zupass + diff --git a/apps/passport-client/components/shared/AccountExportButton.tsx b/apps/passport-client/components/shared/AccountExportButton.tsx index 698d3f89f6..9b4f3c9a8e 100644 --- a/apps/passport-client/components/shared/AccountExportButton.tsx +++ b/apps/passport-client/components/shared/AccountExportButton.tsx @@ -1,12 +1,13 @@ import { serializeStorage } from "@pcd/passport-interface"; -import { LinkButton } from "@pcd/passport-ui"; import { useCallback, useEffect, useState } from "react"; import { toast } from "react-hot-toast"; +import { Link } from "react-router-dom"; import { usePCDCollection, useSelf, useSubscriptions } from "../../src/appHooks"; +import { NewButton } from "../NewButton"; export function AccountExportButton(): JSX.Element | null { const user = useSelf(); @@ -43,13 +44,10 @@ export function AccountExportButton(): JSX.Element | null { }, [pcds, setUrl, subscriptions, user]); return url ? ( - - Export - + + + Export + + ) : null; } diff --git a/apps/passport-client/components/shared/AppHeader.tsx b/apps/passport-client/components/shared/AppHeader.tsx index ed4a74b467..658d5652b9 100644 --- a/apps/passport-client/components/shared/AppHeader.tsx +++ b/apps/passport-client/components/shared/AppHeader.tsx @@ -1,10 +1,10 @@ -import { CircleButton } from "@pcd/passport-ui"; import React, { useCallback } from "react"; -import { IoMdSettings } from "react-icons/io"; -import { MdInfo, MdOutlineQrCodeScanner, MdRssFeed } from "react-icons/md"; +import { FaCog, FaInfoCircle } from "react-icons/fa"; import styled from "styled-components"; import { useDispatch, useSelf, useSubscriptions } from "../../src/appHooks"; import { AppState } from "../../src/state"; +import { cn } from "../../src/util"; +import { NewButton } from "../NewButton"; export const AppHeader = React.memo(AppHeaderImpl); @@ -51,13 +51,10 @@ function AppHeaderImpl({ return ( - - - {children} {!isProveOrAddScreen && ( <> - + {/* {subscriptions.value.getAllErrors().size > 0 && ( @@ -67,22 +64,41 @@ function AppHeaderImpl({ size={34} color={isEdgeCity ? "white" : "var(--accent-lite)"} /> - - + */} + {/* - + */} )} - - - - +
+ + + + { + window.location.href = "#/more"; + }} + > + ZAPPS + + + + +
); } @@ -94,6 +110,7 @@ const AppHeaderWrap = styled.div` justify-content: space-between; align-items: center; gap: 16px; + margin-bottom: 0.75rem; `; const ErrorDot = styled.div` diff --git a/apps/passport-client/components/shared/LoadingIssuedPCDs.tsx b/apps/passport-client/components/shared/LoadingIssuedPCDs.tsx index 511c75d59b..ec1092ce7c 100644 --- a/apps/passport-client/components/shared/LoadingIssuedPCDs.tsx +++ b/apps/passport-client/components/shared/LoadingIssuedPCDs.tsx @@ -1,36 +1,70 @@ +import { useEffect, useMemo, useState } from "react"; import styled from "styled-components"; import { useLoadedIssuedPCDs } from "../../src/appHooks"; -import { RippleLoader } from "../core/RippleLoader"; +import { Spinner } from "./Spinner"; export function LoadingIssuedPCDs(): JSX.Element | null { const loadedIssuedPCDs = useLoadedIssuedPCDs(); + const [alreadyLoaded] = useState(loadedIssuedPCDs); - if (loadedIssuedPCDs) { + const [showLoading, setShowLoading] = useState(true); + + const hiddenStyle = useMemo(() => { + return { + opacity: 0, + height: "0px", + margin: "0px !important", + marginBottom: "0px", + fontSize: "0.1em !important", + padding: "0px" + }; + }, []); + + const [style, setStyle] = useState({}); + + useEffect(() => { + if (loadedIssuedPCDs) { + setTimeout(() => { + setShowLoading(false); + setTimeout(() => { + setStyle(hiddenStyle); + }, 500); + }, 1500); + } + }, [hiddenStyle, loadedIssuedPCDs]); + + if (alreadyLoaded) { return null; } return ( - - - - - Loading Tickets + + ); } const Container = styled.div` user-select: none; - margin: 12px 9px; box-sizing: border-box; display: flex; - justify-content: flex-start; + flex-direction: row; + justify-content: center; align-items: center; - background-color: rgba(255, 255, 255, 0.1); - border-radius: 16px; -`; - -const LoaderContainer = styled.div` - display: inline-block; - transform: scale(50%); + height: 50px; + background-color: rgba(0, 0, 0, 0.3); + font-size: 1em; + transition: all 200ms ease-in-out; `; diff --git a/apps/passport-client/components/shared/MainIdentityCard.tsx b/apps/passport-client/components/shared/MainIdentityCard.tsx index 35ec2d24de..f8d063456c 100644 --- a/apps/passport-client/components/shared/MainIdentityCard.tsx +++ b/apps/passport-client/components/shared/MainIdentityCard.tsx @@ -1,8 +1,7 @@ import { User } from "@pcd/passport-interface"; -import Avatar from "boring-avatars"; +import { QRDisplay } from "@pcd/passport-ui"; import styled from "styled-components"; import { useSelf } from "../../src/appHooks"; -import { Spacer, TextCenter } from "../core"; export function MainIdentityCard({ user }: { user?: User }): JSX.Element { const self = useSelf(); @@ -10,23 +9,13 @@ export function MainIdentityCard({ user }: { user?: User }): JSX.Element { return ( - - - - - + ); } const CardBody = styled.div` color: var(--primary-dark); - border-radius: 0 0 12px 12px; background: var(--primary-darker); + background: white; `; diff --git a/apps/passport-client/components/shared/PCDCard.tsx b/apps/passport-client/components/shared/PCDCard.tsx index 7f59fd6a4a..c89e986e8e 100644 --- a/apps/passport-client/components/shared/PCDCard.tsx +++ b/apps/passport-client/components/shared/PCDCard.tsx @@ -13,7 +13,7 @@ import { usePCDCollection, useUserIdentityPCD } from "../../src/appHooks"; import { StateContext } from "../../src/dispatch"; import { pcdRenderers } from "../../src/pcdRenderers"; import { usePackage } from "../../src/usePackage"; -import { Button, H4, Spacer, TextCenter } from "../core"; +import { H4, Spacer, TextCenter } from "../core"; import { MainIdentityCard } from "./MainIdentityCard"; export const PCDCard = memo(PCDCardImpl); @@ -51,15 +51,21 @@ function PCDCardImpl({ return ( setContainerRef(e ?? undefined)} key={pcd.id} onClick={clickHandler} style={!expanded ? { padding: "8px 12px", cursor: "pointer" } : {}} > {expanded ? ( - + {!hideHeader && ( - + )} @@ -103,6 +109,15 @@ function HeaderContent({ const ui = pcdPackage ? getUI(pcdPackage.name) : undefined; + if (isEdDSATicketPCD(pcd)) { + return ( +
+
{pcd.claim.ticket.eventName}
+
{pcd.claim.ticket.ticketName}
+
+ ); + } + let header = null; if (isMainIdentity) { header = <>ZUPASS IDENTITY; @@ -140,13 +155,15 @@ function CardFooterImpl({ return null; } - return ( - - - - ); + return null; + + // return ( + // + // + // + // ); } function getUI( @@ -269,7 +286,6 @@ function CardBody({ export const CardContainer = styled.div` width: 100%; - padding: 8px; `; export const CardOutlineExpanded = styled.div` diff --git a/apps/passport-client/components/shared/PCDCardList.tsx b/apps/passport-client/components/shared/PCDCardList.tsx index 7f71119457..978e47df48 100644 --- a/apps/passport-client/components/shared/PCDCardList.tsx +++ b/apps/passport-client/components/shared/PCDCardList.tsx @@ -53,7 +53,7 @@ export function PCDCardList({ * If true, all PCDs will have padding hidden. */ hidePadding?: boolean; -}): JSX.Element { +}): React.ReactNode { const pcdCollection = usePCDCollection(); const userIdentityPCD = useUserIdentityPCD(); const userIdentityPCDId = userIdentityPCD?.id; @@ -134,14 +134,7 @@ export function PCDCardList({ return ( - {sortablePCDs.length > 1 && ( - - )} - {sortedPCDs.map((pcd) => ( + {pcds.map((pcd) => ( { + keySelector?: (s: T) => string | string[]; + threshold?: number; + } + + type FullOptions = FuzzyOptions & AdditionalOptions; + type FullOptionsMatchData = FuzzyOptionsMatchData & AdditionalOptions; + + export interface MatchData { + item: T; + original: string; + key: string; + score: number; + match: { + index: number; + length: number; + }; + } + + interface TrieNode { + children: { + [key: string]: TrieNode; + }; + candidates: T[]; + depth: number; + } + + export function fuzzy( + term: string, + candidate: string, + options?: FuzzyOptions + ): number; + export function fuzzy( + term: string, + candidate: string, + options: FuzzyOptionsMatchData + ): MatchData; + export function search( + term: string, + candidates: T[], + options?: FullOptions + ): T[]; + export function search( + term: string, + candidates: T[], + options: FullOptionsMatchData + ): MatchData[]; + export class Searcher { + options: FullOptions | FullOptionsMatchData; + trie: TrieNode; + count: number; + + constructor( + candidates?: T[], + options?: FullOptions + ): this is { options: FullOptions }; + constructor( + candidates?: T[], + options: FullOptionsMatchData + ): this is { options: FullOptionsMatchData }; + add(...candidates: T[]); + search( + term: string, + options?: FullOptions + ): this extends { options: FullOptionsMatchData } ? MatchData[] : T[]; + search(term: string, options: FullOptionsMatchData): MatchData[]; + } +} diff --git a/apps/passport-client/package.json b/apps/passport-client/package.json index f0f37ac798..441387e5f6 100644 --- a/apps/passport-client/package.json +++ b/apps/passport-client/package.json @@ -4,8 +4,10 @@ "license": "GPL-3.0-or-later", "private": true, "scripts": { - "dev": "ts-node build.ts dev", - "build": "tsc --noEmit && ts-node build.ts build", + "dev": "concurrently \"ts-node build.ts dev\" \"yarn watch:css\"", + "build": "tsc --noEmit && ts-node build.ts build && yarn build:css", + "build:css": "tailwindcss build -i src/style.css -o public/built.css", + "watch:css": "tailwindcss -w build -i src/style.css -o public/built.css", "start": "exit 0", "lint": "tsc --noEmit && eslint \"**/*.ts{,x}\"", "test": "ts-mocha --type-check --config ../../.mocharc.js --exit 'test/**/*.spec.ts'", @@ -42,10 +44,10 @@ "@pcd/pcd-collection": "0.11.1", "@pcd/pcd-types": "0.11.1", "@pcd/pod": "0.1.1", - "@pcd/pod-ticket-pcd": "0.1.1", - "@pcd/pod-ticket-pcd-ui": "0.1.1", "@pcd/pod-pcd": "0.1.1", "@pcd/pod-pcd-ui": "0.1.1", + "@pcd/pod-ticket-pcd": "0.1.1", + "@pcd/pod-ticket-pcd-ui": "0.1.1", "@pcd/rsa-image-pcd": "0.5.1", "@pcd/rsa-image-pcd-ui": "0.2.1", "@pcd/rsa-pcd": "0.6.1", @@ -64,16 +66,22 @@ "@pcd/zk-eddsa-frog-pcd": "0.3.1", "@pcd/zk-eddsa-frog-pcd-ui": "0.2.1", "@pixelverse/strichjs-sdk": "^1.4.6", + "@react-three/drei": "^9.109.2", + "@react-three/fiber": "^8.16.8", "@rollbar/react": "^0.11.1", "@semaphore-protocol/identity": "^3.15.2", + "@tanstack/react-table": "^8.20.1", + "@types/three": "^0.167.0", "boring-avatars": "^1.10.1", "broadcast-channel": "^5.3.0", "csstype": "^3.1.3", "dotenv": "^16.0.3", "email-validator": "^2.0.4", "fast-json-stable-stringify": "^2.1.0", + "fuzzy": "^0.1.3", "handlebars": "^4.7.7", "isomorphic-timers-promises": "^1.0.1", + "javascript-time-ago": "^2.5.10", "js-sha256": "^0.11.0", "lodash": "^4.17.21", "pretty-ms": "^8.0.0", @@ -94,10 +102,12 @@ "react-tooltip": "^5.21.4", "rollbar": "^2.26.1", "styled-components": "^5.3.6", + "three": "^0.167.0", "tsparticles": "^2.12.0", "tsparticles-engine": "^2.12.0", "typewriter-effect": "^2.21.0", "use-file-picker": "^2.1.1", + "usehooks-ts": "^3.1.0", "uuid": "^9.0.0", "zod": "^3.22.4" }, @@ -105,6 +115,7 @@ "@esbuild-plugins/node-globals-polyfill": "^0.2.3", "@esbuild-plugins/node-modules-polyfill": "^0.2.2", "@pcd/eslint-config-custom": "0.11.1", + "@pcd/proto-pod-gpc-artifacts": "0.4.0", "@types/chai": "^4.3.11", "@types/email-validator": "^1.0.6", "@types/express": "^4.17.17", @@ -116,14 +127,16 @@ "@types/zxcvbn": "^4.4.4", "@typescript-eslint/eslint-plugin": "^7.4.0", "@typescript-eslint/parser": "^7.4.0", - "@pcd/proto-pod-gpc-artifacts": "0.4.0", + "autoprefixer": "^10.4.19", "esbuild": "^0.17.10", + "esbuild-style-plugin": "^1.6.3", "esbuild-visualizer": "^0.4.1", "eslint": "8.57.0", "eslint-plugin-react": "^7.32.2", "eslint-plugin-react-hooks": "^4.6.0", "express": "^4.18.2", "mocha": "^10.2.0", + "tailwindcss": "^3.4.6", "ts-mocha": "^10.0.0", "ts-node": "^10.9.2", "tsparticles-plugin-emitters": "^2.12.0", diff --git a/apps/passport-client/pages/index.tsx b/apps/passport-client/pages/index.tsx index c66acdf6ec..0ef1cb521a 100644 --- a/apps/passport-client/pages/index.tsx +++ b/apps/passport-client/pages/index.tsx @@ -30,6 +30,8 @@ import { EnterConfirmationCodeScreen } from "../components/screens/EnterConfirma import { FrogManagerScreen } from "../components/screens/FrogScreens/FrogManagerScreen"; import { FrogSubscriptionScreen } from "../components/screens/FrogScreens/FrogSubscriptionScreen"; import { GetWithoutProvingScreen } from "../components/screens/GetWithoutProvingScreen"; +import { ZmailPCDScreen } from "../components/screens/GmailScreen/ZmailPCDScreen"; +import { ZmailScreen } from "../components/screens/GmailScreen/ZmailScreen"; import { HaloScreen } from "../components/screens/HaloScreen/HaloScreen"; import { HomeScreen } from "../components/screens/HomeScreen/HomeScreen"; import { ImportBackupScreen } from "../components/screens/ImportBackupScreen"; @@ -43,6 +45,12 @@ import { OneClickLoginScreen } from "../components/screens/LoginScreens/OneClick import { PrivacyNoticeScreen } from "../components/screens/LoginScreens/PrivacyNoticeScreen"; import { SyncExistingScreen } from "../components/screens/LoginScreens/SyncExistingScreen"; import { MissingScreen } from "../components/screens/MissingScreen"; +import { ParcScreen } from "../components/screens/MoreScreens/0xPARCScreen"; +import { DuckScreen } from "../components/screens/MoreScreens/DuckScreen"; +import { FHEScreen } from "../components/screens/MoreScreens/FHEScreen"; +import { MoreScreen } from "../components/screens/MoreScreens/MoreScreen"; +import { PODScreen } from "../components/screens/MoreScreens/PODScreen"; +import { ZKScreen } from "../components/screens/MoreScreens/ZKScreen"; import { NoWASMScreen } from "../components/screens/NoWASMScreen"; import { ProveScreen } from "../components/screens/ProveScreen/ProveScreen"; import { ScanScreen } from "../components/screens/ScanScreen"; @@ -326,6 +334,17 @@ function RouterImpl(): JSX.Element { } /> } /> + + } /> + } /> + + } /> + } /> + } /> + } /> + } /> + } /> + } /> Zupass + + + + {{!-- Lazily load zxcvbn.js since it contains 700KB+ of data --}} diff --git a/apps/passport-client/src/appHooks.ts b/apps/passport-client/src/appHooks.ts index 3eb51966af..69d5712975 100644 --- a/apps/passport-client/src/appHooks.ts +++ b/apps/passport-client/src/appHooks.ts @@ -64,9 +64,9 @@ export function usePCDs(): PCD[] { return [...pcds.getAll()]; } -export function usePCDsInFolder(folder: string): PCD[] { +export function usePCDsInFolder(folder: string, recursive = false): PCD[] { const pcds = usePCDCollection(); - return [...pcds.getAllPCDsInFolder(folder)]; + return [...pcds.getAllPCDsInFolder(folder, recursive)]; } export function useVisiblePCDsInFolder(folder: string): PCD[] { diff --git a/apps/passport-client/src/dispatch.ts b/apps/passport-client/src/dispatch.ts index a70a1892df..23c4248607 100644 --- a/apps/passport-client/src/dispatch.ts +++ b/apps/passport-client/src/dispatch.ts @@ -23,7 +23,7 @@ import { zupassDefaultSubscriptions, ZupassFeedIds } from "@pcd/passport-interface"; -import { PCDCollection, PCDPermission } from "@pcd/pcd-collection"; +import { PCDCollection, PCDMetadata, PCDPermission } from "@pcd/pcd-collection"; import { PCD, SerializedPCD } from "@pcd/pcd-types"; import { isPODTicketPCD } from "@pcd/pod-ticket-pcd"; import { @@ -130,6 +130,11 @@ export type Action = upsert?: boolean; folder?: string; } + | { + type: "update-pcd-meta"; + pcdId: string; + pcdMeta: Partial; + } | { type: "remove-pcd"; id: string } | { type: "remove-all-pcds-in-folder"; folder: string } | { type: "sync" } @@ -246,6 +251,8 @@ export async function dispatch( state, update ); + case "update-pcd-meta": + return updatePCDMeta(state, update, action.pcdId, action.pcdMeta); case "add-pcds": return addPCDs(state, update, action.pcds, action.upsert, action.folder); case "remove-pcd": @@ -519,6 +526,7 @@ async function createNewUserWithPassword( dismissToCurrentPage: true } }); + notifyLoginToOtherTabs(); } @@ -716,6 +724,17 @@ async function addPCDs( update({ pcds: state.pcds }); } +async function updatePCDMeta( + state: AppState, + update: ZuUpdate, + pcdId: string, + pcdMeta: Partial +): Promise { + state.pcds.updateMetaById(pcdId, pcdMeta); + await savePCDs(state.pcds); + update({ pcds: state.pcds }); +} + async function removePCD( state: AppState, update: ZuUpdate, @@ -1392,7 +1411,8 @@ async function mergeImport( const pcds = new PCDCollection( packages, state.pcds.getAll(), - state.pcds.folders + state.pcds.folders, + state.pcds.meta ); try { diff --git a/apps/passport-client/src/loadInitialState.ts b/apps/passport-client/src/loadInitialState.ts index aa940a25d0..fea1ecc9ff 100644 --- a/apps/passport-client/src/loadInitialState.ts +++ b/apps/passport-client/src/loadInitialState.ts @@ -1,5 +1,6 @@ import { createStorageBackedCredentialCache } from "@pcd/passport-interface"; import { Identity } from "@semaphore-protocol/identity"; +import { initTestData } from "../components/screens/HomeScreen/utils"; import { loadCheckedInOfflineDevconnectTickets, loadEncryptionKey, @@ -70,5 +71,7 @@ export async function loadInitialState(): Promise { state.modal = { modalType: "invalid-participant" }; } + await initTestData(state); + return state; } diff --git a/apps/passport-client/src/state.ts b/apps/passport-client/src/state.ts index 9835e43013..9eced65b81 100644 --- a/apps/passport-client/src/state.ts +++ b/apps/passport-client/src/state.ts @@ -34,6 +34,7 @@ export interface AppState { | { modalType: "require-add-password" } | { modalType: "privacy-notice" } | { modalType: "none" } + | { modalType: "no-tickets" } | { modalType: "frogcrypto-update-telegram"; revealed: boolean; diff --git a/apps/passport-client/src/style.css b/apps/passport-client/src/style.css new file mode 100644 index 0000000000..b5c61c9567 --- /dev/null +++ b/apps/passport-client/src/style.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/apps/passport-client/src/util.ts b/apps/passport-client/src/util.ts index 00a0357b33..6577e2f7f4 100644 --- a/apps/passport-client/src/util.ts +++ b/apps/passport-client/src/util.ts @@ -133,3 +133,7 @@ export function bigintToUint8Array(bigint: bigint): Uint8Array { export function uint8arrayToBigint(uint8Array: Uint8Array): bigint { return BigInt("0x" + Buffer.from(uint8Array).toString("hex")); } + +export function cn(...classNames: (string | undefined)[]): string { + return classNames.filter(Boolean).join(" "); +} diff --git a/apps/passport-client/tailwind.config.js b/apps/passport-client/tailwind.config.js new file mode 100644 index 0000000000..91955d0700 --- /dev/null +++ b/apps/passport-client/tailwind.config.js @@ -0,0 +1,13 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + important: true, + content: [ + "./components/**/*.{js,ts,jsx,tsx}", + "./pages/**/*.{js,ts,jsx,tsx}", + "./src/**/*.{js,ts,jsx,tsx}" + ], + theme: { + extend: {} + }, + plugins: [] +}; diff --git a/packages/lib/pcd-collection/src/PCDCollection.ts b/packages/lib/pcd-collection/src/PCDCollection.ts index 2e02112c23..d589b6174e 100644 --- a/packages/lib/pcd-collection/src/PCDCollection.ts +++ b/packages/lib/pcd-collection/src/PCDCollection.ts @@ -68,6 +68,11 @@ export function matchActionToPermission( return null; } +export interface PCDMetadata { + viewed?: boolean; + updatedTimestamp?: string; +} + /** * This class represents all the PCDs a user may have, and also * contains references to all the relevant {@link PCDPackage}s, @@ -84,15 +89,18 @@ export class PCDCollection { private packages: PCDPackage[]; private pcds: PCD[]; public folders: Record; // pcd id -> folder + public meta: Record; // pcd id -> metadata public constructor( packages: PCDPackage[], pcds?: PCD[], - folders?: Record + folders?: Record, + meta?: Record ) { this.packages = packages; this.pcds = pcds ?? []; this.folders = folders ?? {}; + this.meta = meta ?? {}; this.changeEmitter = new Emitter(); } @@ -261,7 +269,7 @@ export class PCDCollection { )?.[1]; } - public getAllPCDsInFolder(folder: string): PCD[] { + public getAllPCDsInFolder(folder: string, recursive = false): PCD[] { if (isRootFolder(folder)) { const pcdIdsInFolders = new Set([...Object.keys(this.folders)]); const pcdsNotInFolders = this.pcds.filter( @@ -274,6 +282,13 @@ export class PCDCollection { .filter(([_pcdId, f]) => f === folder) .map(([pcdId, _f]) => pcdId); + if (recursive) { + const subFolders = this.getFoldersInFolder(folder); + for (const sub of subFolders) { + pcdIds.push(...this.getAllPCDsInFolder(sub, true).map((p) => p.id)); + } + } + return this.getByIds(pcdIds); } @@ -332,7 +347,8 @@ export class PCDCollection { public async serializeCollection(): Promise { return stringify({ pcds: await Promise.all(this.pcds.map(this.serialize.bind(this))), - folders: this.folders + folders: this.folders, + meta: this.meta } satisfies SerializedPCDCollection); } @@ -360,6 +376,9 @@ export class PCDCollection { this.folders = Object.fromEntries( Object.entries(this.folders).filter(([id]) => id !== pcdId) ); + this.meta = Object.fromEntries( + Object.entries(this.meta).filter(([id]) => id !== pcdId) + ); this.emitChange(); } @@ -388,6 +407,12 @@ export class PCDCollection { this.pcds = Array.from(currentMap.values()); + for (const pcd of pcds) { + const newTimestamp = + this.getMetaById(pcd.id)?.updatedTimestamp ?? new Date().toISOString(); + this.updateMetaById(pcd.id, { updatedTimestamp: newTimestamp }); + } + this.emitChange(); } @@ -411,7 +436,7 @@ export class PCDCollection { /** * Generates a unique hash based on the contents. This hash changes whenever - * the set of pcds, or the contents of the pcds changes. + * the set of pcds, folders, or metadatas change. */ public async getHash(): Promise { const allSerialized = await this.serializeCollection(); @@ -423,6 +448,20 @@ export class PCDCollection { return this.pcds.find((pcd) => pcd.id === id); } + public getMetaById(id: string): PCDMetadata | undefined { + return this.meta[id]; + } + + public updateMetaById(id: string, update: Partial): void { + if (!this.getById(id)) { + return; + } + + const existingMeta = this.meta[id] ?? {}; + this.meta[id] = { ...existingMeta, ...update }; + this.emitChange(); + } + public hasPCDWithId(id: string): boolean { return this.getById(id) !== undefined; } @@ -442,16 +481,19 @@ export class PCDCollection { serialized: string ): Promise { const parsed = JSON.parse(serialized) as Partial; - const collection = new PCDCollection(packages, []); const serializedPcdsList = parsed.pcds ?? []; const parsedFolders = parsed.folders ?? {}; + const parsedMetas = parsed.meta ?? {}; + + const collection = new PCDCollection(packages, []); const pcds: PCD[] = await Promise.all( serializedPcdsList.map(collection.deserialize.bind(collection)) ); collection.addAll(pcds, { upsert: true }); collection.folders = parsedFolders; + collection.meta = parsedMetas; return collection; } @@ -484,6 +526,11 @@ export class PCDCollection { this.setFolder(pcd.id, other.folders[pcd.id]); } } + + // TODO: implement better metadata merge + for (const [pcdId, meta] of Object.entries(other.meta ?? {})) { + this.updateMetaById(pcdId, meta); + } } } @@ -495,4 +542,5 @@ export class PCDCollection { export interface SerializedPCDCollection { pcds: SerializedPCD[]; folders: Record; + meta: Record; } diff --git a/packages/ui/eddsa-ticket-pcd-ui/src/CardBody.tsx b/packages/ui/eddsa-ticket-pcd-ui/src/CardBody.tsx index 22ab531188..f6e5c015e2 100644 --- a/packages/ui/eddsa-ticket-pcd-ui/src/CardBody.tsx +++ b/packages/ui/eddsa-ticket-pcd-ui/src/CardBody.tsx @@ -7,7 +7,6 @@ import { import { ZUCONNECT_23_DAY_PASS_PRODUCT_ID } from "@pcd/passport-interface"; import { FlattenSimpleInterpolation, - Spacer, ToggleSwitch, css, styled @@ -65,8 +64,17 @@ function EdDSATicketPCDCardBody({ {hasImage && ( - {ticketData?.attendeeName} - {ticketData?.attendeeEmail} +
+ {ticketData?.attendeeName} + {ticketData?.attendeeEmail} +
)} {!hasImage && ( @@ -78,15 +86,28 @@ function EdDSATicketPCDCardBody({ idBasedVerifyURL={idBasedVerifyURL} zk={zk} /> - - {ticketData?.attendeeName && ( + {/* */} +
+ {ticketData?.attendeeName && ( + + {ticketData?.attendeeName} + + )} - {ticketData?.attendeeName} + {ticketData?.attendeeEmail} - )} - - {ticketData?.attendeeEmail} - +
{/* TODO: Turn on ZK mode when we have an end-to-end story for it. */} {false && ( @@ -133,7 +154,7 @@ const Container = styled.span<{ padding: boolean }>` ${({ padding }): FlattenSimpleInterpolation => padding ? css` - padding: 16px; + /* padding: 16px; */ ` : css``} overflow: hidden; @@ -141,7 +162,6 @@ const Container = styled.span<{ padding: boolean }>` `; const TicketInfo = styled.div` - margin-top: 8px; display: flex; justify-content: center; align-items: center; @@ -172,11 +192,9 @@ const RedactedText = styled.div<{ redacted: boolean }>` ` : css``} - margin-bottom: 4px; - padding: 2px; - width: 300px; + /* width: 300px; */ position: relative; - text-align: center; + /* text-align: center; */ transition-property: color, background-color; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); /* Same duration as the toggle slide */ diff --git a/todo.md b/todo.md new file mode 100644 index 0000000000..3ba32926a2 --- /dev/null +++ b/todo.md @@ -0,0 +1,52 @@ +# todo + +- devcon screen + - link to frogs + - link to ducks +- make tickets look more special / different from everything other than tickets +- mockup of the zapp screen that shows up when you click on a particular zapp + - how to make it feel more like a browser? +- label that says '1 ticket' should be broken down by type of thing that is in the folder +- fix how zuzalu tickets look +- better dropdown selector for the app that fits in with the rest of the buttons +- go through all the proving and misc. screens + - buttons, dropdowns, spacing + +# in progress + +- better 'input' element throughout the app +- what do I do with the zupass identity? +- convert all buttons in the app to be the new buttons +- better zupass logo and icon + +# done + +- rather than 'next/prev' go back to list view +- progcrypto a separate folder from devcon rather than a folder inside of it +- better loading spinner +- convert modals to be consistent with the rest of the app +- rename 'more cryptography' to 'zapps', move to top row +- ZMAIL: other data -> a 'non-ticketing' view of the app - it shows all PCDs + - like email client? + - table view + - sort / filter / search / flatten (don't show folders) + - star/favorite + - gmail inspire + - labels? + - pcd metadata + - time created + - seen/unseen + - specific-pcd screen + - next/prev buttons? + - 'note' + +# on hold + +- zapps + - Zupoll + - ZK Talks + - Anon-aadhar + - zkPassport + - Cursive + - duck leaderboard zapp +- duck collection screen diff --git a/yarn.lock b/yarn.lock index 4cc2f86dd0..026edd9002 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1068,6 +1068,13 @@ dependencies: regenerator-runtime "^0.14.0" +"@babel/runtime@^7.11.2", "@babel/runtime@^7.17.8": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.25.0.tgz#3af9a91c1b739c569d5d80cc917280919c544ecb" + integrity sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw== + dependencies: + regenerator-runtime "^0.14.0" + "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3", "@babel/runtime@^7.8.7": version "7.23.2" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.2.tgz#062b0ac103261d68a966c4c7baf2ae3e62ec3885" @@ -3704,6 +3711,11 @@ globby "^11.0.0" read-yaml-file "^1.1.0" +"@mediapipe/tasks-vision@0.10.8": + version "0.10.8" + resolved "https://registry.yarnpkg.com/@mediapipe/tasks-vision/-/tasks-vision-0.10.8.tgz#a78e137018a19933b7a1d0e887d553d4ab833d10" + integrity sha512-Rp7ll8BHrKB3wXaRFKhrltwZl1CiXGdibPxuWXvqGnKTnv8fqa/nvftYNuSbf+pbJWKYCXdBtYTITdAUTGGh0Q== + "@monaco-editor/loader@^1.4.0": version "1.4.0" resolved "https://registry.yarnpkg.com/@monaco-editor/loader/-/loader-1.4.0.tgz#f08227057331ec890fa1e903912a5b711a2ad558" @@ -3718,6 +3730,13 @@ dependencies: "@monaco-editor/loader" "^1.4.0" +"@monogrid/gainmap-js@^3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@monogrid/gainmap-js/-/gainmap-js-3.0.5.tgz#8c736088012ae8cd1f7b3d5adbd221c3905ab4ed" + integrity sha512-53sCTG4FaJBaAq/tcufARtVYDMDGqyBT9i7F453pWGhZ5LqubDHDWtYoHo9VhQqMcHTEexdJqSsR58y+9HVmQA== + dependencies: + promise-worker-transferable "^1.0.4" + "@monorepo-utils/package-utils@^2.10.4": version "2.10.4" resolved "https://registry.yarnpkg.com/@monorepo-utils/package-utils/-/package-utils-2.10.4.tgz#330aaf846368218040c27cd97119c66d2a4744ae" @@ -5215,6 +5234,98 @@ dependencies: "@babel/runtime" "^7.13.10" +"@react-spring/animated@~9.6.1": + version "9.6.1" + resolved "https://registry.yarnpkg.com/@react-spring/animated/-/animated-9.6.1.tgz#ccc626d847cbe346f5f8815d0928183c647eb425" + integrity sha512-ls/rJBrAqiAYozjLo5EPPLLOb1LM0lNVQcXODTC1SMtS6DbuBCPaKco5svFUQFMP2dso3O+qcC4k9FsKc0KxMQ== + dependencies: + "@react-spring/shared" "~9.6.1" + "@react-spring/types" "~9.6.1" + +"@react-spring/core@~9.6.1": + version "9.6.1" + resolved "https://registry.yarnpkg.com/@react-spring/core/-/core-9.6.1.tgz#ebe07c20682b360b06af116ea24e2b609e778c10" + integrity sha512-3HAAinAyCPessyQNNXe5W0OHzRfa8Yo5P748paPcmMowZ/4sMfaZ2ZB6e5x5khQI8NusOHj8nquoutd6FRY5WQ== + dependencies: + "@react-spring/animated" "~9.6.1" + "@react-spring/rafz" "~9.6.1" + "@react-spring/shared" "~9.6.1" + "@react-spring/types" "~9.6.1" + +"@react-spring/rafz@~9.6.1": + version "9.6.1" + resolved "https://registry.yarnpkg.com/@react-spring/rafz/-/rafz-9.6.1.tgz#d71aafb92b78b24e4ff84639f52745afc285c38d" + integrity sha512-v6qbgNRpztJFFfSE3e2W1Uz+g8KnIBs6SmzCzcVVF61GdGfGOuBrbjIcp+nUz301awVmREKi4eMQb2Ab2gGgyQ== + +"@react-spring/shared@~9.6.1": + version "9.6.1" + resolved "https://registry.yarnpkg.com/@react-spring/shared/-/shared-9.6.1.tgz#4e2e4296910656c02bd9fd54c559702bc836ac4e" + integrity sha512-PBFBXabxFEuF8enNLkVqMC9h5uLRBo6GQhRMQT/nRTnemVENimgRd+0ZT4yFnAQ0AxWNiJfX3qux+bW2LbG6Bw== + dependencies: + "@react-spring/rafz" "~9.6.1" + "@react-spring/types" "~9.6.1" + +"@react-spring/three@~9.6.1": + version "9.6.1" + resolved "https://registry.yarnpkg.com/@react-spring/three/-/three-9.6.1.tgz#095fcd1dc6509127c33c14486d88289b89baeb9d" + integrity sha512-Tyw2YhZPKJAX3t2FcqvpLRb71CyTe1GvT3V+i+xJzfALgpk10uPGdGaQQ5Xrzmok1340DAeg2pR/MCfaW7b8AA== + dependencies: + "@react-spring/animated" "~9.6.1" + "@react-spring/core" "~9.6.1" + "@react-spring/shared" "~9.6.1" + "@react-spring/types" "~9.6.1" + +"@react-spring/types@~9.6.1": + version "9.6.1" + resolved "https://registry.yarnpkg.com/@react-spring/types/-/types-9.6.1.tgz#913d3a68c5cbc1124fdb18eff919432f7b6abdde" + integrity sha512-POu8Mk0hIU3lRXB3bGIGe4VHIwwDsQyoD1F394OK7STTiX9w4dG3cTLljjYswkQN+hDSHRrj4O36kuVa7KPU8Q== + +"@react-three/drei@^9.109.2": + version "9.109.2" + resolved "https://registry.yarnpkg.com/@react-three/drei/-/drei-9.109.2.tgz#37e79924550614d7e3db32c5d115188c4e3f01af" + integrity sha512-oUbfjiyPQeQch4Mi3jZvFKigMlc97/xvazxyjPBCGa8RP8cHZJl187eZI9Ha1WwkVaX80DfgN7bYAWXS4ywxmw== + dependencies: + "@babel/runtime" "^7.11.2" + "@mediapipe/tasks-vision" "0.10.8" + "@monogrid/gainmap-js" "^3.0.5" + "@react-spring/three" "~9.6.1" + "@use-gesture/react" "^10.2.24" + camera-controls "^2.4.2" + cross-env "^7.0.3" + detect-gpu "^5.0.28" + glsl-noise "^0.0.0" + hls.js "1.3.5" + maath "^0.10.7" + meshline "^3.1.6" + react-composer "^5.0.3" + stats-gl "^2.0.0" + stats.js "^0.17.0" + suspend-react "^0.1.3" + three-mesh-bvh "^0.7.0" + three-stdlib "^2.29.9" + troika-three-text "^0.49.0" + tunnel-rat "^0.1.2" + utility-types "^3.10.0" + uuid "^9.0.1" + zustand "^3.7.1" + +"@react-three/fiber@^8.16.8": + version "8.16.8" + resolved "https://registry.yarnpkg.com/@react-three/fiber/-/fiber-8.16.8.tgz#4d2fecda7b38f534de6bdac49ca37c815cf9a4ef" + integrity sha512-Lc8fjATtvQEfSd8d5iKdbpHtRm/aPMeFj7jQvp6TNHfpo8IQTW3wwcE1ZMrGGoUH+w2mnyS+0MK1NLPLnuzGkQ== + dependencies: + "@babel/runtime" "^7.17.8" + "@types/react-reconciler" "^0.26.7" + "@types/webxr" "*" + base64-js "^1.5.1" + buffer "^6.0.3" + its-fine "^1.0.6" + react-reconciler "^0.27.0" + react-use-measure "^2.1.1" + scheduler "^0.21.0" + suspend-react "^0.1.3" + zustand "^3.7.1" + "@remix-run/router@1.8.0": version "1.8.0" resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.8.0.tgz#e848d2f669f601544df15ce2a313955e4bf0bafc" @@ -5976,6 +6087,13 @@ dependencies: "@tanstack/table-core" "8.15.3" +"@tanstack/react-table@^8.20.1": + version "8.20.1" + resolved "https://registry.yarnpkg.com/@tanstack/react-table/-/react-table-8.20.1.tgz#bd2d549d8a18458fb8284025ce66a9b86176fa6b" + integrity sha512-PJK+07qbengObe5l7c8vCdtefXm8cyR4i078acWrHbdm8JKw1ES7YpmOtVt9ALUVEEFAHscdVpGRhRgikgFMbQ== + dependencies: + "@tanstack/table-core" "8.20.1" + "@tanstack/react-virtual@^3.0.0-beta.60": version "3.2.0" resolved "https://registry.yarnpkg.com/@tanstack/react-virtual/-/react-virtual-3.2.0.tgz#fb70f9c6baee753a5a0f7618ac886205d5a02af9" @@ -5993,6 +6111,11 @@ resolved "https://registry.yarnpkg.com/@tanstack/table-core/-/table-core-8.15.3.tgz#1a11cef82a458e90694bedfb40dcff610e69460e" integrity sha512-wOgV0HfEvuMOv8RlqdR9MdNNqq0uyvQtP39QOvGlggHvIObOE4exS+D5LGO8LZ3LUXxId2IlUKcHDHaGujWhUg== +"@tanstack/table-core@8.20.1": + version "8.20.1" + resolved "https://registry.yarnpkg.com/@tanstack/table-core/-/table-core-8.20.1.tgz#74bfab10fa35bed51fa0bd2f3539a331d7e78f1b" + integrity sha512-5Ly5TIRHnWH7vSDell9B/OVyV380qqIJVg7H7R7jU4fPEmOD4smqAX7VRflpYI09srWR8aj5OLD2Ccs1pI5mTg== + "@tanstack/virtual-core@3.2.0": version "3.2.0" resolved "https://registry.yarnpkg.com/@tanstack/virtual-core/-/virtual-core-3.2.0.tgz#874d36135e4badce2719e7bdc556ce240cbaff14" @@ -6035,6 +6158,11 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== +"@tweenjs/tween.js@~23.1.1", "@tweenjs/tween.js@~23.1.2": + version "23.1.3" + resolved "https://registry.yarnpkg.com/@tweenjs/tween.js/-/tween.js-23.1.3.tgz#eff0245735c04a928bb19c026b58c2a56460539d" + integrity sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA== + "@types/accepts@*": version "1.3.5" resolved "https://registry.yarnpkg.com/@types/accepts/-/accepts-1.3.5.tgz#c34bec115cfc746e04fe5a059df4ce7e7b391575" @@ -6228,6 +6356,11 @@ resolved "https://registry.yarnpkg.com/@types/deep-equal-in-any-order/-/deep-equal-in-any-order-1.0.2.tgz#01e4dd185b3bcbc21adcc788e5b5bcdf3b1fa7ac" integrity sha512-IUjUMsroT9qb8d7ySAl5V+iT/7UsJDpIFspTLxBWxCLqeJwwptSvmjvDBEEaZt0qodMyUSoOQkLhqZAkqt6dLg== +"@types/draco3d@^1.4.0": + version "1.4.10" + resolved "https://registry.yarnpkg.com/@types/draco3d/-/draco3d-1.4.10.tgz#63ec0ba78b30bd58203ec031f4e4f0198c596dca" + integrity sha512-AX22jp8Y7wwaBgAixaSvkoG4M/+PlAcm3Qs4OW8yT9DM4xUpWKeFhLueTAyZF39pviAdcDdeJoACapiAceqNcw== + "@types/elliptic@^6.4.14": version "6.4.14" resolved "https://registry.yarnpkg.com/@types/elliptic/-/elliptic-6.4.14.tgz#7bbaad60567a588c1f08b10893453e6b9b4de48e" @@ -6579,6 +6712,11 @@ dependencies: "@types/koa" "*" +"@types/less@^3.0.3": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/less/-/less-3.0.6.tgz#279b51245ba787c810a0d286226c5900cd5e6765" + integrity sha512-PecSzorDGdabF57OBeQO/xFbAkYWo88g4Xvnsx7LRwqLC17I7OoKtA3bQB9uXkY6UkMWCOsA8HSVpaoitscdXw== + "@types/libsodium-wrappers-sumo@^0.7.6": version "0.7.6" resolved "https://registry.yarnpkg.com/@types/libsodium-wrappers-sumo/-/libsodium-wrappers-sumo-0.7.6.tgz#3ebaf627ddb4957fd6417dd1823490cc2633f01d" @@ -6776,6 +6914,11 @@ resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301" integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw== +"@types/offscreencanvas@^2019.6.4": + version "2019.7.3" + resolved "https://registry.yarnpkg.com/@types/offscreencanvas/-/offscreencanvas-2019.7.3.tgz#90267db13f64d6e9ccb5ae3eac92786a7c77a516" + integrity sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A== + "@types/pako@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@types/pako/-/pako-2.0.0.tgz#12ab4c19107528452e73ac99132c875ccd43bdfb" @@ -6859,6 +7002,20 @@ dependencies: "@types/react" "*" +"@types/react-reconciler@^0.26.7": + version "0.26.7" + resolved "https://registry.yarnpkg.com/@types/react-reconciler/-/react-reconciler-0.26.7.tgz#0c4643f30821ae057e401b0d9037e03e8e9b2a36" + integrity sha512-mBDYl8x+oyPX/VBb3E638N0B7xG+SPk/EAMcVPeexqus/5aTpTphQi0curhhshOqRrc9t6OPoJfEUkbymse/lQ== + dependencies: + "@types/react" "*" + +"@types/react-reconciler@^0.28.0": + version "0.28.8" + resolved "https://registry.yarnpkg.com/@types/react-reconciler/-/react-reconciler-0.28.8.tgz#e51710572bcccf214306833c2438575d310b3e98" + integrity sha512-SN9c4kxXZonFhbX4hJrZy37yw9e7EIxcpHCxQv5JUS18wDE5ovkQKlqQEkufdJCCMfuI9BnjUJvhYeJ9x5Ra7g== + dependencies: + "@types/react" "*" + "@types/react-transition-group@^4.4.0": version "4.4.7" resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.7.tgz#bf69f269d74aa78b99097673ca6dd6824a68ef1c" @@ -6866,7 +7023,7 @@ dependencies: "@types/react" "*" -"@types/react@*", "@types/react@18.2.20", "@types/react@^18", "@types/react@^18.0.22", "@types/react@^18.2.0", "@types/react@^18.2.6": +"@types/react@*", "@types/react@^18", "@types/react@^18.0.22", "@types/react@^18.2.0", "@types/react@^18.2.6": version "18.2.21" resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.21.tgz#774c37fd01b522d0b91aed04811b58e4e0514ed9" integrity sha512-neFKG/sBAwGxHgXiIxnbm3/AAVQ/cMRS93hvBpg8xYRbeQSPVABp9U2bRnPf0iI4+Ucdv3plSxKK+3CW2ENJxA== @@ -6875,6 +7032,15 @@ "@types/scheduler" "*" csstype "^3.0.2" +"@types/react@18.2.20": + version "18.2.20" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.20.tgz#1605557a83df5c8a2cc4eeb743b3dfc0eb6aaeb2" + integrity sha512-WKNtmsLWJM/3D5mG4U84cysVY31ivmyw85dE84fOCk5Hx78wezB/XEjVPWl2JTZ5FkEeaTJf+VgUAUn3PE7Isw== + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + csstype "^3.0.2" + "@types/request@^2.48.8": version "2.48.8" resolved "https://registry.yarnpkg.com/@types/request/-/request-2.48.8.tgz#0b90fde3b655ab50976cb8c5ac00faca22f5a82c" @@ -6899,6 +7065,13 @@ dependencies: "@types/node" "*" +"@types/sass@^1.43.1": + version "1.45.0" + resolved "https://registry.yarnpkg.com/@types/sass/-/sass-1.45.0.tgz#a949eb1e080ff34715e6c2040357b940bffb89bb" + integrity sha512-jn7qwGFmJHwUSphV8zZneO3GmtlgLsmhs/LQyVvQbIIa+fzGMUiHI4HXJZL3FT8MJmgXWbLGiVVY7ElvHq6vDA== + dependencies: + sass "*" + "@types/scheduler@*": version "0.16.3" resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.3.tgz#cef09e3ec9af1d63d2a6cc5b383a737e24e6dcf5" @@ -6962,6 +7135,11 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== +"@types/stats.js@*": + version "0.17.3" + resolved "https://registry.yarnpkg.com/@types/stats.js/-/stats.js-0.17.3.tgz#705446e12ce0fad618557dd88236f51148b7a935" + integrity sha512-pXNfAD3KHOdif9EQXZ9deK82HVNaXP5ZIF5RP2QG6OQFNTaY2YIetfrE9t528vEreGQvEPRDDc8muaoYeK0SxQ== + "@types/strip-bom@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/strip-bom/-/strip-bom-3.0.0.tgz#14a8ec3956c2e81edb7520790aecf21c290aebd2" @@ -6981,6 +7159,13 @@ "@types/react" "*" csstype "^3.0.2" +"@types/stylus@^0.48.38": + version "0.48.42" + resolved "https://registry.yarnpkg.com/@types/stylus/-/stylus-0.48.42.tgz#8fa7d99b48556bb8fe85a052aaba8c1e59a97e2f" + integrity sha512-CPGlr5teL4sqdap+EOowMifLuNGeIoLwc0VQ7u/BPxo+ocqiNa5jeVt0H0IVBblEh6ZwX1sGpIQIFnSSr8NBQA== + dependencies: + "@types/node" "*" + "@types/tedious@^4.0.6": version "4.0.12" resolved "https://registry.yarnpkg.com/@types/tedious/-/tedious-4.0.12.tgz#731a7ac0fde91a3cb493d78446fe2688503f2faf" @@ -6988,6 +7173,28 @@ dependencies: "@types/node" "*" +"@types/three@^0.163.0": + version "0.163.0" + resolved "https://registry.yarnpkg.com/@types/three/-/three-0.163.0.tgz#96f5440fcd39452d2c84dfe0c9b7a9cf0247b9e6" + integrity sha512-uIdDhsXRpQiBUkflBS/i1l3JX14fW6Ot9csed60nfbZNXHDTRsnV2xnTVwXcgbvTiboAR4IW+t+lTL5f1rqIqA== + dependencies: + "@tweenjs/tween.js" "~23.1.1" + "@types/stats.js" "*" + "@types/webxr" "*" + fflate "~0.8.2" + meshoptimizer "~0.18.1" + +"@types/three@^0.167.0": + version "0.167.0" + resolved "https://registry.yarnpkg.com/@types/three/-/three-0.167.0.tgz#bd15122d8ef4770571dc02a922b6f9397b54b02e" + integrity sha512-BC+Vbm0d6yMzct7dhTBe9ZjEh6ygupyn1k/UcZncIIS/5aNIbfvF77gQw1IFP09Oyj1UxWj0EUBBqc1GkqzsOw== + dependencies: + "@tweenjs/tween.js" "~23.1.2" + "@types/stats.js" "*" + "@types/webxr" "*" + fflate "~0.8.2" + meshoptimizer "~0.18.1" + "@types/through@*": version "0.0.33" resolved "https://registry.yarnpkg.com/@types/through/-/through-0.0.33.tgz#14ebf599320e1c7851e7d598149af183c6b9ea56" @@ -7035,6 +7242,11 @@ resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.8.tgz#7545ba4fc3c003d6c756f651f3bf163d8f0f29ba" integrity sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA== +"@types/webxr@*", "@types/webxr@^0.5.2": + version "0.5.19" + resolved "https://registry.yarnpkg.com/@types/webxr/-/webxr-0.5.19.tgz#463a27bc06ff1c0a0c997e86b48bf24c5f50a4af" + integrity sha512-4hxA+NwohSgImdTSlPXEqDqqFktNgmTXQ05ff1uWam05tNGroCMp4G+4XVl6qWm1p7GQ/9oD41kAYsSssF6Mzw== + "@types/which@^3.0.0": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/which/-/which-3.0.3.tgz#41142ed5a4743128f1bc0b69c46890f0453ddb89" @@ -7134,29 +7346,37 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.7.0.tgz#8de8ba9cafadc38e89003fe303e219c9250089ae" integrity sha512-ihPfvOp7pOcN/ysoj0RpBPOx3HQTJTrIN8UZK+WFd3/iDeFHHqeyYxa4hQk4rMhsz9H9mXpR61IzwlBVGXtl9Q== -"@typescript-eslint/types@7.14.1": - version "7.14.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.14.1.tgz#a43a540dbe5df7f2a11269683d777fc50b4350aa" - integrity sha512-mL7zNEOQybo5R3AavY+Am7KLv8BorIv7HCYS5rKoNZKQD9tsfGUpO4KdAn3sSUvTiS4PQkr2+K0KJbxj8H9NDg== - "@typescript-eslint/types@7.4.0": version "7.4.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.4.0.tgz#ee9dafa75c99eaee49de6dcc9348b45d354419b6" integrity sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw== -"@typescript-eslint/typescript-estree@6.7.0", "@typescript-eslint/typescript-estree@7.4.0", "@typescript-eslint/typescript-estree@^7.2.0": - version "7.14.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.14.1.tgz#ba7c9bac8744487749d19569e254d057754a1575" - integrity sha512-k5d0VuxViE2ulIO6FbxxSZaxqDVUyMbXcidC8rHvii0I56XZPv8cq+EhMns+d/EVIL41sMXqRbK3D10Oza1bbA== +"@typescript-eslint/typescript-estree@6.7.0": + version "6.7.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.0.tgz#20ce2801733bd46f02cc0f141f5b63fbbf2afb63" + integrity sha512-dPvkXj3n6e9yd/0LfojNU8VMUGHWiLuBZvbM6V6QYD+2qxqInE7J+J/ieY2iGwR9ivf/R/haWGkIj04WVUeiSQ== dependencies: - "@typescript-eslint/types" "7.14.1" - "@typescript-eslint/visitor-keys" "7.14.1" + "@typescript-eslint/types" "6.7.0" + "@typescript-eslint/visitor-keys" "6.7.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" - minimatch "^9.0.4" - semver "^7.6.0" - ts-api-utils "^1.3.0" + semver "^7.5.4" + ts-api-utils "^1.0.1" + +"@typescript-eslint/typescript-estree@7.4.0": + version "7.4.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.4.0.tgz#12dbcb4624d952f72c10a9f4431284fca24624f4" + integrity sha512-A99j5AYoME/UBQ1ucEbbMEmGkN7SE0BvZFreSnTd1luq7yulcHdyGamZKizU7canpGDWGJ+Q6ZA9SyQobipePg== + dependencies: + "@typescript-eslint/types" "7.4.0" + "@typescript-eslint/visitor-keys" "7.4.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + minimatch "9.0.3" + semver "^7.5.4" + ts-api-utils "^1.0.1" "@typescript-eslint/utils@7.4.0": version "7.4.0" @@ -7179,14 +7399,6 @@ "@typescript-eslint/types" "6.7.0" eslint-visitor-keys "^3.4.1" -"@typescript-eslint/visitor-keys@7.14.1": - version "7.14.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.14.1.tgz#cc79b5ea154aea734b2a13b983670749f5742274" - integrity sha512-Crb+F75U1JAEtBeQGxSKwI60hZmmzaqA3z9sYsVm8X7W5cwLEm5bRe0/uXS6+MR/y8CVpKSR/ontIAIEPFcEkA== - dependencies: - "@typescript-eslint/types" "7.14.1" - eslint-visitor-keys "^3.4.3" - "@typescript-eslint/visitor-keys@7.4.0": version "7.4.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.4.0.tgz#0c8ff2c1f8a6fe8d7d1a57ebbd4a638e86a60a94" @@ -7200,6 +7412,18 @@ resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== +"@use-gesture/core@10.3.1": + version "10.3.1" + resolved "https://registry.yarnpkg.com/@use-gesture/core/-/core-10.3.1.tgz#976c9421e905f0079d49822cfd5c2e56b808fc56" + integrity sha512-WcINiDt8WjqBdUXye25anHiNxPc0VOrlT8F6LLkU6cycrOGUDyY/yyFmsg3k8i5OLvv25llc0QC45GhR/C8llw== + +"@use-gesture/react@^10.2.24": + version "10.3.1" + resolved "https://registry.yarnpkg.com/@use-gesture/react/-/react-10.3.1.tgz#17a743a894d9bd9a0d1980c618f37f0164469867" + integrity sha512-Yy19y6O2GJq8f7CHf7L0nxL8bf4PZCPaVOCgJrusOeFHY1LvHgYXnmnXg6N5iwAnbgbZCDjo60SiM6IPJi9C5g== + dependencies: + "@use-gesture/core" "10.3.1" + "@verdaccio/commons-api@10.2.0": version "10.2.0" resolved "https://registry.yarnpkg.com/@verdaccio/commons-api/-/commons-api-10.2.0.tgz#3b684c31749837b0574375bb2e10644ecea9fcca" @@ -8078,7 +8302,7 @@ arraybuffer.prototype.slice@^1.0.3: is-array-buffer "^3.0.4" is-shared-array-buffer "^1.0.2" -arrify@^1.0.1: +arrify@^1.0.0, arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== @@ -8363,7 +8587,7 @@ base-x@^3.0.2, base-x@^3.0.8: dependencies: safe-buffer "^5.0.1" -base64-js@^1.3.1: +base64-js@^1.3.1, base64-js@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== @@ -8430,6 +8654,13 @@ bfj@^7.0.2: jsonpath "^1.1.1" tryer "^1.0.1" +bidi-js@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/bidi-js/-/bidi-js-1.0.3.tgz#6f8bcf3c877c4d9220ddf49b9bb6930c88f877d2" + integrity sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw== + dependencies: + require-from-string "^2.0.2" + big-integer@^1.6.42, big-integer@^1.6.48: version "1.6.51" resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686" @@ -8751,7 +8982,7 @@ buffer-fill@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" integrity sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ== -buffer-from@^1.0.0: +buffer-from@^1.0.0, buffer-from@^1.1.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== @@ -8935,6 +9166,11 @@ camelize@^1.0.0: resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.1.tgz#89b7e16884056331a35d6b5ad064332c91daa6c3" integrity sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ== +camera-controls@^2.4.2: + version "2.8.5" + resolved "https://registry.yarnpkg.com/camera-controls/-/camera-controls-2.8.5.tgz#9d7e39cf17172c62fc4a79346b972c3408d0ea35" + integrity sha512-7VTwRk7Nu1nRKsY7bEt9HVBfKt8DETvzyYhLN4OW26OByBayMDB5fUaNcPI+z++vG23RH5yqn6ZRhZcgLQy2rA== + caniuse-lite@^1.0.30001406, caniuse-lite@^1.0.30001464, caniuse-lite@^1.0.30001517: version "1.0.30001533" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001533.tgz#1180daeb2518b93c82f19b904d1fefcf82197707" @@ -9149,6 +9385,21 @@ chokidar@3.5.3, chokidar@^3.4.2, chokidar@^3.5.1, chokidar@^3.5.2, chokidar@^3.5 optionalDependencies: fsevents "~2.3.2" +"chokidar@>=3.0.0 <4.0.0": + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + chownr@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" @@ -9738,6 +9989,13 @@ cron@^3.1.6: "@types/luxon" "~3.3.0" luxon "~3.4.0" +cross-env@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" + integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw== + dependencies: + cross-spawn "^7.0.1" + cross-fetch@^3.0.6, cross-fetch@^3.1.5: version "3.1.8" resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82" @@ -9761,7 +10019,7 @@ cross-spawn@^5.1.0: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: +cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -9932,6 +10190,11 @@ debounce-fn@^5.1.2: dependencies: mimic-fn "^4.0.0" +debounce@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.1.tgz#38881d8f4166a5c5848020c11827b834bcb3e0a5" + integrity sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug== + debug@2.6.9, debug@^2.2.0: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -10223,6 +10486,13 @@ detect-file@^1.0.0: resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" integrity sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q== +detect-gpu@^5.0.28: + version "5.0.40" + resolved "https://registry.yarnpkg.com/detect-gpu/-/detect-gpu-5.0.40.tgz#626d41aa55341858ab547c260726a4afbac7dd95" + integrity sha512-5v4jDN/ERdZZitD29UiLjV9Q9+lDfw2OhEJACIqnvdWulVZCy2K6EwonZ/VKyo4YMqvSIzGIDmojX3jGL3dLpA== + dependencies: + webgl-constants "^1.1.1" + detect-indent@^6.0.0: version "6.1.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.1.0.tgz#592485ebbbf6b3b1ab2be175c8393d04ca0d57e6" @@ -10268,6 +10538,11 @@ diff@5.0.0: resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== +diff@^3.1.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== + diff@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" @@ -10419,6 +10694,11 @@ download@^8.0.0: p-event "^2.1.0" pify "^4.0.1" +draco3d@^1.4.1: + version "1.5.7" + resolved "https://registry.yarnpkg.com/draco3d/-/draco3d-1.5.7.tgz#94f9bce293eb8920c159dc91a4ce9124a9e899e0" + integrity sha512-m6WCKt/erDXcw+70IJXnG7M3awwQPAsZvJGX5zY7beBqpELw6RDGkYVU0W43AFxye4pDZ5i2Lbyc/NNGqwjUVQ== + duplexer3@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.5.tgz#0b5e4d7bad5de8901ea4440624c8e1d20099217e" @@ -10878,6 +11158,18 @@ es6-symbol@^3.1.1, es6-symbol@^3.1.3: d "^1.0.1" ext "^1.1.2" +esbuild-style-plugin@^1.6.3: + version "1.6.3" + resolved "https://registry.yarnpkg.com/esbuild-style-plugin/-/esbuild-style-plugin-1.6.3.tgz#123c994047f1393bee6896c1c37bd4f1942c425f" + integrity sha512-XPEKf4FjLjEVLv/dJH4UxDzXCrFHYpD93DBO8B+izdZARW5b7nNKQbnKv3J+7VDWJbgCU+hzfgIh2AuIZzlmXQ== + dependencies: + "@types/less" "^3.0.3" + "@types/sass" "^1.43.1" + "@types/stylus" "^0.48.38" + glob "^10.2.2" + postcss "^8.4.31" + postcss-modules "^6.0.0" + esbuild-visualizer@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/esbuild-visualizer/-/esbuild-visualizer-0.4.1.tgz#d30acb1de2e3edf6ce72383cc8f65b07be656c4b" @@ -11836,6 +12128,16 @@ ffjavascript@0.3.0, ffjavascript@^0.3.0: wasmcurves "0.2.2" web-worker "1.2.0" +fflate@^0.6.9: + version "0.6.10" + resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.6.10.tgz#5f40f9659205936a2d18abf88b2e7781662b6d43" + integrity sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg== + +fflate@~0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.2.tgz#fc8631f5347812ad6028bbe4a2308b2792aa1dea" + integrity sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A== + figures@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" @@ -12300,11 +12602,23 @@ fuzzy-search@^3.2.1: resolved "https://registry.yarnpkg.com/fuzzy-search/-/fuzzy-search-3.2.1.tgz#65d5faad6bc633aee86f1898b7788dfe312ac6c9" integrity sha512-vAcPiyomt1ioKAsAL2uxSABHJ4Ju/e4UeDM+g1OlR0vV4YhLGMNsdLNvZTpEDY4JCSt0E4hASCNM5t2ETtsbyg== +fuzzy@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/fuzzy/-/fuzzy-0.1.3.tgz#4c76ec2ff0ac1a36a9dccf9a00df8623078d4ed8" + integrity sha512-/gZffu4ykarLrCiP3Ygsa86UAo1E5vEVlvTrpkKywXSbP9Xhln3oSp9QSV57gEq3JFFpGJ4GZ+5zdEp3FcUh4w== + fx@*: version "31.0.0" resolved "https://registry.yarnpkg.com/fx/-/fx-31.0.0.tgz#f013b367d711f25daa7d117af0b10ea7148c4993" integrity sha512-OoeYSPKqNKmfnH4s+rGYI0c8OZmqqOOXsUtqy0YyHqQQoQSDiDs3m3M9uXKx5OQR+jDx7/FhYqpO3kl/As/xgg== +generic-names@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/generic-names/-/generic-names-4.0.0.tgz#0bd8a2fd23fe8ea16cbd0a279acd69c06933d9a3" + integrity sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A== + dependencies: + loader-utils "^3.2.0" + generic-pool@*: version "3.9.0" resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-3.9.0.tgz#36f4a678e963f4fdb8707eab050823abc4e8f5e4" @@ -12515,6 +12829,18 @@ glob@7.2.0: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^10.2.2: + version "10.4.5" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" + integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== + dependencies: + foreground-child "^3.1.0" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^1.11.1" + glob@^6.0.1: version "6.0.4" resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" @@ -12608,6 +12934,11 @@ globby@^13.1.2, globby@^13.1.4, globby@^13.2.2: merge2 "^1.4.1" slash "^4.0.0" +glsl-noise@^0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/glsl-noise/-/glsl-noise-0.0.0.tgz#367745f3a33382c0eeec4cb54b7e99cfc1d7670b" + integrity sha512-b/ZCF6amfAUb7dJM/MxRs7AetQEahYzJ8PtgfrmEdtw6uyGOr+ZSGtgjFm6mfsBkxJ4d2W7kg+Nlqzqvn3Bc0w== + goober@^2.1.10: version "2.1.13" resolved "https://registry.yarnpkg.com/goober/-/goober-2.1.13.tgz#e3c06d5578486212a76c9eba860cbc3232ff6d7c" @@ -12935,6 +13266,11 @@ hexoid@^1.0.0: resolved "https://registry.yarnpkg.com/hexoid/-/hexoid-1.0.0.tgz#ad10c6573fb907de23d9ec63a711267d9dc9bc18" integrity sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g== +hls.js@1.3.5: + version "1.3.5" + resolved "https://registry.yarnpkg.com/hls.js/-/hls.js-1.3.5.tgz#0e8b0799ecf2feb7ba199f5e95f35ba9552e04f4" + integrity sha512-uybAvKS6uDe0MnWNEPnO0krWVr+8m2R0hJ/viql8H3MVK+itq8gGQuIYoFHL3rECkIpNH98Lw8YuuWMKZxp3Ew== + hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -13106,6 +13442,11 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" +icss-utils@^5.0.0, icss-utils@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" + integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== + idna-uts46-hx@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz#a1dc5c4df37eee522bf66d969cc980e00e8711f9" @@ -13133,6 +13474,16 @@ ignore@^5.2.4: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.0.tgz#67418ae40d34d6999c95ff56016759c718c82f78" integrity sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg== +immediate@~3.0.5: + version "3.0.6" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" + integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ== + +immutable@^4.0.0: + version "4.3.7" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.7.tgz#c70145fc90d89fb02021e65c84eb0226e4e5a381" + integrity sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw== + import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" @@ -13903,6 +14254,13 @@ iterator.prototype@^1.1.2: reflect.getprototypeof "^1.0.4" set-function-name "^2.0.1" +its-fine@^1.0.6: + version "1.2.5" + resolved "https://registry.yarnpkg.com/its-fine/-/its-fine-1.2.5.tgz#5466c287f86a0a73e772c8d8d515626c97195dc9" + integrity sha512-fXtDA0X0t0eBYAGLVM5YsgJGsJ5jEmqZEPrGbzdf5awjv0xE7nqv3TVnvtUF060Tkes15DbDAKW/I48vsb6SyA== + dependencies: + "@types/react-reconciler" "^0.28.0" + jackspeak@^2.3.5: version "2.3.6" resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" @@ -13912,6 +14270,15 @@ jackspeak@^2.3.5: optionalDependencies: "@pkgjs/parseargs" "^0.11.0" +jackspeak@^3.1.2: + version "3.4.3" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" + integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + jaeger-client@^3.15.0: version "3.19.0" resolved "https://registry.yarnpkg.com/jaeger-client/-/jaeger-client-3.19.0.tgz#9b5bd818ebd24e818616ee0f5cffe1722a53ae6e" @@ -13933,6 +14300,13 @@ jake@^10.8.5: filelist "^1.0.4" minimatch "^3.1.2" +javascript-time-ago@^2.5.10: + version "2.5.10" + resolved "https://registry.yarnpkg.com/javascript-time-ago/-/javascript-time-ago-2.5.10.tgz#f1c188496203a1aa37318276703a2ebd2941c1b1" + integrity sha512-EUxp4BP74QH8xiYHyeSHopx1XhMMJ9qEX4rcBdFtpVWmKRdzpxbNzz2GSbuekZr5wt0rmLehuyp0PE34EAJT9g== + dependencies: + relative-time-format "^1.1.6" + javascript-time-ago@^2.5.9: version "2.5.9" resolved "https://registry.yarnpkg.com/javascript-time-ago/-/javascript-time-ago-2.5.9.tgz#3c5d8012cd493d764c6b26a0ffe6e8b20afcf1fe" @@ -14690,6 +15064,13 @@ libsodium-wrappers-sumo@^0.7.11: dependencies: libsodium-sumo "^0.7.11" +lie@^3.0.2: + version "3.3.0" + resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a" + integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ== + dependencies: + immediate "~3.0.5" + liftoff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-4.0.0.tgz#1a463b9073335cd425cdaa3b468996f7d66d2d81" @@ -14739,6 +15120,11 @@ loader-runner@^4.2.0: resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== +loader-utils@^3.2.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.3.1.tgz#735b9a19fd63648ca7adbd31c2327dfe281304e5" + integrity sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg== + locate-path@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" @@ -14979,6 +15365,11 @@ lru-cache@^10.0.1: resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.0.1.tgz#0a3be479df549cca0e5d693ac402ff19537a6b7a" integrity sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g== +lru-cache@^10.2.0: + version "10.4.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" + integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== + lru-cache@^4.0.1: version "4.1.5" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" @@ -15021,6 +15412,11 @@ luxon@~3.4.0: resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.4.4.tgz#cf20dc27dc532ba41a169c43fdcc0063601577af" integrity sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA== +maath@^0.10.7: + version "0.10.8" + resolved "https://registry.yarnpkg.com/maath/-/maath-0.10.8.tgz#cf647544430141bf6982da6e878abb6c4b804e24" + integrity sha512-tRvbDF0Pgqz+9XUa4jjfgAQ8/aPKmQdWXilFu2tMy4GWj4NOsx99HlULO4IeREfbO3a0sA145DZYyvXPkybm0g== + magic-string@^0.25.3, magic-string@^0.25.7: version "0.25.9" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c" @@ -15280,6 +15676,16 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== +meshline@^3.1.6: + version "3.3.1" + resolved "https://registry.yarnpkg.com/meshline/-/meshline-3.3.1.tgz#20decfd5cdd25c8469e862ddf0ab1ad167759734" + integrity sha512-/TQj+JdZkeSUOl5Mk2J7eLcYTLiQm2IDzmlSvYm7ov15anEcDJ92GHqqazxTSreeNgfnYu24kiEvvv0WlbCdFQ== + +meshoptimizer@~0.18.1: + version "0.18.1" + resolved "https://registry.yarnpkg.com/meshoptimizer/-/meshoptimizer-0.18.1.tgz#cdb90907f30a7b5b1190facd3b7ee6b7087797d8" + integrity sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw== + methods@^1.1.2, methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" @@ -15582,6 +15988,13 @@ minimatch@7.4.6: dependencies: brace-expansion "^2.0.1" +minimatch@9.0.3, minimatch@^9.0.1, minimatch@^9.0.3: + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== + dependencies: + brace-expansion "^2.0.1" + minimatch@^5.0.1: version "5.1.6" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" @@ -15589,13 +16002,6 @@ minimatch@^5.0.1: dependencies: brace-expansion "^2.0.1" -minimatch@^9.0.1, minimatch@^9.0.3: - version "9.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" - integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== - dependencies: - brace-expansion "^2.0.1" - minimatch@^9.0.4: version "9.0.5" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" @@ -15630,6 +16036,11 @@ minipass@^2.6.0, minipass@^2.9.0: resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c" integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ== +minipass@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" + integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== + minizlib@^1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" @@ -15659,7 +16070,7 @@ mkdirp@1.0.4, mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -mkdirp@^0.5.5, mkdirp@~0.5.1: +mkdirp@^0.5.1, mkdirp@^0.5.5, mkdirp@~0.5.1: version "0.5.6" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== @@ -16663,6 +17074,11 @@ pac-resolver@^7.0.0: ip "^1.1.8" netmask "^2.0.2" +package-json-from-dist@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz#e501cd3094b278495eb4258d4c9f6d5ac3019f00" + integrity sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw== + packet-reader@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-1.0.0.tgz#9238e5480dedabacfe1fe3f2771063f164157d74" @@ -16854,6 +17270,14 @@ path-scurry@^1.10.1: lru-cache "^9.1.1 || ^10.0.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" +path-scurry@^1.11.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" + integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== + dependencies: + lru-cache "^10.2.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" @@ -17002,6 +17426,11 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== +picocolors@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" + integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== + picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" @@ -17142,6 +17571,48 @@ postcss-load-config@^4.0.1: lilconfig "^2.0.5" yaml "^2.1.1" +postcss-modules-extract-imports@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz#b4497cb85a9c0c4b5aabeb759bb25e8d89f15002" + integrity sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q== + +postcss-modules-local-by-default@^4.0.0: + version "4.0.5" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz#f1b9bd757a8edf4d8556e8d0f4f894260e3df78f" + integrity sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw== + dependencies: + icss-utils "^5.0.0" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.1.0" + +postcss-modules-scope@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz#a43d28289a169ce2c15c00c4e64c0858e43457d5" + integrity sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ== + dependencies: + postcss-selector-parser "^6.0.4" + +postcss-modules-values@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" + integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== + dependencies: + icss-utils "^5.0.0" + +postcss-modules@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules/-/postcss-modules-6.0.0.tgz#cac283dbabbbdc2558c45391cbd0e2df9ec50118" + integrity sha512-7DGfnlyi/ju82BRzTIjWS5C4Tafmzl3R79YP/PASiocj+aa6yYphHhhKUOEoXQToId5rgyFgJ88+ccOUydjBXQ== + dependencies: + generic-names "^4.0.0" + icss-utils "^5.1.0" + lodash.camelcase "^4.3.0" + postcss-modules-extract-imports "^3.0.0" + postcss-modules-local-by-default "^4.0.0" + postcss-modules-scope "^3.0.0" + postcss-modules-values "^4.0.0" + string-hash "^1.1.1" + postcss-nested@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-6.0.1.tgz#f83dc9846ca16d2f4fa864f16e9d9f7d0961662c" @@ -17157,7 +17628,15 @@ postcss-selector-parser@^6.0.11: cssesc "^3.0.0" util-deprecate "^1.0.2" -postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2, postcss-value-parser@^4.2.0: +postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: + version "6.1.1" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz#5be94b277b8955904476a2400260002ce6c56e38" + integrity sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== @@ -17198,6 +17677,15 @@ postcss@^8.4.23: picocolors "^1.0.0" source-map-js "^1.0.2" +postcss@^8.4.31: + version "8.4.40" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.40.tgz#eb81f2a4dd7668ed869a6db25999e02e9ad909d8" + integrity sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q== + dependencies: + nanoid "^3.3.7" + picocolors "^1.0.1" + source-map-js "^1.2.0" + postcss@^8.4.38: version "8.4.38" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.38.tgz#b387d533baf2054288e337066d81c6bee9db9e0e" @@ -17280,6 +17768,11 @@ postinstall-postinstall@^2.1.0: resolved "https://registry.yarnpkg.com/postinstall-postinstall/-/postinstall-postinstall-2.1.0.tgz#4f7f77441ef539d1512c40bd04c71b06a4704ca3" integrity sha512-7hQX6ZlZXIoRiWNrbMQaLzUUfH+sSx39u8EJ9HYuDc1kLo9IXKWjM5RSquZN1ad5GnH8CGFM78fsAAQi3OKEEQ== +potpack@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/potpack/-/potpack-1.0.2.tgz#23b99e64eb74f5741ffe7656b5b5c4ddce8dfc14" + integrity sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ== + preferred-pm@^3.0.0: version "3.1.2" resolved "https://registry.yarnpkg.com/preferred-pm/-/preferred-pm-3.1.2.tgz#aedb70550734a574dffcbf2ce82642bd1753bdd6" @@ -17370,6 +17863,14 @@ process@^0.11.10: resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== +promise-worker-transferable@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/promise-worker-transferable/-/promise-worker-transferable-1.0.4.tgz#2c72861ba053e5ae42b487b4a83b1ed3ae3786e8" + integrity sha512-bN+0ehEnrXfxV2ZQvU2PetO0n4gqBD4ulq3MI1WOPLgr7/Mg9yRQkX5+0v1vagr74ZTsl7XtzlaYDo2EuCeYJw== + dependencies: + is-promise "^2.1.0" + lie "^3.0.2" + prompts@^2.0.1: version "2.4.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" @@ -17681,6 +18182,13 @@ react-clientside-effect@^1.2.6: dependencies: "@babel/runtime" "^7.12.13" +react-composer@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/react-composer/-/react-composer-5.0.3.tgz#7beb9513da5e8687f4f434ea1333ef36a4f3091b" + integrity sha512-1uWd07EME6XZvMfapwZmc7NgCZqDemcvicRi3wMJzXsQLvZ3L7fTHVyPy1bZdnWXM4iPjYuNE+uJ41MLKeTtnA== + dependencies: + prop-types "^15.6.0" + react-dom@18.2.0, react-dom@^18.2.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" @@ -17763,6 +18271,14 @@ react-qr-reader@^3.0.0-beta-1: "@zxing/library" "^0.18.3" rollup "^2.67.2" +react-reconciler@^0.27.0: + version "0.27.0" + resolved "https://registry.yarnpkg.com/react-reconciler/-/react-reconciler-0.27.0.tgz#360124fdf2d76447c7491ee5f0e04503ed9acf5b" + integrity sha512-HmMDKciQjYmBRGuuhIaKA1ba/7a+UsM5FzOZsMO2JYHt9Jh8reCb7j1eDC95NOyUlKM9KRyvdx0flBuDvYSBoA== + dependencies: + loose-envify "^1.1.0" + scheduler "^0.21.0" + react-redux@^9.1.0: version "9.1.0" resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-9.1.0.tgz#46a46d4cfed4e534ce5452bb39ba18e1d98a8197" @@ -17917,6 +18433,13 @@ react-transition-group@^4.3.0: loose-envify "^1.4.0" prop-types "^15.6.2" +react-use-measure@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/react-use-measure/-/react-use-measure-2.1.1.tgz#5824537f4ee01c9469c45d5f7a8446177c6cc4ba" + integrity sha512-nocZhN26cproIiIduswYpV5y5lQpSQS1y/4KuvUCjSKmw7ZWIS/+g3aFnX3WdBkyuGUtTLif3UTqnLLhbDoQig== + dependencies: + debounce "^1.2.1" + react@18.2.0, react@^18.2.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" @@ -18535,6 +19058,22 @@ safe-stable-stringify@^2.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== +sass@*: + version "1.77.8" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.77.8.tgz#9f18b449ea401759ef7ec1752a16373e296b52bd" + integrity sha512-4UHg6prsrycW20fqLGPShtEvo/WyHRVRHwOP4DzkUrObWoWI05QBSfzU71TVB7PFaL104TwNaHpjlWXAZbQiNQ== + dependencies: + chokidar ">=3.0.0 <4.0.0" + immutable "^4.0.0" + source-map-js ">=0.6.2 <2.0.0" + +scheduler@^0.21.0: + version "0.21.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.21.0.tgz#6fd2532ff5a6d877b6edb12f00d8ab7e8f308820" + integrity sha512-1r87x5fz9MXqswA2ERLo0EbOAU74DpIUO090gIasYTqlVoJeMcl+Z1Rg7WHz+qtPujhS/hGIt9kxZOYBV3faRQ== + dependencies: + loose-envify "^1.1.0" + scheduler@^0.23.0: version "0.23.0" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" @@ -18601,11 +19140,6 @@ semver@^6.3.0, semver@^6.3.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.6.0: - version "7.6.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" - integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== - send@0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" @@ -19016,16 +19550,16 @@ sort-keys@^2.0.0: dependencies: is-plain-obj "^1.0.0" +"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" + integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== + source-map-js@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== -source-map-js@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" - integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== - source-map-support@0.5.13: version "0.5.13" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" @@ -19034,7 +19568,7 @@ source-map-support@0.5.13: buffer-from "^1.0.0" source-map "^0.6.0" -source-map-support@^0.5.12, source-map-support@^0.5.21, source-map-support@~0.5.20: +source-map-support@^0.5.12, source-map-support@^0.5.21, source-map-support@^0.5.6, source-map-support@~0.5.20: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== @@ -19167,6 +19701,18 @@ static-eval@2.0.2: dependencies: escodegen "^1.8.1" +stats-gl@^2.0.0: + version "2.2.8" + resolved "https://registry.yarnpkg.com/stats-gl/-/stats-gl-2.2.8.tgz#72566abc8e4a66e91c26b7d9abf659d032379d68" + integrity sha512-94G5nZvduDmzxBS7K0lYnynYwreZpkknD8g5dZmU6mpwIhy3caCrjAm11Qm1cbyx7mqix7Fp00RkbsonzKWnoQ== + dependencies: + "@types/three" "^0.163.0" + +stats.js@^0.17.0: + version "0.17.0" + resolved "https://registry.yarnpkg.com/stats.js/-/stats.js-0.17.0.tgz#b1c3dc46d94498b578b7fd3985b81ace7131cc7d" + integrity sha512-hNKz8phvYLPEcRkeG1rsGmV5ChMjKDAWU7/OJJdDErPBNChQXxCo3WZurGpnWc6gZhAzEPFad1aVgyOANH1sMw== + statuses@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" @@ -19264,6 +19810,11 @@ strict-uri-encode@^1.0.0: resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" integrity sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ== +string-hash@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b" + integrity sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A== + string-length@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" @@ -19277,16 +19828,7 @@ string-template@~0.2.1: resolved "https://registry.yarnpkg.com/string-template/-/string-template-0.2.1.tgz#42932e598a352d01fc22ec3367d9d84eec6c9add" integrity sha512-Yptehjogou2xm4UJbxJ4CxgZx12HBfeystp0y3x7s4Dj32ltVVG1Gg8YhKjHZkHicuKpZX/ffilA8505VbUbpw== -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -19419,14 +19961,7 @@ stringify-entities@^4.0.0: character-entities-html4 "^2.0.0" character-entities-legacy "^3.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -19614,6 +20149,11 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +suspend-react@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/suspend-react/-/suspend-react-0.1.3.tgz#a52f49d21cfae9a2fb70bd0c68413d3f9d90768e" + integrity sha512-aqldKgX9aZqpoDp3e8/BZ8Dm7x1pJl+qI3ZKxDN0i/IQTWUwBx/ManmlVJ3wowqbno6c2bmiIfs+Um6LbsjJyQ== + swarm-js@^0.1.40: version "0.1.42" resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.42.tgz#497995c62df6696f6e22372f457120e43e727979" @@ -19712,6 +20252,34 @@ tailwindcss@^3.4.3: resolve "^1.22.2" sucrase "^3.32.0" +tailwindcss@^3.4.6: + version "3.4.6" + resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.6.tgz#41faae16607e0916da1eaa4a3b44053457ba70dd" + integrity sha512-1uRHzPB+Vzu57ocybfZ4jh5Q3SdlH7XW23J5sQoM9LhE9eIOlzxer/3XPSsycvih3rboRsvt0QCmzSrqyOYUIA== + dependencies: + "@alloc/quick-lru" "^5.2.0" + arg "^5.0.2" + chokidar "^3.5.3" + didyoumean "^1.2.2" + dlv "^1.1.3" + fast-glob "^3.3.0" + glob-parent "^6.0.2" + is-glob "^4.0.3" + jiti "^1.21.0" + lilconfig "^2.1.0" + micromatch "^4.0.5" + normalize-path "^3.0.0" + object-hash "^3.0.0" + picocolors "^1.0.0" + postcss "^8.4.23" + postcss-import "^15.1.0" + postcss-js "^4.0.1" + postcss-load-config "^4.0.1" + postcss-nested "^6.0.1" + postcss-selector-parser "^6.0.11" + resolve "^1.22.2" + sucrase "^3.32.0" + tapable@^2.1.1, tapable@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" @@ -19837,6 +20405,28 @@ thread-stream@^0.15.1: dependencies: real-require "^0.1.0" +three-mesh-bvh@^0.7.0: + version "0.7.6" + resolved "https://registry.yarnpkg.com/three-mesh-bvh/-/three-mesh-bvh-0.7.6.tgz#6764b39475bdba9450ad3a4065492678ee537272" + integrity sha512-rCjsnxEqR9r1/C/lCqzGLS67NDty/S/eT6rAJfDvsanrIctTWdNoR4ZOGWewCB13h1QkVo2BpmC0wakj1+0m8A== + +three-stdlib@^2.29.9: + version "2.30.5" + resolved "https://registry.yarnpkg.com/three-stdlib/-/three-stdlib-2.30.5.tgz#5d4804b17a7807573cbf96b1159024921596342a" + integrity sha512-BBZkKnTDmUacXU9mv7fA5R7Brb89uUbOUWXXZKNrzdx6JEozJt3e6I5zPMRbb1FC2aw/2QFtgwPi1PI8VjX6FQ== + dependencies: + "@types/draco3d" "^1.4.0" + "@types/offscreencanvas" "^2019.6.4" + "@types/webxr" "^0.5.2" + draco3d "^1.4.1" + fflate "^0.6.9" + potpack "^1.0.1" + +three@^0.167.0: + version "0.167.0" + resolved "https://registry.yarnpkg.com/three/-/three-0.167.0.tgz#399ae7b69604c0a45b93ba3706ad8dc962056c42" + integrity sha512-9Y1a66fpjqF3rhq7ivKTaKtjQLZ97Hj/lZ00DmZWaKHaQFH4uzYT1znwRDWQOcgMmCcOloQzo61gDmqO8l9xmA== + thriftrw@^3.5.0: version "3.11.4" resolved "https://registry.yarnpkg.com/thriftrw/-/thriftrw-3.11.4.tgz#84c990ee89e926631c0b475909ada44ee9249870" @@ -19984,6 +20574,26 @@ trim-repeated@^1.0.0: dependencies: escape-string-regexp "^1.0.2" +troika-three-text@^0.49.0: + version "0.49.1" + resolved "https://registry.yarnpkg.com/troika-three-text/-/troika-three-text-0.49.1.tgz#1aaa75337e507ea4120103fb69a5e4687fff97dd" + integrity sha512-lXGWxgjJP9kw4i4Wh+0k0Q/7cRfS6iOME4knKht/KozPu9GcFA9NnNpRvehIhrUawq9B0ZRw+0oiFHgRO+4Wig== + dependencies: + bidi-js "^1.0.2" + troika-three-utils "^0.49.0" + troika-worker-utils "^0.49.0" + webgl-sdf-generator "1.1.1" + +troika-three-utils@^0.49.0: + version "0.49.0" + resolved "https://registry.yarnpkg.com/troika-three-utils/-/troika-three-utils-0.49.0.tgz#3fbdbf8783740ce3c1f7acac642e7e957ea4f090" + integrity sha512-umitFL4cT+Fm/uONmaQEq4oZlyRHWwVClaS6ZrdcueRvwc2w+cpNQ47LlJKJswpqtMFWbEhOLy0TekmcPZOdYA== + +troika-worker-utils@^0.49.0: + version "0.49.0" + resolved "https://registry.yarnpkg.com/troika-worker-utils/-/troika-worker-utils-0.49.0.tgz#e5e200a09d2e0e4eb9fe818a83effa912e2ec4b4" + integrity sha512-1xZHoJrG0HFfCvT/iyN41DvI/nRykiBtHqFkGaGgJwq5iXfIZFBiPPEHFpPpgyKM3Oo5ITHXP5wM2TNQszYdVg== + trough@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/trough/-/trough-2.2.0.tgz#94a60bd6bd375c152c1df911a4b11d5b0256f50f" @@ -19999,11 +20609,6 @@ ts-api-utils@^1.0.1: resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.0.3.tgz#f12c1c781d04427313dbac808f453f050e54a331" integrity sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg== -ts-api-utils@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" - integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== - ts-custom-error@^3.0.0, ts-custom-error@^3.2.0: version "3.3.1" resolved "https://registry.yarnpkg.com/ts-custom-error/-/ts-custom-error-3.3.1.tgz#8bd3c8fc6b8dc8e1cb329267c45200f1e17a65d1" @@ -20065,7 +20670,7 @@ ts-node-dev@^2.0.0: ts-node "^10.4.0" tsconfig "^7.0.0" -ts-node@*, ts-node@7.0.1, ts-node@^10.4.0, ts-node@^10.9.1, ts-node@^10.9.2: +ts-node@*, ts-node@^10.4.0, ts-node@^10.9.1, ts-node@^10.9.2: version "10.9.2" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== @@ -20084,6 +20689,20 @@ ts-node@*, ts-node@7.0.1, ts-node@^10.4.0, ts-node@^10.9.1, ts-node@^10.9.2: v8-compile-cache-lib "^3.0.1" yn "3.1.1" +ts-node@7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-7.0.1.tgz#9562dc2d1e6d248d24bc55f773e3f614337d9baf" + integrity sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw== + dependencies: + arrify "^1.0.0" + buffer-from "^1.1.0" + diff "^3.1.0" + make-error "^1.1.1" + minimist "^1.2.0" + mkdirp "^0.5.1" + source-map-support "^0.5.6" + yn "^2.0.0" + tsconfig-paths@^3.14.2, tsconfig-paths@^3.5.0: version "3.14.2" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz#6e32f1f79412decd261f92d633a9dc1cfa99f088" @@ -20510,6 +21129,13 @@ tunnel-agent@^0.6.0: dependencies: safe-buffer "^5.0.1" +tunnel-rat@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/tunnel-rat/-/tunnel-rat-0.1.2.tgz#1717efbc474ea2d8aa05a91622457a6e201c0aeb" + integrity sha512-lR5VHmkPhzdhrM092lI2nACsLO4QubF0/yoOhzX7c+wIpbN1GjHNzCc91QlpxBi+cnx8vVJ+Ur6vL5cEoQPFpQ== + dependencies: + zustand "^4.3.2" + turbo-darwin-64@2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/turbo-darwin-64/-/turbo-darwin-64-2.0.4.tgz#83c7835f8ba1f7a5473487ce73cfc8d5ad523614" @@ -21004,7 +21630,7 @@ use-sidecar@^1.1.2: detect-node-es "^1.1.0" tslib "^2.0.0" -use-sync-external-store@^1.0.0: +use-sync-external-store@1.2.0, use-sync-external-store@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== @@ -21044,6 +21670,11 @@ util@^0.12.3, util@^0.12.4, util@^0.12.5: is-typed-array "^1.1.3" which-typed-array "^1.1.2" +utility-types@^3.10.0: + version "3.11.0" + resolved "https://registry.yarnpkg.com/utility-types/-/utility-types-3.11.0.tgz#607c40edb4f258915e901ea7995607fdf319424c" + integrity sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw== + utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" @@ -21545,6 +22176,16 @@ web3@^1.6.0: web3-shh "1.10.2" web3-utils "1.10.2" +webgl-constants@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/webgl-constants/-/webgl-constants-1.1.1.tgz#f9633ee87fea56647a60b9ce735cbdfb891c6855" + integrity sha512-LkBXKjU5r9vAW7Gcu3T5u+5cvSvh5WwINdr0C+9jpzVB41cjQAP5ePArDtk/WHYdVj0GefCgM73BA7FlIiNtdg== + +webgl-sdf-generator@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/webgl-sdf-generator/-/webgl-sdf-generator-1.1.1.tgz#3e1b422b3d87cd3cc77f2602c9db63bc0f6accbd" + integrity sha512-9Z0JcMTFxeE+b2x1LJTdnaT8rT8aEp7MVxkNwoycNmJWwPdzoXzMh0BjJSh/AEFP+KPYZUli814h8bJZFIZ2jA== + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -21745,7 +22386,7 @@ workspace-tools@^0.36.4: js-yaml "^4.1.0" micromatch "^4.0.0" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -21763,15 +22404,6 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" @@ -21996,6 +22628,11 @@ yn@3.1.1: resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== +yn@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yn/-/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a" + integrity sha512-uTv8J/wiWTgUTg+9vLTi//leUl5vDQS6uii/emeTb2ssY7vl6QWf2fFbIIGjnhjvbdKlU0ed7QPgY1htTC86jQ== + yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" @@ -22036,6 +22673,18 @@ zod@^3.22.4: resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.4.tgz#f31c3a9386f61b1f228af56faa9255e845cf3fff" integrity sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg== +zustand@^3.7.1: + version "3.7.2" + resolved "https://registry.yarnpkg.com/zustand/-/zustand-3.7.2.tgz#7b44c4f4a5bfd7a8296a3957b13e1c346f42514d" + integrity sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA== + +zustand@^4.3.2: + version "4.5.4" + resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.5.4.tgz#63abdd81edfb190bc61e0bbae045cc4d52158a05" + integrity sha512-/BPMyLKJPtFEvVL0E9E9BTUM63MNyhPGlvxk1XjrfWTUlV+BR8jufjsovHzrtR6YNcBEcL7cMHovL1n9xHawEg== + dependencies: + use-sync-external-store "1.2.0" + zwitch@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-2.0.4.tgz#c827d4b0acb76fc3e685a4c6ec2902d51070e9d7"