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) => (
+
+ {item.label}
+
+ ))}
+
+
+
+
+
+
+
*/}
+
+
+
+ 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'