1
0
mirror of https://github.com/XFox111/my-website.git synced 2026-04-22 07:28:01 +03:00

chore(deps): dependency bumps + related refactoring (fixes #19)

This commit is contained in:
2025-01-26 21:50:56 +00:00
parent 9d369ad4d2
commit 457fbf33e5
44 changed files with 657 additions and 601 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
@import "../theme.scss";
@use "@/_styles/theme" as *;
.alertBox
{
+1 -1
View File
@@ -1,4 +1,4 @@
@import "../theme.scss";
@use "@/_styles/theme" as *;
.button
{
+1 -1
View File
@@ -1,4 +1,4 @@
@import "../theme.scss";
@use "@/_styles/theme" as *;
.banner
{
+1 -1
View File
@@ -1,4 +1,4 @@
@import "../theme.scss";
@use "@/_styles/theme" as *;
.footer
{
+1 -1
View File
@@ -1,4 +1,4 @@
@import "../theme.scss";
@use "@/_styles/theme" as *;
.header
{
+1 -1
View File
@@ -1,4 +1,4 @@
@import "../theme.scss";
@use "@/_styles/theme" as *;
.navigation
{
+4 -4
View File
@@ -1,4 +1,4 @@
@import "../theme.scss";
@use "@/_styles/theme" as *;
.dialog
{
@@ -15,6 +15,9 @@
color: unset;
border: none;
transition: right $durationNormal $curveEasyEaseMax;
right: -350px;
&::backdrop
{
-webkit-backdrop-filter: blur(8px);
@@ -64,9 +67,6 @@
}
}
transition: right $durationNormal $curveEasyEaseMax;
right: -350px;
&.show
{
right: 0;
+1 -1
View File
@@ -1,4 +1,4 @@
@import "../theme.scss";
@use "@/_styles/theme" as *;
.socials
{
+3 -2
View File
@@ -1,11 +1,12 @@
@import "../theme.scss";
@use "@/_styles/theme" as *;
.section
{
@include centerTwo;
min-height: 75vh;
align-items: end;
@include centerTwo;
.content
{
@include flex(column);
+1 -1
View File
@@ -3,7 +3,7 @@ import React from "react";
const ThirdPartyAttribution: React.FC = () => <>
<p>
Iconography, typography, and color palette of this website are based on
Microsoft's <a target="_blank" href="https://fluentui.dev/">Fluent Design System</a> licensed under
Microsoft&apos;s <a target="_blank" href="https://fluentui.dev/">Fluent Design System</a> licensed under
the <a target="_blank" href="https://github.com/microsoft/fluentui/blob/main/LICENSE">MIT License</a>.
</p>
<p>
+1 -1
View File
@@ -1,4 +1,4 @@
@import "../theme.scss";
@use "@/_styles/theme" as *;
.title
{
+3 -2
View File
@@ -1,12 +1,13 @@
@import "../theme.scss";
@use "@/_styles/theme" as *;
.section
{
@include centerTwo;
@include body2($fontFamilyBaseAlt);
color: $colorNeutralForeground2;
align-items: center;
@include centerTwo;
> div:first-child
{
@include flex(column);
@@ -1,4 +1,4 @@
@import "../theme.scss";
@use "@/_styles/theme" as *;
.section
{
+24 -20
View File
@@ -3,28 +3,31 @@
import Button from "@/_components/Button";
import SocialLinks from "@/_components/SocialLinks";
import contacts from "@/_data/contacts";
import FormStatusTracker from "@/_utils/FormStatusTracker";
import React, { InputHTMLAttributes, useEffect, useMemo, useState } from "react";
import { useFormState } from "react-dom";
import { getSitekey } from "@/_utils/turnstile";
import React, { InputHTMLAttributes, useActionState, useEffect, useMemo, useState } from "react";
import Turnstile from "react-turnstile";
import sendInquiry, { FormStatus } from "../_utils/sendInquiry";
import cls from "./ContactSection.module.scss";
import { getSitekey } from "@/_utils/turnstile";
const defaultState: FormStatus = { status: "idle" };
const ContactSection: React.FC = () =>
{
const [pending, setPending] = useState<boolean>(false);
const [{ status, message }, formAction] = useFormState<FormStatus, FormData>(sendInquiry, defaultState);
// Added state-backing for the form fields to prevent it from resetting on submit
// See https://github.com/facebook/react/issues/29034
// FIXME: Remove form state once #29034 is fixed
const [form, setForm] = useState<{ email: string, subject: string, message: string; }>({ email: "", subject: "", message: "" });
const [{ status, message }, formAction, isPending] = useActionState<FormStatus, FormData>(sendInquiry, defaultState);
const { telephone: phone, email, socials } = contacts;
const [cfSitekey, setCfSitekey] = useState<string | undefined | null>(null);
const sharedProps: InputHTMLAttributes<HTMLInputElement | HTMLTextAreaElement> = useMemo(() => ({
required: true,
disabled: pending,
readOnly: status === "success"
}), [status, pending]);
disabled: isPending,
readOnly: status === "success",
"data-clarity-mask": true
}), [status, isPending]);
useEffect(() =>
{
@@ -33,7 +36,7 @@ const ContactSection: React.FC = () =>
return (
<section id="contacts" className={ cls.section }>
<h2>Let's get in touch</h2>
<h2>Let&apos;s get in touch</h2>
<div className={ cls.content }>
@@ -41,19 +44,20 @@ const ContactSection: React.FC = () =>
<h3>Inquiries, requests or proposals</h3>
<form className={ cls.container } action={ formAction }>
<FormStatusTracker onPendingChanged={ setPending } />
<input name="email" type="email" { ...sharedProps } data-clarity-mask
<input name="email" type="email" { ...sharedProps }
value={ form.email } onChange={ e => setForm({ ...form, email: e.target.value }) }
autoComplete="email" spellCheck="false"
maxLength={ 60 }
placeholder="Email" />
<input name="subject" type="text" { ...sharedProps } data-clarity-mask
<input name="subject" type="text" { ...sharedProps }
value={ form.subject } onChange={ e => setForm({ ...form, subject: e.target.value }) }
autoComplete="off" spellCheck="true"
maxLength={ 120 }
placeholder="Subject" />
<textarea name="message" { ...sharedProps } className={ cls.textarea } data-clarity-mask
<textarea name="message" { ...sharedProps } className={ cls.textarea }
value={ form.message } onChange={ e => setForm({ ...form, message: e.target.value }) }
autoComplete="off" spellCheck="true"
minLength={ 100 } maxLength={ 2000 }
placeholder="Message (min 100 characters)" />
@@ -72,18 +76,18 @@ const ContactSection: React.FC = () =>
</div>
<div className={ cls.formToolbar }>
<div className={ `${cls.status} ${pending ? "" : cls[status]}` }>
{ pending &&
<div className={ `${cls.status} ${isPending ? "" : cls[status]}` }>
{ isPending &&
<span role="alert" aria-live="assertive">
Sending
</span>
}
{ !pending && status === "success" &&
{ !isPending && status === "success" &&
<span role="alert" aria-live="assertive">
Message successfully sent
</span>
}
{ !pending && status === "error" &&
{ !isPending && status === "error" &&
<span role="alert" aria-live="assertive">
{ message ?? "Something went wrong" }
</span>
@@ -91,7 +95,7 @@ const ContactSection: React.FC = () =>
</div>
{ status !== "success" &&
<Button type="submit" disabled={ pending }>
<Button type="submit" disabled={ isPending }>
Submit
</Button>
}
@@ -1,4 +1,4 @@
@import "../theme.scss";
@use "@/_styles/theme" as *;
.section
{
+1 -1
View File
@@ -37,7 +37,7 @@ const ExperienceSection: React.FC = () => (
function getAriaLabel(item: WorkplaceEntry): string
{
let str: string[] = [];
const str: string[] = [];
if (item.year)
str.push(`${item.year} -`);
@@ -1,4 +1,4 @@
@import "../theme.scss";
@use "@/_styles/theme" as *;
.section
{
@@ -30,8 +30,9 @@
.defaultImg
{
@include slideIn;
align-self: center;
@include slideIn;
}
.projectItem
+3 -2
View File
@@ -1,10 +1,11 @@
@import "../theme.scss";
@use "@/_styles/theme" as *;
.section
{
@include centerTwo;
align-items: center;
@include centerTwo;
.illustrations
{
justify-self: center;
+1 -1
View File
@@ -1,4 +1,4 @@
@import "../theme.scss";
@use "@/_styles/theme" as *;
.list
{
@@ -1,4 +1,4 @@
@import "./theme.scss";
@use "./theme" as *;
:root
{
@@ -35,6 +35,12 @@ body
max-width: 100vw;
overflow-x: hidden;
font-synthesis: none;
text-rendering: geometricPrecision;
background-color: $colorNeutralBackground1;
color: $colorNeutralForeground1;
> main
{
@include maxCenter;
@@ -43,12 +49,6 @@ body
margin-top: 56px;
}
font-synthesis: none;
text-rendering: geometricPrecision;
background-color: $colorNeutralBackground1;
color: $colorNeutralForeground1;
::selection
{
background-color: $colorNeutralBackgroundInverted;
+5
View File
@@ -0,0 +1,5 @@
@forward "dark";
@forward "light";
@forward "typography";
@forward "mixins";
@forward "tokens";
@@ -1,3 +1,6 @@
@use "tokens" as *;
@use "typography" as *;
@mixin maxCenter($maxWidth: 1400px)
{
align-self: center;
@@ -1,8 +1,3 @@
@import "./theme.dark.scss";
@import "./theme.light.scss";
@import "./theme.typography.scss";
@import "./theme.mixins.scss";
// Border radius
$borderRadiusNone: 0;
$borderRadiusSmall: 2px;
@@ -1,3 +1,5 @@
@use "tokens" as *;
@mixin caption2($font: $fontFamilyBase)
{
@include setTypography($font, $fontSizeBase100, $fontWeightRegular, $lineHeightBase100);
-32
View File
@@ -1,32 +0,0 @@
"use client";
import React, { useEffect } from "react";
import { useFormStatus } from "react-dom";
// Since useFormStatus requires to be inside of the form, I moved it to a separate helper component.
// Could it be done better? Probably.
// Did I do it? No.
/** Renders a React component that tracks the form status and calls the provided callback function when the form status changes. */
const FormStatusTracker: React.FC<FormStatusTrackerProps> = ({ onPendingChanged }) =>
{
const { pending } = useFormStatus();
useEffect(() =>
{
onPendingChanged(pending);
}, [pending, onPendingChanged]);
return null;
};
export default FormStatusTracker;
/** Props for the `FormStatusTracker` component. */
export type FormStatusTrackerProps =
{
/** The callback function that is called when the form status changes. */
// For some reason ESLint shows a warning for "unused" "pending" parameter.
// eslint-disable-next-line no-unused-vars
onPendingChanged: (pending: boolean) => void;
};
-1
View File
@@ -1,4 +1,3 @@
/* eslint-disable no-unused-vars */
declare global
{
interface Window
+3 -3
View File
@@ -35,9 +35,9 @@ function setCookie(name: string, value: string | number, maxAge: number): void
function getCookie(name: string): string | undefined
{
let cookieName = name + "=";
let rawCookies = decodeURIComponent(window.document.cookie);
let cookies = rawCookies.split(";");
const cookieName = name + "=";
const rawCookies = decodeURIComponent(window.document.cookie);
const cookies = rawCookies.split(";");
for (const cookie of cookies)
if (cookie.trim().startsWith(cookieName))
-2
View File
@@ -43,8 +43,6 @@ export default async function sendInquiry(_: FormStatus, formData: FormData): Pr
message: "Challenge has expired. Try again"
};
console.error(error);
return {
status: "error",
message: "Something went wrong"
+2 -3
View File
@@ -13,12 +13,11 @@ export async function verifyTurnstile(token: string): Promise<[false, TurnstileE
return [true];
const formData = new FormData();
console.log(headers().get("CF-Connecting-IP"));
const headerList = await headers();
formData.append("secret", process.env.CF_SECRET);
formData.append("response", token);
formData.append("remoteip", headers().get("CF-Connecting-IP") ?? "");
formData.append("remoteip", headerList.get("CF-Connecting-IP") ?? "");
const response = await fetch("https://challenges.cloudflare.com/turnstile/v0/siteverify",
{
+1 -1
View File
@@ -1,4 +1,4 @@
@import "../theme.scss";
@use "@/_styles/theme" as *;
.page
{
+4 -4
View File
@@ -42,13 +42,13 @@ const AttributionPage: React.FC = () => (
see the <a href="https://privacy.microsoft.com/privacystatement" target="_blank">Microsoft Privacy Statement</a>.
</p>
<p>
If the "Do Not Track" option is enabled in your browser,
If the &quot;Do Not Track&quot; option is enabled in your browser,
the website will not execute any tracking code.
</p>
{ requireExplicitConsent() &&
<p>
If you previously gave your consent to use cookies,
you can revoke it by clicking "Revoke my consent" button on this page below
you can revoke it by clicking &quot;Revoke my consent&quot; button on this page below
(the button is available only if the consent was given).
Recorded data will be deleted after 30-day retention period.
</p>
@@ -99,7 +99,7 @@ const AttributionPage: React.FC = () => (
<p>Copyright &copy; { new Date().getFullYear() } { Package.author.name }</p>
<p>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
of this software and associated documentation files (the &quot;Software&quot;), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
@@ -110,7 +110,7 @@ const AttributionPage: React.FC = () => (
copies or substantial portions of the Software.
</p>
<p>
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+1 -1
View File
@@ -7,7 +7,7 @@ import Footer from "./_components/Footer";
import Header from "./_components/Header";
import { analyticsEnabled, requireExplicitConsent } from "./_utils/analytics/server";
import fonts from "./fonts";
import "./globals.scss";
import "./_styles/globals.scss";
export const viewport: Viewport =
{
+1 -1
View File
@@ -1,4 +1,4 @@
@import "./theme.scss";
@use "@/_styles/theme" as *;
.root
{
+1 -1
View File
@@ -1,4 +1,4 @@
@import "./theme.scss";
@use "@/_styles/theme" as *;
.page
{
+1 -1
View File
@@ -1,4 +1,4 @@
@import "./theme.scss";
@use "@/_styles/theme" as *;
.page
{
+1 -1
View File
@@ -1,4 +1,4 @@
@import "../theme.scss";
@use "@/_styles/theme" as *;
.page
{