diff --git a/apps/docs/next.config.ts b/apps/docs/next.config.ts index 5a486f4c04..1fa8020d86 100644 --- a/apps/docs/next.config.ts +++ b/apps/docs/next.config.ts @@ -176,7 +176,7 @@ const nextConfig: NextConfig = { // https://github.com/vercel/next.js/issues/71638 sassOptions: { logger: { - warn: function (message) { + warn: function (message: string) { if ( message.includes("deprecat") || message.includes("declarations that appear after nested") diff --git a/apps/docs/source.config.ts b/apps/docs/source.config.ts index f36e80dd45..21c5ac5bcc 100644 --- a/apps/docs/source.config.ts +++ b/apps/docs/source.config.ts @@ -16,6 +16,8 @@ const schema = z.custom<{ date?: string; difficulty?: string; index?: boolean; + featured?: boolean; + href?: string; }>(); const docsData = defineDocs({ diff --git a/apps/docs/src/app/[locale]/developers/cookbook/[...slug]/page.tsx b/apps/docs/src/app/[locale]/developers/cookbook/[...slug]/page.tsx index 0ccc4efeed..3d77bfbdc8 100644 --- a/apps/docs/src/app/[locale]/developers/cookbook/[...slug]/page.tsx +++ b/apps/docs/src/app/[locale]/developers/cookbook/[...slug]/page.tsx @@ -3,7 +3,7 @@ import { CookbookPage, getMetadataFromSlug } from "../cookbook"; import { toStaticParams } from "@@/src/app/sources/utils"; type Props = { - params: Promise<{ slug?: string[]; locale: string }>; + params: Promise<{ slug: string[]; locale: string }>; }; export default async function Page(props: Props) { diff --git a/apps/docs/src/app/[locale]/developers/developers.tsx b/apps/docs/src/app/[locale]/developers/developers.tsx index 535288a74a..37f1052e4b 100644 --- a/apps/docs/src/app/[locale]/developers/developers.tsx +++ b/apps/docs/src/app/[locale]/developers/developers.tsx @@ -2,14 +2,23 @@ import DevelopersHeroSection from "@/components/developers/sections/DevelopersHeroSection/DevelopersHeroSection"; import DevelopersCoursesSection from "@/components/developers/sections/DevelopersCoursesSection/DevelopersCoursesSection"; -import DevelopersResourcesSection from "@/components/developers/sections/DevelopersResourcesSection/DevelopersResourcesSection"; +import DevelopersResourcesSection, { + DevelopersResourcesSectionProps, +} from "@/components/developers/sections/DevelopersResourcesSection/DevelopersResourcesSection"; import DevelopersDocumentsSection from "@/components/developers/sections/DevelopersDocumentsSection/DevelopersDocumentsSection"; import DevelopersContentSection from "@/components/developers/sections/DevelopersContentSection/DevelopersContentSection"; import heroImg from "@@/assets/developers/hero-geometry.png"; import { useTranslations } from "next-intl"; import StackExchangeIcon from "@@/assets/developers/stackexchange.inline.svg"; +import { LatestChangelogVideo } from "@/components/developers/sections/DevelopersDocumentsSection/DevelopersChangelog"; -export function DevelopersPage({ latestChangelogVideo, guides }) { +export function DevelopersPage({ + latestChangelogVideo, + guides, +}: { + latestChangelogVideo?: LatestChangelogVideo; + guides?: DevelopersResourcesSectionProps["items"]; +}) { const t = useTranslations(); return (
{props.children}
diff --git a/apps/docs/src/app/components/code/mermaid-renderer.tsx b/apps/docs/src/app/components/code/mermaid-renderer.tsx
index 073ead4013..0579395991 100644
--- a/apps/docs/src/app/components/code/mermaid-renderer.tsx
+++ b/apps/docs/src/app/components/code/mermaid-renderer.tsx
@@ -5,7 +5,7 @@ import { useEffect, useId, useRef, useState, type RefObject } from "react";
import type { MermaidConfig } from "mermaid";
import { Loader2 } from "lucide-react";
-function useIsVisible(ref: RefObject) {
+function useIsVisible(ref: RefObject) {
const [isIntersecting, setIsIntersecting] = useState(false);
useEffect(() => {
@@ -40,7 +40,7 @@ export function MermaidRenderer({
const id = useId();
const [svg, setSvg] = useState("");
const [isLoading, setIsLoading] = useState(true);
- const containerRef = useRef(null);
+ const containerRef = useRef(null);
const isVisible = useIsVisible(containerRef);
const svgPanZoomInstance = useRef(null);
diff --git a/apps/docs/src/app/components/code/notes.tsx b/apps/docs/src/app/components/code/notes.tsx
index 47491c0ae5..c9cd2a5333 100644
--- a/apps/docs/src/app/components/code/notes.tsx
+++ b/apps/docs/src/app/components/code/notes.tsx
@@ -1,5 +1,6 @@
import { Code } from "./code";
import { WithClientNotes } from "./notes.client";
+import { RawCode } from "codehike/code";
export function WithNotes({
children,
@@ -9,28 +10,38 @@ export function WithNotes({
}) {
// get all the blocks inside
// and put them into Context
- const notes = Object.entries(rest)
+ const notes = (
+ Object.entries(rest) as [
+ string,
+ (
+ | RawCode
+ | {
+ type?: "prose" | "code" | "image";
+ children?: React.ReactNode;
+ url?: string;
+ alt?: string;
+ }
+ ),
+ ][]
+ )
.filter(([name]) => name !== "title" && name !== "_data")
- .map(([name, block]: any) => {
- if (block.hasOwnProperty("children")) {
+ .map(([name, block]) => {
+ if ("children" in block) {
return {
name,
- type: block.type || "prose",
+ type: block.type || ("prose" as const),
children: block.children,
};
- } else if (
- block.hasOwnProperty("value") &&
- block.hasOwnProperty("lang")
- ) {
+ } else if ("value" in block && "lang" in block) {
return {
name,
- type: "code",
+ type: "code" as const,
children: ,
};
- } else if (block.hasOwnProperty("url") && block.hasOwnProperty("alt")) {
+ } else if ("url" in block && "alt" in block) {
return {
name,
- type: "image",
+ type: "image" as const,
children:
,
};
} else {
diff --git a/apps/docs/src/app/components/code/scrollycoding.client.tsx b/apps/docs/src/app/components/code/scrollycoding.client.tsx
index e4c61cc472..efb51d65e5 100644
--- a/apps/docs/src/app/components/code/scrollycoding.client.tsx
+++ b/apps/docs/src/app/components/code/scrollycoding.client.tsx
@@ -12,7 +12,7 @@ type StickerStep = {
export function SelectionSticker({ steps }: { steps: StickerStep[] }) {
const stickerSteps = useMemo(() => {
- const files = {};
+ const files: Record = {};
return steps.map((step) => {
Object.entries(step.codeblocks).forEach(([title, code]) => {
files[title] = code;
@@ -38,7 +38,9 @@ function Sticker(props: {
const { codeblocks } = step;
const filetree = useMemo(() => getFileTree(codeblocks), [codeblocks]);
const defaultSelected = step.selected;
- const [selected, setSelected] = useState(defaultSelected);
+ const [selected, setSelected] = useState(
+ defaultSelected ?? null,
+ );
useEffect(() => {
if (defaultSelected) {
@@ -114,7 +116,7 @@ function FileNodes(props: {
onSelect(node.title)}
+ onClick={() => node.title && onSelect(node.title)}
className={cn(
"transition-colors duration-300",
selected === node.title
diff --git a/apps/docs/src/app/components/code/scrollycoding.tsx b/apps/docs/src/app/components/code/scrollycoding.tsx
index 6dd91cf78c..652fa0676f 100644
--- a/apps/docs/src/app/components/code/scrollycoding.tsx
+++ b/apps/docs/src/app/components/code/scrollycoding.tsx
@@ -21,11 +21,15 @@ const Schema = Block.extend({
),
});
-type Steps = z.infer["steps"];
+type Step = {
+ title?: string;
+ children?: React.ReactNode;
+ code: RawCode[];
+};
+type Steps = Step[];
-export function ScrollyCoding(props: unknown) {
- // @ts-expect-error props are not typed
- const { steps } = parseProps(props, Schema);
+export function ScrollyCoding(props: { steps: unknown[] }) {
+ const { steps } = parseProps(props, Schema) as { steps: Steps };
return (
@@ -38,7 +42,7 @@ function OneColumnLayout(props: { steps: Steps; className?: string }) {
const { steps, className } = props;
return (
- {steps.map((step, i) => (
+ {steps.map((step: Steps[number], i: number) => (
))}
@@ -50,7 +54,7 @@ function OneColumnStep(props: { step: Steps[number] }) {
const codeblocks = {} as Record;
step.code.forEach((code) => {
const { title } = extractFlags(code);
- codeblocks[title] = ;
+ codeblocks[title ?? ""] = ;
});
return (
@@ -123,8 +127,9 @@ function getStickers(steps: Steps) {
step.code.forEach((code, i) => {
const { title } = extractFlags(code);
- codeMap[title] = code;
- if (i === 0) selected = title;
+ const key = title ?? "";
+ codeMap[key] = code;
+ if (i === 0) selected = key;
});
return { codes: codeMap, selected };
diff --git a/apps/docs/src/app/components/docs-footer.tsx b/apps/docs/src/app/components/docs-footer.tsx
index 93f820190c..044c025e5b 100644
--- a/apps/docs/src/app/components/docs-footer.tsx
+++ b/apps/docs/src/app/components/docs-footer.tsx
@@ -4,7 +4,8 @@ import { ChevronLeft, ChevronRight } from "lucide-react";
import { useI18n } from "fumadocs-ui/provider";
import { ReactNode } from "react";
-type DocsLink = { name: ReactNode; url: string };
+export type DocsLink = { name: ReactNode; url: string };
+
export function DocsFooter({
previous,
next,
diff --git a/apps/docs/src/app/components/docs-layout.tsx b/apps/docs/src/app/components/docs-layout.tsx
index 8e55a4a6b3..8f985d22ef 100644
--- a/apps/docs/src/app/components/docs-layout.tsx
+++ b/apps/docs/src/app/components/docs-layout.tsx
@@ -15,7 +15,7 @@ export async function DocsLayout({
children,
tree,
sidebarEnabled = true,
- locale,
+ locale = "en",
}: {
children: ReactNode;
tree: any; // TODO: fix after updating to fumadocs-ui@15
diff --git a/apps/docs/src/app/components/docs-page.tsx b/apps/docs/src/app/components/docs-page.tsx
index 5fcbd0ad4b..9a07f49798 100644
--- a/apps/docs/src/app/components/docs-page.tsx
+++ b/apps/docs/src/app/components/docs-page.tsx
@@ -6,7 +6,7 @@ import {
import { ReactNode } from "react";
import { ScrollToTop } from "./scroll-to-top";
import { EditOnGithub } from "./edit-page";
-import { DocsFooter } from "./docs-footer";
+import { DocsFooter, DocsLink } from "./docs-footer";
import { findNeighbour } from "fumadocs-core/server";
import { Rate } from "./rate";
import { onRateAction } from "./inkeep/inkeep-feedback";
@@ -22,7 +22,7 @@ export function DocsPage(props: {
full?: boolean;
title: string;
description?: string;
- pageTree?: any;
+ pageTree?: Parameters[0];
href: string;
markdown: string;
isRoot?: boolean;
@@ -56,7 +56,9 @@ export function DocsPage(props: {
enabled: !props.hideTableOfContents,
}}
footer={{
- component: ,
+ component: props.pageTree ? (
+
+ ) : undefined,
}}
>
{props.hideHeader ? null : props.isRoot ? (
@@ -114,17 +116,23 @@ function getEditUrl(path: string, editPathPrefix = "content/docs") {
return `https://github.com/solana-foundation/solana-com/blob/main/apps/docs/${editPathPrefix}/${path.startsWith("/") ? path.slice(1) : path}`;
}
-function Footer({ pageUrl, pageTree }: { pageUrl: string; pageTree: any }) {
+function Footer({
+ pageUrl,
+ pageTree,
+}: {
+ pageUrl: string;
+ pageTree: Parameters[0];
+}) {
const { next, previous } = findNeighbour(pageTree, pageUrl);
if (!previous && !next) {
// we are at the root (which isn't part of the page tree)
- let firstPage = pageTree;
+ let firstPage = pageTree as any;
while (firstPage && firstPage.children) {
firstPage = firstPage.index || firstPage.children[0];
}
if (!firstPage) return null;
- return ;
+ return ;
}
return ;
}
diff --git a/apps/docs/src/app/components/rate.tsx b/apps/docs/src/app/components/rate.tsx
index e5645d3147..3dac7e3f0c 100644
--- a/apps/docs/src/app/components/rate.tsx
+++ b/apps/docs/src/app/components/rate.tsx
@@ -56,7 +56,7 @@ export function Rate({
try {
const stream = await onRateAction(pathname, {
- opinion: opinion,
+ opinion: opinion!,
message,
});
diff --git a/apps/docs/src/app/mdx-components.tsx b/apps/docs/src/app/mdx-components.tsx
index b6f6022455..f41374ed9f 100644
--- a/apps/docs/src/app/mdx-components.tsx
+++ b/apps/docs/src/app/mdx-components.tsx
@@ -68,7 +68,7 @@ function Link(props: LinkProps) {
if (props.href?.startsWith("mention:")) {
return ;
} else if (props.href?.startsWith("tooltip")) {
- return {props.children} ;
+ return {props.children} ;
}
return ;
}
diff --git a/apps/docs/src/app/metadata.ts b/apps/docs/src/app/metadata.ts
index 60821fea05..0af7d40649 100644
--- a/apps/docs/src/app/metadata.ts
+++ b/apps/docs/src/app/metadata.ts
@@ -5,6 +5,7 @@ import { getTranslations } from "next-intl/server";
import faviconPng from "@solana-com/ui-chrome/assets/favicon.png";
import faviconSvg from "@solana-com/ui-chrome/assets/favicon.svg";
import appleTouchIcon from "@solana-com/ui-chrome/assets/apple-touch-icon.png";
+import { Page } from "fumadocs-core/source";
export function getBaseMetadata(locale: string) {
const { siteMetadata, siteUrl } = config;
@@ -54,6 +55,11 @@ export async function getIndexMetadata({
descriptionKey,
locale,
path,
+}: {
+ titleKey: string;
+ descriptionKey: string;
+ locale: string;
+ path: string;
}) {
const t = await getTranslations();
return {
@@ -63,11 +69,18 @@ export async function getIndexMetadata({
};
}
-export function getMdxMetadata(page) {
+type DocPage = Page<{
+ title: string;
+ seoTitle?: string;
+ h1?: string;
+ description?: string;
+}>;
+
+export function getMdxMetadata(page: DocPage) {
const url = getUrlWithoutLocale(page);
const title = page.data.seoTitle || page.data.h1 || page.data.title;
const description = page.data.description;
- const { openGraph } = getBaseMetadata(page.locale);
+ const { openGraph } = getBaseMetadata(page.locale ?? "en");
const imagePrefix = url?.startsWith("/docs")
? "/opengraph/developers"
@@ -76,7 +89,7 @@ export function getMdxMetadata(page) {
return {
title,
description,
- alternates: getAlternates(url, page.locale),
+ alternates: getAlternates(url, page.locale ?? "en"),
openGraph: {
...openGraph,
images: [imagePrefix + url],
diff --git a/apps/docs/src/app/opengraph/developers/[[...slug]]/route.ts b/apps/docs/src/app/opengraph/developers/[[...slug]]/route.ts
index 1a68521e1f..72a7130d18 100644
--- a/apps/docs/src/app/opengraph/developers/[[...slug]]/route.ts
+++ b/apps/docs/src/app/opengraph/developers/[[...slug]]/route.ts
@@ -39,8 +39,11 @@ function getImageProps(slugItems: Array) {
const [first, ...rest] = slugItems;
const name = first.toLowerCase();
let title: string | null = null;
- if (collections[name]) {
- title = getTitleFromCollection(collections[name], rest);
+ if (collections[name as keyof typeof collections]) {
+ title = getTitleFromCollection(
+ collections[name as keyof typeof collections],
+ rest,
+ );
if (!title) {
return null;
}
@@ -61,7 +64,7 @@ function getImageProps(slugItems: Array) {
}
function getTitleFromCollection(
- collection: any,
+ collection: (typeof collections)[keyof typeof collections],
slugs: Array,
): string | null {
const page = collection.getPage(slugs);
diff --git a/apps/docs/src/app/sources/guides.ts b/apps/docs/src/app/sources/guides.ts
index ad903cf793..1bfe9302ff 100644
--- a/apps/docs/src/app/sources/guides.ts
+++ b/apps/docs/src/app/sources/guides.ts
@@ -2,6 +2,18 @@ import { guides, guidesMeta } from "@@/.source/index";
import { createMDXSource } from "fumadocs-mdx";
import { loader } from "fumadocs-core/source";
import { locales, defaultLocale } from "@workspace/i18n/config";
+import { ReactNode } from "react";
+
+type GuideNode = Omit<(typeof guidesSource.pageTree)[string], "children"> & {
+ url?: string;
+ href?: string;
+ title?: ReactNode;
+ description?: ReactNode;
+ difficulty?: string;
+ tags?: string[];
+ featured?: boolean;
+ children?: GuideNode[];
+};
export const guidesSource = loader({
i18n: {
@@ -12,23 +24,36 @@ export const guidesSource = loader({
baseUrl: "/developers/guides",
source: createMDXSource(guides, guidesMeta),
pageTree: {
- attachFile(node: any, file: any) {
- node.description = file.data?.description;
- node.slug = file.slugs?.join("/");
- node.featured = file.data?.featured;
- node.tags = file.data?.tags;
- node.href = file.data?.href;
- node.difficulty = file.data?.difficulty;
+ attachFile(node, file) {
+ node.description = file?.data?.description;
+ // @ts-expect-error Adds an unspecified prop
+ node.slug = file?.slugs?.join("/");
+ // @ts-expect-error Adds an unspecified prop
+ node.featured = file?.data?.featured;
+ // @ts-expect-error Adds an unspecified prop
+ node.tags = file?.data?.tags;
+ // @ts-expect-error Adds an unspecified prop
+ node.href = file?.data?.href;
+ // @ts-expect-error Adds an unspecified prop
+ node.difficulty = file?.data?.difficulty;
return node;
},
},
});
export function getGuides(locale: string) {
- return getGuidesFromFolder(guidesSource.pageTree[locale]);
+ return getGuidesFromFolder(guidesSource.pageTree[locale] as GuideNode);
}
-function getGuidesFromFolder(folder: { children: any[] }) {
+function getGuidesFromFolder(folder: GuideNode): {
+ href?: string;
+ title?: ReactNode;
+ description?: ReactNode;
+ difficulty?: string;
+ tags?: string[];
+ featured?: boolean;
+}[] {
+ if (!folder.children) return [];
return folder.children.flatMap((node) => {
if (node.children) {
return getGuidesFromFolder(node);
diff --git a/apps/docs/src/app/sources/utils.ts b/apps/docs/src/app/sources/utils.ts
index d6224bbb8e..d3509a716c 100644
--- a/apps/docs/src/app/sources/utils.ts
+++ b/apps/docs/src/app/sources/utils.ts
@@ -1,15 +1,13 @@
import { defaultLocale } from "@workspace/i18n/config";
-import { LoaderConfig, LoaderOutput, Page } from "fumadocs-core/source";
+import { LoaderConfig, LoaderOutput } from "fumadocs-core/source";
// remove extra params generated by fumadocs i18n
export function toStaticParams(source: LoaderOutput) {
return source.generateParams().filter(({ lang }) => lang === defaultLocale);
}
-export function getUrlWithoutLocale(
- page: Page,
-) {
- return toUrlWithoutLocale(page.url, page.locale);
+export function getUrlWithoutLocale(page: { url: string; locale?: string }) {
+ return toUrlWithoutLocale(page.url, page.locale ?? "en");
}
export function toUrlWithoutLocale(url: string, locale: string) {
diff --git a/apps/docs/src/components/CookieConsent/CookieConsent.jsx b/apps/docs/src/components/CookieConsent/CookieConsent.tsx
similarity index 100%
rename from apps/docs/src/components/CookieConsent/CookieConsent.jsx
rename to apps/docs/src/components/CookieConsent/CookieConsent.tsx
diff --git a/apps/docs/src/components/GTMTrackingSnippet.js b/apps/docs/src/components/GTMTrackingSnippet.tsx
similarity index 100%
rename from apps/docs/src/components/GTMTrackingSnippet.js
rename to apps/docs/src/components/GTMTrackingSnippet.tsx
diff --git a/apps/docs/src/components/SolFormattedMessage/index.js b/apps/docs/src/components/SolFormattedMessage/index.tsx
similarity index 64%
rename from apps/docs/src/components/SolFormattedMessage/index.js
rename to apps/docs/src/components/SolFormattedMessage/index.tsx
index dfc9d56d8f..faff34d275 100644
--- a/apps/docs/src/components/SolFormattedMessage/index.js
+++ b/apps/docs/src/components/SolFormattedMessage/index.tsx
@@ -1,16 +1,20 @@
import { useRouter } from "@workspace/i18n/use-router";
import { useEffect, useMemo, useState } from "react";
-export const formatNumber = (locale, value, options) => {
+export const formatNumber = (
+ locale: string | string[] | undefined,
+ value: number | bigint | string,
+ options?: Intl.NumberFormatOptions,
+): string | number | bigint => {
try {
- return Intl.NumberFormat(locale, options).format(value);
+ return Intl.NumberFormat(locale, options).format(value as number);
} catch (error) {
console.error(error);
return value;
}
};
-const humanFriendlyNumbers = {
+const humanFriendlyNumbers: Record = {
1: "",
1e3: "K",
1e6: "M",
@@ -22,22 +26,15 @@ const humanFriendlyNumbers = {
/**
* Format a number down and adds the above extensions.
- *
- * @param {string} locale
- * @param {number} value
- * @param {number} digits How many digits to display after the floating point, defaults to 1.
- * @param {number} startDividing When to start dividing, default to 1e4, divides by 1e3.
- * @param {NumberFormatOptions} options
- * @return {`${*}${*}`|`${*}${*}`}
*/
export const formatNumberHumanFriendly = (
- locale,
- value,
- digits = 1,
- startDividing = 1e4,
- options = {},
-) => {
- let dividend;
+ locale: string | string[] | undefined,
+ value: number,
+ digits: number = 1,
+ startDividing: number = 1e4,
+ options: Intl.NumberFormatOptions = {},
+): string => {
+ let dividend: number;
switch (true) {
case value >= 1e18: {
dividend = 1e18;
@@ -67,13 +64,16 @@ export const formatNumberHumanFriendly = (
dividend = 1;
}
const dividedDown = (value / dividend).toFixed(digits);
- // console.log(value, dividedDown, dividend);
return `${formatNumber(locale, dividedDown, options)}${
humanFriendlyNumbers[dividend]
}`;
};
-export function FormattedNumber({ value, ...options }) {
+type FormattedNumberProps = Intl.NumberFormatOptions & {
+ value: number;
+};
+
+export function FormattedNumber({ value, ...options }: FormattedNumberProps) {
const { locale } = useRouter();
const formatted = useMemo(() => {
@@ -88,9 +88,13 @@ export function FormattedNumber({ value, ...options }) {
return <>{formatted}>;
}
-export function FormattedDate({ value, ...options }) {
+type FormattedDateProps = Intl.DateTimeFormatOptions & {
+ value: number | Date;
+};
+
+export function FormattedDate({ value, ...options }: FormattedDateProps) {
const { locale } = useRouter();
- const [date, setDate] = useState(null);
+ const [date, setDate] = useState(null);
useEffect(() => {
setDate(value);
@@ -109,5 +113,5 @@ export function FormattedDate({ value, ...options }) {
}
}, [locale, date, options]);
- return <>{formatted}>;
+ return <>{formatted as React.ReactNode}>;
}
diff --git a/apps/docs/src/components/developers/DevelopersContentPage/DevelopersContentPage.tsx b/apps/docs/src/components/developers/DevelopersContentPage/DevelopersContentPage.tsx
index 8f1fa53218..2de1e79bee 100644
--- a/apps/docs/src/components/developers/DevelopersContentPage/DevelopersContentPage.tsx
+++ b/apps/docs/src/components/developers/DevelopersContentPage/DevelopersContentPage.tsx
@@ -62,7 +62,7 @@ export function HeroTitle({
)} */}
-
+
@@ -70,8 +70,9 @@ export function HeroTitle({
>
-
+
{item?.label || item?.title}
diff --git a/apps/docs/src/components/developers/DevelopersContentPage/PageNav.tsx b/apps/docs/src/components/developers/DevelopersContentPage/PageNav.tsx
index aa50584c41..e7a259bb92 100644
--- a/apps/docs/src/components/developers/DevelopersContentPage/PageNav.tsx
+++ b/apps/docs/src/components/developers/DevelopersContentPage/PageNav.tsx
@@ -3,7 +3,19 @@ import styles from "./DevelopersContentPage.module.scss";
import Link from "next/link";
import { useTranslations } from "next-intl";
-export const PageNav = ({ nav }) => {
+type NavLink = {
+ href: string;
+ label: string;
+};
+
+type PageNavProps = {
+ nav: {
+ prev?: NavLink | null;
+ next?: NavLink | null;
+ };
+};
+
+export const PageNav = ({ nav }: PageNavProps) => {
const t = useTranslations();
return (
diff --git a/apps/docs/src/components/developers/DevelopersContentPage/TagCloud.tsx b/apps/docs/src/components/developers/DevelopersContentPage/TagCloud.tsx
index 1b48d07892..99a4f83c37 100644
--- a/apps/docs/src/components/developers/DevelopersContentPage/TagCloud.tsx
+++ b/apps/docs/src/components/developers/DevelopersContentPage/TagCloud.tsx
@@ -2,11 +2,20 @@ import { memo } from "react";
import styles from "./DevelopersContentPage.module.scss";
import Link from "next/link";
+export type TagCloudRecord = {
+ title: string;
+ href: string;
+ date: string;
+ tags?: string[];
+ difficulty?: string;
+ category?: string;
+};
+
type TagCloudProps = {
/** base href to compute the correct tag route */
baseHref: string;
/** content record used */
- record: any;
+ record: TagCloudRecord | null | undefined;
};
/**
diff --git a/apps/docs/src/components/developers/DevelopersFeaturedResourcesList/DevelopersFeaturedResourcesList.jsx b/apps/docs/src/components/developers/DevelopersFeaturedResourcesList/DevelopersFeaturedResourcesList.tsx
similarity index 77%
rename from apps/docs/src/components/developers/DevelopersFeaturedResourcesList/DevelopersFeaturedResourcesList.jsx
rename to apps/docs/src/components/developers/DevelopersFeaturedResourcesList/DevelopersFeaturedResourcesList.tsx
index fdde73601f..8e95752183 100644
--- a/apps/docs/src/components/developers/DevelopersFeaturedResourcesList/DevelopersFeaturedResourcesList.jsx
+++ b/apps/docs/src/components/developers/DevelopersFeaturedResourcesList/DevelopersFeaturedResourcesList.tsx
@@ -1,13 +1,30 @@
-import { memo } from "react";
+import { memo, type ReactNode } from "react";
import classNames from "classnames";
import { useTranslations } from "next-intl";
import styles from "./DevelopersFeaturedResourcesList.module.scss";
import DevelopersFeaturedResourcesListItem from "./DevelopersFeaturedResourcesListItem/DevelopersFeaturedResourcesListItem";
+type FeaturedResourceItem = {
+ title?: ReactNode;
+ description?: ReactNode;
+ href?: string;
+ url?: string;
+ isExternal?: boolean;
+ data?: {
+ title?: string;
+ description?: string;
+ };
+};
+
+type DevelopersFeaturedResourcesListProps = {
+ items: FeaturedResourceItem[];
+ translationTag?: string;
+};
+
export default memo(function DevelopersFeaturedResourcesList({
items,
translationTag = "featured-resources-list",
-}) {
+}: DevelopersFeaturedResourcesListProps) {
const t = useTranslations();
return (
@@ -32,10 +49,15 @@ const Content = memo(function Content({
);
});
+type DevelopersFeaturedResourcesListItemProps = {
+ item: FeaturedResourceItem;
+ translationTag?: string;
+};
+
export default memo(function DevelopersFeaturedResourcesListItem({
item,
translationTag,
-}) {
+}: DevelopersFeaturedResourcesListItemProps) {
if (item.isExternal) {
return (
import("../DevelopersResourcesFilters/DevelopersResourcesFilters"),
@@ -12,45 +12,48 @@ const DevelopersResourcesFilters = dynamic(
},
);
-const mapItemsIntoFilters = (itemFilters) => (item) => {
- // handle the `category` field
- if (!!item?.category) {
- if (!itemFilters.category.items.includes(item?.category)) {
- itemFilters.category.items.push(item?.category);
- }
- }
+type ResourceItem = {
+ category?: string;
+ difficulty?: string;
+ labels?: string[];
+ tags?: string[];
+ [key: string]: unknown;
+};
- // handle the `difficulty` field
- if (!!item?.difficulty) {
- if (!itemFilters.difficulty.items.includes(item?.difficulty)) {
- // console.log(item.difficulty);
- itemFilters.difficulty.items.push(item?.difficulty);
+const mapItemsIntoFilters =
+ (itemFilters: FilterMap) => (item: ResourceItem) => {
+ if (item?.category) {
+ if (!itemFilters.category.items.includes(item.category)) {
+ itemFilters.category.items.push(item.category);
+ }
}
- }
- // handle the `labels` field
- if (!!item?.labels) {
- item.labels?.forEach((label) => {
- if (!itemFilters?.labels.items.includes(label)) {
- itemFilters.labels.items.push(label);
+ if (item?.difficulty) {
+ if (!itemFilters.difficulty.items.includes(item.difficulty)) {
+ itemFilters.difficulty.items.push(item.difficulty);
}
- });
- }
+ }
- // handle the `tags` field
- if (!!item?.tags) {
- item.tags.forEach((tag) => {
- if (!itemFilters.tags.items.includes(tag)) {
- itemFilters.tags.items.push(tag);
- }
- });
- }
+ if (item?.labels) {
+ item.labels?.forEach((label) => {
+ if (!itemFilters?.labels.items.includes(label)) {
+ itemFilters.labels.items.push(label);
+ }
+ });
+ }
- return item;
-};
+ if (item?.tags) {
+ item.tags.forEach((tag) => {
+ if (!itemFilters.tags.items.includes(tag)) {
+ itemFilters.tags.items.push(tag);
+ }
+ });
+ }
+
+ return item;
+ };
-// define the base filters to be used
-const baseFilters = {
+const baseFilters: FilterMap = {
difficulty: {
label: "Difficulty",
items: [],
@@ -69,16 +72,20 @@ const baseFilters = {
},
};
-export default memo(function DevelopersResources({ items, title = "" }) {
- // populate and memoize the available filters,
+type DevelopersResourcesProps = {
+ items: ResourceItem[];
+ title?: string;
+};
+
+export default memo(function DevelopersResources({
+ items,
+ title = "",
+}: DevelopersResourcesProps) {
const filters = useMemo(() => {
- // reset the filters to the their base
const filters = baseFilters;
- // map all the filterable items to populate the filters
items.map(mapItemsIntoFilters(filters));
- // deduplicate all filters
filters.difficulty.items = Array.from(
new Set(filters.difficulty.items.map((item) => item.toLowerCase())),
);
@@ -92,7 +99,6 @@ export default memo(function DevelopersResources({ items, title = "" }) {
new Set(filters.labels.items.map((item) => item.toLowerCase())),
);
- // force sort all filters to the same, always
for (const key in filters) filters[key].items.sort();
return filters;
diff --git a/apps/docs/src/components/developers/DevelopersResourcesFilters/DevelopersResourcesFilters.jsx b/apps/docs/src/components/developers/DevelopersResourcesFilters/DevelopersResourcesFilters.tsx
similarity index 76%
rename from apps/docs/src/components/developers/DevelopersResourcesFilters/DevelopersResourcesFilters.jsx
rename to apps/docs/src/components/developers/DevelopersResourcesFilters/DevelopersResourcesFilters.tsx
index 3b015466dd..81cad52ce0 100644
--- a/apps/docs/src/components/developers/DevelopersResourcesFilters/DevelopersResourcesFilters.jsx
+++ b/apps/docs/src/components/developers/DevelopersResourcesFilters/DevelopersResourcesFilters.tsx
@@ -5,7 +5,26 @@ import { useRouter, useSearchParams } from "next/navigation";
import classNames from "classnames";
import styles from "./DevelopersResourcesFilters.module.scss";
-function Filters({ filters, onReset, onToggle, activeFilters = new Map() }) {
+export type FilterGroup = {
+ label: string;
+ items: string[];
+};
+
+export type FilterMap = Record;
+
+type FiltersProps = {
+ filters: FilterMap;
+ onReset: () => void;
+ onToggle: (_key: string, _filter: string) => void;
+ activeFilters?: Map;
+};
+
+function Filters({
+ filters,
+ onReset,
+ onToggle,
+ activeFilters = new Map(),
+}: FiltersProps) {
return (
Filters
@@ -27,7 +46,7 @@ function Filters({ filters, onReset, onToggle, activeFilters = new Map() }) {
{filters[key].items.map((filter) =>
- !!filter ? (
+ filter ? (
{
+ const createQueryString = useCallback((params: Record) => {
const urlSearchParams = new URLSearchParams();
Object.entries(params).forEach(([key, values]) => {
if (Array.isArray(values)) {
@@ -78,21 +97,19 @@ function FilterLogic({ filters }) {
}, [router]);
const toggleFilter = useCallback(
- (key, filter) => {
+ (key: string, filter: string) => {
const currentValues = searchParams.getAll(key);
const newValues = currentValues.includes(filter)
? currentValues.filter((v) => v !== filter)
: [...currentValues, filter];
- const newParams = {};
- // Preserve other query parameters
- Array.from(searchParams.entries()).forEach(([key, value]) => {
- if (!newParams[key]) {
- newParams[key] = [];
+ const newParams: Record = {};
+ Array.from(searchParams.entries()).forEach(([paramKey, value]) => {
+ if (!newParams[paramKey]) {
+ newParams[paramKey] = [];
}
- newParams[key].push(value);
+ newParams[paramKey].push(value);
});
- // Update the specific filter
newParams[key] = newValues;
startTransition(() => {
@@ -102,12 +119,12 @@ function FilterLogic({ filters }) {
[router, searchParams, createQueryString],
);
- const activeFilters = new Map();
+ const activeFilters = new Map();
Array.from(searchParams.entries()).forEach(([key, value]) => {
if (!activeFilters.has(key)) {
activeFilters.set(key, []);
}
- activeFilters.get(key).push(value);
+ activeFilters.get(key)!.push(value);
});
return (
@@ -120,7 +137,11 @@ function FilterLogic({ filters }) {
);
}
-export default memo(function DevelopersResourcesFilters({ filters }) {
+export default memo(function DevelopersResourcesFilters({
+ filters,
+}: {
+ filters: FilterMap;
+}) {
return (
{items.map((item, id) => (
@@ -27,14 +39,14 @@ function Grid({ items }) {
);
}
-function FilteredGrid({ items }) {
+function FilteredGrid({ items }: { items: ResourceItem[] }) {
const searchParams = useSearchParams();
const filteredItems = useMemo(() => {
return items.filter((item) => {
let matchesFilters = true;
- const filterKeys = new Set();
+ const filterKeys = new Set();
for (const [key] of searchParams.entries()) {
filterKeys.add(key);
}
@@ -66,7 +78,11 @@ function FilteredGrid({ items }) {
return ;
}
-export default memo(function DevelopersResourcesGrid({ items }) {
+export default memo(function DevelopersResourcesGrid({
+ items,
+}: {
+ items: ResourceItem[];
+}) {
return (
}>
diff --git a/apps/docs/src/components/developers/sections/DevelopersContentSection/DevelopersContent.jsx b/apps/docs/src/components/developers/sections/DevelopersContentSection/DevelopersContent.tsx
similarity index 69%
rename from apps/docs/src/components/developers/sections/DevelopersContentSection/DevelopersContent.jsx
rename to apps/docs/src/components/developers/sections/DevelopersContentSection/DevelopersContent.tsx
index 1317e01cea..aa593a792d 100644
--- a/apps/docs/src/components/developers/sections/DevelopersContentSection/DevelopersContent.jsx
+++ b/apps/docs/src/components/developers/sections/DevelopersContentSection/DevelopersContent.tsx
@@ -1,12 +1,13 @@
import classNames from "classnames";
+import type { ReactNode } from "react";
import styles from "./DevelopersContent.module.scss";
-function Title({ children }) {
+function Title({ children }: { children: ReactNode }) {
return {children}
;
}
-function Description({ children }) {
+function Description({ children }: { children: ReactNode }) {
return (
{children}
@@ -14,7 +15,13 @@ function Description({ children }) {
);
}
-function Container({ className, children }) {
+function Container({
+ className,
+ children,
+}: {
+ className?: string;
+ children: ReactNode;
+}) {
return (
{t("developers.courses.description")}
- {/* */}
@@ -81,7 +76,6 @@ export default function DevelopersCoursesSection(/* { courses } */) {
image={solanaDevCourseSmallImg}
/>
{courses}
- {/* */}
@@ -94,29 +88,8 @@ export default function DevelopersCoursesSection(/* { courses } */) {
className={styles["feature-card"]}
/>
{courses}
- {/* */}
);
}
-
-// const CourseCards = memo(function CourseCards({ courses }) {
-// // const t = useTranslations();
-
-// return (
-// <>
-// {courses.map((item, id) => (
-//
-// ))}
-// >
-// );
-// });
diff --git a/apps/docs/src/components/developers/sections/DevelopersDocumentsSection/DevelopersChangelog.jsx b/apps/docs/src/components/developers/sections/DevelopersDocumentsSection/DevelopersChangelog.tsx
similarity index 51%
rename from apps/docs/src/components/developers/sections/DevelopersDocumentsSection/DevelopersChangelog.jsx
rename to apps/docs/src/components/developers/sections/DevelopersDocumentsSection/DevelopersChangelog.tsx
index 35801fb79f..9e37cd5672 100644
--- a/apps/docs/src/components/developers/sections/DevelopersDocumentsSection/DevelopersChangelog.jsx
+++ b/apps/docs/src/components/developers/sections/DevelopersDocumentsSection/DevelopersChangelog.tsx
@@ -4,7 +4,21 @@ import Button from "../../../shared/Button";
import { useTranslations } from "next-intl";
import styles from "./DevelopersChangelog.module.scss";
-export default function DevelopersChangelog({ latestVideo }) {
+export type LatestChangelogVideo = {
+ snippet: {
+ description?: string;
+ resourceId?: {
+ videoId?: string;
+ };
+ playlistId?: string;
+ };
+};
+
+export default function DevelopersChangelog({
+ latestVideo,
+}: {
+ latestVideo?: LatestChangelogVideo | null;
+}) {
const t = useTranslations();
if (!latestVideo) {
return null;
@@ -23,14 +37,17 @@ export default function DevelopersChangelog({ latestVideo }) {
"...",
)}
-
+ {latestVideo.snippet?.resourceId?.videoId &&
+ latestVideo.snippet?.playlistId ? (
+
+ ) : null}
);
}
diff --git a/apps/web/src/components/developers/sections/DevelopersDocumentsSection/DevelopersDocumentItem.jsx b/apps/docs/src/components/developers/sections/DevelopersDocumentsSection/DevelopersDocumentItem.tsx
similarity index 86%
rename from apps/web/src/components/developers/sections/DevelopersDocumentsSection/DevelopersDocumentItem.jsx
rename to apps/docs/src/components/developers/sections/DevelopersDocumentsSection/DevelopersDocumentItem.tsx
index 6713ae7d1f..8ff6d9456b 100644
--- a/apps/web/src/components/developers/sections/DevelopersDocumentsSection/DevelopersDocumentItem.jsx
+++ b/apps/docs/src/components/developers/sections/DevelopersDocumentsSection/DevelopersDocumentItem.tsx
@@ -4,13 +4,21 @@ import Button from "../../../shared/Button";
import { useTranslations } from "next-intl";
import styles from "./DevelopersDocumentItem.module.scss";
+type DevelopersDocumentItemProps = {
+ title: string;
+ description: string;
+ url: string;
+ newTab?: boolean;
+ ctaLabel?: string;
+};
+
export default function DevelopersDocumentItem({
title,
description,
url,
newTab = true,
ctaLabel,
-}) {
+}: DevelopersDocumentItemProps) {
const t = useTranslations();
return (
diff --git a/apps/docs/src/components/developers/sections/DevelopersDocumentsSection/DevelopersDocumentsSection.jsx b/apps/docs/src/components/developers/sections/DevelopersDocumentsSection/DevelopersDocumentsSection.tsx
similarity index 89%
rename from apps/docs/src/components/developers/sections/DevelopersDocumentsSection/DevelopersDocumentsSection.jsx
rename to apps/docs/src/components/developers/sections/DevelopersDocumentsSection/DevelopersDocumentsSection.tsx
index 8675c631ed..e44c134152 100644
--- a/apps/docs/src/components/developers/sections/DevelopersDocumentsSection/DevelopersDocumentsSection.jsx
+++ b/apps/docs/src/components/developers/sections/DevelopersDocumentsSection/DevelopersDocumentsSection.tsx
@@ -2,7 +2,9 @@ import { useTranslations } from "next-intl";
import Image from "next/image";
import DevelopersDocumentItem from "./DevelopersDocumentItem";
-import DevelopersChangelog from "./DevelopersChangelog";
+import DevelopersChangelog, {
+ type LatestChangelogVideo,
+} from "./DevelopersChangelog";
import styles from "./DevelopersDocumentsSection.module.scss";
@@ -11,7 +13,13 @@ import { InlineLink } from "../../../../utils/Link";
import DevelopersSectionTitle from "../DevelopersSectionTitle";
import { YT_PLAYLIST_CHANGELOG } from "@/constants/developerContentConfig";
-export default function DevelopersDocumentsSection({ latestVideo }) {
+type DevelopersDocumentsSectionProps = {
+ latestVideo?: LatestChangelogVideo | null;
+};
+
+export default function DevelopersDocumentsSection({
+ latestVideo,
+}: DevelopersDocumentsSectionProps) {
const t = useTranslations();
return (
diff --git a/apps/docs/src/components/developers/sections/DevelopersHeroSection/DevelopersHeroSection.jsx b/apps/docs/src/components/developers/sections/DevelopersHeroSection/DevelopersHeroSection.tsx
similarity index 74%
rename from apps/docs/src/components/developers/sections/DevelopersHeroSection/DevelopersHeroSection.jsx
rename to apps/docs/src/components/developers/sections/DevelopersHeroSection/DevelopersHeroSection.tsx
index 1b24e5c866..fd0ccf2ee8 100644
--- a/apps/docs/src/components/developers/sections/DevelopersHeroSection/DevelopersHeroSection.jsx
+++ b/apps/docs/src/components/developers/sections/DevelopersHeroSection/DevelopersHeroSection.tsx
@@ -1,14 +1,34 @@
import classNames from "classnames";
-import Image from "next/image";
+import Image, { type StaticImageData } from "next/image";
+import type { ReactNode } from "react";
import Button from "@/components/shared/Button";
import styles from "./DevelopersHeroSection.module.scss";
+type HeroSectionButton = {
+ href?: string;
+ label: string;
+ icon?: ReactNode;
+};
+
+type HeroSectionProps = {
+ img: {
+ src: StaticImageData | string;
+ alt?: string;
+ };
+ title: string;
+ description: string;
+ buttons?: {
+ cta?: HeroSectionButton;
+ secondary?: HeroSectionButton;
+ };
+};
+
const HeroSection = ({
img: { src, alt = "" },
title,
description,
buttons,
-}) => {
+}: HeroSectionProps) => {
return (
{buttons.secondary.label}
diff --git a/apps/docs/src/components/developers/sections/DevelopersResourcesSection/DevelopersResourceItem.jsx b/apps/docs/src/components/developers/sections/DevelopersResourcesSection/DevelopersResourceItem.tsx
similarity index 77%
rename from apps/docs/src/components/developers/sections/DevelopersResourcesSection/DevelopersResourceItem.jsx
rename to apps/docs/src/components/developers/sections/DevelopersResourcesSection/DevelopersResourceItem.tsx
index b61cc6830d..914a9af167 100644
--- a/apps/docs/src/components/developers/sections/DevelopersResourcesSection/DevelopersResourceItem.jsx
+++ b/apps/docs/src/components/developers/sections/DevelopersResourcesSection/DevelopersResourceItem.tsx
@@ -5,7 +5,17 @@ import { InlineLink, Link } from "@/utils/Link";
import { useTranslations } from "next-intl";
import styles from "./DevelopersResourceItem.module.scss";
-import { memo } from "react";
+import { type ReactNode } from "react";
+
+type DevelopersResourceItemProps = {
+ category?: string;
+ children?: ReactNode;
+ title?: ReactNode;
+ description?: ReactNode;
+ url?: string;
+ isExternal?: boolean;
+ ctaLabel?: string;
+};
export default function DevelopersResourceItem({
category = "Resource",
@@ -15,19 +25,13 @@ export default function DevelopersResourceItem({
url,
isExternal,
ctaLabel,
-}) {
+}: DevelopersResourceItemProps) {
const t = useTranslations();
- // use the correct type of link
- const ResourceLink = memo(
- ({ children, ...props }) => {
- if (isExternal) return {children} ;
- else return {children};
- },
- [isExternal],
- );
+ const linkTo = url ?? "#";
+ const ResourceLink = isExternal ? InlineLink : Link;
return (
-
+
{category}
diff --git a/apps/docs/src/components/developers/sections/DevelopersResourcesSection/DevelopersResourcesSection.jsx b/apps/docs/src/components/developers/sections/DevelopersResourcesSection/DevelopersResourcesSection.tsx
similarity index 79%
rename from apps/docs/src/components/developers/sections/DevelopersResourcesSection/DevelopersResourcesSection.jsx
rename to apps/docs/src/components/developers/sections/DevelopersResourcesSection/DevelopersResourcesSection.tsx
index 272ac9316d..95611eea83 100644
--- a/apps/docs/src/components/developers/sections/DevelopersResourcesSection/DevelopersResourcesSection.jsx
+++ b/apps/docs/src/components/developers/sections/DevelopersResourcesSection/DevelopersResourcesSection.tsx
@@ -1,4 +1,4 @@
-import { memo } from "react";
+import { memo, ReactNode } from "react";
import { useTranslations } from "next-intl";
import CarouselCards from "@/components/shared/CarouselCards";
import DevelopersResourceItem from "./DevelopersResourceItem";
@@ -7,11 +7,26 @@ import DevelopersSectionTitle from "../DevelopersSectionTitle";
import styles from "./DevelopersResourcesSection.module.scss";
import Button from "@/components/shared/Button";
+export type ResourceItem = {
+ category?: string;
+ difficulty?: string;
+ title?: ReactNode;
+ description?: ReactNode;
+ href?: string;
+ isExternal?: boolean;
+};
+
+export type DevelopersResourcesSectionProps = {
+ items: ResourceItem[];
+ baseHref?: string;
+ translationKey?: string;
+};
+
export default function DevelopersResourcesSection({
items,
baseHref = "/developers/guides",
translationKey = "guides",
-}) {
+}: DevelopersResourcesSectionProps) {
const t = useTranslations();
return (
@@ -44,9 +59,11 @@ export default function DevelopersResourcesSection({
);
}
-const ResourceCards = memo(function ResourceCards({ items }) {
- // const t = useTranslations();
-
+const ResourceCards = memo(function ResourceCards({
+ items,
+}: {
+ items: ResourceItem[];
+}) {
return (
<>
{items.map((item, id) => (
diff --git a/apps/docs/src/components/developers/sections/DevelopersSectionTitle.jsx b/apps/docs/src/components/developers/sections/DevelopersSectionTitle.tsx
similarity index 69%
rename from apps/docs/src/components/developers/sections/DevelopersSectionTitle.jsx
rename to apps/docs/src/components/developers/sections/DevelopersSectionTitle.tsx
index af02901a28..4a764ec8c8 100644
--- a/apps/docs/src/components/developers/sections/DevelopersSectionTitle.jsx
+++ b/apps/docs/src/components/developers/sections/DevelopersSectionTitle.tsx
@@ -1,7 +1,11 @@
import { useTranslations } from "next-intl";
import styles from "./DevelopersSectionTitle.module.scss";
-export default function DevelopersSectionTitle({ titleId }) {
+export default function DevelopersSectionTitle({
+ titleId,
+}: {
+ titleId: string;
+}) {
const t = useTranslations();
return {t(titleId)}
;
}
diff --git a/apps/docs/src/components/opengraph/DeveloperDocsImage.tsx b/apps/docs/src/components/opengraph/DeveloperDocsImage.tsx
index fe67af5095..13ecd9b55e 100644
--- a/apps/docs/src/components/opengraph/DeveloperDocsImage.tsx
+++ b/apps/docs/src/components/opengraph/DeveloperDocsImage.tsx
@@ -6,10 +6,11 @@ import {
import { ImageResponse } from "next/og";
import { config } from "@@/src/config";
import { generateRandomInRange } from "@@/src/utils/general";
+import { ReactNode } from "react";
type DeveloperDocsImageProps = {
- heading: string;
- title: string;
+ heading: ReactNode;
+ title?: ReactNode;
};
// Image generation
diff --git a/apps/web/src/components/shared/EmailSubscribeForm/IterableEmailSubscribeForm.jsx b/apps/docs/src/components/shared/EmailSubscribeForm/IterableEmailSubscribeForm.tsx
similarity index 83%
rename from apps/web/src/components/shared/EmailSubscribeForm/IterableEmailSubscribeForm.jsx
rename to apps/docs/src/components/shared/EmailSubscribeForm/IterableEmailSubscribeForm.tsx
index 1e42cd4ee2..f0f71eae2c 100644
--- a/apps/web/src/components/shared/EmailSubscribeForm/IterableEmailSubscribeForm.jsx
+++ b/apps/docs/src/components/shared/EmailSubscribeForm/IterableEmailSubscribeForm.tsx
@@ -1,7 +1,8 @@
import classNames from "classnames";
import { useTranslations } from "next-intl";
-import { memo, useMemo } from "react";
+import { memo, useMemo, type Ref } from "react";
import * as Yup from "yup";
+import type { AnySchema } from "yup";
import Button from "../Button";
import useIterableSignUp, { ActionForm } from "../Iterable/useIterableSignUp";
@@ -11,12 +12,18 @@ const Status = {
Sending: "sending",
Error: "error",
Success: "success",
-};
+} as const;
+
+type StatusValue = (typeof Status)[keyof typeof Status] | null;
+
+type StatusMessageProps = { status: StatusValue };
-const StatusMessage = memo(function StatusMessage({ status }) {
+const StatusMessage = memo(function StatusMessage({
+ status,
+}: StatusMessageProps) {
const t = useTranslations();
- if (!Object.values(Status).includes(status)) {
+ if (!status || !Object.values(Status).includes(status)) {
return null;
}
@@ -42,6 +49,15 @@ const defaultValues = {
email: "",
};
+type IterableEmailSubscribeFormProps = {
+ inputRef?: Ref;
+ formId: string;
+ schema?: AnySchema;
+ initialValues?: Record;
+ placeholderTextID?: string;
+ ctaTextID?: string;
+};
+
export default function IterableEmailSubscribeForm({
inputRef,
formId,
@@ -49,7 +65,7 @@ export default function IterableEmailSubscribeForm({
initialValues = defaultValues,
placeholderTextID,
ctaTextID,
-}) {
+}: IterableEmailSubscribeFormProps) {
const t = useTranslations();
const {
@@ -72,7 +88,7 @@ export default function IterableEmailSubscribeForm({
return isDirty && isSubmitting && !schema.isValidSync(values);
}, [schema, isDirty, isSubmitting, values]);
- const status = useMemo(() => {
+ const status = useMemo(() => {
if (error) {
return Status.Error;
}
@@ -124,7 +140,7 @@ export default function IterableEmailSubscribeForm({
onClick={onSubmit}
>
{ctaTextID
- ? t({ ctaTextID })
+ ? t({ ctaTextID } as never)
: t("shared.mail-signup.form.signup")}
diff --git a/apps/docs/src/components/shared/EmailSubscribeForm/index.js b/apps/docs/src/components/shared/EmailSubscribeForm/index.ts
similarity index 100%
rename from apps/docs/src/components/shared/EmailSubscribeForm/index.js
rename to apps/docs/src/components/shared/EmailSubscribeForm/index.ts
diff --git a/apps/web/src/components/shared/Iterable/useIterableSignUp.jsx b/apps/docs/src/components/shared/Iterable/useIterableSignUp.tsx
similarity index 57%
rename from apps/web/src/components/shared/Iterable/useIterableSignUp.jsx
rename to apps/docs/src/components/shared/Iterable/useIterableSignUp.tsx
index acf72c20d7..55ffa85c22 100644
--- a/apps/web/src/components/shared/Iterable/useIterableSignUp.jsx
+++ b/apps/docs/src/components/shared/Iterable/useIterableSignUp.tsx
@@ -1,9 +1,18 @@
-import { useCallback, useState } from "react";
+import {
+ useCallback,
+ useState,
+ type FormHTMLAttributes,
+ type ReactNode,
+} from "react";
+import type { AnySchema } from "yup";
const ITERABLE_BASE_URL =
"https://links.iterable.com/lists/publicAddSubscriberForm?publicIdString=";
-async function sendFormRequest(actionUrl, dataObject) {
+async function sendFormRequest(
+ actionUrl: string,
+ dataObject: Record,
+): Promise {
const data = new FormData();
Object.keys(dataObject).map((key) => {
@@ -22,13 +31,18 @@ async function sendFormRequest(actionUrl, dataObject) {
}
}
+type ActionFormProps = FormHTMLAttributes & {
+ children: ReactNode;
+ action?: string;
+};
+
export function ActionForm({
children,
action,
target = "_blank",
method = "post",
...props
-}) {
+}: ActionFormProps) {
return (
)}
@@ -93,7 +93,7 @@ export const LinkCard = ({ link }: LinkCardProps) => {
{link.title}
- {link.description && (
+ {link.description ? (
{typeof link.description === "string" ? (
{link.description}
@@ -101,7 +101,7 @@ export const LinkCard = ({ link }: LinkCardProps) => {
{String(link.description)}
)}
- )}
+ ) : null}
{link.tags?.map(
(tag: string) =>
diff --git a/apps/media/components/magicui/script-copy-btn.tsx b/apps/media/components/magicui/script-copy-btn.tsx
index 6b6ddfc611..1da7d76f59 100644
--- a/apps/media/components/magicui/script-copy-btn.tsx
+++ b/apps/media/components/magicui/script-copy-btn.tsx
@@ -31,8 +31,9 @@ export function ScriptCopyBtn({
const [highlightedCode, setHighlightedCode] = useState("");
const { theme } = useTheme();
const command =
- commands.find((line) => line.startsWith(packageManager))?.split("|")[1] ||
- "";
+ commands
+ .find((line) => line.startsWith(packageManager ?? ""))
+ ?.split("|")[1] || "";
useEffect(() => {
async function loadHighlightedCode() {
diff --git a/apps/media/components/mdx-components.tsx b/apps/media/components/mdx-components.tsx
index 7b43b5c72f..b12352e689 100644
--- a/apps/media/components/mdx-components.tsx
+++ b/apps/media/components/mdx-components.tsx
@@ -1,7 +1,7 @@
import { format } from "date-fns";
import React from "react";
import type { ReactNode, ElementType } from "react";
-import Image from "next/image";
+import Image, { ImageProps } from "next/image";
import { Video } from "./blocks/video";
import { Mermaid } from "./blocks/mermaid";
import { Tweet } from "react-tweet";
@@ -368,7 +368,7 @@ export const components = {
gallery: (props: { background?: string; images?: GalleryImage[] }) => {
// Cast to any to avoid type conflicts between Keystatic schema and Gallery component
- return ;
+ return ;
},
stats: (props: StatsBlockData) => {
@@ -397,7 +397,7 @@ export const components = {
),
},
} as DocumentRendererProps["renderers"] & {
- block?: Record React.ReactNode>;
+ block?: Record>;
};
// Custom component tags used in MDX content (from Keystatic component blocks).
@@ -500,7 +500,7 @@ const StatsBlock = (props: StatsBlockData) => {
const statsData = {
title: props.title || "",
description: props.description || "",
- stats: props.stats?.map((stat: any) => ({
+ stats: props.stats?.map((stat) => ({
stat: stat?.stat,
type: stat?.type,
})),
@@ -590,7 +590,7 @@ const SupBlock = (props: { children: React.ReactNode }) => (
// - Capitalized names: for custom inline JSX components (after preprocessMDX capitalizes tags)
// MDX v3 resolves capitalized JSX from props.components via destructuring
// - Lowercase names: for markdown-generated HTML element overrides (img, blockquote from > syntax)
-export const mdxComponents: Record> = {
+export const mdxComponents = {
// Capitalized custom components (resolved by MDX v3 for inline JSX)
Tweet: TweetBlock,
Video: VideoBlock,
@@ -604,7 +604,7 @@ export const mdxComponents: Record> = {
Sup: SupBlock,
// Lowercase overrides for markdown-generated elements
blockquote: BlockquoteBlock,
- img: ({ src, alt }: any) => {
+ img: ({ src, alt }: { src?: ImageProps["src"]; alt?: ImageProps["alt"] }) => {
if (!src) return null;
return (
diff --git a/apps/media/components/motion-primitives/text-effect.tsx b/apps/media/components/motion-primitives/text-effect.tsx
index 84740a84d7..5a2f75c92a 100644
--- a/apps/media/components/motion-primitives/text-effect.tsx
+++ b/apps/media/components/motion-primitives/text-effect.tsx
@@ -184,8 +184,8 @@ const createVariantsWithTransition = (
visible: {
...baseVariants.visible,
transition: {
- ...(hasTransition(baseVariants.visible)
- ? baseVariants.visible.transition
+ ...(hasTransition(baseVariants.visible ?? {})
+ ? (baseVariants.visible as TargetAndTransition).transition
: {}),
...mainTransition,
},
@@ -193,8 +193,8 @@ const createVariantsWithTransition = (
exit: {
...baseVariants.exit,
transition: {
- ...(hasTransition(baseVariants.exit)
- ? baseVariants.exit.transition
+ ...(hasTransition(baseVariants.exit ?? {})
+ ? (baseVariants.exit as TargetAndTransition).transition
: {}),
...mainTransition,
staggerDirection: -1,
diff --git a/apps/media/components/podcast/audio-player.tsx b/apps/media/components/podcast/audio-player.tsx
index ca69547447..8e0b9cd2c6 100644
--- a/apps/media/components/podcast/audio-player.tsx
+++ b/apps/media/components/podcast/audio-player.tsx
@@ -108,7 +108,7 @@ export const AudioPlayer = ({
const rates = [0.5, 0.75, 1, 1.25, 1.5, 2];
const currentIndex = rates.indexOf(globalPlayer.playbackRate);
const nextIndex = (currentIndex + 1) % rates.length;
- globalPlayer.setPlaybackRate(rates[nextIndex]);
+ globalPlayer.setPlaybackRate(rates[nextIndex] ?? 1);
}, [isGlobalEpisode, globalPlayer]);
const getProgressFromPosition = useCallback((clientX: number) => {
diff --git a/apps/media/components/podcast/player-context.tsx b/apps/media/components/podcast/player-context.tsx
index b2d366b433..77bbe9d09e 100644
--- a/apps/media/components/podcast/player-context.tsx
+++ b/apps/media/components/podcast/player-context.tsx
@@ -28,18 +28,18 @@ interface PlayerContextValue {
isMuted: boolean;
playbackRate: number;
play: (
- episode: PodcastEpisode,
- podcastTitle?: string,
- podcastSlug?: string,
+ _episode: PodcastEpisode,
+ _podcastTitle?: string,
+ _podcastSlug?: string,
) => void;
pause: () => void;
togglePlayPause: () => void;
- seek: (fraction: number) => void;
- skipForward: (seconds?: number) => void;
- skipBackward: (seconds?: number) => void;
- setVolume: (volume: number) => void;
+ seek: (_fraction: number) => void;
+ skipForward: (_seconds?: number) => void;
+ skipBackward: (_seconds?: number) => void;
+ setVolume: (_volume: number) => void;
toggleMute: () => void;
- setPlaybackRate: (rate: number) => void;
+ setPlaybackRate: (_rate: number) => void;
setProgress: (_progress: number) => void;
setDuration: (_duration: number) => void;
dismiss: () => void;
diff --git a/apps/media/components/podcast/podcast-card.tsx b/apps/media/components/podcast/podcast-card.tsx
index aa600f6cbe..b3d8111bea 100644
--- a/apps/media/components/podcast/podcast-card.tsx
+++ b/apps/media/components/podcast/podcast-card.tsx
@@ -81,7 +81,7 @@ export const PodcastCard = ({
{podcast.hosts.length === 1
- ? podcast.hosts[0].name
+ ? podcast.hosts[0]?.name
: podcast.hosts.map((h) => h.name).join(", ")}
diff --git a/apps/media/components/post/post-card.tsx b/apps/media/components/post/post-card.tsx
index 4b6239c815..5492a79ad7 100644
--- a/apps/media/components/post/post-card.tsx
+++ b/apps/media/components/post/post-card.tsx
@@ -2,7 +2,10 @@ import Link from "next/link";
import Image from "next/image";
import { Badge } from "@/components/ui/badge";
import { PostItem } from "@/lib/post-types";
-import { DocumentRenderer } from "@keystatic/core/renderer";
+import {
+ DocumentRenderer,
+ DocumentRendererProps,
+} from "@keystatic/core/renderer";
import { components } from "@/components/mdx-components";
import { ArrowUpRight } from "lucide-react";
import { cn } from "@/lib/utils";
@@ -17,8 +20,14 @@ function getUniqueValues(values: string[] | undefined): string[] {
return Array.from(new Set(values.filter(Boolean)));
}
+interface DescriptionContentProps {
+ description?:
+ | DocumentRendererProps["document"]
+ | { node: { children: DocumentRendererProps["document"] } };
+}
+
// Helper: render description as plain text or DocumentRenderer document
-function DescriptionContent({ description }: { description: any }) {
+function DescriptionContent({ description }: DescriptionContentProps) {
if (!description) return null;
// Plain string from fields.text()
@@ -33,7 +42,8 @@ function DescriptionContent({ description }: { description: any }) {
// Object with node.children
if (typeof description === "object" && "node" in description) {
- const children = description.node?.children;
+ const children =
+ "children" in description.node ? description.node?.children : null;
if (Array.isArray(children)) {
return ;
}
@@ -79,7 +89,11 @@ export const PostCard = ({ post, variant = "vertical" }: PostCardProps) => {
)}
-
+
@@ -128,7 +142,11 @@ export const PostCard = ({ post, variant = "vertical" }: PostCardProps) => {
{post.title}
-
+
Read article
diff --git a/apps/media/components/raw-renderer.tsx b/apps/media/components/raw-renderer.tsx
index 1d50613b0c..73abce7f8e 100644
--- a/apps/media/components/raw-renderer.tsx
+++ b/apps/media/components/raw-renderer.tsx
@@ -10,8 +10,13 @@ import {
} from "@headlessui/react";
import { useLayout } from "./layout/layout-context";
-//@ts-ignore
-export const RawRenderer = ({ rawData, parentColor }) => {
+export const RawRenderer = ({
+ rawData,
+ parentColor,
+}: {
+ rawData?: object;
+ parentColor?: string;
+}) => {
const { theme } = useLayout();
const buttonColorClasses = {
blue: "text-blue-500",
@@ -38,7 +43,6 @@ export const RawRenderer = ({ rawData, parentColor }) => {
);
}
diff --git a/apps/web/src/app/[locale]/community/page.tsx b/apps/web/src/app/[locale]/community/page.tsx
index 0eee75112b..089d589fb7 100644
--- a/apps/web/src/app/[locale]/community/page.tsx
+++ b/apps/web/src/app/[locale]/community/page.tsx
@@ -24,9 +24,9 @@ export default async function Page(_props: Props) {
]);
const socialData = {
- youtube: youtube.status === "fulfilled" ? youtube.value : null,
- github: github.status === "fulfilled" ? github.value : null,
- meetup: meetup.status === "fulfilled" ? meetup.value : null,
+ youtube: youtube.status === "fulfilled" ? youtube.value : undefined,
+ github: github.status === "fulfilled" ? github.value : undefined,
+ meetup: meetup.status === "fulfilled" ? meetup.value : undefined,
};
return (
diff --git a/apps/web/src/app/[locale]/community/report-2024-newsletter-sign-up/community-report-2024-newsletter-sign-up.tsx b/apps/web/src/app/[locale]/community/report-2024-newsletter-sign-up/community-report-2024-newsletter-sign-up.tsx
index c06192ac5e..b5231a6a2f 100644
--- a/apps/web/src/app/[locale]/community/report-2024-newsletter-sign-up/community-report-2024-newsletter-sign-up.tsx
+++ b/apps/web/src/app/[locale]/community/report-2024-newsletter-sign-up/community-report-2024-newsletter-sign-up.tsx
@@ -21,7 +21,7 @@ export function CommunityReport2024NewsletterSignUpPage({
return (
-
+ ["cards"]
+ }
+ numCols={CARD_DECK_COLUMNS}
+ />
- false}
/>
-
+ ["cards"]}
+ />
["listItems"]
+ }
/>
>
diff --git a/apps/web/src/app/[locale]/developers/defi/developers-defi.tsx b/apps/web/src/app/[locale]/developers/defi/developers-defi.tsx
index ee8cae235c..2b4e7ee95a 100644
--- a/apps/web/src/app/[locale]/developers/defi/developers-defi.tsx
+++ b/apps/web/src/app/[locale]/developers/defi/developers-defi.tsx
@@ -128,7 +128,11 @@ export function DevelopersDefiPage() {
eyebrow={t("switchback.eyebrow")}
headline={t("switchback.headline")}
body={t.raw("switchback.body")}
- buttons={switchbackButtons as any}
+ buttons={
+ switchbackButtons as React.ComponentProps<
+ typeof Switchback
+ >["buttons"]
+ }
/>
@@ -140,7 +144,12 @@ export function DevelopersDefiPage() {
-
+ ["cards"]
+ }
+ numCols={CARD_DECK_COLUMNS}
+ />
@@ -148,7 +157,11 @@ export function DevelopersDefiPage() {
variant={CONVERSION_PANEL_PRIMARY.variant as "centered"}
heading={t("conversionPanel.heading")}
body={t("conversionPanel.body")}
- buttons={conversionPanelButtons as any}
+ buttons={
+ conversionPanelButtons as React.ComponentProps<
+ typeof ConversionPanel
+ >["buttons"]
+ }
logos={[]}
showLogos={false}
/>
@@ -157,7 +170,11 @@ export function DevelopersDefiPage() {
["cards"]
+ }
/>
@@ -169,7 +186,11 @@ export function DevelopersDefiPage() {
buttons={[]}
logos={[]}
showLogos={CONVERSION_PANEL_COMMUNITY.showLogos}
- listItems={communityListItems as any}
+ listItems={
+ communityListItems as React.ComponentProps<
+ typeof ConversionPanel
+ >["listItems"]
+ }
/>
>
diff --git a/apps/web/src/app/[locale]/developers/evm-to-svm/erc4626/developers-evm-to-svm-erc4626.tsx b/apps/web/src/app/[locale]/developers/evm-to-svm/erc4626/developers-evm-to-svm-erc4626.tsx
index 6512f23556..8d690e06f8 100644
--- a/apps/web/src/app/[locale]/developers/evm-to-svm/erc4626/developers-evm-to-svm-erc4626.tsx
+++ b/apps/web/src/app/[locale]/developers/evm-to-svm/erc4626/developers-evm-to-svm-erc4626.tsx
@@ -100,7 +100,7 @@ export function DevelopersEvmToSvmErc4626Page() {
{t(row.objectKey)}
- {"purposeParts" in row ? (
+ {"purposeParts" in row && row.purposeParts ? (
row.purposeParts.map((part, partIndex) => {
if (part.type === "code") {
return (
@@ -116,9 +116,9 @@ export function DevelopersEvmToSvmErc4626Page() {
);
})
- ) : (
+ ) : "purposeKey" in row ? (
{t(row.purposeKey)}
- )}
+ ) : null}
))}
diff --git a/apps/web/src/app/[locale]/developers/gaming/developers-gaming.tsx b/apps/web/src/app/[locale]/developers/gaming/developers-gaming.tsx
index 9d156c1bd1..53cbbbb8dc 100644
--- a/apps/web/src/app/[locale]/developers/gaming/developers-gaming.tsx
+++ b/apps/web/src/app/[locale]/developers/gaming/developers-gaming.tsx
@@ -24,8 +24,6 @@ import {
} from "@/data/developers/gaming";
import { useTranslations } from "next-intl";
-const FeatureHighlightAny = FeatureHighlight as any;
-
export function DevelopersGamingPage() {
const t = useTranslations("developers-gaming");
const blockSpacing = { large: { marginTop: "20px" } };
@@ -40,11 +38,13 @@ export function DevelopersGamingPage() {
label: t(`conversionPanels.gamesKit.listItems.${index}`),
}));
- const featureHighlightCards = FEATURE_HIGHLIGHT_CARDS.map((card, index) => ({
- ...card,
- feature: t(`featureHighlight.cards.${index}.feature`),
- body: t(`featureHighlight.cards.${index}.body`),
- }));
+ const featureHighlightCards = FEATURE_HIGHLIGHT_CARDS.map(
+ ({ ...card }, index) => ({
+ ...card,
+ feature: t(`featureHighlight.cards.${index}.feature`),
+ body: t(`featureHighlight.cards.${index}.body`),
+ }),
+ );
const featureHighlightButtons = FEATURE_HIGHLIGHT.buttons.map(
(button, index) => ({
@@ -124,15 +124,16 @@ export function DevelopersGamingPage() {
- false}
/>
@@ -173,7 +174,11 @@ export function DevelopersGamingPage() {
["switchbacks"]
+ }
/>
@@ -191,7 +196,11 @@ export function DevelopersGamingPage() {
variant={FUNDING_PANEL.variant as "centered"}
heading={t("conversionPanels.funding.heading")}
body={t("conversionPanels.funding.body")}
- buttons={fundingButtons as any}
+ buttons={
+ fundingButtons as React.ComponentProps<
+ typeof ConversionPanel
+ >["buttons"]
+ }
logos={FUNDING_PANEL.logos}
listItems={[]}
showLogos={FUNDING_PANEL.showLogos}
@@ -205,7 +214,11 @@ export function DevelopersGamingPage() {
body={t("conversionPanels.community.body")}
buttons={[]}
logos={[]}
- listItems={communityListItems as any}
+ listItems={
+ communityListItems as React.ComponentProps<
+ typeof ConversionPanel
+ >["listItems"]
+ }
showLogos={COMMUNITY_PANEL.showLogos}
/>
diff --git a/apps/web/src/app/[locale]/developers/nfts/developers-nfts.tsx b/apps/web/src/app/[locale]/developers/nfts/developers-nfts.tsx
index 7b088a4e88..46f70046ef 100644
--- a/apps/web/src/app/[locale]/developers/nfts/developers-nfts.tsx
+++ b/apps/web/src/app/[locale]/developers/nfts/developers-nfts.tsx
@@ -157,9 +157,10 @@ export function DevelopersNftsPage() {
headline={t("featureHighlight.headline")}
body={t("featureHighlight.body")}
desktopBackground={FEATURE_HIGHLIGHT.desktopBackground}
- cards={featureHighlightCards as any}
- buttons={featureHighlightButtons as any}
- valueOf={null}
+ cards={featureHighlightCards}
+ buttons={featureHighlightButtons}
+ // Check if it exists in @solana-foundation/solana-lib after the upstream fix.
+ valueOf={() => false}
/>
({
- ...card,
- feature: t(`featureHighlight.cards.${index}.feature`),
- body: t(`featureHighlight.cards.${index}.body`),
- }));
+ const featureHighlightCards = FEATURE_HIGHLIGHT_CARDS.map(
+ ({ ...card }, index) => ({
+ ...card,
+ feature: t(`featureHighlight.cards.${index}.feature`),
+ body: t(`featureHighlight.cards.${index}.body`),
+ }),
+ );
const switchbackButtons = SWITCHBACK_BUTTONS.map((button, index) => ({
...button,
label: t(`switchback.buttons.${index}`),
@@ -106,9 +108,10 @@ export function DevelopersPaymentsPage() {
body={t("featureHighlight.body")}
headingAs={"h2"}
desktopBackground={FEATURE_HIGHLIGHT.desktopBackground}
- cards={featureHighlightCards as any}
+ cards={featureHighlightCards}
buttons={[]}
- valueOf={null}
+ // Check if it exists in @solana-foundation/solana-lib after the upstream fix.
+ valueOf={() => false}
/>
diff --git a/apps/web/src/app/[locale]/events/archive/events-archive.tsx b/apps/web/src/app/[locale]/events/archive/events-archive.tsx
index 9095f9ed0a..0bc0bfc23d 100644
--- a/apps/web/src/app/[locale]/events/archive/events-archive.tsx
+++ b/apps/web/src/app/[locale]/events/archive/events-archive.tsx
@@ -4,9 +4,10 @@ import { StrictMode, useState } from "react";
import EventsHeroSection from "@/components/events/EventsHeroSection";
import EventsList from "@/components/events/EventsList";
import EventsArchivePagination from "@/components/events/archive/EventsArchivePagination";
+import type { CalendarEvent } from "@/lib/events/fetchCalendarEvents";
interface EventsArchivePageProps {
- events: any[];
+ events: CalendarEvent[];
}
export function EventsArchivePage({ events }: EventsArchivePageProps) {
diff --git a/apps/web/src/app/[locale]/events/archive/page.tsx b/apps/web/src/app/[locale]/events/archive/page.tsx
index 64c61d5afa..48c4bf3962 100644
--- a/apps/web/src/app/[locale]/events/archive/page.tsx
+++ b/apps/web/src/app/[locale]/events/archive/page.tsx
@@ -33,7 +33,10 @@ export default async function Page(_props: Props) {
limit: 20,
});
- const sortInstructions = [[(x: any) => x.schedule.from], ["desc"]];
+ const sortInstructions = [
+ [(x: { schedule: { from: string | null } }) => x.schedule.from],
+ ["desc"],
+ ];
const sorted = orderBy(
[...mainEvents, ...hhEvents, ...communityEvents, ...communityRiverEvents],
...sortInstructions,
diff --git a/apps/web/src/app/[locale]/events/events.tsx b/apps/web/src/app/[locale]/events/events.tsx
index cb9d92b1b2..64a9977c29 100644
--- a/apps/web/src/app/[locale]/events/events.tsx
+++ b/apps/web/src/app/[locale]/events/events.tsx
@@ -8,12 +8,13 @@ import EventsList from "@/components/events/EventsList";
import Button from "@/components/shared/Button";
import Divider from "@/components/shared/Divider";
import { InlineLink } from "@/utils/Link";
+import type { CalendarEvent } from "@/lib/events/fetchCalendarEvents";
interface EventsLandingPageProps {
- events: any[];
- communityEvents: any[];
- featuredEvent: any;
- usEvents: any[];
+ events: CalendarEvent[];
+ communityEvents: CalendarEvent[];
+ featuredEvent: CalendarEvent | null;
+ usEvents: CalendarEvent[];
translations: {
usHeading: string;
usDescription: string;
diff --git a/apps/web/src/app/[locale]/events/page.tsx b/apps/web/src/app/[locale]/events/page.tsx
index 5f466ce539..70067d72b1 100644
--- a/apps/web/src/app/[locale]/events/page.tsx
+++ b/apps/web/src/app/[locale]/events/page.tsx
@@ -40,7 +40,10 @@ export default async function Page(_props: Props) {
limit: 20,
});
- const sortInstructions = [[(x: any) => x.schedule.from], ["asc"]];
+ const sortInstructions = [
+ [(x: { schedule: { from: string | null } }) => x.schedule.from],
+ ["asc"],
+ ];
// sorted and unique main events
const sorted = orderBy([...mainEvents], ...sortInstructions);
@@ -54,7 +57,7 @@ export default async function Page(_props: Props) {
// Set featured event: prefer explicitly marked featured, else first by date
const featuredEvent =
- unique.find((e: any) => e.featured === true) || unique[0] || null;
+ unique.find((e) => e.featured === true) || unique[0] || null;
const events = [...unique];
const t = await getTranslations();
diff --git a/apps/web/src/app/[locale]/home.tsx b/apps/web/src/app/[locale]/home.tsx
index c6f996e7a6..cc4c19aa0c 100644
--- a/apps/web/src/app/[locale]/home.tsx
+++ b/apps/web/src/app/[locale]/home.tsx
@@ -76,9 +76,7 @@ interface HomePageProps {
communitySubtitle: string;
communityLinksTranslations: { title: string; description: string }[];
};
- events: (Omit & {
- schedule: CalendarEvent["schedule"] & { from: string; to: string };
- })[];
+ events: CalendarEvent[];
firstFeaturedEventIndex: number;
videos: YouTubePlaylistItem[];
news: PostItem[];
@@ -130,8 +128,8 @@ export function HomePage({
return eventDate >= oneWeekAgo;
})
.sort((a, b) => {
- const dateA = new Date(a.schedule.from).getTime();
- const dateB = new Date(b.schedule.from).getTime();
+ const dateA = new Date(a.schedule.from ?? 0).getTime();
+ const dateB = new Date(b.schedule.from ?? 0).getTime();
return dateA - dateB;
});
}, [events]);
@@ -211,8 +209,8 @@ export function HomePage({
key={event.key}
imageSrc={event.img.primary || defaultImg.src}
title={event.title}
- date={event.schedule.from}
- location={event.venue.city || event.venue.address}
+ date={event.schedule.from ?? undefined}
+ location={event.venue.city ?? event.venue.address ?? undefined}
href={event.rsvp}
className="px-1"
/>
@@ -278,7 +276,7 @@ export function HomePage({
(
{/* Animation styles */}
+ {/* eslint-disable-next-line react/no-unknown-property*/}