mirror of
https://github.com/TheRealOwenRees/echecsfrance.git
synced 2026-07-22 20:16:57 +00:00
import grouping and sorting with Prettier plugin
This commit is contained in:
+5
-1
@@ -1,5 +1,9 @@
|
|||||||
{
|
{
|
||||||
"trailingComma": "all",
|
"trailingComma": "all",
|
||||||
"bracketSpacing": true,
|
"bracketSpacing": true,
|
||||||
"plugins": ["prettier-plugin-tailwindcss"]
|
"plugins": ["@trivago/prettier-plugin-sort-imports", "prettier-plugin-tailwindcss"],
|
||||||
|
"importOrder": ["^react$", "^@?\\w", "^@\\\\", "<THIRD_PARTY_MODULES>", "^\\.\\.", "^\\."],
|
||||||
|
"importOrderSeparation": true,
|
||||||
|
"importOrderSortSpecifiers": true,
|
||||||
|
"tailwindFunctions": ["twMerge"]
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+3
@@ -23,9 +23,12 @@
|
|||||||
"spiderfied",
|
"spiderfied",
|
||||||
"Spiderfy",
|
"Spiderfy",
|
||||||
"spiderified",
|
"spiderified",
|
||||||
|
"superjson",
|
||||||
"tailwindcss",
|
"tailwindcss",
|
||||||
"timothyarmes",
|
"timothyarmes",
|
||||||
"tournois",
|
"tournois",
|
||||||
|
"trivago",
|
||||||
|
"TRPC",
|
||||||
"unspiderfied",
|
"unspiderfied",
|
||||||
"unspiderfy"
|
"unspiderfy"
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -23,6 +23,18 @@ and is deployed on [Vercel](https://vercel.com/)
|
|||||||
- [Leaflet](https://leafletjs.com/) - a Javascript library for interactive maps
|
- [Leaflet](https://leafletjs.com/) - a Javascript library for interactive maps
|
||||||
- [Nodemailer](https://nodemailer.com/) - a module for Node.js applications to allow easy as cake email sending
|
- [Nodemailer](https://nodemailer.com/) - a module for Node.js applications to allow easy as cake email sending
|
||||||
|
|
||||||
|
## Required VSCode plugins
|
||||||
|
|
||||||
|
- ESLint
|
||||||
|
- Prettier - Code formatter
|
||||||
|
|
||||||
|
## Recommended VSCode plugins
|
||||||
|
|
||||||
|
- Tailwind CSS IntelliSense
|
||||||
|
- Tailwind Docs
|
||||||
|
- Code Spell Checker (to avoid English spelling mistakes in the code)
|
||||||
|
- Console Ninja (for easier debugging)
|
||||||
|
|
||||||
## Contributions
|
## Contributions
|
||||||
|
|
||||||
Contributions are encouraged. Please open an issue to discuss your ideas.
|
Contributions are encouraged. Please open an issue to discuss your ideas.
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { MapProps } from "@/types";
|
import { ChangeEvent, useMemo, useRef } from "react";
|
||||||
import { useMemo, useRef, ChangeEvent } from "react";
|
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { useSetAtom } from "jotai";
|
|
||||||
import { mapBoundsAtom } from "@/app/atoms";
|
|
||||||
|
|
||||||
|
import { useSetAtom } from "jotai";
|
||||||
import L from "leaflet";
|
import L from "leaflet";
|
||||||
import { MapContainer, TileLayer, Marker } from "react-leaflet";
|
|
||||||
import "leaflet/dist/leaflet.css";
|
|
||||||
import "leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.css";
|
|
||||||
import "leaflet-defaulticon-compatibility";
|
import "leaflet-defaulticon-compatibility";
|
||||||
|
import "leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.css";
|
||||||
|
import "leaflet/dist/leaflet.css";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
import { MapContainer, Marker, TileLayer } from "react-leaflet";
|
||||||
|
|
||||||
import MapEvents from "@/app/[lang]/components/MapEvents";
|
import MapEvents from "@/app/[lang]/components/MapEvents";
|
||||||
|
import { mapBoundsAtom } from "@/app/atoms";
|
||||||
|
import { MapProps } from "@/types";
|
||||||
|
|
||||||
const Map = ({ position, setPosition, center }: MapProps) => {
|
const Map = ({ position, setPosition, center }: MapProps) => {
|
||||||
const t = useTranslations("Map");
|
const t = useTranslations("Map");
|
||||||
|
|||||||
@@ -1,17 +1,19 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import dynamic from "next/dynamic";
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { useAtomValue } from "jotai";
|
import { useAtomValue } from "jotai";
|
||||||
import { franceCenterAtom } from "@/app/atoms";
|
import { useTranslations } from "next-intl";
|
||||||
import useTournamentForm from "@/hooks/useTournamentForm";
|
import dynamic from "next/dynamic";
|
||||||
|
|
||||||
import InfoMessage from "@/app/[lang]/components/InfoMessage";
|
import InfoMessage from "@/app/[lang]/components/InfoMessage";
|
||||||
import {
|
|
||||||
handleTournamentSubmit,
|
|
||||||
handleClearTournamentForm,
|
|
||||||
} from "@/handlers/formHandlers";
|
|
||||||
import LoadingMap from "@/app/[lang]/components/LoadingMap";
|
import LoadingMap from "@/app/[lang]/components/LoadingMap";
|
||||||
|
import { franceCenterAtom } from "@/app/atoms";
|
||||||
|
import {
|
||||||
|
handleClearTournamentForm,
|
||||||
|
handleTournamentSubmit,
|
||||||
|
} from "@/handlers/formHandlers";
|
||||||
|
import useTournamentForm from "@/hooks/useTournamentForm";
|
||||||
|
|
||||||
const Map = dynamic(() => import("./Map"), {
|
const Map = dynamic(() => import("./Map"), {
|
||||||
ssr: false,
|
ssr: false,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
import { useTranslations } from "next-intl";
|
||||||
import Link from "next-intl/link";
|
import Link from "next-intl/link";
|
||||||
import { FaGithub, FaRegEnvelope } from "react-icons/fa";
|
import { FaGithub, FaRegEnvelope } from "react-icons/fa";
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import ThemeSwitcher from "@/app/[lang]/components/ThemeSwitcher";
|
import ThemeSwitcher from "@/app/[lang]/components/ThemeSwitcher";
|
||||||
|
|
||||||
export default function Footer() {
|
export default function Footer() {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useRef, useState } from "react";
|
import { useRef, useState } from "react";
|
||||||
|
|
||||||
import { twMerge } from "tailwind-merge";
|
import { twMerge } from "tailwind-merge";
|
||||||
|
|
||||||
import HamburgerMenu from "./HamburgerMenu";
|
import HamburgerMenu from "./HamburgerMenu";
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
|
import { Dispatch, RefObject, SetStateAction, useRef, useState } from "react";
|
||||||
|
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
import Link from "next-intl/link";
|
||||||
|
import { twMerge } from "tailwind-merge";
|
||||||
|
|
||||||
|
import useHamburgerClose from "@/hooks/useHamburgerClose";
|
||||||
|
|
||||||
interface HamburgerMenuState {
|
interface HamburgerMenuState {
|
||||||
menuVisible: boolean;
|
menuVisible: boolean;
|
||||||
setMenuVisible: Dispatch<SetStateAction<boolean>>;
|
setMenuVisible: Dispatch<SetStateAction<boolean>>;
|
||||||
hamburgerButtonRef: RefObject<HTMLDivElement>;
|
hamburgerButtonRef: RefObject<HTMLDivElement>;
|
||||||
}
|
}
|
||||||
|
|
||||||
import { Dispatch, RefObject, SetStateAction, useRef, useState } from "react";
|
|
||||||
import { twMerge } from "tailwind-merge";
|
|
||||||
import Link from "next-intl/link";
|
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
|
|
||||||
import useHamburgerClose from "@/hooks/useHamburgerClose";
|
|
||||||
|
|
||||||
const HamburgerMenu = ({
|
const HamburgerMenu = ({
|
||||||
menuVisible,
|
menuVisible,
|
||||||
setMenuVisible,
|
setMenuVisible,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { ResponseMessage } from "@/types";
|
|
||||||
import { Dispatch, SetStateAction } from "react";
|
import { Dispatch, SetStateAction } from "react";
|
||||||
|
|
||||||
|
import { ResponseMessage } from "@/types";
|
||||||
|
|
||||||
const InfoMessage = ({
|
const InfoMessage = ({
|
||||||
responseMessage,
|
responseMessage,
|
||||||
}: {
|
}: {
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
|
||||||
import { useSetAtom } from "jotai";
|
import { useSetAtom } from "jotai";
|
||||||
import { mapBoundsAtom } from "@/app/atoms";
|
|
||||||
import L from "leaflet";
|
import L from "leaflet";
|
||||||
import { useMapEvent } from "react-leaflet";
|
import { useMapEvent } from "react-leaflet";
|
||||||
|
|
||||||
|
import { mapBoundsAtom } from "@/app/atoms";
|
||||||
|
|
||||||
const MapEvents = () => {
|
const MapEvents = () => {
|
||||||
const setMapBounds = useSetAtom(mapBoundsAtom);
|
const setMapBounds = useSetAtom(mapBoundsAtom);
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import Link from "next-intl/link";
|
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
|
import Link from "next-intl/link";
|
||||||
|
|
||||||
import Hamburger from "./Hamburger";
|
import Hamburger from "./Hamburger";
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import { NextIntlClientProvider, AbstractIntlMessages } from "next-intl";
|
|
||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
|
|
||||||
|
import { AbstractIntlMessages, NextIntlClientProvider } from "next-intl";
|
||||||
|
|
||||||
import "@/css/globals.css";
|
import "@/css/globals.css";
|
||||||
|
|
||||||
import Navbar from "./Navbar";
|
|
||||||
import Footer from "./Footer";
|
import Footer from "./Footer";
|
||||||
|
import Navbar from "./Navbar";
|
||||||
|
|
||||||
const TestableLayout = ({
|
const TestableLayout = ({
|
||||||
children,
|
children,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
import useDarkMode from "@/hooks/useDarkMode";
|
import useDarkMode from "@/hooks/useDarkMode";
|
||||||
|
|
||||||
const ThemeSwitcher = () => {
|
const ThemeSwitcher = () => {
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
import useContactForm from "@/hooks/useContactForm";
|
|
||||||
import { handleEmailSubmit } from "@/handlers/formHandlers";
|
|
||||||
|
|
||||||
import InfoMessage from "@/app/[lang]/components/InfoMessage";
|
import InfoMessage from "@/app/[lang]/components/InfoMessage";
|
||||||
|
import { handleEmailSubmit } from "@/handlers/formHandlers";
|
||||||
|
import useContactForm from "@/hooks/useContactForm";
|
||||||
|
|
||||||
const ContactForm = () => {
|
const ContactForm = () => {
|
||||||
const t = useTranslations("Contact");
|
const t = useTranslations("Contact");
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
import Script from "next/script";
|
|
||||||
import { Inter, Julius_Sans_One } from "next/font/google";
|
|
||||||
import { useLocale, NextIntlClientProvider } from "next-intl";
|
|
||||||
import { getTranslator } from "next-intl/server";
|
|
||||||
import { notFound } from "next/navigation";
|
|
||||||
import { ReactNode } from "react";
|
import { ReactNode } from "react";
|
||||||
|
|
||||||
|
import { NextIntlClientProvider, useLocale } from "next-intl";
|
||||||
|
import { getTranslator } from "next-intl/server";
|
||||||
|
import { Inter, Julius_Sans_One } from "next/font/google";
|
||||||
|
import { notFound } from "next/navigation";
|
||||||
|
import Script from "next/script";
|
||||||
|
|
||||||
import "@/css/globals.css";
|
import "@/css/globals.css";
|
||||||
|
|
||||||
import Providers from "./providers";
|
|
||||||
import Navbar from "./components/Navbar";
|
|
||||||
import Footer from "./components/Footer";
|
import Footer from "./components/Footer";
|
||||||
|
import Navbar from "./components/Navbar";
|
||||||
|
import Providers from "./providers";
|
||||||
|
|
||||||
const inter = Inter({ subsets: ["latin"], variable: "--font-inter" });
|
const inter = Inter({ subsets: ["latin"], variable: "--font-inter" });
|
||||||
const title = Julius_Sans_One({
|
const title = Julius_Sans_One({
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
import Link from "next/link";
|
|
||||||
import Image from "next/image";
|
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
|
import Image from "next/image";
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
import bgImage from "@/public/images/map-bg.jpg";
|
import bgImage from "@/public/images/map-bg.jpg";
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import Link from "next-intl/link";
|
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
|
import Link from "next-intl/link";
|
||||||
|
|
||||||
export default function About() {
|
export default function About() {
|
||||||
const t = useTranslations("About");
|
const t = useTranslations("About");
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import { useMap } from "react-leaflet";
|
|
||||||
import { useEffect, useMemo } from "react";
|
import { useEffect, useMemo } from "react";
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import L from "leaflet";
|
|
||||||
import { useAtomValue } from "jotai";
|
|
||||||
|
|
||||||
import { TimeControl } from "@/types";
|
import { useAtomValue } from "jotai";
|
||||||
|
import L from "leaflet";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
import { useMap } from "react-leaflet";
|
||||||
|
|
||||||
import { filteredTournamentsByTimeControlAtom } from "@/app/atoms";
|
import { filteredTournamentsByTimeControlAtom } from "@/app/atoms";
|
||||||
import { TimeControlColours } from "@/app/constants";
|
import { TimeControlColours } from "@/app/constants";
|
||||||
|
import { TimeControl } from "@/types";
|
||||||
|
|
||||||
const Legend = () => {
|
const Legend = () => {
|
||||||
const t = useTranslations("Tournaments");
|
const t = useTranslations("Tournaments");
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { ScrollableElement } from "@/types";
|
import { useEffect, useRef, useState } from "react";
|
||||||
|
|
||||||
import { FaArrowUp } from "react-icons/fa";
|
import { FaArrowUp } from "react-icons/fa";
|
||||||
|
|
||||||
import { handleScrollToTop } from "@/handlers/scrollHandlers";
|
import { handleScrollToTop } from "@/handlers/scrollHandlers";
|
||||||
import { useEffect, useRef, useState } from "react";
|
|
||||||
import { useBreakpoint } from "@/hooks/tailwind";
|
import { useBreakpoint } from "@/hooks/tailwind";
|
||||||
|
import { ScrollableElement } from "@/types";
|
||||||
|
|
||||||
const ScrollToTopButton = () => {
|
const ScrollToTopButton = () => {
|
||||||
const scrollToTopElementRef = useRef<ScrollableElement | null>(null);
|
const scrollToTopElementRef = useRef<ScrollableElement | null>(null);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { useAtom } from "jotai/index";
|
import { useAtom } from "jotai/index";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
import { IoCloseOutline } from "react-icons/io5";
|
import { IoCloseOutline } from "react-icons/io5";
|
||||||
|
|
||||||
import { searchStringAtom } from "@/app/atoms";
|
import { searchStringAtom } from "@/app/atoms";
|
||||||
|
|
||||||
const SearchBar = () => {
|
const SearchBar = () => {
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import { useAtom, useAtomValue } from "jotai";
|
import { useAtom, useAtomValue } from "jotai";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
classicAtom,
|
|
||||||
rapidAtom,
|
|
||||||
blitzAtom,
|
blitzAtom,
|
||||||
|
classicAtom,
|
||||||
otherAtom,
|
otherAtom,
|
||||||
|
rapidAtom,
|
||||||
tournamentsAtom,
|
tournamentsAtom,
|
||||||
} from "@/app/atoms";
|
} from "@/app/atoms";
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { TimeControl } from "@/types";
|
import { TimeControl } from "@/types";
|
||||||
|
|
||||||
const TimeControlFilters = () => {
|
const TimeControlFilters = () => {
|
||||||
|
|||||||
@@ -1,34 +1,32 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { TimeControl } from "@/types";
|
import { useCallback, useEffect, useMemo, useRef } from "react";
|
||||||
|
|
||||||
import { useMemo, useRef, useCallback, useEffect } from "react";
|
|
||||||
import L, { LatLngLiteral, Marker, DomUtil } from "leaflet";
|
|
||||||
import { MapContainer, TileLayer, LayerGroup } from "react-leaflet";
|
|
||||||
import MarkerClusterGroup from "react-leaflet-cluster";
|
|
||||||
import { FaAngleDoubleDown } from "react-icons/fa";
|
|
||||||
import { useAtomValue, useSetAtom } from "jotai";
|
import { useAtomValue, useSetAtom } from "jotai";
|
||||||
|
import L, { DomUtil, LatLngLiteral, Marker } from "leaflet";
|
||||||
|
import "leaflet-defaulticon-compatibility";
|
||||||
|
import "leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.css";
|
||||||
|
import "leaflet.smooth_marker_bouncing";
|
||||||
|
import "leaflet/dist/leaflet.css";
|
||||||
import { countBy, groupBy } from "lodash";
|
import { countBy, groupBy } from "lodash";
|
||||||
|
import { FaAngleDoubleDown } from "react-icons/fa";
|
||||||
import {
|
import { LayerGroup, MapContainer, TileLayer } from "react-leaflet";
|
||||||
mapBoundsAtom,
|
import MarkerClusterGroup from "react-leaflet-cluster";
|
||||||
debouncedHoveredListTournamentIdAtom,
|
|
||||||
filteredTournamentsByTimeControlAtom,
|
|
||||||
normsOnlyAtom,
|
|
||||||
} from "@/app/atoms";
|
|
||||||
import { generatePieSVG } from "@/lib/pie";
|
|
||||||
import { TimeControlColours } from "@/app/constants";
|
|
||||||
|
|
||||||
import Legend from "./Legend";
|
|
||||||
import { TournamentMarker, TournamentMarkerRef } from "./TournamentMarker";
|
|
||||||
import TimeControlFilters from "./TimeControlFilters";
|
|
||||||
|
|
||||||
import MapEvents from "@/app/[lang]/components/MapEvents";
|
import MapEvents from "@/app/[lang]/components/MapEvents";
|
||||||
|
import {
|
||||||
|
debouncedHoveredListTournamentIdAtom,
|
||||||
|
filteredTournamentsByTimeControlAtom,
|
||||||
|
mapBoundsAtom,
|
||||||
|
normsOnlyAtom,
|
||||||
|
} from "@/app/atoms";
|
||||||
|
import { TimeControlColours } from "@/app/constants";
|
||||||
|
import { generatePieSVG } from "@/lib/pie";
|
||||||
|
import { TimeControl } from "@/types";
|
||||||
|
|
||||||
import "leaflet/dist/leaflet.css";
|
import Legend from "./Legend";
|
||||||
import "leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.css";
|
import TimeControlFilters from "./TimeControlFilters";
|
||||||
import "leaflet-defaulticon-compatibility";
|
import { TournamentMarker, TournamentMarkerRef } from "./TournamentMarker";
|
||||||
import "leaflet.smooth_marker_bouncing";
|
|
||||||
|
|
||||||
// Declare a class type that adds in methods etc. defined by leaflet.smooth_marker_bouncing
|
// Declare a class type that adds in methods etc. defined by leaflet.smooth_marker_bouncing
|
||||||
// to keep Typescript happy
|
// to keep Typescript happy
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { forwardRef, useMemo, useImperativeHandle, useRef } from "react";
|
import { forwardRef, useImperativeHandle, useMemo, useRef } from "react";
|
||||||
import { Tournament } from "@/types";
|
|
||||||
import L from "leaflet";
|
import { useSetAtom } from "jotai";
|
||||||
import { Marker, Popup, MarkerProps } from "react-leaflet";
|
import L from "leaflet";
|
||||||
import { useTranslations } from "next-intl";
|
import { last } from "lodash";
|
||||||
import { useSetAtom } from "jotai";
|
import { useTranslations } from "next-intl";
|
||||||
import { FaTrophy } from "react-icons/fa";
|
import { FaTrophy } from "react-icons/fa";
|
||||||
import { last } from "lodash";
|
import { Marker, MarkerProps, Popup } from "react-leaflet";
|
||||||
|
|
||||||
import type { BouncingMarker } from "@/leafletTypes";
|
|
||||||
import { debouncedHoveredMapTournamentGroupIdAtom } from "@/app/atoms";
|
import { debouncedHoveredMapTournamentGroupIdAtom } from "@/app/atoms";
|
||||||
import { TimeControlColours } from "@/app/constants";
|
import { TimeControlColours } from "@/app/constants";
|
||||||
|
import type { BouncingMarker } from "@/leafletTypes";
|
||||||
|
import { Tournament } from "@/types";
|
||||||
|
|
||||||
export type TournamentMarkerRef = {
|
export type TournamentMarkerRef = {
|
||||||
getMarker: () => L.Marker<any>;
|
getMarker: () => L.Marker<any>;
|
||||||
|
|||||||
@@ -1,26 +1,27 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
|
||||||
|
import { useAtom, useAtomValue, useSetAtom } from "jotai";
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
import { useAtomValue, useSetAtom, useAtom } from "jotai";
|
|
||||||
import { twMerge } from "tailwind-merge";
|
|
||||||
import { FaExternalLinkAlt } from "react-icons/fa";
|
import { FaExternalLinkAlt } from "react-icons/fa";
|
||||||
import { FaTrophy } from "react-icons/fa";
|
import { FaTrophy } from "react-icons/fa";
|
||||||
import { Tooltip } from "react-tooltip";
|
import { Tooltip } from "react-tooltip";
|
||||||
|
import { twMerge } from "tailwind-merge";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
filteredTournamentsListAtom,
|
|
||||||
syncVisibleAtom,
|
|
||||||
normsOnlyAtom,
|
|
||||||
hoveredMapTournamentGroupIdAtom,
|
|
||||||
debouncedHoveredMapTournamentGroupIdAtom,
|
|
||||||
debouncedHoveredListTournamentIdAtom,
|
debouncedHoveredListTournamentIdAtom,
|
||||||
|
debouncedHoveredMapTournamentGroupIdAtom,
|
||||||
|
filteredTournamentsListAtom,
|
||||||
|
hoveredMapTournamentGroupIdAtom,
|
||||||
|
normsOnlyAtom,
|
||||||
|
syncVisibleAtom,
|
||||||
} from "@/app/atoms";
|
} from "@/app/atoms";
|
||||||
import { useBreakpoint } from "@/hooks/tailwind";
|
import { useBreakpoint } from "@/hooks/tailwind";
|
||||||
|
|
||||||
|
import ScrollToTopButton from "./ScrollToTopButton";
|
||||||
import SearchBar from "./SearchBar";
|
import SearchBar from "./SearchBar";
|
||||||
import TimeControlFilters from "./TimeControlFilters";
|
import TimeControlFilters from "./TimeControlFilters";
|
||||||
import ScrollToTopButton from "./ScrollToTopButton";
|
|
||||||
|
|
||||||
export default function TournamentTable() {
|
export default function TournamentTable() {
|
||||||
const t = useTranslations("Tournaments");
|
const t = useTranslations("Tournaments");
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
import { useHydrateAtoms } from "jotai/utils";
|
||||||
|
import dynamic from "next/dynamic";
|
||||||
|
|
||||||
|
import LoadingMap from "@/app/[lang]/components/LoadingMap";
|
||||||
|
import { tournamentsAtom } from "@/app/atoms";
|
||||||
|
import { Tournament } from "@/types";
|
||||||
|
|
||||||
|
import TournamentTable from "./TournamentTable";
|
||||||
|
|
||||||
type TournamentsDisplayProps = {
|
type TournamentsDisplayProps = {
|
||||||
tournaments: Tournament[];
|
tournaments: Tournament[];
|
||||||
};
|
};
|
||||||
|
|
||||||
import { Tournament } from "@/types";
|
|
||||||
|
|
||||||
import dynamic from "next/dynamic";
|
|
||||||
import { useHydrateAtoms } from "jotai/utils";
|
|
||||||
import { tournamentsAtom } from "@/app/atoms";
|
|
||||||
|
|
||||||
import TournamentTable from "./TournamentTable";
|
|
||||||
import LoadingMap from "@/app/[lang]/components/LoadingMap";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Imports the tournament map component, ensuring CSR only.
|
* Imports the tournament map component, ensuring CSR only.
|
||||||
* @remarks SSR is not supported by react-leaflet
|
* @remarks SSR is not supported by react-leaflet
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import clientPromise from "@/lib/mongodb";
|
import { differenceInDays, isSameDay, parse } from "date-fns";
|
||||||
|
|
||||||
import { errorLog } from "@/utils/logger";
|
|
||||||
import { Tournament, TimeControl } from "@/types";
|
|
||||||
import { groupBy } from "lodash";
|
import { groupBy } from "lodash";
|
||||||
import { parse, differenceInDays, isSameDay } from "date-fns";
|
import { ObjectId } from "mongodb";
|
||||||
|
|
||||||
|
import clientPromise from "@/lib/mongodb";
|
||||||
|
import { TimeControl, Tournament } from "@/types";
|
||||||
|
import { errorLog } from "@/utils/logger";
|
||||||
|
|
||||||
import TournamentsDisplay from "./TournamentsDisplay";
|
import TournamentsDisplay from "./TournamentsDisplay";
|
||||||
import { ObjectId } from "mongodb";
|
|
||||||
|
|
||||||
export const revalidate = 3600; // Revalidate cache every 6 hours
|
export const revalidate = 3600; // Revalidate cache every 6 hours
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import clientPromise from "@/lib/mongodb";
|
|
||||||
import { NextResponse } from "next/server";
|
import { NextResponse } from "next/server";
|
||||||
|
|
||||||
|
import clientPromise from "@/lib/mongodb";
|
||||||
import { errorLog } from "@/utils/logger";
|
import { errorLog } from "@/utils/logger";
|
||||||
|
|
||||||
export async function POST(req: Request) {
|
export async function POST(req: Request) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import NodeMailer from "nodemailer";
|
|
||||||
import { NextResponse } from "next/server";
|
import { NextResponse } from "next/server";
|
||||||
import { infoLog, errorLog } from "@/utils/logger";
|
import NodeMailer from "nodemailer";
|
||||||
|
|
||||||
|
import { errorLog, infoLog } from "@/utils/logger";
|
||||||
|
|
||||||
export async function POST(req: Request) {
|
export async function POST(req: Request) {
|
||||||
const { email, subject, message } = await req.json();
|
const { email, subject, message } = await req.json();
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
import { TimeControl, Tournament } from "@/types";
|
|
||||||
import { atom } from "jotai";
|
import { atom } from "jotai";
|
||||||
import { LatLngBounds, LatLngLiteral } from "leaflet";
|
import { LatLngBounds, LatLngLiteral } from "leaflet";
|
||||||
|
|
||||||
|
import { TimeControl, Tournament } from "@/types";
|
||||||
import atomWithDebounce from "@/utils/atomWithDebounce";
|
import atomWithDebounce from "@/utils/atomWithDebounce";
|
||||||
import { normalizedContains } from "@/utils/string";
|
import { normalizedContains } from "@/utils/string";
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,8 +1,8 @@
|
|||||||
import { TimeControl } from "@/types"
|
import { TimeControl } from "@/types";
|
||||||
|
|
||||||
export const TimeControlColours = {
|
export const TimeControlColours = {
|
||||||
[TimeControl.Classic]: "#00ac39",
|
[TimeControl.Classic]: "#00ac39",
|
||||||
[TimeControl.Rapid]: "#0086c7",
|
[TimeControl.Rapid]: "#0086c7",
|
||||||
[TimeControl.Blitz]: "#ddce20",
|
[TimeControl.Blitz]: "#ddce20",
|
||||||
[TimeControl.Other]: "#ea5f17",
|
[TimeControl.Other]: "#ea5f17",
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
import { ResponseMessage, TournamentFormProps } from "@/types";
|
|
||||||
import { LatLngLiteral } from "leaflet";
|
|
||||||
import { Dispatch, FormEvent, SetStateAction } from "react";
|
import { Dispatch, FormEvent, SetStateAction } from "react";
|
||||||
|
|
||||||
|
import { LatLngLiteral } from "leaflet";
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
import { clearMessage } from "@/app/[lang]/components/InfoMessage";
|
import { clearMessage } from "@/app/[lang]/components/InfoMessage";
|
||||||
import { errorLog } from "@/utils/logger";
|
import discordWebhook from "@/lib/discordWebhook";
|
||||||
import sendMail from "@/lib/sendMail";
|
import sendMail from "@/lib/sendMail";
|
||||||
import tournamentFormToDB from "@/lib/tournamentFormToDB";
|
import tournamentFormToDB from "@/lib/tournamentFormToDB";
|
||||||
import discordWebhook from "@/lib/discordWebhook";
|
import { ResponseMessage, TournamentFormProps } from "@/types";
|
||||||
|
import { errorLog } from "@/utils/logger";
|
||||||
|
|
||||||
export const handleClearTournamentForm = (
|
export const handleClearTournamentForm = (
|
||||||
formRefs: TournamentFormProps,
|
formRefs: TournamentFormProps,
|
||||||
|
|||||||
+24
-7
@@ -1,11 +1,15 @@
|
|||||||
import { useLayoutEffect, useEffect, useState, useRef, useMemo } from "react";
|
import { useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
||||||
|
|
||||||
import resolveConfig from "tailwindcss/resolveConfig";
|
import resolveConfig from "tailwindcss/resolveConfig";
|
||||||
|
|
||||||
import tailwindConfig from "@/tailwind.config.js";
|
import tailwindConfig from "@/tailwind.config.js";
|
||||||
|
|
||||||
const config = resolveConfig(tailwindConfig);
|
const config = resolveConfig(tailwindConfig);
|
||||||
|
|
||||||
const isSSR =
|
const isSSR =
|
||||||
typeof window === "undefined" || !window.navigator || /ServerSideRendering|^Deno\//.test(window.navigator.userAgent);
|
typeof window === "undefined" ||
|
||||||
|
!window.navigator ||
|
||||||
|
/ServerSideRendering|^Deno\//.test(window.navigator.userAgent);
|
||||||
|
|
||||||
const isBrowser = !isSSR;
|
const isBrowser = !isSSR;
|
||||||
const useIsomorphicEffect = isBrowser ? useLayoutEffect : useEffect;
|
const useIsomorphicEffect = isBrowser ? useLayoutEffect : useEffect;
|
||||||
@@ -18,7 +22,9 @@ export type CreatorReturnType = {
|
|||||||
|
|
||||||
function create(screens: object | undefined) {
|
function create(screens: object | undefined) {
|
||||||
if (!screens) {
|
if (!screens) {
|
||||||
throw new Error("Failed to create breakpoint hooks, given `screens` value is invalid.");
|
throw new Error(
|
||||||
|
"Failed to create breakpoint hooks, given `screens` value is invalid.",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function useBreakpoint(breakpoint: string, defaultValue: boolean = false) {
|
function useBreakpoint(breakpoint: string, defaultValue: boolean = false) {
|
||||||
@@ -46,15 +52,25 @@ function create(screens: object | undefined) {
|
|||||||
return match;
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
function useBreakpointEffect<Breakpoint extends string>(breakpoint: Breakpoint, effect: (match: boolean) => void) {
|
function useBreakpointEffect<Breakpoint extends string>(
|
||||||
|
breakpoint: Breakpoint,
|
||||||
|
effect: (match: boolean) => void,
|
||||||
|
) {
|
||||||
const match = useBreakpoint(breakpoint);
|
const match = useBreakpoint(breakpoint);
|
||||||
useEffect(() => effect(match));
|
useEffect(() => effect(match));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function useBreakpointValue<Breakpoint extends string, T, U>(breakpoint: Breakpoint, valid: T, invalid: U) {
|
function useBreakpointValue<Breakpoint extends string, T, U>(
|
||||||
|
breakpoint: Breakpoint,
|
||||||
|
valid: T,
|
||||||
|
invalid: U,
|
||||||
|
) {
|
||||||
const match = useBreakpoint(breakpoint);
|
const match = useBreakpoint(breakpoint);
|
||||||
const value = useMemo(() => (match ? valid : invalid), [invalid, match, valid]);
|
const value = useMemo(
|
||||||
|
() => (match ? valid : invalid),
|
||||||
|
[invalid, match, valid],
|
||||||
|
);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,4 +81,5 @@ function create(screens: object | undefined) {
|
|||||||
} as CreatorReturnType;
|
} as CreatorReturnType;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const { useBreakpoint, useBreakpointEffect, useBreakpointValue } = create(config.theme!.screens);
|
export const { useBreakpoint, useBreakpointEffect, useBreakpointValue } =
|
||||||
|
create(config.theme!.screens);
|
||||||
|
|||||||
@@ -1,31 +1,36 @@
|
|||||||
export const useDynamicViewportUnits = () => {
|
export const useDynamicViewportUnits = () => {
|
||||||
const setVh = function () {
|
const setVh = function () {
|
||||||
var svh = document.documentElement.clientHeight * 0.01;
|
var svh = document.documentElement.clientHeight * 0.01;
|
||||||
document.documentElement.style.setProperty('--1svh', (svh + "px"));
|
document.documentElement.style.setProperty("--1svh", svh + "px");
|
||||||
var dvh = window.innerHeight * 0.01;
|
var dvh = window.innerHeight * 0.01;
|
||||||
document.documentElement.style.setProperty('--1dvh', (dvh + "px"));
|
document.documentElement.style.setProperty("--1dvh", dvh + "px");
|
||||||
};
|
};
|
||||||
|
|
||||||
const isMobile = function() {
|
const isMobile = function () {
|
||||||
if(/Android|iPhone|iPad|iPod/i.test(navigator.userAgent) || (navigator.userAgent.match(/Mac/) && navigator.maxTouchPoints && navigator.maxTouchPoints > 2)) {
|
if (
|
||||||
return true;
|
/Android|iPhone|iPad|iPod/i.test(navigator.userAgent) ||
|
||||||
|
(navigator.userAgent.match(/Mac/) &&
|
||||||
|
navigator.maxTouchPoints &&
|
||||||
|
navigator.maxTouchPoints > 2)
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
// SSR support
|
// SSR support
|
||||||
if (typeof window === 'undefined') {
|
if (typeof window === "undefined") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't run polyfill if browser supports the units natively
|
// Don't run polyfill if browser supports the units natively
|
||||||
if ('CSS' in window &&
|
if (
|
||||||
'supports' in window.CSS &&
|
"CSS" in window &&
|
||||||
window.CSS.supports('height: 100svh') &&
|
"supports" in window.CSS &&
|
||||||
window.CSS.supports('height: 100dvh') &&
|
window.CSS.supports("height: 100svh") &&
|
||||||
window.CSS.supports('height: 100lvh')
|
window.CSS.supports("height: 100dvh") &&
|
||||||
|
window.CSS.supports("height: 100lvh")
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -35,10 +40,10 @@ export const useDynamicViewportUnits = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener('resize', setVh);
|
window.addEventListener("resize", setVh);
|
||||||
setVh();
|
setVh();
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener('resize', setVh);
|
window.removeEventListener("resize", setVh);
|
||||||
}
|
};
|
||||||
}
|
};
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { Dispatch, RefObject, SetStateAction, useEffect } from "react";
|
||||||
|
|
||||||
interface HamburgerClose {
|
interface HamburgerClose {
|
||||||
menuVisible: boolean;
|
menuVisible: boolean;
|
||||||
setMenuVisible: Dispatch<SetStateAction<boolean>>;
|
setMenuVisible: Dispatch<SetStateAction<boolean>>;
|
||||||
@@ -9,8 +11,6 @@ interface HamburgerClose {
|
|||||||
menuTimeout: () => void;
|
menuTimeout: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
import { Dispatch, RefObject, SetStateAction, useEffect } from "react";
|
|
||||||
|
|
||||||
const useHamburgerClose = ({
|
const useHamburgerClose = ({
|
||||||
menuVisible,
|
menuVisible,
|
||||||
setMenuVisible,
|
setMenuVisible,
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import { TournamentFormProps } from "@/types";
|
|
||||||
import { useRef, useState } from "react";
|
import { useRef, useState } from "react";
|
||||||
import { LatLngLiteral } from "leaflet";
|
|
||||||
import { useAtomValue } from "jotai";
|
import { useAtomValue } from "jotai";
|
||||||
|
import { LatLngLiteral } from "leaflet";
|
||||||
|
|
||||||
import { franceCenterAtom } from "@/app/atoms";
|
import { franceCenterAtom } from "@/app/atoms";
|
||||||
|
import { TournamentFormProps } from "@/types";
|
||||||
|
|
||||||
export const useTournamentForm = (): TournamentFormProps => {
|
export const useTournamentForm = (): TournamentFormProps => {
|
||||||
const center = useAtomValue(franceCenterAtom);
|
const center = useAtomValue(franceCenterAtom);
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import { Marker } from "leaflet";
|
import { Marker } from "leaflet";
|
||||||
|
|
||||||
declare class BouncingOptions {
|
declare class BouncingOptions {
|
||||||
bounceHeight: number;
|
bounceHeight: number;
|
||||||
|
|||||||
+28
-12
@@ -3,11 +3,11 @@ function round(n: number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function polarToCartesian(radius: number, angleInDegrees: number) {
|
function polarToCartesian(radius: number, angleInDegrees: number) {
|
||||||
var radians = (angleInDegrees - 90) * Math.PI / 180;
|
var radians = ((angleInDegrees - 90) * Math.PI) / 180;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
x: round(radius + (radius * Math.cos(radians))),
|
x: round(radius + radius * Math.cos(radians)),
|
||||||
y: round(radius + (radius * Math.sin(radians)))
|
y: round(radius + radius * Math.sin(radians)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,8 +21,17 @@ function getDAttribute(radius: number, startAngle: number, endAngle: number) {
|
|||||||
|
|
||||||
const largeArcFlag = endAngle - startAngle <= 180 ? 0 : 1;
|
const largeArcFlag = endAngle - startAngle <= 180 ? 0 : 1;
|
||||||
const d = [
|
const d = [
|
||||||
"M", start.x, start.y,
|
"M",
|
||||||
"A", radius, radius, 0, largeArcFlag, 1, end.x, end.y
|
start.x,
|
||||||
|
start.y,
|
||||||
|
"A",
|
||||||
|
radius,
|
||||||
|
radius,
|
||||||
|
0,
|
||||||
|
largeArcFlag,
|
||||||
|
1,
|
||||||
|
end.x,
|
||||||
|
end.y,
|
||||||
];
|
];
|
||||||
|
|
||||||
if (isCircle) {
|
if (isCircle) {
|
||||||
@@ -37,32 +46,39 @@ function path(d: string, colour: string) {
|
|||||||
return `<path d='${d}' style="fill: ${colour}" />`;
|
return `<path d='${d}' style="fill: ${colour}" />`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function svg(className: string, width: number, content: string ) {
|
function svg(className: string, width: number, content: string) {
|
||||||
return `<svg class="${className}" viewBox="0 0 ${width} ${width}"><g class='pie'>${content}</g></svg>`;
|
return `<svg class="${className}" viewBox="0 0 ${width} ${width}"><g class='pie'>${content}</g></svg>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
type PieSlice = {
|
type PieSlice = {
|
||||||
value: number;
|
value: number;
|
||||||
colour: string;
|
colour: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export function generatePieSVG(className: string, radius: number, values: PieSlice[]) {
|
export function generatePieSVG(
|
||||||
|
className: string,
|
||||||
|
radius: number,
|
||||||
|
values: PieSlice[],
|
||||||
|
) {
|
||||||
type Sector = {
|
type Sector = {
|
||||||
colour: string;
|
colour: string;
|
||||||
degrees: number;
|
degrees: number;
|
||||||
from?: number;
|
from?: number;
|
||||||
to?: number;
|
to?: number;
|
||||||
}
|
};
|
||||||
|
|
||||||
const total = values.reduce((a, b) => a + b.value, 0);
|
const total = values.reduce((a, b) => a + b.value, 0);
|
||||||
const data: Sector[] = values.map(({ value, colour }) => ({ colour, degrees: value / total * 360 }));
|
const data: Sector[] = values.map(({ value, colour }) => ({
|
||||||
|
colour,
|
||||||
|
degrees: (value / total) * 360,
|
||||||
|
}));
|
||||||
|
|
||||||
const paths = data.reduce<[number, string][]>((prev, value, i) => {
|
const paths = data.reduce<[number, string][]>((prev, value, i) => {
|
||||||
const from = i === 0 ? 0 : prev[i - 1][0];
|
const from = i === 0 ? 0 : prev[i - 1][0];
|
||||||
const to = from + value.degrees;
|
const to = from + value.degrees;
|
||||||
|
|
||||||
return [...prev, [to, path(getDAttribute(radius, from, to ), value.colour)]];
|
return [...prev, [to, path(getDAttribute(radius, from, to), value.colour)]];
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return svg(className, radius * 2, paths.map(([to, path]) => path) .join(''));
|
return svg(className, radius * 2, paths.map(([to, path]) => path).join(""));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { LatLngLiteral } from "leaflet";
|
import { LatLngLiteral } from "leaflet";
|
||||||
|
|
||||||
import { TournamentFormProps } from "@/types";
|
import { TournamentFormProps } from "@/types";
|
||||||
import formatDate from "@/utils/formatDate";
|
import formatDate from "@/utils/formatDate";
|
||||||
|
|
||||||
|
|||||||
Generated
+312
-26
@@ -10,6 +10,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@kodingdotninja/use-tailwind-breakpoint": "^0.0.5",
|
"@kodingdotninja/use-tailwind-breakpoint": "^0.0.5",
|
||||||
"@next/bundle-analyzer": "^13.4.12",
|
"@next/bundle-analyzer": "^13.4.12",
|
||||||
|
"@trivago/prettier-plugin-sort-imports": "^4.2.0",
|
||||||
"@types/node": "20.5.1",
|
"@types/node": "20.5.1",
|
||||||
"@types/react": "18.2.21",
|
"@types/react": "18.2.21",
|
||||||
"@types/react-dom": "18.2.7",
|
"@types/react-dom": "18.2.7",
|
||||||
@@ -82,34 +83,198 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/code-frame": {
|
"node_modules/@babel/code-frame": {
|
||||||
"version": "7.22.5",
|
"version": "7.22.13",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
|
||||||
"integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==",
|
"integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/highlight": "^7.22.5"
|
"@babel/highlight": "^7.22.13",
|
||||||
|
"chalk": "^2.4.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/helper-validator-identifier": {
|
"node_modules/@babel/code-frame/node_modules/ansi-styles": {
|
||||||
|
"version": "3.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||||
|
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||||
|
"dependencies": {
|
||||||
|
"color-convert": "^1.9.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/code-frame/node_modules/chalk": {
|
||||||
|
"version": "2.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||||
|
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-styles": "^3.2.1",
|
||||||
|
"escape-string-regexp": "^1.0.5",
|
||||||
|
"supports-color": "^5.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/code-frame/node_modules/color-convert": {
|
||||||
|
"version": "1.9.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||||
|
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||||
|
"dependencies": {
|
||||||
|
"color-name": "1.1.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/code-frame/node_modules/color-name": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||||
|
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
|
||||||
|
},
|
||||||
|
"node_modules/@babel/code-frame/node_modules/escape-string-regexp": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||||
|
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/code-frame/node_modules/has-flag": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/code-frame/node_modules/supports-color": {
|
||||||
|
"version": "5.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||||
|
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||||
|
"dependencies": {
|
||||||
|
"has-flag": "^3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/generator": {
|
||||||
|
"version": "7.17.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.7.tgz",
|
||||||
|
"integrity": "sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/types": "^7.17.0",
|
||||||
|
"jsesc": "^2.5.1",
|
||||||
|
"source-map": "^0.5.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/helper-environment-visitor": {
|
||||||
"version": "7.22.5",
|
"version": "7.22.5",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
|
||||||
"integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==",
|
"integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==",
|
||||||
"dev": true,
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/helper-function-name": {
|
||||||
|
"version": "7.22.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz",
|
||||||
|
"integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/template": "^7.22.5",
|
||||||
|
"@babel/types": "^7.22.5"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/helper-function-name/node_modules/@babel/types": {
|
||||||
|
"version": "7.22.17",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
|
||||||
|
"integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/helper-string-parser": "^7.22.5",
|
||||||
|
"@babel/helper-validator-identifier": "^7.22.15",
|
||||||
|
"to-fast-properties": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/helper-hoist-variables": {
|
||||||
|
"version": "7.22.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
|
||||||
|
"integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/types": "^7.22.5"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/helper-hoist-variables/node_modules/@babel/types": {
|
||||||
|
"version": "7.22.17",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
|
||||||
|
"integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/helper-string-parser": "^7.22.5",
|
||||||
|
"@babel/helper-validator-identifier": "^7.22.15",
|
||||||
|
"to-fast-properties": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/helper-split-export-declaration": {
|
||||||
|
"version": "7.22.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
|
||||||
|
"integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/types": "^7.22.5"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/helper-split-export-declaration/node_modules/@babel/types": {
|
||||||
|
"version": "7.22.17",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
|
||||||
|
"integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/helper-string-parser": "^7.22.5",
|
||||||
|
"@babel/helper-validator-identifier": "^7.22.15",
|
||||||
|
"to-fast-properties": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/helper-string-parser": {
|
||||||
|
"version": "7.22.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
|
||||||
|
"integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/helper-validator-identifier": {
|
||||||
|
"version": "7.22.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
|
||||||
|
"integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/highlight": {
|
"node_modules/@babel/highlight": {
|
||||||
"version": "7.22.5",
|
"version": "7.22.13",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz",
|
||||||
"integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==",
|
"integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-validator-identifier": "^7.22.5",
|
"@babel/helper-validator-identifier": "^7.22.5",
|
||||||
"chalk": "^2.0.0",
|
"chalk": "^2.4.2",
|
||||||
"js-tokens": "^4.0.0"
|
"js-tokens": "^4.0.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -120,7 +285,6 @@
|
|||||||
"version": "3.2.1",
|
"version": "3.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"color-convert": "^1.9.0"
|
"color-convert": "^1.9.0"
|
||||||
},
|
},
|
||||||
@@ -132,7 +296,6 @@
|
|||||||
"version": "2.4.2",
|
"version": "2.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ansi-styles": "^3.2.1",
|
"ansi-styles": "^3.2.1",
|
||||||
"escape-string-regexp": "^1.0.5",
|
"escape-string-regexp": "^1.0.5",
|
||||||
@@ -146,7 +309,6 @@
|
|||||||
"version": "1.9.3",
|
"version": "1.9.3",
|
||||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"color-name": "1.1.3"
|
"color-name": "1.1.3"
|
||||||
}
|
}
|
||||||
@@ -154,14 +316,12 @@
|
|||||||
"node_modules/@babel/highlight/node_modules/color-name": {
|
"node_modules/@babel/highlight/node_modules/color-name": {
|
||||||
"version": "1.1.3",
|
"version": "1.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||||
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
|
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/@babel/highlight/node_modules/escape-string-regexp": {
|
"node_modules/@babel/highlight/node_modules/escape-string-regexp": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||||
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
|
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
}
|
}
|
||||||
@@ -170,7 +330,6 @@
|
|||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||||
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
|
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
@@ -179,7 +338,6 @@
|
|||||||
"version": "5.5.0",
|
"version": "5.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"has-flag": "^3.0.0"
|
"has-flag": "^3.0.0"
|
||||||
},
|
},
|
||||||
@@ -187,6 +345,17 @@
|
|||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@babel/parser": {
|
||||||
|
"version": "7.22.16",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz",
|
||||||
|
"integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==",
|
||||||
|
"bin": {
|
||||||
|
"parser": "bin/babel-parser.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@babel/runtime": {
|
"node_modules/@babel/runtime": {
|
||||||
"version": "7.22.6",
|
"version": "7.22.6",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz",
|
||||||
@@ -198,6 +367,72 @@
|
|||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@babel/template": {
|
||||||
|
"version": "7.22.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
|
||||||
|
"integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/code-frame": "^7.22.13",
|
||||||
|
"@babel/parser": "^7.22.15",
|
||||||
|
"@babel/types": "^7.22.15"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/template/node_modules/@babel/types": {
|
||||||
|
"version": "7.22.17",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
|
||||||
|
"integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/helper-string-parser": "^7.22.5",
|
||||||
|
"@babel/helper-validator-identifier": "^7.22.15",
|
||||||
|
"to-fast-properties": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/traverse": {
|
||||||
|
"version": "7.17.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz",
|
||||||
|
"integrity": "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/code-frame": "^7.16.7",
|
||||||
|
"@babel/generator": "^7.17.3",
|
||||||
|
"@babel/helper-environment-visitor": "^7.16.7",
|
||||||
|
"@babel/helper-function-name": "^7.16.7",
|
||||||
|
"@babel/helper-hoist-variables": "^7.16.7",
|
||||||
|
"@babel/helper-split-export-declaration": "^7.16.7",
|
||||||
|
"@babel/parser": "^7.17.3",
|
||||||
|
"@babel/types": "^7.17.0",
|
||||||
|
"debug": "^4.1.0",
|
||||||
|
"globals": "^11.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/traverse/node_modules/globals": {
|
||||||
|
"version": "11.12.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
|
||||||
|
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@babel/types": {
|
||||||
|
"version": "7.17.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz",
|
||||||
|
"integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/helper-validator-identifier": "^7.16.7",
|
||||||
|
"to-fast-properties": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@eslint-community/eslint-utils": {
|
"node_modules/@eslint-community/eslint-utils": {
|
||||||
"version": "4.4.0",
|
"version": "4.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
|
||||||
@@ -815,6 +1050,28 @@
|
|||||||
"react-dom": "^18.0.0"
|
"react-dom": "^18.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@trivago/prettier-plugin-sort-imports": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-YBepjbt+ZNBVmN3ev1amQH3lWCmHyt5qTbLCp/syXJRu/Kw2koXh44qayB1gMRxcL/gV8egmjN5xWSrYyfUtyw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/generator": "7.17.7",
|
||||||
|
"@babel/parser": "^7.20.5",
|
||||||
|
"@babel/traverse": "7.17.3",
|
||||||
|
"@babel/types": "7.17.0",
|
||||||
|
"javascript-natural-sort": "0.7.1",
|
||||||
|
"lodash": "^4.17.21"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@vue/compiler-sfc": "3.x",
|
||||||
|
"prettier": "2.x - 3.x"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@vue/compiler-sfc": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/aria-query": {
|
"node_modules/@types/aria-query": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.1.tgz",
|
||||||
@@ -1725,7 +1982,6 @@
|
|||||||
"version": "4.3.4",
|
"version": "4.3.4",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ms": "2.1.2"
|
"ms": "2.1.2"
|
||||||
},
|
},
|
||||||
@@ -3584,6 +3840,11 @@
|
|||||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/javascript-natural-sort": {
|
||||||
|
"version": "0.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz",
|
||||||
|
"integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw=="
|
||||||
|
},
|
||||||
"node_modules/jiti": {
|
"node_modules/jiti": {
|
||||||
"version": "1.19.1",
|
"version": "1.19.1",
|
||||||
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.19.1.tgz",
|
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.19.1.tgz",
|
||||||
@@ -3625,6 +3886,17 @@
|
|||||||
"js-yaml": "bin/js-yaml.js"
|
"js-yaml": "bin/js-yaml.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/jsesc": {
|
||||||
|
"version": "2.5.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
|
||||||
|
"integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
|
||||||
|
"bin": {
|
||||||
|
"jsesc": "bin/jsesc"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/json-schema-traverse": {
|
"node_modules/json-schema-traverse": {
|
||||||
"version": "0.4.1",
|
"version": "0.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||||
@@ -3942,8 +4214,7 @@
|
|||||||
"node_modules/ms": {
|
"node_modules/ms": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/mz": {
|
"node_modules/mz": {
|
||||||
"version": "2.7.0",
|
"version": "2.7.0",
|
||||||
@@ -4663,7 +4934,6 @@
|
|||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz",
|
||||||
"integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==",
|
"integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==",
|
||||||
"dev": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"prettier": "bin/prettier.cjs"
|
"prettier": "bin/prettier.cjs"
|
||||||
},
|
},
|
||||||
@@ -5416,6 +5686,14 @@
|
|||||||
"npm": ">= 3.0.0"
|
"npm": ">= 3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/source-map": {
|
||||||
|
"version": "0.5.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
|
||||||
|
"integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/source-map-js": {
|
"node_modules/source-map-js": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
||||||
@@ -5802,6 +6080,14 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/to-fast-properties": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/to-regex-range": {
|
"node_modules/to-regex-range": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||||
|
|||||||
+4
-1
@@ -6,11 +6,14 @@
|
|||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
"build": "ANALYZE=true next build",
|
"build": "ANALYZE=true next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"lint": "next lint"
|
"lint": "next lint",
|
||||||
|
"format": "prettier --check \"**/*.{js,jsx,ts,tsx}\"",
|
||||||
|
"format:fix": "prettier --write \"**/*.{js,jsx,ts,tsx}\""
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@kodingdotninja/use-tailwind-breakpoint": "^0.0.5",
|
"@kodingdotninja/use-tailwind-breakpoint": "^0.0.5",
|
||||||
"@next/bundle-analyzer": "^13.4.12",
|
"@next/bundle-analyzer": "^13.4.12",
|
||||||
|
"@trivago/prettier-plugin-sort-imports": "^4.2.0",
|
||||||
"@types/node": "20.5.1",
|
"@types/node": "20.5.1",
|
||||||
"@types/react": "18.2.21",
|
"@types/react": "18.2.21",
|
||||||
"@types/react-dom": "18.2.7",
|
"@types/react-dom": "18.2.7",
|
||||||
|
|||||||
+24
-18
@@ -9,35 +9,41 @@ module.exports = {
|
|||||||
theme: {
|
theme: {
|
||||||
extend: {
|
extend: {
|
||||||
fontFamily: {
|
fontFamily: {
|
||||||
sans: ['var(--font-inter)'],
|
sans: ["var(--font-inter)"],
|
||||||
title: ['var(--font-title)'],
|
title: ["var(--font-title)"],
|
||||||
},
|
},
|
||||||
colors: {
|
colors: {
|
||||||
'primary': {
|
primary: {
|
||||||
DEFAULT: '#0086C7',
|
DEFAULT: "#0086C7",
|
||||||
50: '#A8E3FF',
|
50: "#A8E3FF",
|
||||||
100: '#94DCFF',
|
100: "#94DCFF",
|
||||||
200: '#6BCFFF',
|
200: "#6BCFFF",
|
||||||
300: '#42C1FF',
|
300: "#42C1FF",
|
||||||
400: '#1AB4FF',
|
400: "#1AB4FF",
|
||||||
500: '#00A1F0',
|
500: "#00A1F0",
|
||||||
600: '#0086C7',
|
600: "#0086C7",
|
||||||
700: '#00608F',
|
700: "#00608F",
|
||||||
800: '#003A57',
|
800: "#003A57",
|
||||||
900: '#00151F',
|
900: "#00151F",
|
||||||
950: '#000203'
|
950: "#000203",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
minHeight: {
|
minHeight: {
|
||||||
// We use 100svh, falling back to the the --1svh var that we add as a polyfill for older browsers.
|
// We use 100svh, falling back to the the --1svh var that we add as a polyfill for older browsers.
|
||||||
// The 9rem is for the header and footer.
|
// The 9rem is for the header and footer.
|
||||||
// In the event that the polyfill fails, we fall back to 0.9vh as a guess of how much 1svh is.
|
// In the event that the polyfill fails, we fall back to 0.9vh as a guess of how much 1svh is.
|
||||||
content: ["calc(var(--1svh, 0.9vh) * 100 - 9rem)", "calc(100svh - 9rem)"],
|
content: [
|
||||||
|
"calc(var(--1svh, 0.9vh) * 100 - 9rem)",
|
||||||
|
"calc(100svh - 9rem)",
|
||||||
|
],
|
||||||
},
|
},
|
||||||
height: {
|
height: {
|
||||||
content: ["calc(var(--1svh, 0.9vh) * 100 - 9rem)", "calc(100svh - 9rem)"],
|
content: [
|
||||||
|
"calc(var(--1svh, 0.9vh) * 100 - 9rem)",
|
||||||
|
"calc(100svh - 9rem)",
|
||||||
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [require('@tailwindcss/forms')],
|
plugins: [require("@tailwindcss/forms")],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { LatLngLiteral } from "leaflet";
|
|
||||||
import { Dispatch, MutableRefObject, SetStateAction } from "react";
|
import { Dispatch, MutableRefObject, SetStateAction } from "react";
|
||||||
|
|
||||||
|
import { LatLngLiteral } from "leaflet";
|
||||||
|
|
||||||
export enum TimeControl {
|
export enum TimeControl {
|
||||||
Classic = "Classic",
|
Classic = "Classic",
|
||||||
Rapid = "Rapid",
|
Rapid = "Rapid",
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { atom, SetStateAction } from "jotai";
|
import { SetStateAction, atom } from "jotai";
|
||||||
|
|
||||||
export default function atomWithDebounce<T>(
|
export default function atomWithDebounce<T>(
|
||||||
initialValue: T,
|
initialValue: T,
|
||||||
@@ -37,9 +37,14 @@ export default function atomWithDebounce<T>(
|
|||||||
|
|
||||||
onDebounceStart();
|
onDebounceStart();
|
||||||
|
|
||||||
const nextTimeoutId = setTimeout(() => {
|
const nextTimeoutId = setTimeout(
|
||||||
onDebounceEnd();
|
() => {
|
||||||
}, nextValue === initialValue ? delayOnResetMilliseconds : delayMilliseconds);
|
onDebounceEnd();
|
||||||
|
},
|
||||||
|
nextValue === initialValue
|
||||||
|
? delayOnResetMilliseconds
|
||||||
|
: delayMilliseconds,
|
||||||
|
);
|
||||||
|
|
||||||
// set previous timeout atom in case it needs to get cleared
|
// set previous timeout atom in case it needs to get cleared
|
||||||
set(prevTimeoutAtom, nextTimeoutId);
|
set(prevTimeoutAtom, nextTimeoutId);
|
||||||
|
|||||||
Reference in New Issue
Block a user