From 54de91bc7c9941eb541910690412bcd6cd3e329e Mon Sep 17 00:00:00 2001 From: Joshua Melville Date: Fri, 15 Nov 2024 15:35:23 +0200 Subject: [PATCH] biome passing --- .vscode/settings.json | 3 ++ .../analytics/EventsTable/EventsTable.tsx | 4 +- .../EventsTable/StackTraceDialog.tsx | 2 +- .../analytics/EventsTable/TableFilter.tsx | 7 ++- .../users/UsersTable/UsersTable.tsx | 2 +- .../analytics-web/components/DialogButton.tsx | 2 +- apps/analytics-web/drizzle.config.ts | 6 ++- .../_components/InnerLanguageSwitcher.tsx | 2 +- apps/documentation/app/types.ts | 18 +++---- .../documentation/components/FancyHeading.tsx | 2 + .../components/FancyParagraph.tsx | 2 + .../components/ProjectSwitcher.tsx | 8 ++-- apps/documentation/components/Sidebar.tsx | 38 ++++++++------- apps/documentation/components/ui/sheet.tsx | 1 + apps/documentation/hooks/useHighlighted.ts | 8 ++-- apps/documentation/lib/docs.tsx | 3 +- apps/documentation/lib/processPreTags.ts | 4 +- apps/documentation/lib/tableOfContents.ts | 10 ++-- apps/documentation/lib/writeSidebarJson.ts | 26 +++++----- apps/documentation/styles/prism.css | 47 ------------------- biome.json | 2 +- packages/analytics/src/index.ts | 9 ++-- .../src/BackgroundBlobs/BackgroundBlobs.tsx | 6 ++- packages/ui/src/CloseButton.tsx | 5 +- packages/ui/src/FancyBox.tsx | 8 ++-- packages/ui/src/FancyButton.tsx | 2 +- packages/ui/src/toast.tsx | 6 +-- packages/ui/src/use-toast.ts | 11 +++-- 28 files changed, 113 insertions(+), 131 deletions(-) delete mode 100644 apps/documentation/styles/prism.css diff --git a/.vscode/settings.json b/.vscode/settings.json index 37d7042..51b6e92 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -6,5 +6,8 @@ "editor.defaultFormatter": "biomejs.biome", "[typescriptreact]": { "editor.defaultFormatter": "biomejs.biome" + }, + "[typescript]": { + "editor.defaultFormatter": "biomejs.biome" } } diff --git a/apps/analytics-web/app/_components/analytics/EventsTable/EventsTable.tsx b/apps/analytics-web/app/_components/analytics/EventsTable/EventsTable.tsx index 6220f33..dfa01d4 100644 --- a/apps/analytics-web/app/_components/analytics/EventsTable/EventsTable.tsx +++ b/apps/analytics-web/app/_components/analytics/EventsTable/EventsTable.tsx @@ -26,7 +26,9 @@ export default function EventsTable() { useEffect(() => { const eventTypesMap = new Map(); - events.forEach((event) => eventTypesMap.set(event.type, { text: event.type, isSelected: true })); + for (const event of events) { + eventTypesMap.set(event.type, { text: event.type, isSelected: true }); + } setEventTypes([...Array.from(eventTypesMap.values())]); }, [events]); diff --git a/apps/analytics-web/app/_components/analytics/EventsTable/StackTraceDialog.tsx b/apps/analytics-web/app/_components/analytics/EventsTable/StackTraceDialog.tsx index d07e107..a7c63c5 100644 --- a/apps/analytics-web/app/_components/analytics/EventsTable/StackTraceDialog.tsx +++ b/apps/analytics-web/app/_components/analytics/EventsTable/StackTraceDialog.tsx @@ -3,6 +3,6 @@ import { DialogButton } from "~/components/DialogButton"; export function StackTraceDialog({ error }: { error: Event }) { return ( - + ); } diff --git a/apps/analytics-web/app/_components/analytics/EventsTable/TableFilter.tsx b/apps/analytics-web/app/_components/analytics/EventsTable/TableFilter.tsx index 5df49cd..8014849 100644 --- a/apps/analytics-web/app/_components/analytics/EventsTable/TableFilter.tsx +++ b/apps/analytics-web/app/_components/analytics/EventsTable/TableFilter.tsx @@ -57,10 +57,15 @@ const TableFilter = ({ eventTypes, setEventTypes }: TableFilterProps) => { {options.map((option) => ( ))} diff --git a/apps/analytics-web/app/_components/users/UsersTable/UsersTable.tsx b/apps/analytics-web/app/_components/users/UsersTable/UsersTable.tsx index a78b1ec..1bc6d51 100644 --- a/apps/analytics-web/app/_components/users/UsersTable/UsersTable.tsx +++ b/apps/analytics-web/app/_components/users/UsersTable/UsersTable.tsx @@ -9,7 +9,7 @@ export default async function VerifiedUsersTable() { const users = clerkUsers.data.map((user) => { return { id: user.id, - fullName: user.firstName + " " + user.lastName, + fullName: `${user.firstName} ${user.lastName}`, username: user.username, verified: !!user.publicMetadata.verified, }; diff --git a/apps/analytics-web/components/DialogButton.tsx b/apps/analytics-web/components/DialogButton.tsx index 3ad0523..e7b2c60 100644 --- a/apps/analytics-web/components/DialogButton.tsx +++ b/apps/analytics-web/components/DialogButton.tsx @@ -12,7 +12,7 @@ import { type DialogButtonProps = { buttonLabel: string; title: string; - description: string; + description: string | null; content: ReactNode; }; diff --git a/apps/analytics-web/drizzle.config.ts b/apps/analytics-web/drizzle.config.ts index 973182c..fb707cc 100644 --- a/apps/analytics-web/drizzle.config.ts +++ b/apps/analytics-web/drizzle.config.ts @@ -4,11 +4,13 @@ dotenv.config(); import { defineConfig } from "drizzle-kit"; export default defineConfig({ + dialect: "postgresql", schema: "./db/schema.ts", out: "./drizzle", - driver: "pg", + driver: "pglite", dbCredentials: { - connectionString: process.env.POSTGRES_URL!, + // biome-ignore lint/style/noNonNullAssertion: env variable must be defined + url: process.env.POSTGRES_URL!, }, verbose: true, strict: true, diff --git a/apps/documentation/app/[locale]/[project]/_components/InnerLanguageSwitcher.tsx b/apps/documentation/app/[locale]/[project]/_components/InnerLanguageSwitcher.tsx index e0a7eb2..7ab663a 100644 --- a/apps/documentation/app/[locale]/[project]/_components/InnerLanguageSwitcher.tsx +++ b/apps/documentation/app/[locale]/[project]/_components/InnerLanguageSwitcher.tsx @@ -11,7 +11,7 @@ type InnerLanguageSwitcherProps = { const InnerLanguageSwitcher = async ({ pathSegment, currentLocale, project }: InnerLanguageSwitcherProps) => { const t = await getTranslations("DocPage"); const availableLocales = getAvailableLocalesForPath(project, pathSegment); - const filePath = `/${project}/` + pathSegment.join("/"); //document file path to navigate to + const filePath = `/${project}/${pathSegment.join("/")}`; //document file path to navigate to // removes the current locale from availableLocales const supportedLanguages = availableLocales.filter((locale) => locale !== currentLocale); diff --git a/apps/documentation/app/types.ts b/apps/documentation/app/types.ts index 0c5bcbd..8baf05c 100644 --- a/apps/documentation/app/types.ts +++ b/apps/documentation/app/types.ts @@ -2,11 +2,13 @@ import { z } from "zod"; export const projects = ["desktop", "fresco"] as const; -export type ProjectsEnum = (typeof projects)[number]; +export type Project = (typeof projects)[number]; export const locales = ["en"] as const; -const Locale = z.enum(locales); +export const zlocales = z.enum(locales); + +export type Locales = typeof locales; export type Locale = (typeof locales)[number]; @@ -16,10 +18,7 @@ export const itemTypes = [ "page", // Single page ] as const; -const ItemTypesEnum = z.enum(itemTypes); - export const SidebarItemBase = z.object({ - type: ItemTypesEnum, sourceFile: z.string().optional(), label: z.string(), }); @@ -60,13 +59,14 @@ export const SidebarProjectSchema = SidebarItemBase.extend({ export type SidebarProject = z.infer; -export const SidebarLocaleDefinitionSchema = z.record(z.string(), SidebarProjectSchema); +export const SidebarLocaleDefinitionSchema = z.record(z.enum(projects), SidebarProjectSchema); -export type SidebarLocaleDefinition = z.infer; +export type SidebarLocaleDefinition = Record; -export const SideBarSchema = z.record(Locale, SidebarLocaleDefinitionSchema); +export const SideBarSchema = z.record(zlocales, SidebarLocaleDefinitionSchema); -export type TSideBar = z.infer; +// Can't infer this from above because of this: https://github.com/colinhacks/zod/issues/2623 +export type TSideBar = Record; const metadatatypes = ["folder", "project"] as const; diff --git a/apps/documentation/components/FancyHeading.tsx b/apps/documentation/components/FancyHeading.tsx index 3fbe82d..363511c 100644 --- a/apps/documentation/components/FancyHeading.tsx +++ b/apps/documentation/components/FancyHeading.tsx @@ -26,6 +26,7 @@ const FancyHeading = (props: HeadingProps) => { const segments = word.split(" "); return segments.map((segment, innerIndex) => ( @@ -49,6 +50,7 @@ const FancyHeading = (props: HeadingProps) => { renderWord(word, index) ) : ( { const segments = word.split(" "); return segments.map((segment, innerIndex) => ( @@ -49,6 +50,7 @@ const FancyParagraph = (props: ParagraphProps) => { renderWord(word, index) ) : ( { +const getImageForProject = (project: Project) => { if (project === "desktop") { return {project}; } @@ -21,7 +21,7 @@ const getImageForProject = (project: ProjectsEnum) => { const ProjectValue = forwardRef< HTMLDivElement, { - project: ProjectsEnum; + project: Project; showDescription?: boolean; } >(({ project, showDescription }, ref) => { @@ -51,7 +51,7 @@ export default function ProjectSwitcher() { const router = useRouter(); const pathname = usePathname(); // biome-ignore lint/style/noNonNullAssertion: path structure is known - const project = pathname.split("/")[2]! as ProjectsEnum; + const project = pathname.split("/")[2]! as Project; const locale = useLocale() as Locale; return ( diff --git a/apps/documentation/components/Sidebar.tsx b/apps/documentation/components/Sidebar.tsx index 1b03337..5917dbb 100644 --- a/apps/documentation/components/Sidebar.tsx +++ b/apps/documentation/components/Sidebar.tsx @@ -5,7 +5,7 @@ import { useLocale } from "next-intl"; import Link from "next/link"; import { usePathname } from "next/navigation"; import { type RefObject, useEffect, useMemo, useRef, useState } from "react"; -import type { Locale, SidebarPage, TSideBar, SidebarFolder as TSidebarFolder } from "~/app/types"; +import type { Locale, Project, SidebarPage, TSideBar, SidebarFolder as TSidebarFolder } from "~/app/types"; import { cn } from "~/lib/utils"; import sidebarData from "~/public/sidebar.json"; import DocSearchComponent from "./DocSearchComponent"; @@ -27,19 +27,23 @@ const sortSidebarItems = (sidebarItems: (TSidebarFolder | SidebarPage)[]) => if (a.navOrder !== null && b.navOrder !== null) { return a.navOrder - b.navOrder; // if only 'a' has navOrder, make it first - } else if (a.navOrder !== null) { + } + if (a.navOrder !== null) { return -1; // if only 'b' has navOrder, make it first - } else if (b.navOrder !== null) { + } + if (b.navOrder !== null) { return 1; - } else { - // If neither has navOrder, sort alphabetically by label - return a.label.localeCompare(b.label); } + // If neither has navOrder, sort alphabetically by label + return a.label.localeCompare(b.label); }); +export function processSourceFile(type: "page", locale: Locale, sourceFile: string): string; +export function processSourceFile(type: "folder", locale: Locale, sourceFile: string | undefined): string | undefined; + // Used by sidebar to process sourceFile values into usable routes -export const processSourceFile = (type: "folder" | "page", locale: Locale, sourceFile?: string) => { +export function processSourceFile(type: "folder" | "page", locale: Locale, sourceFile?: string) { if (!sourceFile) return; // We can't use path.sep because the webpack node shim always returns '/'. // Because this might be running on Windows, we need to use a regex to split @@ -55,7 +59,7 @@ export const processSourceFile = (type: "folder" | "page", locale: Locale, sourc // Process the last item to remove the locale and file extension .map((segment, index, array) => { if (index === array.length - 1) { - return segment.split(".")[0]!; + return segment.split(".")[0]; } return segment; }) @@ -63,7 +67,7 @@ export const processSourceFile = (type: "folder" | "page", locale: Locale, sourc } return `/${locale}/${returnPath}`; -}; +} const SidebarFolder = ({ label, @@ -192,29 +196,31 @@ const renderSidebarItem = ( locale: Locale, sidebarContainerRef: RefObject, ) => { - const sourceFile = processSourceFile(item.type, locale, item.sourceFile); if (item.type === "folder") { + const sourceFile = processSourceFile(item.type, locale, item.sourceFile); const sortedChildren = sortSidebarItems(Object.values(item.children)); return ( {sortedChildren.map((child) => renderSidebarItem(child, locale, sidebarContainerRef))} ); - } else { - return ( - - ); } + + const sourceFile = processSourceFile(item.type, locale, item.sourceFile); + return ( + + ); }; export function Sidebar({ className }: { className?: string }) { const pathname = usePathname(); const locale = useLocale() as Locale; - const project = pathname.split("/")[2]!; + // biome-ignore lint/style/noNonNullAssertion: path structure is known + const project = pathname.split("/")[2]! as Project; const typedSidebarData = sidebarData as TSideBar; const sidebarContainerRef = useRef(null); - const formattedSidebarData = typedSidebarData[locale]![project]!.children; + const formattedSidebarData = typedSidebarData[locale][project].children; const sortedSidebarItems = sortSidebarItems(Object.values(formattedSidebarData)); return ( diff --git a/apps/documentation/components/ui/sheet.tsx b/apps/documentation/components/ui/sheet.tsx index 1f19820..2a2794a 100644 --- a/apps/documentation/components/ui/sheet.tsx +++ b/apps/documentation/components/ui/sheet.tsx @@ -56,6 +56,7 @@ const SheetContent = React.forwardRef { const handleObserver = (entries: IntersectionObserverEntry[]) => { - entries.forEach((entry) => { + for (const entry of entries) { if (entry.isIntersecting) { setActiveId(entry.target.id); } - }); + } }; observer.current = new IntersectionObserver(handleObserver, { @@ -20,7 +20,9 @@ const useHighlighted = (id: string): [boolean, React.Dispatch observer.current?.observe(elem)); + for (const elem of elements) { + observer.current?.observe(elem); + } return () => observer.current?.disconnect(); }, []); diff --git a/apps/documentation/lib/docs.tsx b/apps/documentation/lib/docs.tsx index 62efa85..7479ac2 100644 --- a/apps/documentation/lib/docs.tsx +++ b/apps/documentation/lib/docs.tsx @@ -80,6 +80,7 @@ export const processPath = (docPath: string) => { // Process the last item to remove the locale and file extension .map((segment, index, array) => { if (index === array.length - 1) { + // biome-ignore lint/style/noNonNullAssertion: we know that the last element is a string return segment.split(".")[0]!; } return segment; @@ -254,7 +255,7 @@ export async function getDocumentForPath({ figcaption: (props) =>
, img: (props) => ( - {props.alt} + {props.alt} ), keyconcept: (props: { title: string; children: ReactNode }) => , diff --git a/apps/documentation/lib/processPreTags.ts b/apps/documentation/lib/processPreTags.ts index 2913133..f2e12e6 100644 --- a/apps/documentation/lib/processPreTags.ts +++ b/apps/documentation/lib/processPreTags.ts @@ -1,4 +1,4 @@ -import { toString } from "hast-util-to-string"; +import { toString as hastNodeToString } from "hast-util-to-string"; import { visit } from "unist-util-visit"; type Tree = { @@ -21,7 +21,7 @@ const processPreTags = () => { if (!codeElement) return; // Extract the text content from the `code` element - const rawCodeContent = toString(codeElement); + const rawCodeContent = hastNodeToString(codeElement); // Add the `raw` property with the extracted content to the `pre` element node.properties = { ...(node.properties || {}), raw: rawCodeContent }; diff --git a/apps/documentation/lib/tableOfContents.ts b/apps/documentation/lib/tableOfContents.ts index b4dfbbe..026d8bd 100644 --- a/apps/documentation/lib/tableOfContents.ts +++ b/apps/documentation/lib/tableOfContents.ts @@ -1,6 +1,6 @@ import type { Nodes, Root } from "hast"; import { headingRank } from "hast-util-heading-rank"; -import { toString } from "mdast-util-to-string"; +import { toString as hastNodeToString } from "mdast-util-to-string"; import { visit } from "unist-util-visit"; import type { VFile } from "vfile"; @@ -28,12 +28,12 @@ function getHeadingsForTree(root: Nodes): HeadingNode[] { visit(root, "element", (node: SpecialNodes) => { if (headingRank(node) && node.properties.id) { - const level = headingRank(node)!; + const level = headingRank(node); // If this is a level 2 heading, we want to start a new tree if (level === 2) { indexMap.push({ - value: toString(node), + value: hastNodeToString(node), level, id: node.properties.id, children: [], @@ -46,7 +46,7 @@ function getHeadingsForTree(root: Nodes): HeadingNode[] { if (!lastLevel2) { indexMap.push({ - value: toString(node), + value: hastNodeToString(node), level: 2, id: node.properties.id, children: [], @@ -56,7 +56,7 @@ function getHeadingsForTree(root: Nodes): HeadingNode[] { } lastLevel2.children.push({ - value: toString(node), + value: hastNodeToString(node), level, id: node.properties.id, children: [], diff --git a/apps/documentation/lib/writeSidebarJson.ts b/apps/documentation/lib/writeSidebarJson.ts index 081f61f..02261e2 100644 --- a/apps/documentation/lib/writeSidebarJson.ts +++ b/apps/documentation/lib/writeSidebarJson.ts @@ -32,19 +32,17 @@ function generateSidebarData() { const sortedFiles = sortDirectoryListing(files); - sortedFiles.forEach((file: fs.Dirent) => { + for (const file of sortedFiles) { if (file.isDirectory()) { const metadata = getMetaDataForDirectory(join(file.path, file.name)); if (metadata.type === "project") { - Object.keys(sidebarData).forEach((l) => { - const locale = l as Locale; - + for (const locale of Object.keys(sidebarData) as Locale[]) { sidebarData[locale] = { ...sidebarData[locale], [file.name]: createProjectEntry(file, locale, metadata), }; - }); + } return; } @@ -54,10 +52,9 @@ function generateSidebarData() { const nestedPath = getNestedPath(file.path); // Insert folder entry for each locale in the nested path - Object.keys(sidebarData).forEach((l) => { - const locale = l as Locale; - set(sidebarData[locale]!, [...nestedPath, file.name], createFolderEntry(file, locale, metadata)); - }); + for (const locale of Object.keys(sidebarData) as Locale[]) { + set(sidebarData[locale], [...nestedPath, file.name], createFolderEntry(file, locale, metadata)); + } return; } @@ -78,18 +75,19 @@ function generateSidebarData() { } // create a key based on the filename without the locale or extension - const key = file.name.split(".")[0]; + // biome-ignore lint/style/noNonNullAssertion: filename is known to have a value here + const key = file.name.split(".")[0]!; - const nestedPath = getNestedPath(file.path); + const nestedPath = getNestedPath(file.parentPath); - const markdownFile = readFileSync(join(file.path, file.name), "utf-8"); + const markdownFile = readFileSync(join(file.parentPath, file.name), "utf-8"); const matterResult = matter(markdownFile); // If file has "hidden: true" in frontmatter, skip it if (matterResult.data.hidden) return; - set(sidebarData[locale]!, [...nestedPath, key!], createPageEntry(file, matterResult)); - }); + set(sidebarData[locale], [...nestedPath, key], createPageEntry(file, matterResult)); + } return sidebarData; } diff --git a/apps/documentation/styles/prism.css b/apps/documentation/styles/prism.css deleted file mode 100644 index cc64b02..0000000 --- a/apps/documentation/styles/prism.css +++ /dev/null @@ -1,47 +0,0 @@ -pre[class*="language-"] { - color: theme("colors.platinum.DEFAULT"); -} - -.token.tag, -.token.class-name, -.token.selector, -.token.selector .class, -.token.selector.class, -.token.function { - color: theme("colors.barbie-pink.DEFAULT"); -} - -.token.attr-name, -.token.keyword, -.token.rule, -.token.pseudo-class, -.token.important { - color: theme("colors.platinum.DEFAULT"); -} - -.token.module { - color: theme("colors.barbie-pink.DEFAULT"); -} - -.token.attr-value, -.token.class, -.token.string, -.token.property { - color: theme("colors.cerulean-blue.DEFAULT"); -} - -.token.punctuation, -.token.attr-equals { - color: theme("colors.platinum.dark"); -} - -.token.unit, -.language-css .token.function { - color: theme("colors.slate-blue.DEFAULT"); -} - -.token.comment, -.token.operator, -.token.combinator { - color: theme("colors.neon-coral.dark"); -} diff --git a/biome.json b/biome.json index bed03aa..b28bd04 100644 --- a/biome.json +++ b/biome.json @@ -1,7 +1,7 @@ { "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", "organizeImports": { - "enabled": true + "enabled": false }, "linter": { "rules": { diff --git a/packages/analytics/src/index.ts b/packages/analytics/src/index.ts index 5e56b06..171619d 100644 --- a/packages/analytics/src/index.ts +++ b/packages/analytics/src/index.ts @@ -148,15 +148,16 @@ export const createRouteHandler = ({ let error = `Analytics platform returned an unexpected error: ${response.statusText}`; if (response.status === 400) { - error = `Analytics platform rejected the event as invalid. Please check the event schema`; + error = "Analytics platform rejected the event as invalid. Please check the event schema"; } if (response.status === 404) { - error = `Analytics platform could not be reached. Please specify a valid platform URL, or check that the platform is online.`; + error = + "Analytics platform could not be reached. Please specify a valid platform URL, or check that the platform is online."; } if (response.status === 500) { - error = `Analytics platform returned an internal server error. Please check the platform logs.`; + error = "Analytics platform returned an internal server error. Please check the platform logs."; } console.info(`⚠️ Analytics platform rejected event: ${error}`); @@ -208,7 +209,7 @@ export const makeEventTracker = if (!response.ok) { if (response.status === 404) { return { - error: `Analytics endpoint not found, did you forget to add the route?`, + error: "Analytics endpoint not found, did you forget to add the route?", success: false, }; } diff --git a/packages/art/src/BackgroundBlobs/BackgroundBlobs.tsx b/packages/art/src/BackgroundBlobs/BackgroundBlobs.tsx index 41fe6b4..f8b8eab 100644 --- a/packages/art/src/BackgroundBlobs/BackgroundBlobs.tsx +++ b/packages/art/src/BackgroundBlobs/BackgroundBlobs.tsx @@ -257,7 +257,11 @@ const BackgroundBlobs = memo( const drawBlobs = (ctx: CanvasRenderingContext2D, time: number) => { ctx.globalCompositeOperation = compositeOperation; ctx.filter = filter; - blobs.forEach((layer) => layer.forEach((blob) => blob.render(ctx, time))); + for (const layer of blobs) { + for (const blob of layer) { + blob.render(ctx, time); + } + } }; return ; diff --git a/packages/ui/src/CloseButton.tsx b/packages/ui/src/CloseButton.tsx index 1b5e353..3661bd2 100644 --- a/packages/ui/src/CloseButton.tsx +++ b/packages/ui/src/CloseButton.tsx @@ -17,6 +17,7 @@ export const CloseButton = ({ )} > - - + + Close diff --git a/packages/ui/src/FancyBox.tsx b/packages/ui/src/FancyBox.tsx index ce0a2ba..76602e6 100644 --- a/packages/ui/src/FancyBox.tsx +++ b/packages/ui/src/FancyBox.tsx @@ -63,15 +63,13 @@ export default function FancyBox - + + diff --git a/packages/ui/src/FancyButton.tsx b/packages/ui/src/FancyButton.tsx index 8cee51c..9680561 100644 --- a/packages/ui/src/FancyButton.tsx +++ b/packages/ui/src/FancyButton.tsx @@ -32,7 +32,7 @@ const FancyButton = React.forwardRef( return ( diff --git a/packages/ui/src/toast.tsx b/packages/ui/src/toast.tsx index 9a2c1dc..0b7d90b 100644 --- a/packages/ui/src/toast.tsx +++ b/packages/ui/src/toast.tsx @@ -23,9 +23,9 @@ const ToastViewport = React.forwardRef< ToastViewport.displayName = ToastPrimitives.Viewport.displayName; const toastBaseClasses = cn( - `group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border bg-card p-6 font-semibold shadow-lg transition-all`, - `data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none `, - `data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full`, + "group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border bg-card p-6 font-semibold shadow-lg transition-all", + "data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none ", + "data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full", ); const toastVariants = cva(toastBaseClasses, { diff --git a/packages/ui/src/use-toast.ts b/packages/ui/src/use-toast.ts index 4401074..36528a1 100644 --- a/packages/ui/src/use-toast.ts +++ b/packages/ui/src/use-toast.ts @@ -92,9 +92,9 @@ export const reducer = (state: State, action: Action): State => { if (toastId) { addToRemoveQueue(toastId); } else { - state.toasts.forEach((toast) => { - addToRemoveQueue(toast.id); - }); + for (const [id] of toastTimeouts) { + addToRemoveQueue(id); + } } return { @@ -129,9 +129,9 @@ let memoryState: State = { toasts: [] }; function dispatch(action: Action) { memoryState = reducer(memoryState, action); - listeners.forEach((listener) => { + for (const listener of listeners) { listener(memoryState); - }); + } } type Toast = Omit; @@ -168,6 +168,7 @@ function toast({ ...props }: Toast) { function useToast() { const [state, setState] = React.useState(memoryState); + // biome-ignore lint/correctness/useExhaustiveDependencies: state is a reference, so it's fine React.useEffect(() => { listeners.push(setState); return () => {