wip routeContext

This commit is contained in:
ozakione 2024-05-16 09:41:34 +02:00
parent 7e417aa77d
commit 8ad074773a
6 changed files with 63 additions and 98 deletions

View file

@ -13,10 +13,12 @@ import {
useQueryStringList, useQueryStringList,
type ListUpdateFunction, type ListUpdateFunction,
} from '@docusaurus/theme-common'; } from '@docusaurus/theme-common';
import useRouteContext from '@docusaurus/useRouteContext';
import type { import type {
TagType, TagType,
Operator, Operator,
ShowcaseItem, ShowcaseItem,
TagsOption,
} from '@docusaurus/plugin-content-showcase'; } from '@docusaurus/plugin-content-showcase';
export function filterItems({ export function filterItems({
@ -130,3 +132,34 @@ export function sortItems(params: ShowcaseItem[]): ShowcaseItem[] {
result = sortBy(result, (user) => !user.tags.includes('favorite')); result = sortBy(result, (user) => !user.tags.includes('favorite'));
return result; return result;
} }
export interface ShowcaseContextType {
items: ShowcaseItem[];
tags: TagsOption;
screenshotApi: string;
}
function useShowcase() {
const routeContext = useRouteContext();
console.log('routeContext:', routeContext);
const showcase = routeContext?.data?.showcase;
console.log('showcase:', showcase);
if (!showcase) {
throw new Error(
'showcase-related hooks can only be called on the showcase page',
);
}
return showcase as ShowcaseContextType;
}
export function useShowcaseItems(): ShowcaseItem[] {
return useShowcase().items;
}
export function useShowcaseApiScreenshot(): string {
return useShowcase().screenshotApi;
}
export function useShowcaseTags(): TagsOption {
return useShowcase().tags;
}

View file

@ -9,11 +9,11 @@ import React from 'react';
import clsx from 'clsx'; import clsx from 'clsx';
import Link from '@docusaurus/Link'; import Link from '@docusaurus/Link';
import Translate from '@docusaurus/Translate'; import Translate from '@docusaurus/Translate';
import {sortBy} from '@docusaurus/plugin-content-showcase/client';
import { import {
sortBy,
useShowcaseTags, useShowcaseTags,
useShowcaseApiScreenshot, useShowcaseApiScreenshot,
} from '@docusaurus/theme-common/internal'; } from '@docusaurus/plugin-content-showcase/client';
import Heading from '@theme/Heading'; import Heading from '@theme/Heading';
import FavoriteIcon from '@theme/Showcase/FavoriteIcon'; import FavoriteIcon from '@theme/Showcase/FavoriteIcon';
import type {ShowcaseItem, TagType} from '@docusaurus/plugin-content-showcase'; import type {ShowcaseItem, TagType} from '@docusaurus/plugin-content-showcase';

View file

@ -11,8 +11,8 @@ import Translate from '@docusaurus/Translate';
import { import {
useFilteredItems, useFilteredItems,
sortItems, sortItems,
useShowcaseItems,
} from '@docusaurus/plugin-content-showcase/client'; } from '@docusaurus/plugin-content-showcase/client';
import {useShowcaseItems} from '@docusaurus/theme-common/internal';
import Heading from '@theme/Heading'; import Heading from '@theme/Heading';
import FavoriteIcon from '@theme/Showcase/FavoriteIcon'; import FavoriteIcon from '@theme/Showcase/FavoriteIcon';
import ShowcaseCard from '@theme/Showcase/ShowcaseCard'; import ShowcaseCard from '@theme/Showcase/ShowcaseCard';

View file

@ -11,11 +11,9 @@ import Translate from '@docusaurus/Translate';
import { import {
useFilteredItems, useFilteredItems,
useSiteCountPlural, useSiteCountPlural,
} from '@docusaurus/plugin-content-showcase/client';
import {
useShowcaseItems, useShowcaseItems,
useShowcaseTags, useShowcaseTags,
} from '@docusaurus/theme-common/internal'; } from '@docusaurus/plugin-content-showcase/client';
import FavoriteIcon from '@theme/Showcase/FavoriteIcon'; import FavoriteIcon from '@theme/Showcase/FavoriteIcon';
import Heading from '@theme/Heading'; import Heading from '@theme/Heading';
import ShowcaseTagSelect from '@theme/Showcase/ShowcaseTagSelect'; import ShowcaseTagSelect from '@theme/Showcase/ShowcaseTagSelect';

View file

@ -5,8 +5,7 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
import React, {useMemo, type ReactNode, useContext} from 'react'; import React, {createContext, useMemo, type ReactNode} from 'react';
import {ReactContextError} from '../utils/reactUtils';
import type { import type {
ShowcaseItem, ShowcaseItem,
TagsOption, TagsOption,
@ -20,100 +19,40 @@ type Props = {
children: ReactNode; children: ReactNode;
}; };
const ItemsContext = React.createContext<ShowcaseItem[] | null>(null); export interface ShowcaseContextType {
const ApiContext = React.createContext<string | null>(null);
const TagsContext = React.createContext<TagsOption | null>(null);
function useItemsContextValue(content: ShowcaseItem[]): ShowcaseItem[] {
return useMemo(() => content, [content]);
}
function useApiScreenshotContextValue(content: string): string {
return useMemo(() => content, [content]);
}
function useTagsContextValue(tags: TagsOption): TagsOption {
return useMemo(() => tags, [tags]);
}
function ItemsProvider({
children,
items,
}: {
children: ReactNode;
items: ShowcaseItem[]; items: ShowcaseItem[];
}): JSX.Element {
const contextValue = useItemsContextValue(items);
return (
<ItemsContext.Provider value={contextValue}>
{children}
</ItemsContext.Provider>
);
}
function ApiScreenshotProvider({
children,
api,
}: {
children: ReactNode;
api: string;
}): JSX.Element {
const contextValue = useApiScreenshotContextValue(api);
return (
<ApiContext.Provider value={contextValue}>{children}</ApiContext.Provider>
);
}
function TagsProvider({
children,
tags,
}: {
children: ReactNode;
tags: TagsOption; tags: TagsOption;
}): JSX.Element { screenshotApi: string;
const contextValue = useTagsContextValue(tags);
return (
<TagsContext.Provider value={contextValue}>{children}</TagsContext.Provider>
);
} }
const ShowcaseContext = createContext<ShowcaseContextType | undefined>(
undefined,
);
// const useShowcaseContext = (): ShowcaseContextType => {
// const context = useContext(ShowcaseContext);
// if (!context) {
// throw new Error(
// 'useShowcaseContext must be used within a ShowcaseProvider',
// );
// }
// return context;
// };
export function ShowcaseProvider({ export function ShowcaseProvider({
items, items,
tags, tags,
screenshotApi, screenshotApi,
children, children,
}: Props): JSX.Element { }: Props): JSX.Element {
const contextValue = useMemo(
() => ({items, tags, screenshotApi}),
[items, tags, screenshotApi],
);
return ( return (
<ItemsProvider items={items}> <ShowcaseContext.Provider value={contextValue}>
<TagsProvider tags={tags}>
<ApiScreenshotProvider api={screenshotApi}>
{children} {children}
</ApiScreenshotProvider> </ShowcaseContext.Provider>
</TagsProvider>
</ItemsProvider>
); );
} }
export function useShowcaseItems(): ShowcaseItem[] {
const showcaseItems = useContext(ItemsContext);
if (showcaseItems === null) {
throw new ReactContextError('ItemsProvider');
}
return showcaseItems;
}
export function useShowcaseApiScreenshot(): string {
const showcaseItems = useContext(ApiContext);
if (showcaseItems === null) {
throw new ReactContextError('ItemsProvider');
}
return showcaseItems;
}
export function useShowcaseTags(): TagsOption {
const tags = useContext(TagsContext);
if (tags === null) {
throw new ReactContextError('TagsProvider');
}
return tags;
}

View file

@ -26,12 +26,7 @@ export {DocsVersionProvider, useDocsVersion} from './contexts/docsVersion';
export {DocsSidebarProvider, useDocsSidebar} from './contexts/docsSidebar'; export {DocsSidebarProvider, useDocsSidebar} from './contexts/docsSidebar';
export {DocProvider, useDoc, type DocContextValue} from './contexts/doc'; export {DocProvider, useDoc, type DocContextValue} from './contexts/doc';
export { export {ShowcaseProvider} from './contexts/showcase';
useShowcaseItems,
useShowcaseTags,
useShowcaseApiScreenshot,
ShowcaseProvider,
} from './contexts/showcase';
export { export {
BlogPostProvider, BlogPostProvider,
useBlogPost, useBlogPost,