Add locale support (#228)

This commit is contained in:
Luke Vella 2022-07-21 12:12:35 +01:00 committed by GitHub
parent 800af20132
commit 416a17c5b7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
47 changed files with 967 additions and 467 deletions

View file

@ -93,6 +93,10 @@ yarn start
If you would like to contribute to the development of the project please reach out first before spending significant time on it.
### Translators 🇫🇷 🇩🇪 🇮🇹 🇪🇸
If you'd like to volunteer to translate Rallly to another language, check out our [guide for translators](https://github.com/lukevella/rallly/wiki/Guide-for-translators).
## 👮‍♂️ License
Rallly is open-source under the GNU Affero General Public License Version 3 (AGPLv3) or any later version. See [LICENSE](LICENSE) for more detail.

View file

@ -1,11 +1,13 @@
import "react-i18next";
import app from "~/public/locales/en/app.json";
import common from "~/public/locales/en/common.json";
import homepage from "~/public/locales/en/homepage.json";
declare module "next-i18next" {
interface Resources {
homepage: typeof homepage;
app: typeof app;
common: typeof common;
}
}

View file

@ -3,7 +3,7 @@ const path = require("path");
module.exports = {
i18n: {
defaultLocale: "en",
locales: ["en"],
locales: ["en", "de"],
localePath: path.resolve("./public/locales"),
reloadOnPrerender: process.env.NODE_ENV === "development",
},

View file

@ -35,7 +35,7 @@
"js-cookie": "^3.0.1",
"lodash": "^4.17.21",
"nanoid": "^3.1.30",
"next": "^12.1.4",
"next": "^12.2.2",
"next-i18next": "^10.5.0",
"next-plausible": "^3.1.9",
"nodemailer": "^6.7.2",
@ -43,7 +43,6 @@
"react": "17.0.2",
"react-big-calendar": "^0.38.9",
"react-dom": "17.0.2",
"react-github-btn": "^1.2.2",
"react-hook-form": "^7.31.3",
"react-hot-toast": "^2.2.0",
"react-i18next": "^11.16.9",
@ -70,7 +69,7 @@
"@typescript-eslint/parser": "^5.21.0",
"autoprefixer": "^10.4.2",
"eslint": "^7.26.0",
"eslint-config-next": "12.1.0",
"eslint-config-next": "^12.2.2",
"eslint-import-resolver-typescript": "^2.7.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-react": "^7.23.2",

129
public/locales/de/app.json Normal file
View file

@ -0,0 +1,129 @@
{
"12h": "12 Stunden",
"24h": "24 Stunden",
"addTimeOption": "Uhrzeit hinzufügen",
"applyToAllDates": "Auf alle Termine anwenden",
"areYouSure": "Bist du sicher?",
"back": "Zurück",
"blog": "Blog",
"calendarHelp": "Du kannst keine Umfrage ohne Optionen erstellen. Füge mindestens eine Option hinzu, um fortzufahren.",
"calendarHelpTitle": "Irgendwas vergessen?",
"cancel": "Abbrechen",
"comment": "Kommentieren",
"commentPlaceholder": "Kommentar zu dieser Umfrage hinterlassen (für jeden sichtbar)",
"comments": "Kommentare",
"continue": "Weiter",
"copied": "Kopiert",
"copyLink": "Link kopieren",
"createdBy": "von <b>{{name}}</b>",
"createPoll": "Umfrage erstellen",
"creatingDemo": "Demo-Umfrage wird erstellt…",
"delete": "Löschen",
"deleteComment": "Kommentar löschen",
"deleteDate": "Tag löschen",
"deletedPoll": "Umfrage gelöscht",
"deletedPollInfo": "Diese Umfrage existiert nicht mehr.",
"deletePoll": "Umfrage löschen",
"deletePollDescription": "Alle Daten zu dieser Umfrage werden gelöscht. Zur Bestätigung geben Sie bitte <s>“{{confirmText}}”</s> in das folgende Feld ein:",
"deletingOptionsWarning": "Du löschst Optionen, für die bereits Teilnehmer gestimmt haben. Ihre Stimmen werden ebenfalls gelöscht.",
"demoPollNotice": "Demo-Umfragen werden automatisch nach einem Tag gelöscht",
"description": "Beschreibung",
"descriptionPlaceholder": "Hallo ihr, bitte wählt alle Termine aus, die für euch passen!",
"discussions": "Diskussion",
"donate": "Spenden",
"editDetails": "Details bearbeiten",
"editOptions": "Optionen bearbeiten",
"email": "E-Mail",
"emailPlaceholder": "Max.Mustermann@mail.de",
"endingGuestSessionNotice": "Sobald eine Gastsitzung beendet ist, kann sie nicht fortgesetzt werden. Du kannst weder Auswahl noch Kommentare bearbeiten, die Du mit dieser Sitzung gemacht hast.",
"endSession": "Sitzung beenden",
"errorCreate": "Oh oh! Es gab ein Problem beim Erstellen deiner Umfrage. Der Fehler wurde protokolliert und wir werden versuchen, ihn zu beheben.",
"exportToCsv": "CSV exportieren",
"finish": "Fertigstellen",
"forgetMe": "Vergiss mich",
"goToAdmin": "Zur Admin Oberfläche",
"guest": "Gast",
"guestSessionNotice": "Du benutzt eine Gastsitzung, so können wir dich erkennen, wenn du später wiederkommst, damit du deine Angaben bearbeiten kannst.",
"guestSessionReadMore": "Mehr über Gastsitzungen.",
"hide": "Ausblenden",
"ifNeedBe": "Falls erforderlich",
"linkHasExpired": "Der Link ist abgelaufen oder ungültig",
"loading": "Wird geladen…",
"loadingParticipants": "Teilnehmerliste wird geladen…",
"location": "Ort",
"locationPlaceholder": "Joe's Café",
"lockPoll": "Umfragen sperren",
"login": "Login",
"loginCheckInbox": "Bitte überprüfe deinen Posteingang.",
"loginMagicLinkSent": "Ein magischer Link wurde geschickt an:",
"loginSendMagicLink": "Schicke mir einen magischen Link",
"loginViaMagicLink": "Anmeldung über magischen Link",
"loginViaMagicLinkDescription": "Wir senden dir eine E-Mail mit einem magischen Link, mit dem du dich anmelden kannst.",
"loginWithValidEmail": "Bitte gib eine gültige E-Mail-Adresse ein",
"logout": "Logout",
"manage": "Verwalten",
"menu": "Menü",
"mixedOptionsDescription": "Du kannst keine Zeit- und Datumsoptionen in der gleichen Umfrage haben. Welche möchtest Du beibehalten?",
"mixedOptionsKeepDates": "Datumsoptionen beibehalten",
"mixedOptionsKeepTimes": "Zeitoptionen beibehalten",
"mixedOptionsTitle": "Warte einen Moment…🤔",
"monday": "Montag",
"monthView": "Monatsansicht",
"name": "Name",
"namePlaceholder": "Max Mustermann",
"newPoll": "Neue Umfrage",
"next": "Weiter",
"nextMonth": "Nächster Monat",
"no": "Nein",
"noDatesSelected": "Kein Datum ausgewählt",
"notificationsDisabled": "Benachrichtigungen wurden deaktiviert",
"notificationsOff": "Benachrichtigungen sind deaktiviert",
"notificationsOn": "Benachrichtigungen sind aktiv",
"notificationsOnDescription": "Wenn diese Umfrage bearbeitet wird, wird eine E-Mail an <b>{{email}}</b> gesendet.",
"notificationsVerifyEmail": "Du musst deine E-Mail-Adresse bestätigen, um Benachrichtigungen zu aktivieren",
"ok": "Ok",
"options": "Optionen",
"participant": "Teilnehmer",
"addParticipant": "Add participant",
"alreadyVoted": "You have already voted",
"participantCount_other": "{{count}} Teilnehmer",
"participantCount": "{{count}} Teilnehmer",
"pollHasBeenLocked": "Diese Umfrage wurde gesperrt",
"pollHasBeenVerified": "Deine Umfrage wurde verifiziert",
"pollOwnerNotice": "Hallo {{name}}, sieht so aus, als ob du der Besitzer dieser Umfrage bist.",
"pollsEmpty": "Keine Umfragen erstellt",
"possibleAnswers": "Mögliche Antworten",
"preferences": "Einstellungen",
"previousMonth": "Vorheriger Monat",
"profileLogin": "Profil - Login",
"profileUser": "Profil - {{username}}",
"requiredNameError": "Bitte gib einen Namen an",
"save": "Speichern",
"saveInstruction": "Select your availability and click <b>{{save}}</b>",
"share": "Teilen",
"shareDescription": "Gib diesen Link deinen <b>Teilnehmern</b> damit sie an deiner Umfrage teilnehmen können.",
"shareLink": "Über Link teilen",
"specifyTimes": "Uhrzeiten angeben",
"specifyTimesDescription": "Start- und Endzeit für jede Option angeben",
"stepSummary": "Schritt {{current}} von {{total}}",
"sunday": "Sonntag",
"support": "Hilfe",
"timeAndDate": "Datum & Uhrzeit",
"timeFormat": "Uhrzeitformat:",
"timeZone": "Zeitzone:",
"title": "Titel",
"titlePlaceholder": "Monatliches Meeting",
"unlockPoll": "Umfrage entsperren",
"unverifiedMessage": "Ein Link zur Bestätigung der E-Mail-Adresse wurde an <b>{{email}}</b> versendet.",
"user": "Benutzer",
"vote": "Abstimmen",
"voteCount_other": "{{count}} Stimmen",
"voteCount": "{{count}} Stimme",
"weekStartsOn": "Woche beginnt am",
"weekView": "Wochenansicht",
"whatsThis": "Was ist das?",
"yes": "Ja",
"yourDetails": "Persönliche Angaben",
"yourName": "Your name…",
"yourPolls": "Deine Umfragen"
}

View file

@ -0,0 +1,13 @@
{
"language": "Sprache",
"english": "Englisch",
"german": "Deutsch",
"home": "Home",
"blog": "Blog",
"support": "Support",
"donate": "Donate",
"volunteerTranslator": "Help translate this site",
"starOnGithub": "Star us on Github",
"footerCredit": "Made by <a>@imlukevella</a>",
"footerSponsor": "This project is user-funded. Please consider supporting it by <a>donating</a>."
}

View file

@ -0,0 +1,44 @@
{
"3Ls": "Ja mit 3 <e>L</e>s",
"adFree": "Ohne Werbung",
"adFreeDescription": "Gönn deinem Adblocker eine Pause - du brauchst ihn hier nicht.",
"blog": "Blog",
"comments": "Kommentare",
"commentsDescription": "Teilnehmer können deine Umfrage kommentieren, die Kommentare sind für alle sichtbar.",
"discussions": "Diskussion",
"features": "Funktionen",
"featuresSubheading": "Terminfindung leicht gemacht",
"follow": "Folgen",
"getStarted": "Los geht's",
"heroSubText": "Finde ohne Hin-und Her den richtigen Termin",
"heroText": "Plane<br/><s>Besprechungen</s><br />ganz einfach",
"links": "Links",
"liveDemo": "Live Demo",
"metaDescription": "Erstelle Umfragen und stimme ab, um den besten Tag oder die beste Zeit zu finden. Eine kostenlose Alternative zu Doodle.",
"metaTitle": "Rallly - Gruppenmeetings planen",
"mobileFriendly": "Für Mobilgeräte optimiert",
"mobileFriendlyDescription": "Funktioniert hervorragend auf mobilen Geräten, so dass Teilnehmer auf Umfragen antworten können, wo immer sie sich befinden.",
"new": "Neu",
"noLoginRequired": "Keine Anmeldung benötigt",
"noLoginRequiredDescription": "Du musst dich nicht einloggen, um eine Umfrage zu erstellen oder an ihr teilzunehmen",
"notifications": "Benachrichtigungen",
"notificationsDescription": "Behalte den Überblick darüber, wer geantwortet hat. Werde benachrichtigt, wenn Teilnehmer abstimmen oder deine Umfrage kommentieren.",
"openSource": "Open Source",
"openSourceDescription": "Die Codebase ist vollständig Open-Source und <a>auf GitHub</a> verfügbar.",
"participant": "Teilnehmer",
"participantCount_other": "{{count}} Teilnehmer",
"social": "Social",
"participantCount": "{{count}} Teilnehmer",
"perfect": "Perfekt!",
"poweredBy": "Unterstützt von",
"principles": "Grundsätze",
"principlesSubheading": "Wir sind nicht wie die anderen",
"privacyPolicy": "Datenschutzrichtlinie",
"selfHostable": "Selfhosting möglich",
"selfHostableDescription": "Betreibe es auf deinem eigenen Server, um die volle Kontrolle über deine Daten zu haben",
"sponsorThisProject": "Dieses Projekt unterstützen",
"star": "Star",
"support": "Hilfe",
"timeSlots": "Zeitfenster",
"timeSlotsDescription": "Wähle individuelle Start- und Endzeiten für jede Option in deiner Umfrage. Die Zeiten können automatisch an die Zeitzone jedes Teilnehmers angepasst werden oder so eingestellt werden, dass Zeitzonen komplett ignoriert werden."
}

View file

@ -2,7 +2,6 @@
"12h": "12-hour",
"24h": "24-hour",
"addTimeOption": "Add time option",
"admin": "Admin",
"applyToAllDates": "Apply to all dates",
"areYouSure": "Are you sure?",
"back": "Back",
@ -23,7 +22,7 @@
"deleteComment": "Delete comment",
"deleteDate": "Delete date",
"deletedPoll": "Deleted poll",
"deletedPollInfo": "this poll doesn't exist anymore.",
"deletedPollInfo": "This poll doesn't exist anymore.",
"deletePoll": "Delete poll",
"deletePollDescription": "All data related to this poll will be deleted. To confirm, please type <s>“{{confirmText}}”</s> in to the input below:",
"deletingOptionsWarning": "You are deleting options that participants have voted for. Their votes will be also be deleted.",
@ -85,6 +84,8 @@
"ok": "Ok",
"options": "Options",
"participant": "Participant",
"addParticipant": "Add participant",
"alreadyVoted": "You have already voted",
"participantCount_other": "{{count}} participants",
"participantCount": "{{count}} participant",
"pollHasBeenLocked": "This poll has been locked",
@ -96,9 +97,9 @@
"previousMonth": "Previous month",
"profileLogin": "Profile - Login",
"profileUser": "Profile - {{username}}",
"remove": "Remove",
"requiredNameError": "Name is required",
"save": "Save",
"saveInstruction": "Select your availability and click <b>{{save}}</b>",
"share": "Share",
"shareDescription": "Give this link to your <b>participants</b> to allow them to vote on your poll.",
"shareLink": "Share via link",
@ -123,5 +124,6 @@
"whatsThis": "What's this?",
"yes": "Yes",
"yourDetails": "Your details",
"yourName": "Your name…",
"yourPolls": "Your polls"
}

View file

@ -1,3 +1,13 @@
{
"appName": "Rallly"
"language": "Language",
"english": "English",
"german": "German",
"home": "Home",
"blog": "Blog",
"support": "Support",
"donate": "Donate",
"volunteerTranslator": "Help translate this site",
"starOnGithub": "Star us on Github",
"footerCredit": "Made by <a>@imlukevella</a>",
"footerSponsor": "This project is user-funded. Please consider supporting it by <a>donating</a>."
}

View file

@ -9,7 +9,6 @@
"features": "Features",
"featuresSubheading": "Scheduling, the smart way",
"follow": "Follow",
"footerCredit": "Self-funded and built by <a>@imlukevella</a>",
"getStarted": "Get started",
"heroSubText": "Find the right date without the back and forth",
"heroText": "Schedule<br/><s>group meetings</s><br />with ease",
@ -28,6 +27,7 @@
"openSourceDescription": "The codebase is fully open-source and <a>available on GitHub</a>.",
"participant": "Participant",
"participantCount_other": "{{count}} participants",
"social": "Social",
"participantCount": "{{count}} participant",
"perfect": "Perfect!",
"poweredBy": "Powered by",
@ -38,7 +38,7 @@
"selfHostableDescription": "Run it on your own server to take full control of your data",
"sponsorThisProject": "Sponsor this project",
"star": "Star",
"support": "support",
"support": "Support",
"timeSlots": "Time slots",
"timeSlotsDescription": "Set individual start and end times for each option in your poll. Times can be automatically adjusted to each participant's timezone or they can be set to ignore timezones completely."
}

View file

@ -156,7 +156,7 @@ const Page: NextPage<CreatePollPageProps> = ({
<div className="max-w-full py-4 md:px-3 lg:px-6">
<div className="mx-auto w-fit max-w-full lg:mx-0">
<div className="mb-4 flex items-center justify-center space-x-4 px-4 lg:justify-start">
<h1 className="m-0">New Poll</h1>
<h1 className="m-0">{t("newPoll")}</h1>
<Steps current={currentStepIndex} total={steps.length} />
</div>
<div className="overflow-hidden border-t border-b bg-white shadow-sm md:rounded-lg md:border">

View file

@ -66,7 +66,7 @@ const WeekCalendar: React.VoidFunctionComponent<DateTimePickerProps> = ({
);
}}
components={{
toolbar: (props) => {
toolbar: function Toolbar(props) {
return (
<DateNavigationToolbar
year={props.date.getFullYear()}
@ -83,7 +83,7 @@ const WeekCalendar: React.VoidFunctionComponent<DateTimePickerProps> = ({
/>
);
},
eventWrapper: (props) => {
eventWrapper: function EventWraper(props) {
const start = dayjs(props.event.start);
const end = dayjs(props.event.end);
return (
@ -105,7 +105,7 @@ const WeekCalendar: React.VoidFunctionComponent<DateTimePickerProps> = ({
},
week: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
header: ({ date }: any) => {
header: function Header({ date }: any) {
const dateString = formatDateWithoutTime(date);
const selectedOption = options.find((option) => {
return option.type === "date" && option.date === dateString;
@ -143,7 +143,7 @@ const WeekCalendar: React.VoidFunctionComponent<DateTimePickerProps> = ({
);
},
},
timeSlotWrapper: ({ children }) => {
timeSlotWrapper: function TimeSlotWrapper({ children }) {
return <div className="h-8 text-xs text-gray-500">{children}</div>;
},
}}

View file

@ -10,7 +10,7 @@ import Ban from "./ban-ads.svg";
const Bonus: React.VoidFunctionComponent = () => {
const { t } = useTranslation("homepage");
return (
<div className="mx-auto max-w-7xl px-8 pt-8 pb-24">
<div className="mx-auto max-w-7xl px-8 py-8">
<h2 className="heading">{t("principles")}</h2>
<p className="subheading">{t("principlesSubheading")}</p>
<div className="grid grid-cols-4 gap-16">

View file

@ -26,12 +26,12 @@ const Hero: React.VoidFunctionComponent = () => {
</h1>
<div className="mb-12 text-xl text-gray-400">{t("heroSubText")}</div>
<div className="space-x-3">
<Link href="/new">
<Link href="/new" locale={false}>
<a className="rounded-lg bg-primary-500 px-5 py-3 font-semibold text-white shadow-sm transition-all hover:bg-primary-500/90 hover:text-white hover:no-underline hover:shadow-md focus:ring-2 focus:ring-primary-200 active:bg-primary-600/90">
{t("getStarted")}
</a>
</Link>
<Link href="/demo">
<Link href="/demo" locale={false}>
<a
className="rounded-lg bg-slate-500 px-5 py-3 font-semibold text-white shadow-sm transition-all hover:bg-slate-500/90 hover:text-white hover:no-underline hover:shadow-md focus:ring-2 focus:ring-primary-200 active:bg-slate-600/90"
rel="nofollow"

View file

@ -1,3 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M14.06 3.44a1.5 1.5 0 0 1 0 2.12l-7 7a1.5 1.5 0 0 1-2.12 0l-3-3a1.5 1.5 0 1 1 2.12-2.12L6 9.378l5.94-5.94a1.5 1.5 0 0 1 2.12 0Z" clip-rule="evenodd" />
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" />
</svg>

Before

Width:  |  Height:  |  Size: 270 B

After

Width:  |  Height:  |  Size: 211 B

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 24 24">
<path d="M20.317 4.537a19.596 19.596 0 0 0-4.885-1.536.074.074 0 0 0-.079.038c-.21.38-.444.877-.608 1.267-1.845-.28-3.68-.28-5.487 0a12.891 12.891 0 0 0-.617-1.267A.077.077 0 0 0 8.562 3c-1.714.3-3.354.824-4.885 1.536a.07.07 0 0 0-.032.028C.533 9.278-.32 13.875.099 18.414a.084.084 0 0 0 .031.057 19.797 19.797 0 0 0 5.993 3.071.077.077 0 0 0 .084-.028c.462-.639.874-1.313 1.226-2.022a.078.078 0 0 0-.041-.107 13.021 13.021 0 0 1-1.872-.904.079.079 0 0 1-.008-.13c.126-.095.252-.195.372-.295a.073.073 0 0 1 .078-.01c3.927 1.817 8.18 1.817 12.061 0a.073.073 0 0 1 .079.009c.12.1.245.2.372.296a.079.079 0 0 1-.006.13 12.23 12.23 0 0 1-1.873.903.078.078 0 0 0-.041.108c.36.708.772 1.382 1.225 2.021a.076.076 0 0 0 .084.03 19.731 19.731 0 0 0 6.002-3.072.078.078 0 0 0 .032-.056c.5-5.248-.838-9.807-3.549-13.849a.061.061 0 0 0-.031-.029ZM8.02 15.65c-1.182 0-2.157-1.1-2.157-2.452 0-1.352.956-2.453 2.157-2.453 1.21 0 2.176 1.11 2.157 2.453 0 1.351-.956 2.452-2.157 2.452Zm7.975 0c-1.183 0-2.157-1.1-2.157-2.452 0-1.352.955-2.453 2.157-2.453 1.21 0 2.176 1.11 2.157 2.453 0 1.351-.946 2.452-2.157 2.452Z" />
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>

After

Width:  |  Height:  |  Size: 254 B

View file

@ -1,3 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" />
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z" />
</svg>

Before

Width:  |  Height:  |  Size: 463 B

After

Width:  |  Height:  |  Size: 540 B

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M3 5h12M9 3v2m1.048 9.5A18.022 18.022 0 016.412 9m6.088 9h7M11 21l5-10 5 10M12.751 5C11.783 10.77 8.07 15.61 3 18.129" />
</svg>

After

Width:  |  Height:  |  Size: 314 B

View file

@ -1,4 +1,5 @@
import clsx from "clsx";
import { useTranslation } from "next-i18next";
import * as React from "react";
import UserAvatar from "./poll/user-avatar";
@ -16,6 +17,7 @@ const NameInput: React.ForwardRefRenderFunction<
HTMLInputElement,
NameInputProps
> = ({ value, defaultValue, className, ...forwardProps }, ref) => {
const { t } = useTranslation("app");
return (
<div className="relative flex items-center">
<UserAvatar
@ -25,7 +27,7 @@ const NameInput: React.ForwardRefRenderFunction<
<input
ref={ref}
className={clsx("input pl-[35px]", className)}
placeholder="Your name…"
placeholder={t("yourName")}
value={value}
{...forwardProps}
/>

View file

@ -1,6 +1,5 @@
import clsx from "clsx";
import dynamic from "next/dynamic";
import Head from "next/head";
import Link from "next/link";
import { useRouter } from "next/router";
import { Trans, useTranslation } from "next-i18next";
@ -24,6 +23,7 @@ const Menu: React.VoidFunctionComponent<{ className: string }> = ({
className,
}) => {
const { pathname } = useRouter();
const { t } = useTranslation("common");
return (
<nav className={className}>
<Link href="/">
@ -36,7 +36,7 @@ const Menu: React.VoidFunctionComponent<{ className: string }> = ({
},
)}
>
Home
{t("home")}
</a>
</Link>
<Link href="https://blog.rallly.co">
@ -45,14 +45,14 @@ const Menu: React.VoidFunctionComponent<{ className: string }> = ({
"text-gray-400 transition-colors hover:text-primary-500 hover:no-underline hover:underline-offset-2",
)}
>
Blog
{t("blog")}
</a>
</Link>
<a
href="https://support.rallly.co"
className="text-gray-400 transition-colors hover:text-primary-500 hover:no-underline hover:underline-offset-2"
>
Support
{t("support")}
</a>
<Link href="https://github.com/lukevella/rallly">
<a className="text-gray-400 transition-colors hover:text-primary-500 hover:no-underline hover:underline-offset-2">
@ -70,9 +70,6 @@ const PageLayout: React.VoidFunctionComponent<PageLayoutProps> = ({
const { t } = useTranslation("homepage");
return (
<div className="bg-pattern min-h-full overflow-x-hidden">
<Head>
<title>Rallly - Support</title>
</Head>
<div className="mx-auto flex max-w-7xl items-center py-8 px-8">
<div className="grow">
<div className="relative inline-block">

View file

@ -1,115 +1,151 @@
import Link from "next/link";
import { useRouter } from "next/router";
import { Trans, useTranslation } from "next-i18next";
import * as React from "react";
import GitHubButton from "react-github-btn";
import Discord from "@/components/icons/discord.svg";
import Star from "@/components/icons/star.svg";
import Translate from "@/components/icons/translate.svg";
import Twitter from "@/components/icons/twitter.svg";
import DigitalOcean from "~/public/digitalocean.svg";
import Logo from "~/public/logo.svg";
import Sentry from "~/public/sentry.svg";
import Vercel from "~/public/vercel-logotype-dark.svg";
import { LanguageSelect } from "../poll/language-selector";
const Footer: React.VoidFunctionComponent = () => {
const { t } = useTranslation("homepage");
const { t } = useTranslation(["common", "homepage"]);
const router = useRouter();
return (
<div className="mt-16 bg-slate-50/70">
<div className="mx-auto grid max-w-7xl grid-cols-10 gap-8 py-20 px-8">
<div className="col-span-12 md:col-span-4">
<Logo className="mb-4 w-32 text-gray-400" />
<p className="text-sm text-gray-400">
<Trans
t={t}
i18nKey="footerCredit"
components={{
a: (
<a
className="font-normal leading-loose text-gray-400 hover:text-gray-800 hover:no-underline"
href="https://twitter.com/imlukevella"
/>
),
}}
/>
</p>
<div className="flex space-x-3">
<GitHubButton
<div className="mx-auto max-w-7xl space-y-8 p-8 lg:grid lg:grid-cols-12 lg:gap-16 lg:space-y-0">
<div className=" lg:col-span-4">
<Logo className="w-32 text-slate-400" />
<div className="mb-8 mt-4 text-slate-400">
<p>
<Trans
t={t}
i18nKey="common:footerSponsor"
components={{
a: (
<a
className="font-normal leading-loose text-slate-400 underline hover:text-slate-800 hover:underline"
href="https://www.paypal.com/donate/?hosted_button_id=7QXP2CUBLY88E"
/>
),
}}
/>
</p>
<div>
<Trans
t={t}
i18nKey="common:footerCredit"
components={{
a: (
<a
className="font-normal leading-loose text-slate-400 underline hover:text-slate-800 hover:underline"
href="https://twitter.com/imlukevella"
/>
),
}}
/>
</div>
</div>
<div className="mb-8 flex items-center space-x-6">
<a
href="https://twitter.com/ralllyco"
className="text-sm text-slate-400 transition-colors hover:text-primary-500 hover:no-underline"
>
<Twitter className="h-5 w-5" />
</a>
<a
href="https://discord.gg/m5UFXavc2C"
className="text-sm text-slate-400 transition-colors hover:text-primary-500 hover:no-underline"
>
<Discord className="h-5 w-5" />
</a>
<a
href="https://github.com/lukevella/rallly"
data-icon="octicon-star"
aria-label="Star lukevella/rallly on GitHub"
data-show-count={true}
className="inline-flex h-8 items-center rounded-full bg-slate-100 pl-2 pr-3 text-sm text-slate-400 transition-colors hover:bg-primary-500 hover:text-white hover:no-underline focus:ring-2 focus:ring-primary-500 focus:ring-offset-1 active:bg-primary-600"
>
{t("star")}
</GitHubButton>
<GitHubButton
href="https://github.com/sponsors/lukevella"
data-icon="octicon-heart"
aria-label="Sponsor @lukevella on GitHub"
>
{t("sponsorThisProject")}
</GitHubButton>
<Star className="mr-2 inline-block w-5" />
<span>{t("common:starOnGithub")}</span>
</a>
</div>
</div>
<div className="col-span-6 md:col-span-2">
<div className="mb-4 font-medium">{t("links")}</div>
<div className="lg:col-span-2">
<div className="mb-4 font-medium">{t("homepage:links")}</div>
<ul>
<li>
<a
className="font-normal leading-loose text-gray-400 hover:text-gray-800 hover:no-underline"
className="font-normal leading-loose text-slate-400 hover:text-slate-800 hover:no-underline"
href="https://github.com/lukevella/rallly/discussions"
>
{t("discussions")}
{t("homepage:discussions")}
</a>
</li>
<li>
<Link href="https://blog.rallly.co">
<a className="font-normal leading-loose text-gray-400 hover:text-gray-800 hover:no-underline">
{t("blog")}
<a className="font-normal leading-loose text-slate-400 hover:text-slate-800 hover:no-underline">
{t("homepage:blog")}
</a>
</Link>
</li>
<li>
<a
href="https://support.rallly.co"
className="font-normal leading-loose text-gray-400 hover:text-gray-800 hover:no-underline"
className="font-normal leading-loose text-slate-400 hover:text-slate-800 hover:no-underline"
>
{t("support")}
{t("homepage:support")}
</a>
</li>
<li>
<Link href="/privacy-policy">
<a className="font-normal leading-loose text-gray-400 hover:text-gray-800 hover:no-underline">
{t("privacyPolicy")}
<a className="font-normal leading-loose text-slate-400 hover:text-slate-800 hover:no-underline">
{t("homepage:privacyPolicy")}
</a>
</Link>
</li>
</ul>
</div>
<div className="col-span-6 md:col-span-2">
<div className="mb-4 font-medium">{t("follow")}</div>
<ul>
<li>
<div className="lg:col-span-3">
<div className="mb-4 font-medium">{t("homepage:poweredBy")}</div>
<div className="block space-y-4">
<div>
<a
className="font-normal leading-loose text-gray-400 hover:text-gray-800 hover:no-underline"
href="https://github.com/lukevella/rallly"
href="https://vercel.com?utm_source=rallly&utm_campaign=oss"
className="inline-block text-white"
>
Github
<Vercel className="h-5" />
</a>
</li>
<li>
<a
className="font-normal leading-loose text-gray-400 hover:text-gray-800 hover:no-underline"
href="https://twitter.com/ralllyco"
>
Twitter
</div>
<div>
<a className="inline-block" href="https://m.do.co/c/f91efc9c9e50">
<DigitalOcean className="h-7" />
</a>
</li>
</ul>
</div>
<div>
<a className="inline-block" href="https://sentry.io">
<Sentry className="h-6" />
</a>
</div>
</div>
</div>
<div className="col-span-12 md:col-span-2">
<div className="lg:col-span-3">
<div className="mb-4 font-medium">{t("common:language")}</div>
<LanguageSelect
className="mb-4 w-full"
onChange={(locale) => {
router.push(router.asPath, router.asPath, { locale });
}}
/>
<a
href="https://vercel.com?utm_source=rallly&utm_campaign=oss"
className="inline-block text-white"
href="https://github.com/lukevella/rallly/wiki/Guide-for-translators"
className="inline-flex items-center rounded-md border px-3 py-2 text-xs text-slate-500"
>
<span className="mb-1 inline-block w-full text-right text-xs italic text-gray-400">
{t("poweredBy")}
</span>
<Vercel className="w-24" />
<Translate className="mr-2 h-5 w-5" />
{t("common:volunteerTranslator")} &rarr;
</a>
</div>
</div>

View file

@ -174,13 +174,6 @@ const PollPage: NextPage = () => {
<Sharing
onHide={() => {
setSharingVisible(false);
router.replace(
`/admin/${router.query.urlId}`,
undefined,
{
shallow: true,
},
);
}}
/>
</motion.div>

View file

@ -1,12 +1,14 @@
import { AnimatePresence, motion } from "framer-motion";
import { useTranslation } from "next-i18next";
import { Trans, useTranslation } from "next-i18next";
import * as React from "react";
import { useMeasure } from "react-use";
import smoothscroll from "smoothscroll-polyfill";
import ArrowLeft from "@/components/icons/arrow-left.svg";
import ArrowRight from "@/components/icons/arrow-right.svg";
import Check from "@/components/icons/check.svg";
import Plus from "@/components/icons/plus-sm.svg";
import { Button } from "../button";
import ArrowLeft from "../icons/arrow-left.svg";
import ArrowRight from "../icons/arrow-right.svg";
import { useParticipants } from "../participants-provider";
import { usePoll } from "../poll-context";
import TimeZonePicker from "../time-zone-picker";
@ -14,11 +16,10 @@ import ParticipantRow from "./desktop-poll/participant-row";
import ParticipantRowForm from "./desktop-poll/participant-row-form";
import { PollContext } from "./desktop-poll/poll-context";
import PollHeader from "./desktop-poll/poll-header";
import { useAddParticipantMutation } from "./mutations";
if (typeof window !== "undefined") {
smoothscroll.polyfill();
}
import {
useAddParticipantMutation,
useUpdateParticipantMutation,
} from "./mutations";
const MotionButton = motion(Button);
@ -27,7 +28,8 @@ const minSidebarWidth = 200;
const Poll: React.VoidFunctionComponent = () => {
const { t } = useTranslation("app");
const { poll, options, targetTimeZone, setTargetTimeZone } = usePoll();
const { poll, options, targetTimeZone, setTargetTimeZone, userAlreadyVoted } =
usePoll();
const { participants } = useParticipants();
@ -35,7 +37,7 @@ const Poll: React.VoidFunctionComponent = () => {
const [editingParticipantId, setEditingParticipantId] =
React.useState<string | null>(null);
const actionColumnWidth = 140;
const actionColumnWidth = 100;
const columnWidth = Math.min(
130,
Math.max(
@ -65,7 +67,8 @@ const Poll: React.VoidFunctionComponent = () => {
const maxScrollPosition =
columnWidth * options.length - columnWidth * numberOfVisibleColumns;
const shouldShowNewParticipantForm = !poll.closed;
const [shouldShowNewParticipantForm, setShouldShowNewParticipantForm] =
React.useState(!poll.closed && !userAlreadyVoted);
const pollWidth =
sidebarWidth + options.length * columnWidth + actionColumnWidth;
@ -87,6 +90,8 @@ const Poll: React.VoidFunctionComponent = () => {
);
};
const updateParticipant = useUpdateParticipantMutation();
const participantListContainerRef = React.useRef<HTMLDivElement>(null);
return (
<PollContext.Provider
@ -192,28 +197,93 @@ const Poll: React.VoidFunctionComponent = () => {
isEditing ? participant.id : null,
);
}}
onSubmit={async ({ name, votes }) => {
await updateParticipant.mutateAsync({
participantId: participant.id,
pollId: poll.id,
votes,
name,
});
}}
/>
);
})}
</div>
) : null}
{shouldShowNewParticipantForm ? (
{shouldShowNewParticipantForm &&
!poll.closed &&
!editingParticipantId ? (
<ParticipantRowForm
className="border-t bg-gray-50"
className="shrink-0 border-t bg-gray-50"
onSubmit={async ({ name, votes }) => {
const participant = await addParticipant.mutateAsync({
await addParticipant.mutateAsync({
name,
votes,
pollId: poll.id,
});
setTimeout(() => {
participantListContainerRef.current
?.querySelector(`[data-participantid=${participant.id}]`)
?.scrollIntoView();
}, 100);
setShouldShowNewParticipantForm(false);
}}
/>
) : null}
{!poll.closed ? (
<div className="flex h-14 shrink-0 items-center border-t bg-gray-50 px-3">
{shouldShowNewParticipantForm || editingParticipantId ? (
<div className="flex items-center space-x-3">
<Button
key="submit"
form="participant-row-form"
htmlType="submit"
type="primary"
icon={<Check />}
loading={
addParticipant.isLoading || updateParticipant.isLoading
}
>
{t("save")}
</Button>
<Button
onClick={() => {
if (editingParticipantId) {
setEditingParticipantId(null);
} else {
setShouldShowNewParticipantForm(false);
}
}}
>
{t("cancel")}
</Button>
<div className="text-sm">
<Trans
t={t}
i18nKey="saveInstruction"
values={{
save: t("save"),
}}
components={{ b: <strong /> }}
/>
</div>
</div>
) : (
<div className="flex w-full items-center space-x-3">
<Button
key="add-participant"
onClick={() => {
setShouldShowNewParticipantForm(true);
}}
icon={<Plus />}
>
{t("addParticipant")}
</Button>
{userAlreadyVoted ? (
<div className="flex items-center text-sm text-gray-400">
<Check className="mr-1 h-5" />
<div>{t("alreadyVoted")}</div>
</div>
) : null}
</div>
)}
</div>
) : null}
</div>
</div>
</PollContext.Provider>

View file

@ -1,11 +1,10 @@
import clsx from "clsx";
import { AnimatePresence, motion } from "framer-motion";
import { useTranslation } from "next-i18next";
import * as React from "react";
import { Controller, useForm } from "react-hook-form";
import CompactButton from "@/components/compact-button";
import Check from "@/components/icons/check.svg";
import X from "@/components/icons/x.svg";
import ArrowRight from "@/components/icons/arrow-right.svg";
import { requiredString } from "../../../utils/form-validation";
import { Button } from "../../button";
@ -17,6 +16,7 @@ import { VoteSelector } from "../vote-selector";
import ControlledScrollArea from "./controlled-scroll-area";
import { usePollContext } from "./poll-context";
const MotionButton = motion(Button);
export interface ParticipantRowFormProps {
defaultValues?: Partial<ParticipantForm>;
onSubmit: (data: ParticipantFormSubmitted) => Promise<void>;
@ -43,7 +43,7 @@ const ParticipantRowForm: React.ForwardRefRenderFunction<
const {
handleSubmit,
control,
formState: { errors, submitCount, isSubmitting },
formState: { errors, submitCount },
reset,
} = useForm({
defaultValues: {
@ -69,6 +69,7 @@ const ParticipantRowForm: React.ForwardRefRenderFunction<
return (
<form
id="participant-row-form"
ref={ref}
onSubmit={handleSubmit(async ({ name, votes }) => {
await onSubmit({
@ -91,7 +92,7 @@ const ParticipantRowForm: React.ForwardRefRenderFunction<
className={clsx("w-full", {
"input-error": errors.name && submitCount > 0,
})}
placeholder="Your name"
placeholder={t("yourName")}
{...field}
onKeyDown={(e) => {
if (e.code === "Tab" && scrollPosition > 0) {
@ -126,7 +127,7 @@ const ParticipantRowForm: React.ForwardRefRenderFunction<
return (
<div
key={optionId}
className="flex shrink-0 items-center justify-center"
className="flex shrink-0 items-center justify-center px-2"
style={{ width: columnWidth }}
>
<VoteSelector
@ -162,28 +163,25 @@ const ParticipantRowForm: React.ForwardRefRenderFunction<
/>
<div className="flex items-center space-x-2 px-2 transition-all">
{scrollPosition >= maxScrollPosition ? (
<Button
htmlType="submit"
icon={<Check />}
type="primary"
loading={isSubmitting}
data-testid="submitNewParticipant"
>
{t("save")}
</Button>
) : null}
{scrollPosition < maxScrollPosition ? (
<Button
onClick={(e) => {
e.stopPropagation();
goToNextPage();
}}
>
{t("next")} &rarr;
</Button>
<AnimatePresence initial={false}>
{scrollPosition < maxScrollPosition ? (
<MotionButton
transition={{ duration: 0.1 }}
initial={{ opacity: 0, scale: 0.9 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.8 }}
className="text-xs"
rounded={true}
onClick={() => {
goToNextPage();
}}
>
<ArrowRight className="h-4 w-4" />
</MotionButton>
) : null}
</AnimatePresence>
) : null}
{onCancel ? <CompactButton onClick={onCancel} icon={X} /> : null}
</div>
</form>
);

View file

@ -8,7 +8,7 @@ import Trash from "@/components/icons/trash.svg";
import { usePoll } from "@/components/poll-context";
import { useSession } from "@/components/session";
import { useUpdateParticipantMutation } from "../mutations";
import { ParticipantFormSubmitted } from "../types";
import { useDeleteParticipantModal } from "../use-delete-participant-modal";
import UserAvatar from "../user-avatar";
import VoteIcon from "../vote-icon";
@ -18,8 +18,9 @@ import { usePollContext } from "./poll-context";
export interface ParticipantRowProps {
participant: Participant & { votes: Vote[] };
editMode: boolean;
onChangeEditMode: (value: boolean) => void;
editMode?: boolean;
onChangeEditMode?: (editMode: boolean) => void;
onSubmit?: (data: ParticipantFormSubmitted) => Promise<void>;
}
export const ParticipantRowView: React.VoidFunctionComponent<{
@ -49,7 +50,7 @@ export const ParticipantRowView: React.VoidFunctionComponent<{
<div
data-testid="participant-row"
data-participantid={participantId}
className="group flex h-14"
className="group flex h-14 items-center"
>
<div
className="flex shrink-0 items-center px-4"
@ -74,12 +75,12 @@ export const ParticipantRowView: React.VoidFunctionComponent<{
return (
<div
key={i}
className="relative shrink-0 transition-colors"
className="relative flex shrink-0 items-center justify-center px-2 transition-colors"
style={{ width: columnWidth }}
>
<div
className={clsx(
"absolute inset-1 flex items-center justify-center rounded-lg",
"flex h-10 w-full items-center justify-center rounded-md",
{
"bg-green-50": vote === "yes",
"bg-amber-50": vote === "ifNeedBe",
@ -100,12 +101,11 @@ export const ParticipantRowView: React.VoidFunctionComponent<{
const ParticipantRow: React.VoidFunctionComponent<ParticipantRowProps> = ({
participant,
editMode,
onSubmit,
onChangeEditMode,
}) => {
const { columnWidth, sidebarWidth } = usePollContext();
const updateParticipant = useUpdateParticipantMutation();
const confirmDeleteParticipant = useDeleteParticipantModal();
const session = useSession();
@ -128,12 +128,7 @@ const ParticipantRow: React.VoidFunctionComponent<ParticipantRowProps> = ({
}),
}}
onSubmit={async ({ name, votes }) => {
await updateParticipant.mutateAsync({
participantId: participant.id,
pollId: poll.id,
votes,
name,
});
await onSubmit?.({ name, votes });
onChangeEditMode?.(false);
}}
onCancel={() => onChangeEditMode?.(false)}

View file

@ -0,0 +1,27 @@
import clsx from "clsx";
import Cookies from "js-cookie";
import { useRouter } from "next/router";
import { useTranslation } from "next-i18next";
export const LanguageSelect: React.VoidFunctionComponent<{
className?: string;
onChange?: (language: string) => void;
}> = ({ className, onChange }) => {
const { t } = useTranslation("common");
const router = useRouter();
return (
<select
className={clsx("input", className)}
defaultValue={router.locale}
onChange={(e) => {
Cookies.set("NEXT_LOCALE", e.target.value, {
expires: 365,
});
onChange?.(e.target.value);
}}
>
<option value="en">{t("english")}</option>
<option value="de">{t("german")}</option>
</select>
);
};

View file

@ -213,16 +213,18 @@ const ManagePoll: React.VoidFunctionComponent<{
onClick={() => {
modalContext.render({
overlayClosable: true,
content: ({ close }) => (
<DeletePollForm
onConfirm={async () => {
close();
setDeleted(true);
}}
onCancel={close}
urlId={urlId}
/>
),
content: function Content({ close }) {
return (
<DeletePollForm
onConfirm={async () => {
close();
setDeleted(true);
}}
onCancel={close}
urlId={urlId}
/>
);
},
footer: null,
});
}}

View file

@ -229,6 +229,7 @@ const PollOption: React.VoidFunctionComponent<PollOptionProps> = ({
ref={selectorRef}
value={vote}
onChange={onChange}
className="w-9"
/>
</div>
) : (

View file

@ -29,6 +29,10 @@ export const useAddParticipantMutation = () => {
return [...existingParticipants, participant];
},
);
queryClient.invalidateQueries([
"polls.participants.list",
{ pollId: participant.pollId },
]);
session.refresh();
},
});

View file

@ -1,4 +1,5 @@
import { VoteType } from "@prisma/client";
import clsx from "clsx";
import { AnimatePresence, motion } from "framer-motion";
import * as React from "react";
@ -10,6 +11,7 @@ export interface VoteSelectorProps {
onFocus?: React.FocusEventHandler<HTMLButtonElement>;
onBlur?: React.FocusEventHandler<HTMLButtonElement>;
onKeyDown?: React.KeyboardEventHandler<HTMLButtonElement>;
className?: string;
}
const orderedVoteTypes: VoteType[] = ["yes", "ifNeedBe", "no"];
@ -23,7 +25,10 @@ const getNext = (value: VoteType) => {
export const VoteSelector = React.forwardRef<
HTMLButtonElement,
VoteSelectorProps
>(function VoteSelector({ value, onChange, onFocus, onBlur, onKeyDown }, ref) {
>(function VoteSelector(
{ value, onChange, onFocus, onBlur, onKeyDown, className },
ref,
) {
return (
<button
data-testid="vote-selector"
@ -31,7 +36,20 @@ export const VoteSelector = React.forwardRef<
onFocus={onFocus}
onBlur={onBlur}
onKeyDown={onKeyDown}
className="focus-visible:ring-primary-500 relative inline-flex h-9 w-9 items-center justify-center rounded-lg border bg-white shadow-sm transition focus-visible:border-0 focus-visible:ring-2 active:scale-95"
className={clsx(
"group relative inline-flex h-9 w-full items-center justify-center overflow-hidden rounded-md border bg-white transition-all hover:ring-4 focus-visible:border-0 focus-visible:ring-2 focus-visible:ring-primary-500",
{
"border-green-200 bg-green-50 hover:ring-green-100/50 active:bg-green-100/50":
value === "yes",
"border-amber-200 bg-amber-50 hover:ring-amber-100/50 active:bg-amber-100/50":
value === "ifNeedBe",
"border-gray-200 bg-gray-50 hover:ring-gray-100/50 active:bg-gray-100/50":
value === "no",
"border-gray-200 hover:ring-gray-100/50 active:bg-gray-100/50":
value === undefined,
},
className,
)}
onClick={() => {
onChange?.(value ? getNext(value) : orderedVoteTypes[0]);
}}
@ -40,10 +58,10 @@ export const VoteSelector = React.forwardRef<
<AnimatePresence initial={false}>
<motion.span
className="absolute flex items-center justify-center"
transition={{ duration: 0.15 }}
initial={{ opacity: 0, y: -15 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: 15 }}
transition={{ duration: 0.2 }}
initial={{ opacity: 0, scale: 1.5, y: -45 }}
animate={{ opacity: 1, scale: 1, y: 0 }}
exit={{ opacity: 0, scale: 0.5, y: 45 }}
key={value}
>
<VoteIcon type={value} />

View file

@ -1,29 +1,33 @@
import clsx from "clsx";
import { useRouter } from "next/router";
import { useTranslation } from "next-i18next";
import { usePlausible } from "next-plausible";
import React from "react";
import Calendar from "@/components/icons/calendar.svg";
import { LanguageSelect } from "./poll/language-selector";
import { usePreferences } from "./preferences/use-preferences";
const Preferences: React.VoidFunctionComponent = () => {
const { t } = useTranslation("app");
const { t } = useTranslation(["app", "common"]);
const { weekStartsOn, setWeekStartsOn, timeFormat, setTimeFormat } =
usePreferences();
const router = useRouter();
const plausible = usePlausible();
return (
<div className="-mb-2">
<div className="mb-4 flex items-center space-x-2 text-base font-semibold">
<Calendar className="inline-block w-5" />
<span>{t("timeAndDate")}</span>
<div>
<div className="mb-4 space-y-2">
<div className="grow text-sm text-slate-500">
{t("common:language")}
</div>
<LanguageSelect className="w-full" onChange={() => router.reload()} />
</div>
<div className="grow">
<div className="mb-2">
<div className="grow space-y-2">
<div>
<div className="mb-2 grow text-sm text-slate-500">
{t("weekStartsOn")}
{t("app:weekStartsOn")}
</div>
<div>
<div className="segment-button inline-flex">
@ -41,7 +45,7 @@ const Preferences: React.VoidFunctionComponent = () => {
}}
type="button"
>
{t("monday")}
{t("app:monday")}
</button>
<button
className={clsx({
@ -57,14 +61,14 @@ const Preferences: React.VoidFunctionComponent = () => {
}}
type="button"
>
{t("sunday")}
{t("app:sunday")}
</button>
</div>
</div>
</div>
<div className="mb-2">
<div className="">
<div className="mb-2 grow text-sm text-slate-500">
{t("timeFormat")}
{t("app:timeFormat")}
</div>
<div className="segment-button inline-flex">
<button
@ -81,7 +85,7 @@ const Preferences: React.VoidFunctionComponent = () => {
}}
type="button"
>
{t("12h")}
{t("app:12h")}
</button>
<button
className={clsx({
@ -97,7 +101,7 @@ const Preferences: React.VoidFunctionComponent = () => {
}}
type="button"
>
{t("24h")}
{t("app:24h")}
</button>
</div>
</div>

View file

@ -1,4 +1,5 @@
import dayjs from "dayjs";
import de from "dayjs/locale/de";
import en from "dayjs/locale/en";
import duration from "dayjs/plugin/duration";
import isBetween from "dayjs/plugin/isBetween";
@ -9,12 +10,18 @@ import minMax from "dayjs/plugin/minMax";
import relativeTime from "dayjs/plugin/relativeTime";
import timezone from "dayjs/plugin/timezone";
import utc from "dayjs/plugin/utc";
import { useRouter } from "next/router";
import * as React from "react";
import { useLocalStorage } from "react-use";
type TimeFormat = "12h" | "24h";
type StartOfWeek = "monday" | "sunday";
const dayJsLocales = {
de,
en,
};
dayjs.extend(localizedFormat);
dayjs.extend(relativeTime);
dayjs.extend(localeData);
@ -43,11 +50,13 @@ const PreferencesProvider: React.VoidFunctionComponent<{
const [weekStartsOn = "monday", setWeekStartsOn] =
useLocalStorage<StartOfWeek>("rallly-week-starts-on");
const router = useRouter();
const userLocale = dayJsLocales[router.locale ?? "en"];
const [timeFormat = "12h", setTimeFormat] =
useLocalStorage<TimeFormat>("rallly-time-format");
dayjs.locale({
...en,
...userLocale,
weekStart: weekStartsOn === "monday" ? 1 : 0,
formats: { LT: timeFormat === "12h" ? "h:mm A" : "HH:mm" },
});

View file

@ -12,6 +12,7 @@ import Logo from "~/public/logo.svg";
import Dropdown, { DropdownItem, DropdownProps } from "./dropdown";
import Adjustments from "./icons/adjustments.svg";
import Cash from "./icons/cash.svg";
import Discord from "./icons/discord.svg";
import DotsVertical from "./icons/dots-vertical.svg";
import Github from "./icons/github.svg";
import Login from "./icons/login.svg";
@ -293,7 +294,7 @@ const StandardLayout: React.VoidFunctionComponent<{
<AnimatePresence initial={false}>
{user ? (
<UserDropdown
className="w-full"
className="mb-4 w-full"
placement="bottom-end"
openLoginModal={openLoginModal}
trigger={
@ -358,25 +359,34 @@ const StandardLayout: React.VoidFunctionComponent<{
</Link>
<div className="hidden text-slate-300 lg:block">&bull;</div>
<div className="flex items-center space-x-6">
<Link href="https://twitter.com/ralllyco">
<a className="text-sm text-slate-400 transition-colors hover:text-primary-500 hover:no-underline">
<Twitter className="h-5 w-5" />
</a>
</Link>
<Link href="https://github.com/lukevella/rallly">
<a className="text-sm text-slate-400 transition-colors hover:text-primary-500 hover:no-underline">
<Github className="h-5 w-5" />
</a>
</Link>
<a
href="https://twitter.com/ralllyco"
className="text-sm text-slate-400 transition-colors hover:text-primary-500 hover:no-underline"
>
<Twitter className="h-5 w-5" />
</a>
<a
href="https://github.com/lukevella/rallly"
className="text-sm text-slate-400 transition-colors hover:text-primary-500 hover:no-underline"
>
<Github className="h-5 w-5" />
</a>
<a
href="https://discord.gg/m5UFXavc2C"
className="text-sm text-slate-400 transition-colors hover:text-primary-500 hover:no-underline"
>
<Discord className="h-5 w-5" />
</a>
</div>
</div>
<div className="hidden text-slate-300 lg:block">&bull;</div>
<Link href="https://www.paypal.com/donate/?hosted_button_id=7QXP2CUBLY88E">
<a className="inline-flex h-8 items-center rounded-full bg-slate-100 pl-2 pr-3 text-sm text-slate-400 transition-colors hover:bg-primary-500 hover:text-white hover:no-underline focus:ring-2 focus:ring-primary-500 focus:ring-offset-1 active:bg-primary-600">
<Cash className="mr-1 inline-block w-5" />
<span>{t("donate")}</span>
</a>
</Link>
<a
href="https://www.paypal.com/donate/?hosted_button_id=7QXP2CUBLY88E"
className="inline-flex h-8 items-center rounded-full bg-slate-100 pl-2 pr-3 text-sm text-slate-400 transition-colors hover:bg-primary-500 hover:text-white hover:no-underline focus:ring-2 focus:ring-primary-500 focus:ring-offset-1 active:bg-primary-600"
>
<Cash className="mr-1 inline-block w-5" />
<span>{t("donate")}</span>
</a>
</div>
</div>
</div>

22
src/middleware.ts Normal file
View file

@ -0,0 +1,22 @@
import { NextRequest, NextResponse } from "next/server";
export function middleware({ headers, cookies, nextUrl }: NextRequest) {
const locale =
cookies.get("NEXT_LOCALE") ??
(headers
.get("accept-language")
?.split(",")?.[0]
.split("-")?.[0]
.toLowerCase() ||
"en");
const newUrl = nextUrl.clone();
newUrl.pathname = `/${locale}${newUrl.pathname}`;
return NextResponse.rewrite(newUrl);
}
export const config = {
// these are paths we should rewrite to prev
matcher: ["/admin/:id", "/demo", "/p/:id", "/profile", "/new"],
};

View file

@ -1,13 +1,13 @@
import { GetStaticProps, NextPage } from "next";
import { NextPage } from "next";
import { useRouter } from "next/router";
import { useTranslation } from "next-i18next";
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
import { usePlausible } from "next-plausible";
import React from "react";
import { useMount } from "react-use";
import FullPageLoader from "../components/full-page-loader";
import { trpc } from "../utils/trpc";
import { withPageTranslations } from "../utils/with-page-translations";
const Demo: NextPage = () => {
const { t } = useTranslation("app");
@ -25,12 +25,6 @@ const Demo: NextPage = () => {
return <FullPageLoader>{t("creatingDemo")}</FullPageLoader>;
};
export const getStaticProps: GetStaticProps = async ({ locale = "en" }) => {
return {
props: {
...(await serverSideTranslations(locale, ["app"])),
},
};
};
export const getServerSideProps = withPageTranslations(["common", "app"]);
export default Demo;

View file

@ -4,13 +4,9 @@ import { serverSideTranslations } from "next-i18next/serverSideTranslations";
export { default } from "@/components/home";
export const getStaticProps: GetStaticProps = async ({ locale = "en" }) => {
try {
return {
props: {
...(await serverSideTranslations(locale, ["homepage"])),
},
};
} catch {
return { notFound: true };
}
return {
props: {
...(await serverSideTranslations(locale, ["common", "homepage"])),
},
};
};

View file

@ -1,19 +1,11 @@
import { GetServerSideProps } from "next";
import dynamic from "next/dynamic";
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
import { withSessionSsr } from "../utils/auth";
import { withPageTranslations } from "../utils/with-page-translations";
export const getServerSideProps: GetServerSideProps = withSessionSsr(
async ({ locale = "en", query, req }) => {
return {
props: {
...(await serverSideTranslations(locale, ["app"])),
...query,
user: req.session.user ?? null,
},
};
},
withPageTranslations(["common", "app"]),
);
export default dynamic(() => import("@/components/create-poll"), {

View file

@ -2,21 +2,21 @@ import { GetServerSideProps, NextPage } from "next";
import dynamic from "next/dynamic";
import { useRouter } from "next/router";
import { useTranslation } from "next-i18next";
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
import React from "react";
import FullPageLoader from "@/components/full-page-loader";
import { PollContextProvider } from "@/components/poll-context";
import { SessionProps, withSession } from "@/components/session";
import { withSession } from "@/components/session";
import { ParticipantsProvider } from "../components/participants-provider";
import { withSessionSsr } from "../utils/auth";
import { trpc } from "../utils/trpc";
import { withPageTranslations } from "../utils/with-page-translations";
import Custom404 from "./404";
const PollPage = dynamic(() => import("@/components/poll"), { ssr: false });
const PollPageLoader: NextPage<SessionProps> = () => {
const PollPageLoader: NextPage = () => {
const { query, asPath } = useRouter();
const { t } = useTranslation("app");
const urlId = query.urlId as string;
@ -50,14 +50,7 @@ const PollPageLoader: NextPage<SessionProps> = () => {
};
export const getServerSideProps: GetServerSideProps = withSessionSsr(
async ({ locale = "en", req }) => {
return {
props: {
...(await serverSideTranslations(locale, ["app"])),
user: req.session.user ?? null,
},
};
},
withPageTranslations(["common", "app"]),
);
export default withSession(PollPageLoader);

View file

@ -370,7 +370,7 @@ export const getStaticProps: GetStaticProps = async ({ locale = "en" }) => {
try {
return {
props: {
...(await serverSideTranslations(locale, ["app", "homepage"])),
...(await serverSideTranslations(locale, ["common", "homepage"])),
},
};
} catch {

View file

@ -1,11 +1,11 @@
import { NextPage } from "next";
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
import { withSessionSsr } from "@/utils/auth";
import { Profile } from "../components/profile";
import { withSession } from "../components/session";
import StandardLayout from "../components/standard-layout";
import { withPageTranslations } from "../utils/with-page-translations";
const Page: NextPage = () => {
return (
@ -16,14 +16,7 @@ const Page: NextPage = () => {
};
export const getServerSideProps = withSessionSsr(
async ({ locale = "en", query }) => {
return {
props: {
...(await serverSideTranslations(locale, ["app"])),
...query,
},
};
},
withPageTranslations(["common", "app"]),
);
export default withSession(Page);

View file

@ -1,6 +1,5 @@
import * as Eta from "eta";
import { readFileSync } from "fs";
import { NextApiRequest } from "next";
import path from "path";
import { prisma } from "~/prisma/db";
@ -8,11 +7,6 @@ import { prisma } from "~/prisma/db";
import { absoluteUrl } from "./absolute-url";
import { sendEmail } from "./send-email";
export const getQueryParam = (req: NextApiRequest, queryKey: string) => {
const value = req.query[queryKey];
return typeof value === "string" ? value : value[0];
};
type NotificationAction =
| {
type: "newParticipant";

View file

@ -32,7 +32,13 @@ export function withSessionSsr(handler: GetServerSideProps) {
req.session.user = await createGuestUser();
await req.session.save();
}
return await handler(context);
const res = await handler(context);
if ("props" in res) {
return { ...res, props: { ...res.props, user: req.session.user } };
}
return res;
}, sessionOptions);
}

View file

@ -0,0 +1,15 @@
import { GetServerSideProps, GetServerSidePropsContext } from "next";
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
export const withPageTranslations = (
namespaces: string[],
): GetServerSideProps => {
return async (ctx: GetServerSidePropsContext) => {
const locale = ctx.locale ?? "en";
return {
props: {
...(await serverSideTranslations(locale, namespaces)),
},
};
};
};

View file

@ -32,7 +32,7 @@
@apply outline-none;
}
a {
@apply rounded-sm font-medium text-primary-500 outline-none hover:text-primary-400 hover:underline focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-1;
@apply rounded-sm font-medium text-primary-500 outline-none hover:text-primary-500 hover:underline hover:no-underline focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-1;
}
label {
@apply mb-1 block text-sm text-slate-800;

View file

@ -11,12 +11,12 @@ test("should be able to vote and comment on a poll", async ({ page }) => {
await expect(page.locator('text="Lunch Meeting"')).toBeVisible();
await page.type('[placeholder="Your name"]', "Test user");
await page.type('[placeholder="Your name"]', "Test user");
// There is a hidden checkbox (nth=0) that exists so that the behaviour of the form is consistent even
// when we only have a single option/checkbox.
await page.locator("data-testid=vote-selector >> nth=0").click();
await page.locator("data-testid=vote-selector >> nth=2").click();
await page.click('[data-testid="submitNewParticipant"]');
await page.click("text='Save'");
await expect(page.locator("text='Test user'")).toBeVisible();
await expect(page.locator("text=Guest")).toBeVisible();
await expect(

507
yarn.lock
View file

@ -1188,77 +1188,82 @@
dependencies:
webpack-bundle-analyzer "4.3.0"
"@next/env@12.1.4":
version "12.1.4"
resolved "https://registry.yarnpkg.com/@next/env/-/env-12.1.4.tgz#5af629b43075281ecd7f87938802b7cf5b67e94b"
integrity sha512-7gQwotJDKnfMxxXd8xJ2vsX5AzyDxO3zou0+QOXX8/unypA6icw5+wf6A62yKZ6qQ4UZHHxS68pb6UV+wNneXg==
"@next/env@12.2.2":
version "12.2.2"
resolved "https://registry.yarnpkg.com/@next/env/-/env-12.2.2.tgz#cc1a0a445bd254499e30f632968c03192455f4cc"
integrity sha512-BqDwE4gDl1F608TpnNxZqrCn6g48MBjvmWFEmeX5wEXDXh3IkAOw6ASKUgjT8H4OUePYFqghDFUss5ZhnbOUjw==
"@next/eslint-plugin-next@12.1.0":
version "12.1.0"
resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-12.1.0.tgz#32586a11378b3ffa5a93ac40a3c44ad99d70e95a"
integrity sha512-WFiyvSM2G5cQmh32t/SiQuJ+I2O+FHVlK/RFw5b1565O2kEM/36EXncjt88Pa+X5oSc+1SS+tWxowWJd1lqI+g==
"@next/eslint-plugin-next@12.2.2":
version "12.2.2"
resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-12.2.2.tgz#b4a22c06b6454068b54cc44502168d90fbb29a6d"
integrity sha512-XOi0WzJhGH3Lk51SkSu9eZxF+IY1ZZhWcJTIGBycAbWU877IQa6+6KxMATWCOs7c+bmp6Sd8KywXJaDRxzu0JA==
dependencies:
glob "7.1.7"
"@next/swc-android-arm-eabi@12.1.4":
version "12.1.4"
resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.1.4.tgz#c3dae178b7c15ad627d2e9b8dfb38caecb5c4ac7"
integrity sha512-FJg/6a3s2YrUaqZ+/DJZzeZqfxbbWrynQMT1C5wlIEq9aDLXCFpPM/PiOyJh0ahxc0XPmi6uo38Poq+GJTuKWw==
"@next/swc-android-arm-eabi@12.2.2":
version "12.2.2"
resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.2.2.tgz#f6c4111e6371f73af6bf80c9accb3d96850a92cd"
integrity sha512-VHjuCHeq9qCprUZbsRxxM/VqSW8MmsUtqB5nEpGEgUNnQi/BTm/2aK8tl7R4D0twGKRh6g1AAeFuWtXzk9Z/vQ==
"@next/swc-android-arm64@12.1.4":
version "12.1.4"
resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.1.4.tgz#f320d60639e19ecffa1f9034829f2d95502a9a51"
integrity sha512-LXraazvQQFBgxIg3Htny6G5V5he9EK7oS4jWtMdTGIikmD/OGByOv8ZjLuVLZLtVm3UIvaAiGtlQSLecxJoJDw==
"@next/swc-android-arm64@12.2.2":
version "12.2.2"
resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.2.2.tgz#b69de59c51e631a7600439e7a8993d6e82f3369e"
integrity sha512-v5EYzXUOSv0r9mO/2PX6mOcF53k8ndlu9yeFHVAWW1Dhw2jaJcvTRcCAwYYN8Q3tDg0nH3NbEltJDLKmcJOuVA==
"@next/swc-darwin-arm64@12.1.4":
version "12.1.4"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.1.4.tgz#fd578278312613eddcf3aee26910100509941b63"
integrity sha512-SSST/dBymecllZxcqTCcSTCu5o1NKk9I+xcvhn/O9nH6GWjgvGgGkNqLbCarCa0jJ1ukvlBA138FagyrmZ/4rQ==
"@next/swc-darwin-arm64@12.2.2":
version "12.2.2"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.2.2.tgz#80157c91668eff95b72d052428c353eab0fc4c50"
integrity sha512-JCoGySHKGt+YBk7xRTFGx1QjrnCcwYxIo3yGepcOq64MoiocTM3yllQWeOAJU2/k9MH0+B5E9WUSme4rOCBbpA==
"@next/swc-darwin-x64@12.1.4":
version "12.1.4"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.1.4.tgz#ace5f80d8c8348efe194f6d7074c6213c52b3944"
integrity sha512-p1lwdX0TVjaoDXQVuAkjtxVBbCL/urgxiMCBwuPDO7TikpXtSRivi+mIzBj5q7ypgICFmIAOW3TyupXeoPRAnA==
"@next/swc-darwin-x64@12.2.2":
version "12.2.2"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.2.2.tgz#12be2f58e676fccff3d48a62921b9927ed295133"
integrity sha512-dztDtvfkhUqiqpXvrWVccfGhLe44yQ5tQ7B4tBfnsOR6vxzI9DNPHTlEOgRN9qDqTAcFyPxvg86mn4l8bB9Jcw==
"@next/swc-linux-arm-gnueabihf@12.1.4":
version "12.1.4"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.1.4.tgz#2bf2c83863635f19c71c226a2df936e001cce29c"
integrity sha512-67PZlgkCn3TDxacdVft0xqDCL7Io1/C4xbAs0+oSQ0xzp6OzN2RNpuKjHJrJgKd0DsE1XZ9sCP27Qv0591yfyg==
"@next/swc-freebsd-x64@12.2.2":
version "12.2.2"
resolved "https://registry.yarnpkg.com/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.2.2.tgz#de1363431a49059f1efb8c0f86ce6a79c53b3a95"
integrity sha512-JUnXB+2xfxqsAvhFLPJpU1NeyDsvJrKoOjpV7g3Dxbno2Riu4tDKn3kKF886yleAuD/1qNTUCpqubTvbbT2VoA==
"@next/swc-linux-arm64-gnu@12.1.4":
version "12.1.4"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.1.4.tgz#d577190f641c9b4b463719dd6b8953b6ba9be8d9"
integrity sha512-OnOWixhhw7aU22TQdQLYrgpgFq0oA1wGgnjAiHJ+St7MLj82KTDyM9UcymAMbGYy6nG/TFOOHdTmRMtCRNOw0g==
"@next/swc-linux-arm-gnueabihf@12.2.2":
version "12.2.2"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.2.2.tgz#d5b8e0d1bb55bbd9db4d2fec018217471dc8b9e6"
integrity sha512-XeYC/qqPLz58R4pjkb+x8sUUxuGLnx9QruC7/IGkK68yW4G17PHwKI/1njFYVfXTXUukpWjcfBuauWwxp9ke7Q==
"@next/swc-linux-arm64-musl@12.1.4":
version "12.1.4"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.1.4.tgz#e70ffe70393d8f9242deecdb282ce5a8fd588b14"
integrity sha512-UoRMzPZnsAavdWtVylYxH8DNC7Uy0i6RrvNwT4PyQVdfANBn2omsUkcH5lgS2O7oaz0nAYLk1vqyZDO7+tJotA==
"@next/swc-linux-arm64-gnu@12.2.2":
version "12.2.2"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.2.2.tgz#3bc75984e1d5ec8f59eb53702cc382d8e1be2061"
integrity sha512-d6jT8xgfKYFkzR7J0OHo2D+kFvY/6W8qEo6/hmdrTt6AKAqxs//rbbcdoyn3YQq1x6FVUUd39zzpezZntg9Naw==
"@next/swc-linux-x64-gnu@12.1.4":
version "12.1.4"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.1.4.tgz#91498a130387fb1961902f2bee55863f8e910cff"
integrity sha512-nM+MA/frxlTLUKLJKorctdI20/ugfHRjVEEkcLp/58LGG7slNaP1E5d5dRA1yX6ISjPcQAkywas5VlGCg+uTvA==
"@next/swc-linux-arm64-musl@12.2.2":
version "12.2.2"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.2.2.tgz#270db73e07a18d999f61e79a917943fa5bc1ef56"
integrity sha512-rIZRFxI9N/502auJT1i7coas0HTHUM+HaXMyJiCpnY8Rimbo0495ir24tzzHo3nQqJwcflcPTwEh/DV17sdv9A==
"@next/swc-linux-x64-musl@12.1.4":
version "12.1.4"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.1.4.tgz#78057b03c148c121553d41521ad38f6c732762ff"
integrity sha512-GoRHxkuW4u4yKw734B9SzxJwVdyEJosaZ62P7ifOwcujTxhgBt3y76V2nNUrsSuopcKI2ZTDjaa+2wd5zyeXbA==
"@next/swc-linux-x64-gnu@12.2.2":
version "12.2.2"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.2.2.tgz#e6c72fa20478552e898c434f4d4c0c5e89d2ea78"
integrity sha512-ir1vNadlUDj7eQk15AvfhG5BjVizuCHks9uZwBfUgT5jyeDCeRvaDCo1+Q6+0CLOAnYDR/nqSCvBgzG2UdFh9A==
"@next/swc-win32-arm64-msvc@12.1.4":
version "12.1.4"
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.1.4.tgz#05bbaabacac23b8edf6caa99eb86b17550a09051"
integrity sha512-6TQkQze0ievXwHJcVUrIULwCYVe3ccX6T0JgZ1SiMeXpHxISN7VJF/O8uSCw1JvXZYZ6ud0CJ7nfC5HXivgfPg==
"@next/swc-linux-x64-musl@12.2.2":
version "12.2.2"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.2.2.tgz#b9ef9efe2c401839cdefa5e70402386aafdce15a"
integrity sha512-bte5n2GzLN3O8JdSFYWZzMgEgDHZmRz5wiispiiDssj4ik3l8E7wq/czNi8RmIF+ioj2sYVokUNa/ekLzrESWw==
"@next/swc-win32-ia32-msvc@12.1.4":
version "12.1.4"
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.1.4.tgz#8fd2fb48f04a2802e51fc320878bf6b411c1c866"
integrity sha512-CsbX/IXuZ5VSmWCpSetG2HD6VO5FTsO39WNp2IR2Ut/uom9XtLDJAZqjQEnbUTLGHuwDKFjrIO3LkhtROXLE/g==
"@next/swc-win32-arm64-msvc@12.2.2":
version "12.2.2"
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.2.2.tgz#18fa7ec7248da3a7926a0601d9ececc53ac83157"
integrity sha512-ZUGCmcDmdPVSAlwJ/aD+1F9lYW8vttseiv4n2+VCDv5JloxiX9aY32kYZaJJO7hmTLNrprvXkb4OvNuHdN22Jg==
"@next/swc-win32-x64-msvc@12.1.4":
version "12.1.4"
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.1.4.tgz#a72ed44c9b1f850986a30fe36c59e01f8a79b5f3"
integrity sha512-JtYuWzKXKLDMgE/xTcFtCm1MiCIRaAc5XYZfYX3n/ZWSI1SJS/GMm+Su0SAHJgRFavJh6U/p998YwO/iGTIgqQ==
"@next/swc-win32-ia32-msvc@12.2.2":
version "12.2.2"
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.2.2.tgz#54936e84f4a219441d051940354da7cd3eafbb4f"
integrity sha512-v7ykeEDbr9eXiblGSZiEYYkWoig6sRhAbLKHUHQtk8vEWWVEqeXFcxmw6LRrKu5rCN1DY357UlYWToCGPQPCRA==
"@next/swc-win32-x64-msvc@12.2.2":
version "12.2.2"
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.2.2.tgz#7460be700a60d75816f01109400b51fe929d7e89"
integrity sha512-2D2iinWUL6xx8D9LYVZ5qi7FP6uLAoWymt8m8aaG2Ld/Ka8/k723fJfiklfuAcwOxfufPJI+nRbT5VcgHGzHAQ==
"@nodelib/fs.scandir@2.1.4":
version "2.1.4"
@ -1324,10 +1329,10 @@
lodash "^4.17.20"
lodash-es "^4.17.20"
"@rushstack/eslint-patch@^1.0.8":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.1.1.tgz#782fa5da44c4f38ae9fd38e9184b54e451936118"
integrity sha512-BUyKJGdDWqvWC5GEhyOiUrGNi9iJUr4CU0O2WxJL6QJhHeeA/NVBalH+FeK0r/x/W0rPymXt5s78TDS7d6lCwg==
"@rushstack/eslint-patch@^1.1.3":
version "1.1.4"
resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.1.4.tgz#0c8b74c50f29ee44f423f7416829c0bf8bb5eb27"
integrity sha512-LwzQKA4vzIct1zNZzBmRKI9QuNpLgTQMEjsQLf3BXuGYb3QPTP4Yjf6mkdX+X1mYttZ808QpOwAzZjv28kq7DA==
"@sentry/browser@7.0.0":
version "7.0.0"
@ -1573,6 +1578,13 @@
"@svgr/plugin-jsx" "^6.2.1"
"@svgr/plugin-svgo" "^6.2.0"
"@swc/helpers@0.4.2":
version "0.4.2"
resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.4.2.tgz#ed1f6997ffbc22396665d9ba74e2a5c0a2d782f8"
integrity sha512-556Az0VX7WR6UdoTn4htt/l3zPQ7bsQWK+HqdG4swV7beUCxo/BqmvbOpUkTIm/9ih86LIf1qsUnywNL3obGHw==
dependencies:
tslib "^2.4.0"
"@tailwindcss/forms@^0.4.0":
version "0.4.0"
resolved "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.4.0.tgz"
@ -1799,16 +1811,6 @@
semver "^7.3.5"
tsutils "^3.21.0"
"@typescript-eslint/parser@^5.0.0":
version "5.16.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.16.0.tgz#e4de1bde4b4dad5b6124d3da227347616ed55508"
integrity sha512-fkDq86F0zl8FicnJtdXakFs4lnuebH6ZADDw6CYQv0UZeIjHvmEw87m9/29nk2Dv5Lmdp0zQ3zDQhiMWQf/GbA==
dependencies:
"@typescript-eslint/scope-manager" "5.16.0"
"@typescript-eslint/types" "5.16.0"
"@typescript-eslint/typescript-estree" "5.16.0"
debug "^4.3.2"
"@typescript-eslint/parser@^5.21.0":
version "5.21.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.21.0.tgz#6cb72673dbf3e1905b9c432175a3c86cdaf2071f"
@ -1819,14 +1821,6 @@
"@typescript-eslint/typescript-estree" "5.21.0"
debug "^4.3.2"
"@typescript-eslint/scope-manager@5.16.0":
version "5.16.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.16.0.tgz#7e7909d64bd0c4d8aef629cdc764b9d3e1d3a69a"
integrity sha512-P+Yab2Hovg8NekLIR/mOElCDPyGgFZKhGoZA901Yax6WR6HVeGLbsqJkZ+Cvk5nts/dAlFKm8PfL43UZnWdpIQ==
dependencies:
"@typescript-eslint/types" "5.16.0"
"@typescript-eslint/visitor-keys" "5.16.0"
"@typescript-eslint/scope-manager@5.21.0":
version "5.21.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.21.0.tgz#a4b7ed1618f09f95e3d17d1c0ff7a341dac7862e"
@ -1844,29 +1838,11 @@
debug "^4.3.2"
tsutils "^3.21.0"
"@typescript-eslint/types@5.16.0":
version "5.16.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.16.0.tgz#5827b011982950ed350f075eaecb7f47d3c643ee"
integrity sha512-oUorOwLj/3/3p/HFwrp6m/J2VfbLC8gjW5X3awpQJ/bSG+YRGFS4dpsvtQ8T2VNveV+LflQHjlLvB6v0R87z4g==
"@typescript-eslint/types@5.21.0":
version "5.21.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.21.0.tgz#8cdb9253c0dfce3f2ab655b9d36c03f72e684017"
integrity sha512-XnOOo5Wc2cBlq8Lh5WNvAgHzpjnEzxn4CJBwGkcau7b/tZ556qrWXQz4DJyChYg8JZAD06kczrdgFPpEQZfDsA==
"@typescript-eslint/typescript-estree@5.16.0":
version "5.16.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.16.0.tgz#32259459ec62f5feddca66adc695342f30101f61"
integrity sha512-SE4VfbLWUZl9MR+ngLSARptUv2E8brY0luCdgmUevU6arZRY/KxYoLI/3V/yxaURR8tLRN7bmZtJdgmzLHI6pQ==
dependencies:
"@typescript-eslint/types" "5.16.0"
"@typescript-eslint/visitor-keys" "5.16.0"
debug "^4.3.2"
globby "^11.0.4"
is-glob "^4.0.3"
semver "^7.3.5"
tsutils "^3.21.0"
"@typescript-eslint/typescript-estree@5.21.0":
version "5.21.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.21.0.tgz#9f0c233e28be2540eaed3df050f0d54fb5aa52de"
@ -1892,14 +1868,6 @@
eslint-scope "^5.1.1"
eslint-utils "^3.0.0"
"@typescript-eslint/visitor-keys@5.16.0":
version "5.16.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.16.0.tgz#f27dc3b943e6317264c7492e390c6844cd4efbbb"
integrity sha512-jqxO8msp5vZDhikTwq9ubyMHqZ67UIvawohr4qF3KhlpL7gzSjOd+8471H3nh5LyABkaI85laEKKU8SnGUK5/g==
dependencies:
"@typescript-eslint/types" "5.16.0"
eslint-visitor-keys "^3.0.0"
"@typescript-eslint/visitor-keys@5.21.0":
version "5.21.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.21.0.tgz#453fb3662409abaf2f8b1f65d515699c888dd8ae"
@ -2078,6 +2046,17 @@ array-includes@^3.1.4:
get-intrinsic "^1.1.1"
is-string "^1.0.7"
array-includes@^3.1.5:
version "3.1.5"
resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.5.tgz#2c320010db8d31031fd2a5f6b3bbd4b1aad31bdb"
integrity sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==
dependencies:
call-bind "^1.0.2"
define-properties "^1.1.4"
es-abstract "^1.19.5"
get-intrinsic "^1.1.1"
is-string "^1.0.7"
array-union@^2.1.0:
version "2.1.0"
resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz"
@ -2111,14 +2090,15 @@ array.prototype.flatmap@^1.2.4:
es-abstract "^1.18.0-next.1"
function-bind "^1.1.1"
array.prototype.flatmap@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.5.tgz#908dc82d8a406930fdf38598d51e7411d18d4446"
integrity sha512-08u6rVyi1Lj7oqWbS9nUxliETrtIROT4XGTA4D/LWGten6E3ocm7cy9SIrmNHOL5XVbVuckUp3X6Xyg8/zpvHA==
array.prototype.flatmap@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.0.tgz#a7e8ed4225f4788a70cd910abcf0791e76a5534f"
integrity sha512-PZC9/8TKAIxcWKdyeb77EzULHPrIX/tIZebLJUQOMR1OwYosT8yggdfWScfTBCDj5utONvOuPQQumYsU2ULbkg==
dependencies:
call-bind "^1.0.0"
call-bind "^1.0.2"
define-properties "^1.1.3"
es-abstract "^1.19.0"
es-abstract "^1.19.2"
es-shim-unscopables "^1.0.0"
ast-types-flow@^0.0.7:
version "0.0.7"
@ -2280,16 +2260,16 @@ camelcase@^6.2.0:
resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz"
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
caniuse-lite@^1.0.30001283:
version "1.0.30001304"
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001304.tgz"
integrity sha512-bdsfZd6K6ap87AGqSHJP/s1V+U6Z5lyrcbBu3ovbCCf8cSYpwTtGrCBObMpJqwxfTbLW6YTIdbb1jEeTelcpYQ==
caniuse-lite@^1.0.30001286, caniuse-lite@^1.0.30001297:
version "1.0.30001303"
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001303.tgz"
integrity sha512-/Mqc1oESndUNszJP0kx0UaQU9kEv9nNtJ7Kn8AdA0mNnH8eR1cj0kG+NbNuC1Wq/b21eA8prhKRA3bbkjONegQ==
caniuse-lite@^1.0.30001332:
version "1.0.30001367"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001367.tgz#2b97fe472e8fa29c78c5970615d7cd2ee414108a"
integrity sha512-XDgbeOHfifWV3GEES2B8rtsrADx4Jf+juKX2SICJcaUhjYBO3bR96kvEIHa15VU6ohtOhBZuPGGYGbXMRn0NCw==
chalk@^2.0.0:
version "2.4.2"
resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz"
@ -2584,6 +2564,14 @@ define-properties@^1.1.3:
dependencies:
object-keys "^1.0.12"
define-properties@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1"
integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==
dependencies:
has-property-descriptors "^1.0.0"
object-keys "^1.1.1"
defined@^1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz"
@ -2784,6 +2772,42 @@ es-abstract@^1.19.0, es-abstract@^1.19.1:
string.prototype.trimstart "^1.0.4"
unbox-primitive "^1.0.1"
es-abstract@^1.19.2, es-abstract@^1.19.5:
version "1.20.1"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.1.tgz#027292cd6ef44bd12b1913b828116f54787d1814"
integrity sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==
dependencies:
call-bind "^1.0.2"
es-to-primitive "^1.2.1"
function-bind "^1.1.1"
function.prototype.name "^1.1.5"
get-intrinsic "^1.1.1"
get-symbol-description "^1.0.0"
has "^1.0.3"
has-property-descriptors "^1.0.0"
has-symbols "^1.0.3"
internal-slot "^1.0.3"
is-callable "^1.2.4"
is-negative-zero "^2.0.2"
is-regex "^1.1.4"
is-shared-array-buffer "^1.0.2"
is-string "^1.0.7"
is-weakref "^1.0.2"
object-inspect "^1.12.0"
object-keys "^1.1.1"
object.assign "^4.1.2"
regexp.prototype.flags "^1.4.3"
string.prototype.trimend "^1.0.5"
string.prototype.trimstart "^1.0.5"
unbox-primitive "^1.0.2"
es-shim-unscopables@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241"
integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==
dependencies:
has "^1.0.3"
es-to-primitive@^1.2.1:
version "1.2.1"
resolved "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz"
@ -2803,20 +2827,20 @@ escape-string-regexp@^1.0.5:
resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz"
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
eslint-config-next@12.1.0:
version "12.1.0"
resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-12.1.0.tgz#8ace680dc5207e6ab6c915f3989adec122f582e7"
integrity sha512-tBhuUgoDITcdcM7xFvensi9I5WTI4dnvH4ETGRg1U8ZKpXrZsWQFdOKIDzR3RLP5HR3xXrLviaMM4c3zVoE/pA==
eslint-config-next@^12.2.2:
version "12.2.2"
resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-12.2.2.tgz#4bb996026e118071849bc4011283a160ad5bde46"
integrity sha512-oJhWBLC4wDYYUFv/5APbjHUFd0QRFCojMdj/QnMoOEktmeTvwnnoA8F8uaXs0fQgsaTK0tbUxBRv9/Y4/rpxOA==
dependencies:
"@next/eslint-plugin-next" "12.1.0"
"@rushstack/eslint-patch" "^1.0.8"
"@typescript-eslint/parser" "^5.0.0"
eslint-import-resolver-node "^0.3.4"
eslint-import-resolver-typescript "^2.4.0"
eslint-plugin-import "^2.25.2"
"@next/eslint-plugin-next" "12.2.2"
"@rushstack/eslint-patch" "^1.1.3"
"@typescript-eslint/parser" "^5.21.0"
eslint-import-resolver-node "^0.3.6"
eslint-import-resolver-typescript "^2.7.1"
eslint-plugin-import "^2.26.0"
eslint-plugin-jsx-a11y "^6.5.1"
eslint-plugin-react "^7.27.0"
eslint-plugin-react-hooks "^4.3.0"
eslint-plugin-react "^7.29.4"
eslint-plugin-react-hooks "^4.5.0"
eslint-import-resolver-node@^0.3.4:
version "0.3.4"
@ -2834,7 +2858,7 @@ eslint-import-resolver-node@^0.3.6:
debug "^3.2.7"
resolve "^1.20.0"
eslint-import-resolver-typescript@^2.4.0, eslint-import-resolver-typescript@^2.7.0:
eslint-import-resolver-typescript@^2.7.0:
version "2.7.0"
resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.7.0.tgz#1f9d391b636dccdbaa4a3b1a87eb9a8237e23963"
integrity sha512-MNHS3u5pebvROX4MjGP9coda589ZGfL1SqdxUV4kSrcclfDRWvNE2D+eljbnWVMvWDVRgT89nhscMHPKYGcObQ==
@ -2845,6 +2869,17 @@ eslint-import-resolver-typescript@^2.4.0, eslint-import-resolver-typescript@^2.7
resolve "^1.22.0"
tsconfig-paths "^3.14.1"
eslint-import-resolver-typescript@^2.7.1:
version "2.7.1"
resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.7.1.tgz#a90a4a1c80da8d632df25994c4c5fdcdd02b8751"
integrity sha512-00UbgGwV8bSgUv34igBDbTOtKhqoRMy9bFjNehT40bXg6585PNIct8HhXZ0SybqB9rWtXj9crcku8ndDn/gIqQ==
dependencies:
debug "^4.3.4"
glob "^7.2.0"
is-glob "^4.0.3"
resolve "^1.22.0"
tsconfig-paths "^3.14.1"
eslint-module-utils@^2.6.0:
version "2.6.0"
resolved "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz"
@ -2853,7 +2888,7 @@ eslint-module-utils@^2.6.0:
debug "^2.6.9"
pkg-dir "^2.0.0"
eslint-module-utils@^2.7.2:
eslint-module-utils@^2.7.3:
version "2.7.3"
resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz#ad7e3a10552fdd0642e1e55292781bd6e34876ee"
integrity sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==
@ -2880,24 +2915,24 @@ eslint-plugin-import@^2.22.1:
resolve "^1.17.0"
tsconfig-paths "^3.9.0"
eslint-plugin-import@^2.25.2:
version "2.25.4"
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.25.4.tgz#322f3f916a4e9e991ac7af32032c25ce313209f1"
integrity sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA==
eslint-plugin-import@^2.26.0:
version "2.26.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz#f812dc47be4f2b72b478a021605a59fc6fe8b88b"
integrity sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==
dependencies:
array-includes "^3.1.4"
array.prototype.flat "^1.2.5"
debug "^2.6.9"
doctrine "^2.1.0"
eslint-import-resolver-node "^0.3.6"
eslint-module-utils "^2.7.2"
eslint-module-utils "^2.7.3"
has "^1.0.3"
is-core-module "^2.8.0"
is-core-module "^2.8.1"
is-glob "^4.0.3"
minimatch "^3.0.4"
minimatch "^3.1.2"
object.values "^1.1.5"
resolve "^1.20.0"
tsconfig-paths "^3.12.0"
resolve "^1.22.0"
tsconfig-paths "^3.14.1"
eslint-plugin-jsx-a11y@^6.5.1:
version "6.5.1"
@ -2922,10 +2957,10 @@ eslint-plugin-react-hooks@^4.2.0:
resolved "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz"
integrity sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ==
eslint-plugin-react-hooks@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.3.0.tgz#318dbf312e06fab1c835a4abef00121751ac1172"
integrity sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA==
eslint-plugin-react-hooks@^4.5.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3"
integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==
eslint-plugin-react@^7.23.2:
version "7.23.2"
@ -2945,25 +2980,25 @@ eslint-plugin-react@^7.23.2:
resolve "^2.0.0-next.3"
string.prototype.matchall "^4.0.4"
eslint-plugin-react@^7.27.0:
version "7.29.4"
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.29.4.tgz#4717de5227f55f3801a5fd51a16a4fa22b5914d2"
integrity sha512-CVCXajliVh509PcZYRFyu/BoUEz452+jtQJq2b3Bae4v3xBUWPLCmtmBM+ZinG4MzwmxJgJ2M5rMqhqLVn7MtQ==
eslint-plugin-react@^7.29.4:
version "7.30.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.30.1.tgz#2be4ab23ce09b5949c6631413ba64b2810fd3e22"
integrity sha512-NbEvI9jtqO46yJA3wcRF9Mo0lF9T/jhdHqhCHXiXtD+Zcb98812wvokjWpU7Q4QH5edo6dmqrukxVvWWXHlsUg==
dependencies:
array-includes "^3.1.4"
array.prototype.flatmap "^1.2.5"
array-includes "^3.1.5"
array.prototype.flatmap "^1.3.0"
doctrine "^2.1.0"
estraverse "^5.3.0"
jsx-ast-utils "^2.4.1 || ^3.0.0"
minimatch "^3.1.2"
object.entries "^1.1.5"
object.fromentries "^2.0.5"
object.hasown "^1.1.0"
object.hasown "^1.1.1"
object.values "^1.1.5"
prop-types "^15.8.1"
resolve "^2.0.0-next.3"
semver "^6.3.0"
string.prototype.matchall "^4.0.6"
string.prototype.matchall "^4.0.7"
eslint-plugin-simple-import-sort@^7.0.0:
version "7.0.0"
@ -3230,11 +3265,26 @@ function-bind@^1.1.1:
resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz"
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
function.prototype.name@^1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621"
integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==
dependencies:
call-bind "^1.0.2"
define-properties "^1.1.3"
es-abstract "^1.19.0"
functions-have-names "^1.2.2"
functional-red-black-tree@^1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz"
integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=
functions-have-names@^1.2.2:
version "1.2.3"
resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834"
integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==
gauge@~2.7.3:
version "2.7.4"
resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
@ -3271,11 +3321,6 @@ get-symbol-description@^1.0.0:
call-bind "^1.0.2"
get-intrinsic "^1.1.1"
github-buttons@^2.21.1:
version "2.21.1"
resolved "https://registry.yarnpkg.com/github-buttons/-/github-buttons-2.21.1.tgz#9e55eb83b70c9149a21c235db2e971c53d4d98a2"
integrity sha512-n9bCQ8sj+5oX1YH5NeyWGbAclRDtHEhMBzqw2ctsWpdEHOwVgfruRu0VIVy01Ah10dd/iFajMHYU71L7IBWBOw==
glob-parent@^5.0.0, glob-parent@^5.1.2, glob-parent@~5.1.2:
version "5.1.2"
resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz"
@ -3367,6 +3412,11 @@ has-bigints@^1.0.1:
resolved "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz"
integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==
has-bigints@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa"
integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==
has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz"
@ -3377,6 +3427,13 @@ has-flag@^4.0.0:
resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz"
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
has-property-descriptors@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861"
integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==
dependencies:
get-intrinsic "^1.1.1"
has-symbols@^1.0.1, has-symbols@^1.0.2:
version "1.0.2"
resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz"
@ -3590,7 +3647,7 @@ is-core-module@^2.2.0:
dependencies:
has "^1.0.3"
is-core-module@^2.8.0, is-core-module@^2.8.1:
is-core-module@^2.8.1:
version "2.8.1"
resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz"
integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==
@ -3638,6 +3695,11 @@ is-negative-zero@^2.0.1:
resolved "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz"
integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==
is-negative-zero@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150"
integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==
is-number-object@^1.0.4:
version "1.0.5"
resolved "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz"
@ -3669,6 +3731,13 @@ is-shared-array-buffer@^1.0.1:
resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz#97b0c85fbdacb59c9c446fe653b82cf2b5b7cfe6"
integrity sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==
is-shared-array-buffer@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79"
integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==
dependencies:
call-bind "^1.0.2"
is-string@^1.0.5:
version "1.0.6"
resolved "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz"
@ -3688,7 +3757,7 @@ is-symbol@^1.0.2, is-symbol@^1.0.3:
dependencies:
has-symbols "^1.0.2"
is-weakref@^1.0.1:
is-weakref@^1.0.1, is-weakref@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2"
integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==
@ -4093,28 +4162,31 @@ next-plausible@^3.1.9:
resolved "https://registry.yarnpkg.com/next-plausible/-/next-plausible-3.1.9.tgz#4795df2e83a6ca14495d2fa0d31a92649c42425f"
integrity sha512-6Ro6lVnuXAtqbbBQfuKuu0cpZHWWvJWbOE1G+Rx6i42T6lLYtbQzbu09Cutv3vc/wD/4ySHzJkuTnxsqnlArGA==
next@^12.1.4:
version "12.1.4"
resolved "https://registry.yarnpkg.com/next/-/next-12.1.4.tgz#597a9bdec7aec778b442c4f6d41afd2c64a54b23"
integrity sha512-DA4g97BM4Z0nKtDvCTm58RxdvoQyYzeg0AeVbh0N4Y/D8ELrNu47lQeEgRGF8hV4eQ+Sal90zxrJQQG/mPQ8CQ==
next@^12.2.2:
version "12.2.2"
resolved "https://registry.yarnpkg.com/next/-/next-12.2.2.tgz#029bf5e4a18a891ca5d05b189b7cd983fd22c072"
integrity sha512-zAYFY45aBry/PlKONqtlloRFqU/We3zWYdn2NoGvDZkoYUYQSJC8WMcalS5C19MxbCZLUVCX7D7a6gTGgl2yLg==
dependencies:
"@next/env" "12.1.4"
caniuse-lite "^1.0.30001283"
"@next/env" "12.2.2"
"@swc/helpers" "0.4.2"
caniuse-lite "^1.0.30001332"
postcss "8.4.5"
styled-jsx "5.0.1"
styled-jsx "5.0.2"
use-sync-external-store "1.1.0"
optionalDependencies:
"@next/swc-android-arm-eabi" "12.1.4"
"@next/swc-android-arm64" "12.1.4"
"@next/swc-darwin-arm64" "12.1.4"
"@next/swc-darwin-x64" "12.1.4"
"@next/swc-linux-arm-gnueabihf" "12.1.4"
"@next/swc-linux-arm64-gnu" "12.1.4"
"@next/swc-linux-arm64-musl" "12.1.4"
"@next/swc-linux-x64-gnu" "12.1.4"
"@next/swc-linux-x64-musl" "12.1.4"
"@next/swc-win32-arm64-msvc" "12.1.4"
"@next/swc-win32-ia32-msvc" "12.1.4"
"@next/swc-win32-x64-msvc" "12.1.4"
"@next/swc-android-arm-eabi" "12.2.2"
"@next/swc-android-arm64" "12.2.2"
"@next/swc-darwin-arm64" "12.2.2"
"@next/swc-darwin-x64" "12.2.2"
"@next/swc-freebsd-x64" "12.2.2"
"@next/swc-linux-arm-gnueabihf" "12.2.2"
"@next/swc-linux-arm64-gnu" "12.2.2"
"@next/swc-linux-arm64-musl" "12.2.2"
"@next/swc-linux-x64-gnu" "12.2.2"
"@next/swc-linux-x64-musl" "12.2.2"
"@next/swc-win32-arm64-msvc" "12.2.2"
"@next/swc-win32-ia32-msvc" "12.2.2"
"@next/swc-win32-x64-msvc" "12.2.2"
node-fetch@^2.6.7:
version "2.6.7"
@ -4190,6 +4262,11 @@ object-inspect@^1.11.0:
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0"
integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==
object-inspect@^1.12.0:
version "1.12.2"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea"
integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==
object-inspect@^1.9.0:
version "1.10.3"
resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz"
@ -4248,13 +4325,13 @@ object.fromentries@^2.0.5:
define-properties "^1.1.3"
es-abstract "^1.19.1"
object.hasown@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.0.tgz#7232ed266f34d197d15cac5880232f7a4790afe5"
integrity sha512-MhjYRfj3GBlhSkDHo6QmvgjRLXQ2zndabdf3nX0yTyZK9rPfxb6uRpAac8HXNLy1GpqWtZ81Qh4v3uOls2sRAg==
object.hasown@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.1.tgz#ad1eecc60d03f49460600430d97f23882cf592a3"
integrity sha512-LYLe4tivNQzq4JdaWW6WO3HMZZJWzkkH8fnI6EebWl0VZth2wL2Lovm74ep2/gZzlaTdV62JZHEqHQ2yVn8Q/A==
dependencies:
define-properties "^1.1.3"
es-abstract "^1.19.1"
define-properties "^1.1.4"
es-abstract "^1.19.5"
object.values@^1.1.1, object.values@^1.1.3:
version "1.1.3"
@ -4579,13 +4656,6 @@ react-dom@17.0.2:
object-assign "^4.1.1"
scheduler "^0.20.2"
react-github-btn@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/react-github-btn/-/react-github-btn-1.2.2.tgz#9aab2498ff311b9f9c448a2d2b902d0277037d5c"
integrity sha512-X4IcX2qwaLciSa4wcUsrFgF2PcT+ukMbZZRBT50ZvO2HJMyqQJNYNHErCN2R0sgZfSFQHUuUHlGndF15VQUhPA==
dependencies:
github-buttons "^2.21.1"
react-hook-form@^7.31.3:
version "7.31.3"
resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.31.3.tgz#b61bafb9a7435f91695351a7a9f714d8c4df0121"
@ -4772,6 +4842,15 @@ regexp.prototype.flags@^1.4.1:
call-bind "^1.0.2"
define-properties "^1.1.3"
regexp.prototype.flags@^1.4.3:
version "1.4.3"
resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac"
integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==
dependencies:
call-bind "^1.0.2"
define-properties "^1.1.3"
functions-have-names "^1.2.2"
regexpp@^3.1.0:
version "3.1.0"
resolved "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz"
@ -5128,7 +5207,7 @@ string.prototype.matchall@^4.0.4:
regexp.prototype.flags "^1.3.1"
side-channel "^1.0.4"
string.prototype.matchall@^4.0.6:
string.prototype.matchall@^4.0.7:
version "4.0.7"
resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz#8e6ecb0d8a1fb1fda470d81acecb2dba057a481d"
integrity sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==
@ -5150,6 +5229,15 @@ string.prototype.trimend@^1.0.4:
call-bind "^1.0.2"
define-properties "^1.1.3"
string.prototype.trimend@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0"
integrity sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==
dependencies:
call-bind "^1.0.2"
define-properties "^1.1.4"
es-abstract "^1.19.5"
string.prototype.trimstart@^1.0.4:
version "1.0.4"
resolved "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz"
@ -5158,6 +5246,15 @@ string.prototype.trimstart@^1.0.4:
call-bind "^1.0.2"
define-properties "^1.1.3"
string.prototype.trimstart@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz#5466d93ba58cfa2134839f81d7f42437e8c01fef"
integrity sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==
dependencies:
call-bind "^1.0.2"
define-properties "^1.1.4"
es-abstract "^1.19.5"
string_decoder@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
@ -5204,10 +5301,10 @@ style-value-types@5.0.0:
hey-listen "^1.0.8"
tslib "^2.1.0"
styled-jsx@5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.1.tgz#78fecbbad2bf95ce6cd981a08918ce4696f5fc80"
integrity sha512-+PIZ/6Uk40mphiQJJI1202b+/dYeTVd9ZnMPR80pgiWbjIwvN2zIp4r9et0BgqBuShh48I0gttPlAXA7WVvBxw==
styled-jsx@5.0.2:
version "5.0.2"
resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.2.tgz#ff230fd593b737e9e68b630a694d460425478729"
integrity sha512-LqPQrbBh3egD57NBcHET4qcgshPks+yblyhPlH2GY8oaDgKs8SK4C3dBh3oSJjgzJ3G5t1SYEZGHkP+QEpX9EQ==
stylis@^4.0.6:
version "4.0.13"
@ -5349,7 +5446,7 @@ ts-easing@^0.2.0:
resolved "https://registry.npmjs.org/ts-easing/-/ts-easing-0.2.0.tgz"
integrity sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ==
tsconfig-paths@^3.12.0, tsconfig-paths@^3.14.1:
tsconfig-paths@^3.14.1:
version "3.14.1"
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz#ba0734599e8ea36c862798e920bcf163277b137a"
integrity sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==
@ -5379,6 +5476,11 @@ tslib@^2.1.0:
resolved "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz"
integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==
tslib@^2.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3"
integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==
tsutils@^3.21.0:
version "3.21.0"
resolved "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz"
@ -5423,6 +5525,16 @@ unbox-primitive@^1.0.0, unbox-primitive@^1.0.1:
has-symbols "^1.0.2"
which-boxed-primitive "^1.0.2"
unbox-primitive@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e"
integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==
dependencies:
call-bind "^1.0.2"
has-bigints "^1.0.2"
has-symbols "^1.0.3"
which-boxed-primitive "^1.0.2"
uncontrollable@^7.0.0:
version "7.2.1"
resolved "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz"
@ -5476,6 +5588,11 @@ use-isomorphic-layout-effect@^1.1.1:
resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz#497cefb13d863d687b08477d9e5a164ad8c1a6fb"
integrity sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==
use-sync-external-store@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.1.0.tgz#3343c3fe7f7e404db70f8c687adf5c1652d34e82"
integrity sha512-SEnieB2FPKEVne66NpXPd1Np4R1lTNKfjuy3XdIoPQKYBAFdzbzSZlSn1KJZUiihQLQC5Znot4SBz1EOTBwQAQ==
util-deprecate@^1.0.2, util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"