diff --git a/app/libraries/index.tsx b/app/libraries/index.tsx index 28a140fc..67b4640b 100644 --- a/app/libraries/index.tsx +++ b/app/libraries/index.tsx @@ -15,6 +15,7 @@ import { tableProject } from './table' import { virtualProject } from './virtual' import { rangerProject } from './ranger' import { storeProject } from './store' +import { pacerProject } from './pacer' export const frameworkOptions = [ { label: 'React', value: 'react', logo: reactLogo }, @@ -39,6 +40,7 @@ export type Library = { | 'virtual' | 'ranger' | 'store' + | 'pacer' | 'config' | 'react-charts' name: string @@ -88,8 +90,9 @@ export const libraries = [ tableProject, formProject, virtualProject, - rangerProject, storeProject, + rangerProject, + pacerProject, configProject, ] satisfies Library[] diff --git a/app/libraries/pacer.tsx b/app/libraries/pacer.tsx new file mode 100644 index 00000000..29242670 --- /dev/null +++ b/app/libraries/pacer.tsx @@ -0,0 +1,100 @@ +import { VscPreview, VscWand } from 'react-icons/vsc' +import { Library } from '.' +import { FaGithub, FaBolt, FaCogs } from 'react-icons/fa' +import { BiBookAlt } from 'react-icons/bi' +import { twMerge } from 'tailwind-merge' + +const repo = 'tanstack/pacer' + +const textStyles = `text-lime-600 dark:text-lime-500` + +export const pacerProject = { + id: 'pacer', + name: 'TanStack Pacer', + cardStyles: `shadow-xl shadow-lime-700/20 dark:shadow-lg dark:shadow-lime-500/20 text-lime-500 dark:text-lime-400 border-2 border-transparent hover:border-current`, + to: '/pacer', + tagline: `Framework agnostic debouncing, throttling, and queueing utilities`, + description: `Set the pace of interactions in your applications. Limit the rate at which functions can fire, or intelligently queue long-running tasks with Concurrency Control.`, + ogImage: 'https://github.com/tanstack/pacer/raw/main/media/repo-header.png', + badge: 'soon', + bgStyle: `bg-lime-700`, + textStyle: `text-lime-500`, + repo, + latestBranch: 'main', + latestVersion: 'v0', + availableVersions: ['v0'], + colorFrom: `from-lime-500`, + colorTo: `to-lime-700`, + textColor: `text-lime-700`, + frameworks: ['react', 'solid'], + scarfId: '302d0fef-cb3f-43c6-b45c-f055b9745edb', + defaultDocs: 'overview', + menu: [ + { + icon: , + label: 'Examples', + to: '/pacer/latest/docs/framework/react/examples/simple', + }, + { + icon: , + label: 'Docs', + to: '/pacer/latest/docs', + }, + { + icon: , + label: 'Github', + to: `https://github.com/${repo}`, + }, + ], + featureHighlights: [ + { + title: 'Framework Agnostic & Type-Safe', + icon: , + description: ( +
+ TanStack Pacer provides an intuitive and flexible API that works + across any JavaScript framework.{' '} + + Every utility is fully type-safe with reactive framework adapters + {' '} + that seamlessly connect to your state management of choice. Choose + from multiple layers of abstraction to confidently control timing in + your applications. +
+ ), + }, + { + title: 'Flexible Rate Limiting Controls', + icon: , + description: ( +
+ Take control of your application's timing with powerful utilities for{' '} + + rate limiting, throttling, and debouncing + + . Leverage built-in cleanup and cancellation capabilities to help you + manage execution timing with precision while preventing memory leaks. + Flexible configuration options let you fine-tune the behavior to match + your needs. +
+ ), + }, + { + title: 'Async/Sync Queue Management', + icon: , + description: ( +
+ Handle complex asynchronous workflows with intelligent queuing and + concurrency control.{' '} + + Manage long-running tasks with FIFO/LIFO ordering, priority queuing, + and parallel execution + + . Built-in pause, resume and cancel capabilities give you complete + control over your queue's lifecycle. Perfect for managing API calls, + animations, and other sequential operations. +
+ ), + }, + ], +} satisfies Library diff --git a/app/routeTree.gen.ts b/app/routeTree.gen.ts index 19a21b15..1eac62b4 100644 --- a/app/routeTree.gen.ts +++ b/app/routeTree.gen.ts @@ -37,6 +37,7 @@ import { Route as LibrariesStartVersionIndexImport } from './routes/_libraries/s import { Route as LibrariesRouterVersionIndexImport } from './routes/_libraries/router.$version.index' import { Route as LibrariesRangerVersionIndexImport } from './routes/_libraries/ranger.$version.index' import { Route as LibrariesQueryVersionIndexImport } from './routes/_libraries/query.$version.index' +import { Route as LibrariesPacerVersionIndexImport } from './routes/_libraries/pacer.$version.index' import { Route as LibrariesFormVersionIndexImport } from './routes/_libraries/form.$version.index' import { Route as LibrariesConfigVersionIndexImport } from './routes/_libraries/config.$version.index' import { Route as LibraryIdVersionDocsIndexImport } from './routes/$libraryId/$version.docs.index' @@ -212,6 +213,14 @@ const LibrariesQueryVersionIndexRoute = LibrariesQueryVersionIndexImport.update( } as any, ) +const LibrariesPacerVersionIndexRoute = LibrariesPacerVersionIndexImport.update( + { + id: '/pacer/$version/', + path: '/pacer/$version/', + getParentRoute: () => LibrariesRouteRoute, + } as any, +) + const LibrariesFormVersionIndexRoute = LibrariesFormVersionIndexImport.update({ id: '/form/$version/', path: '/form/$version/', @@ -416,6 +425,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof LibrariesFormVersionIndexImport parentRoute: typeof LibrariesRouteImport } + '/_libraries/pacer/$version/': { + id: '/_libraries/pacer/$version/' + path: '/pacer/$version' + fullPath: '/pacer/$version' + preLoaderRoute: typeof LibrariesPacerVersionIndexImport + parentRoute: typeof LibrariesRouteImport + } '/_libraries/query/$version/': { id: '/_libraries/query/$version/' path: '/query/$version' @@ -553,6 +569,7 @@ interface LibrariesRouteRouteChildren { LibrariesIndexRoute: typeof LibrariesIndexRoute LibrariesConfigVersionIndexRoute: typeof LibrariesConfigVersionIndexRoute LibrariesFormVersionIndexRoute: typeof LibrariesFormVersionIndexRoute + LibrariesPacerVersionIndexRoute: typeof LibrariesPacerVersionIndexRoute LibrariesQueryVersionIndexRoute: typeof LibrariesQueryVersionIndexRoute LibrariesRangerVersionIndexRoute: typeof LibrariesRangerVersionIndexRoute LibrariesRouterVersionIndexRoute: typeof LibrariesRouterVersionIndexRoute @@ -573,6 +590,7 @@ const LibrariesRouteRouteChildren: LibrariesRouteRouteChildren = { LibrariesIndexRoute: LibrariesIndexRoute, LibrariesConfigVersionIndexRoute: LibrariesConfigVersionIndexRoute, LibrariesFormVersionIndexRoute: LibrariesFormVersionIndexRoute, + LibrariesPacerVersionIndexRoute: LibrariesPacerVersionIndexRoute, LibrariesQueryVersionIndexRoute: LibrariesQueryVersionIndexRoute, LibrariesRangerVersionIndexRoute: LibrariesRangerVersionIndexRoute, LibrariesRouterVersionIndexRoute: LibrariesRouterVersionIndexRoute, @@ -610,6 +628,7 @@ export interface FileRoutesByFullPath { '/$libraryId/$version/docs/': typeof LibraryIdVersionDocsIndexRoute '/config/$version': typeof LibrariesConfigVersionIndexRoute '/form/$version': typeof LibrariesFormVersionIndexRoute + '/pacer/$version': typeof LibrariesPacerVersionIndexRoute '/query/$version': typeof LibrariesQueryVersionIndexRoute '/ranger/$version': typeof LibrariesRangerVersionIndexRoute '/router/$version': typeof LibrariesRouterVersionIndexRoute @@ -641,6 +660,7 @@ export interface FileRoutesByTo { '/$libraryId/$version/docs': typeof LibraryIdVersionDocsIndexRoute '/config/$version': typeof LibrariesConfigVersionIndexRoute '/form/$version': typeof LibrariesFormVersionIndexRoute + '/pacer/$version': typeof LibrariesPacerVersionIndexRoute '/query/$version': typeof LibrariesQueryVersionIndexRoute '/ranger/$version': typeof LibrariesRangerVersionIndexRoute '/router/$version': typeof LibrariesRouterVersionIndexRoute @@ -677,6 +697,7 @@ export interface FileRoutesById { '/$libraryId/$version/docs/': typeof LibraryIdVersionDocsIndexRoute '/_libraries/config/$version/': typeof LibrariesConfigVersionIndexRoute '/_libraries/form/$version/': typeof LibrariesFormVersionIndexRoute + '/_libraries/pacer/$version/': typeof LibrariesPacerVersionIndexRoute '/_libraries/query/$version/': typeof LibrariesQueryVersionIndexRoute '/_libraries/ranger/$version/': typeof LibrariesRangerVersionIndexRoute '/_libraries/router/$version/': typeof LibrariesRouterVersionIndexRoute @@ -714,6 +735,7 @@ export interface FileRouteTypes { | '/$libraryId/$version/docs/' | '/config/$version' | '/form/$version' + | '/pacer/$version' | '/query/$version' | '/ranger/$version' | '/router/$version' @@ -744,6 +766,7 @@ export interface FileRouteTypes { | '/$libraryId/$version/docs' | '/config/$version' | '/form/$version' + | '/pacer/$version' | '/query/$version' | '/ranger/$version' | '/router/$version' @@ -778,6 +801,7 @@ export interface FileRouteTypes { | '/$libraryId/$version/docs/' | '/_libraries/config/$version/' | '/_libraries/form/$version/' + | '/_libraries/pacer/$version/' | '/_libraries/query/$version/' | '/_libraries/ranger/$version/' | '/_libraries/router/$version/' @@ -846,6 +870,7 @@ export const routeTree = rootRoute "/_libraries/", "/_libraries/config/$version/", "/_libraries/form/$version/", + "/_libraries/pacer/$version/", "/_libraries/query/$version/", "/_libraries/ranger/$version/", "/_libraries/router/$version/", @@ -948,6 +973,10 @@ export const routeTree = rootRoute "filePath": "_libraries/form.$version.index.tsx", "parent": "/_libraries" }, + "/_libraries/pacer/$version/": { + "filePath": "_libraries/pacer.$version.index.tsx", + "parent": "/_libraries" + }, "/_libraries/query/$version/": { "filePath": "_libraries/query.$version.index.tsx", "parent": "/_libraries" diff --git a/app/routes/_libraries/config.$version.index.tsx b/app/routes/_libraries/config.$version.index.tsx index 8eb951ca..52285dae 100644 --- a/app/routes/_libraries/config.$version.index.tsx +++ b/app/routes/_libraries/config.$version.index.tsx @@ -33,7 +33,7 @@ export default function FormVersionIndex() { const { version } = Route.useParams() const library = getLibrary('config') - const gradientText = `inline-block leading-snug text-transparent bg-clip-text bg-gradient-to-r ${configProject.colorFrom} ${configProject.colorTo}` + const gradientText = `pr-1 inline-block leading-snug text-transparent bg-clip-text bg-gradient-to-r ${configProject.colorFrom} ${configProject.colorTo}` return ( <> diff --git a/app/routes/_libraries/form.$version.index.tsx b/app/routes/_libraries/form.$version.index.tsx index b645f061..d3701b25 100644 --- a/app/routes/_libraries/form.$version.index.tsx +++ b/app/routes/_libraries/form.$version.index.tsx @@ -43,7 +43,7 @@ export default function FormVersionIndex() { setIsDark(window.matchMedia?.(`(prefers-color-scheme: dark)`).matches) }, []) - const gradientText = `inline-block text-transparent bg-clip-text bg-gradient-to-r ${formProject.colorFrom} ${formProject.colorTo}` + const gradientText = `pr-1 inline-block text-transparent bg-clip-text bg-gradient-to-r ${formProject.colorFrom} ${formProject.colorTo}` return ( <> diff --git a/app/routes/_libraries/pacer.$version.index.tsx b/app/routes/_libraries/pacer.$version.index.tsx new file mode 100644 index 00000000..6c37396b --- /dev/null +++ b/app/routes/_libraries/pacer.$version.index.tsx @@ -0,0 +1,252 @@ +import { CgSpinner } from 'react-icons/cg' +import * as React from 'react' +import { Link, createFileRoute, getRouteApi } from '@tanstack/react-router' +import { Carbon } from '~/components/Carbon' +import { Footer } from '~/components/Footer' +import { TbHeartHandshake } from 'react-icons/tb' +import { FaCheckCircle } from 'react-icons/fa' +import SponsorPack from '~/components/SponsorPack' +import { pacerProject } from '~/libraries/pacer' +import { Await } from '@tanstack/react-router' +import { seo } from '~/utils/seo' +import { twMerge } from 'tailwind-merge' +import { getLibrary } from '~/libraries' +import { LibraryFeatureHighlights } from '~/components/LibraryFeatureHighlights' + +export const Route = createFileRoute('/_libraries/pacer/$version/')({ + component: PacerVersionIndex, + head: () => ({ + meta: seo({ + title: pacerProject.name, + description: pacerProject.description, + }), + }), +}) + +const librariesRouteApi = getRouteApi('/_libraries') +const library = getLibrary('pacer') + +export default function PacerVersionIndex() { + const { sponsorsPromise } = librariesRouteApi.useLoaderData() + const { version } = Route.useParams() + + const gradientText = `pr-1 inline-block text-transparent bg-clip-text bg-gradient-to-r ${pacerProject.colorFrom} ${pacerProject.colorTo}` + + return ( + <> +
+
+

+ TanStack + Pacer +

+

+ + Framework agnostic + {' '} + type-safe rate-limiting and queueing utilities +

+

+ Take control of your application's timing with TanStack Pacer's{' '} + rate limiting, throttling, and debouncing utilities + . Manage complex async workflows using{' '} + intelligent queuing and concurrency controls while + maintaining full control with built-in pause, resume, and cancel + capabilities. +

+ + Get Started + +
+ + +
+
+

+ Framework Agnostic & Feature Rich +

+

+ TanStack Pacer's API is highly modular and framework-independent + while still prioritizing ergonomics. Behold, the obligatory + feature-list: +

+
+
+ {[ + 'Lightweight', + 'Tree-Shaking', + 'Type-Safe', + 'Rate Limiting', + 'Throttling', + 'Debouncing', + 'Queueing', + 'LIFO/FIFO/Dequeue Ordering', + 'Concurrency Control', + 'Queue Prioritization', + 'Pause/Resume Controls', + 'Cancellation', + 'Abort Controller Support', + 'Promise Integration', + 'Multiple Layers of Abstraction', + ].map((d, i) => { + return ( + + {d} + + ) + })} +
+
+ +
+

+ Partners +

+
+
+ + Pacer You? + +
+
+ We're looking for a TanStack Pacer OSS Partner to go above and + beyond the call of sponsorship. Are you as invested in TanStack + Pacer as we are? Let's push the boundaries of Pacer together! +
+ + Let's chat + +
+
+
+ +
+

+ Sponsors +

+
+ } + children={(sponsors) => { + return + }} + /> +
+ +
+ +
+
+ +
+ + This ad helps us be happy about our invested time and not burn out + and rage-quit OSS. Yay money! 😉 + +
+ + {/*
+
+

+ Take it for a spin! +

+

+ With just a few lines of code, you can start using powerful rate + limiting, throttling, debouncing, and queueing utilities. +

+
+ {( + [ + { label: 'React', value: 'react' }, + // More adapters coming soon + // { label: 'Solid', value: 'solid' }, + // { label: 'Svelte', value: 'svelte' }, + // { label: 'Vue', value: 'vue' }, + // { label: 'Vanilla', value: 'vanilla' }, + ] as const + ).map((item) => ( + + ))} +
+
+
+ +
+ +
*/} + +
+
+ Wow, you've come a long way! +
+
+ Only one thing left to do... +
+
+ + Get Started! + +
+
+
+
+ + ) +} diff --git a/app/routes/_libraries/query.$version.index.tsx b/app/routes/_libraries/query.$version.index.tsx index e58e6c4b..9e1831a6 100644 --- a/app/routes/_libraries/query.$version.index.tsx +++ b/app/routes/_libraries/query.$version.index.tsx @@ -41,7 +41,7 @@ export default function VersionIndex() { setIsDark(window.matchMedia?.(`(prefers-color-scheme: dark)`).matches) }, []) - const gradientText = `inline-block leading-snug text-transparent bg-clip-text bg-gradient-to-r ${queryProject.colorFrom} ${queryProject.colorTo}` + const gradientText = `pr-1 inline-block leading-snug text-transparent bg-clip-text bg-gradient-to-r ${queryProject.colorFrom} ${queryProject.colorTo}` return (
diff --git a/app/routes/_libraries/ranger.$version.index.tsx b/app/routes/_libraries/ranger.$version.index.tsx index fc26e710..04acf091 100644 --- a/app/routes/_libraries/ranger.$version.index.tsx +++ b/app/routes/_libraries/ranger.$version.index.tsx @@ -36,7 +36,7 @@ export default function VersionIndex() { setIsDark(window.matchMedia?.(`(prefers-color-scheme: dark)`).matches) }, []) - const gradientText = `inline-block leading-snug text-transparent bg-clip-text bg-gradient-to-r ${rangerProject.colorFrom} ${rangerProject.colorTo}` + const gradientText = `pr-1 inline-block leading-snug text-transparent bg-clip-text bg-gradient-to-r ${rangerProject.colorFrom} ${rangerProject.colorTo}` return ( <> diff --git a/app/routes/_libraries/router.$version.index.tsx b/app/routes/_libraries/router.$version.index.tsx index 2489df2c..e2eb81dd 100644 --- a/app/routes/_libraries/router.$version.index.tsx +++ b/app/routes/_libraries/router.$version.index.tsx @@ -41,7 +41,7 @@ function RouterVersionIndex() { setIsDark(window.matchMedia?.(`(prefers-color-scheme: dark)`).matches) }, []) - const gradientText = `inline-block text-transparent bg-clip-text bg-gradient-to-r ${routerProject.colorFrom} ${routerProject.colorTo}` + const gradientText = `pr-1 inline-block text-transparent bg-clip-text bg-gradient-to-r ${routerProject.colorFrom} ${routerProject.colorTo}` return (
diff --git a/app/routes/_libraries/start.$version.index.tsx b/app/routes/_libraries/start.$version.index.tsx index 46ef2b34..de468dcc 100644 --- a/app/routes/_libraries/start.$version.index.tsx +++ b/app/routes/_libraries/start.$version.index.tsx @@ -40,7 +40,7 @@ export default function VersionIndex() { setIsDark(window.matchMedia?.(`(prefers-color-scheme: dark)`).matches) }, [isDark]) - const gradientText = `text-transparent bg-clip-text bg-gradient-to-r ${startProject.colorFrom} ${startProject.colorTo}` + const gradientText = `pr-1 text-transparent bg-clip-text bg-gradient-to-r ${startProject.colorFrom} ${startProject.colorTo}` return (
diff --git a/app/routes/_libraries/store.$version.index.tsx b/app/routes/_libraries/store.$version.index.tsx index f60bdacc..12da7eed 100644 --- a/app/routes/_libraries/store.$version.index.tsx +++ b/app/routes/_libraries/store.$version.index.tsx @@ -28,7 +28,7 @@ export default function StoreVersionIndex() { const { sponsorsPromise } = librariesRouteApi.useLoaderData() const { version } = Route.useParams() - const gradientText = `inline-block text-transparent bg-clip-text bg-gradient-to-r ${storeProject.colorFrom} ${storeProject.colorTo}` + const gradientText = `pr-1inline-block text-transparent bg-clip-text bg-gradient-to-r ${storeProject.colorFrom} ${storeProject.colorTo}` return ( <> diff --git a/app/routes/_libraries/table.$version.index.tsx b/app/routes/_libraries/table.$version.index.tsx index ffbab97c..d842f293 100644 --- a/app/routes/_libraries/table.$version.index.tsx +++ b/app/routes/_libraries/table.$version.index.tsx @@ -41,7 +41,7 @@ export default function TableVersionIndex() { setIsDark(window.matchMedia?.(`(prefers-color-scheme: dark)`).matches) }, []) - const gradientText = `inline-block text-transparent bg-clip-text bg-gradient-to-r ${tableProject.colorFrom} ${tableProject.colorTo}` + const gradientText = `pr-1 inline-block text-transparent bg-clip-text bg-gradient-to-r ${tableProject.colorFrom} ${tableProject.colorTo}` return (
@@ -69,7 +69,7 @@ export default function TableVersionIndex() { markup and styles.

Get Started diff --git a/app/routes/_libraries/virtual.$version.index.tsx b/app/routes/_libraries/virtual.$version.index.tsx index d661b709..a30c1c67 100644 --- a/app/routes/_libraries/virtual.$version.index.tsx +++ b/app/routes/_libraries/virtual.$version.index.tsx @@ -44,7 +44,7 @@ export default function RouteComp() { setIsDark(window.matchMedia?.(`(prefers-color-scheme: dark)`).matches) }, []) - const gradientText = `inline-block text-transparent bg-clip-text bg-gradient-to-r ${virtualProject.colorFrom} ${virtualProject.colorTo}` + const gradientText = `pr-1 inline-block text-transparent bg-clip-text bg-gradient-to-r ${virtualProject.colorFrom} ${virtualProject.colorTo}` return (
diff --git a/app/utils/sandbox.ts b/app/utils/sandbox.ts index a519fe5a..ea2b4703 100644 --- a/app/utils/sandbox.ts +++ b/app/utils/sandbox.ts @@ -8,7 +8,7 @@ export const getInitialSandboxFileName = ( return 'src/routes/__root.tsx' } - const dir = 'src' + const dir = framework === 'angular' ? 'src/app' : 'src' return `${dir}/${getFrameworkStartFileName(framework, libraryId)}` as const } @@ -22,7 +22,7 @@ export function getFrameworkStartFileName( ? 'app.component' : ['svelte', 'vue'].includes(framework) ? 'App' - : ['form', 'query'].includes(libraryId!) + : ['form', 'query', 'pacer'].includes(libraryId!) ? 'index' : 'main'