diff --git a/package.json b/package.json
index d7520178082..b567db4a0d3 100644
--- a/package.json
+++ b/package.json
@@ -38,7 +38,8 @@
"react-collapsed": "4.0.4",
"react-dom": "^0.0.0-experimental-16d053d59-20230506",
"remark-frontmatter": "^4.0.1",
- "remark-gfm": "^3.0.1"
+ "remark-gfm": "^3.0.1",
+ "semver": "^7.6.0"
},
"devDependencies": {
"@babel/core": "^7.12.9",
@@ -54,6 +55,7 @@
"@types/parse-numeric-range": "^0.0.1",
"@types/react": "^18.0.9",
"@types/react-dom": "^18.0.5",
+ "@types/semver": "^7.5.8",
"@typescript-eslint/eslint-plugin": "^5.36.2",
"@typescript-eslint/parser": "^5.36.2",
"asyncro": "^3.0.0",
diff --git a/src/components/Layout/Sidebar/SidebarRouteTree.tsx b/src/components/Layout/Sidebar/SidebarRouteTree.tsx
index a9fa575b510..f2c51745f7f 100644
--- a/src/components/Layout/Sidebar/SidebarRouteTree.tsx
+++ b/src/components/Layout/Sidebar/SidebarRouteTree.tsx
@@ -5,6 +5,7 @@
import {useRef, useLayoutEffect, Fragment} from 'react';
import cn from 'classnames';
+import * as Semver from 'semver';
import {useRouter} from 'next/router';
import {SidebarLink} from './SidebarLink';
import {useCollapse} from 'react-collapsed';
@@ -77,6 +78,8 @@ export function SidebarRouteTree({
}: SidebarRouteTreeProps) {
const slug = useRouter().asPath.split(/[\?\#]/)[0];
const pendingRoute = usePendingRoute();
+ const selectedVersion: string =
+ (useRouter().query.version as string) ?? '19.0.0';
const currentRoutes = routeTree.routes as RouteItem[];
return (
@@ -86,13 +89,22 @@ export function SidebarRouteTree({
path,
title,
routes,
- canary,
heading,
hasSectionHeader,
sectionHeader,
+ version,
},
index
) => {
+ if (
+ version &&
+ !Semver.satisfies(
+ Semver.coerce(selectedVersion) as Semver.SemVer,
+ version
+ )
+ ) {
+ return null;
+ }
const selected = slug === path;
let listItem = null;
if (!path || heading) {
@@ -120,7 +132,6 @@ export function SidebarRouteTree({
selected={selected}
level={level}
title={title}
- canary={canary}
isExpanded={isExpanded}
hideArrow={isForceExpanded}
/>
@@ -144,7 +155,6 @@ export function SidebarRouteTree({
selected={selected}
level={level}
title={title}
- canary={canary}
/>
);
@@ -163,7 +173,7 @@ export function SidebarRouteTree({
'mb-1 text-sm font-bold ms-5 text-tertiary dark:text-tertiary-dark',
index !== 0 && 'mt-2'
)}>
- {sectionHeader}
+ {sectionHeader?.replace('%VERSION%', selectedVersion)}
);
diff --git a/src/components/Layout/SidebarNav/SidebarNav.tsx b/src/components/Layout/SidebarNav/SidebarNav.tsx
index 17127096035..efb9be321cc 100644
--- a/src/components/Layout/SidebarNav/SidebarNav.tsx
+++ b/src/components/Layout/SidebarNav/SidebarNav.tsx
@@ -8,6 +8,7 @@ import cn from 'classnames';
import {Feedback} from '../Feedback';
import {SidebarRouteTree} from '../Sidebar/SidebarRouteTree';
import type {RouteItem} from '../getRouteMeta';
+import {useRouter} from 'next/router';
declare global {
interface Window {
@@ -23,6 +24,14 @@ export default function SidebarNav({
routeTree: RouteItem;
breadcrumbs: RouteItem[];
}) {
+ const {push, query} = useRouter();
+ const onChangeVersion = React.useCallback(
+ (e: any) => {
+ push({query: {...query, version: e.target.value}});
+ },
+ [push, query]
+ );
+
// HACK. Fix up the data structures instead.
if ((routeTree as any).routes.length === 1) {
routeTree = (routeTree as any).routes[0];
@@ -48,6 +57,12 @@ export default function SidebarNav({
className="w-full pt-6 scrolling-touch lg:h-auto grow pe-0 lg:pe-5 lg:pb-16 md:pt-4 lg:pt-4 scrolling-gpu">
{/* No fallback UI so need to be careful not to suspend directly inside. */}
+
+ # 19+ content example
+
+
+
+ # pre 19 content example
+
+
Call `useCallback` at the top level of your component to cache a function definition between re-renders:
```js {4,9}
diff --git a/src/sidebarReference.json b/src/sidebarReference.json
index 2b13649fa0d..ac0e3993e0f 100644
--- a/src/sidebarReference.json
+++ b/src/sidebarReference.json
@@ -4,7 +4,7 @@
"routes": [
{
"hasSectionHeader": true,
- "sectionHeader": "react@18.2.0"
+ "sectionHeader": "react@%VERSION%"
},
{
"title": "Overview",
@@ -17,7 +17,7 @@
{
"title": "use",
"path": "/reference/react/use",
- "canary": true
+ "version": ">= 19"
},
{
"title": "useCallback",
@@ -62,7 +62,7 @@
{
"title": "useOptimistic",
"path": "/reference/react/useOptimistic",
- "canary": true
+ "version": ">= 19"
},
{
"title": "useReducer",
@@ -168,7 +168,7 @@
},
{
"hasSectionHeader": true,
- "sectionHeader": "react-dom@18.2.0"
+ "sectionHeader": "react-dom@%VERSION%"
},
{
"title": "Hooks",
diff --git a/yarn.lock b/yarn.lock
index b20c796efce..5ec81c1e240 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1073,6 +1073,11 @@
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39"
integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==
+"@types/semver@^7.5.8":
+ version "7.5.8"
+ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e"
+ integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==
+
"@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2":
version "2.0.6"
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d"
@@ -5704,6 +5709,13 @@ semver@^7.3.7:
dependencies:
lru-cache "^6.0.0"
+semver@^7.6.0:
+ version "7.6.0"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d"
+ integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==
+ dependencies:
+ lru-cache "^6.0.0"
+
send@0.18.0:
version "0.18.0"
resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be"