diff --git a/plugins/techdocs-addons/api-report.md b/plugins/techdocs-addons/api-report.md index c5a61a34e3..26c0825493 100644 --- a/plugins/techdocs-addons/api-report.md +++ b/plugins/techdocs-addons/api-report.md @@ -5,6 +5,7 @@ ```ts /// +import { AsyncState } from 'react-use/lib/useAsyncFn'; import { ComponentType } from 'react'; import { CompoundEntityRef } from '@backstage/catalog-model'; import { Extension } from '@backstage/core-plugin-api'; @@ -17,6 +18,9 @@ export function createTechDocsAddon( options: TechDocsAddonOptions, ): Extension>; +// @public +export type TechDocsAddonAsyncMetadata = AsyncState; + // @public export enum TechDocsAddonLocations { COMPONENT = 'component', @@ -48,16 +52,18 @@ export type TechDocsReaderPageProps = { }; // @public -export const useEntityMetadata: () => TechDocsEntityMetadata | undefined; - -// @public -export const useMetadata: () => TechDocsMetadata | undefined; +export const useEntityMetadata: () => TechDocsAddonAsyncMetadata; // @public export const useShadowRoot: () => ShadowRoot | undefined; // @public -export const useShadowRootElements: ( +export const useShadowRootElements: < + TReturnedElement extends HTMLElement = HTMLElement, +>( selectors: string[], -) => T[]; +) => TReturnedElement[]; + +// @public +export const useTechDocsMetadata: () => TechDocsAddonAsyncMetadata; ``` diff --git a/plugins/techdocs-addons/src/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.tsx b/plugins/techdocs-addons/src/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.tsx index 66eef06c3e..6a8322e57e 100644 --- a/plugins/techdocs-addons/src/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.tsx +++ b/plugins/techdocs-addons/src/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.tsx @@ -22,7 +22,7 @@ import React, { useEffect } from 'react'; import Helmet from 'react-helmet'; import { useTechDocsAddons } from '../../addons'; -import { useMetadata, useTechDocsReaderPage } from '../../context'; +import { useTechDocsMetadata, useTechDocsReaderPage } from '../../context'; import { TechDocsAddonLocations as locations } from '../../types'; const skeleton = ; @@ -31,7 +31,7 @@ export const TechDocsReaderPageHeader = () => { const addons = useTechDocsAddons(); const configApi = useApi(configApiRef); - const metadata = useMetadata(); + const { value: metadata } = useTechDocsMetadata(); const { title, setTitle, subtitle, setSubtitle } = useTechDocsReaderPage(); diff --git a/plugins/techdocs-addons/src/context.tsx b/plugins/techdocs-addons/src/context.tsx index 7908033874..7576bdc163 100644 --- a/plugins/techdocs-addons/src/context.tsx +++ b/plugins/techdocs-addons/src/context.tsx @@ -15,7 +15,7 @@ */ import { CompoundEntityRef } from '@backstage/catalog-model'; -import { useApi, useApp } from '@backstage/core-plugin-api'; +import { useApi } from '@backstage/core-plugin-api'; import { techdocsApiRef, TechDocsEntityMetadata, @@ -30,30 +30,33 @@ import React, { useState, } from 'react'; import useAsync from 'react-use/lib/useAsync'; +import { TechDocsAddonAsyncMetadata } from './types'; type PropsWithEntityName = PropsWithChildren<{ entityName: CompoundEntityRef }>; -const TechDocsMetadataContext = createContext( - undefined, -); +const initialContextValue = { + loading: true, + error: undefined, + value: undefined, +}; + +const TechDocsMetadataContext = + createContext>( + initialContextValue, + ); export const TechDocsMetadataProvider = ({ entityName, children, }: PropsWithEntityName) => { - const { NotFoundErrorPage } = useApp().getComponents(); const techdocsApi = useApi(techdocsApiRef); - const { value, loading, error } = useAsync(async () => { + const metadataResponse = useAsync(async () => { return await techdocsApi.getTechDocsMetadata(entityName); }, []); - if (!loading && error) { - return ; - } - return ( - + {children} ); @@ -64,31 +67,27 @@ export const TechDocsMetadataProvider = ({ * current TechDocs site. * @public */ -export const useMetadata = () => { +export const useTechDocsMetadata = () => { return useContext(TechDocsMetadataContext); }; -const TechDocsEntityContext = createContext( - undefined, -); +const TechDocsEntityContext = + createContext>( + initialContextValue, + ); export const TechDocsEntityProvider = ({ entityName, children, }: PropsWithEntityName) => { - const { NotFoundErrorPage } = useApp().getComponents(); const techdocsApi = useApi(techdocsApiRef); - const { value, loading, error } = useAsync(async () => { + const metadataResponse = useAsync(async () => { return await techdocsApi.getEntityMetadata(entityName); }, []); - if (!loading && error) { - return ; - } - return ( - + {children} ); @@ -180,13 +179,15 @@ export const useShadowRoot = () => { * * @public */ -export const useShadowRootElements = ( +export const useShadowRootElements = < + TReturnedElement extends HTMLElement = HTMLElement, +>( selectors: string[], -): T[] => { +): TReturnedElement[] => { const shadowRoot = useShadowRoot(); if (!shadowRoot) return []; return selectors - .map(selector => shadowRoot?.querySelectorAll(selector)) + .map(selector => shadowRoot?.querySelectorAll(selector)) .filter(nodeList => nodeList.length) .map(nodeList => Array.from(nodeList)) .flat(); diff --git a/plugins/techdocs-addons/src/index.ts b/plugins/techdocs-addons/src/index.ts index aa337982f1..5114a2b2e6 100644 --- a/plugins/techdocs-addons/src/index.ts +++ b/plugins/techdocs-addons/src/index.ts @@ -24,8 +24,12 @@ export { createTechDocsAddon, TechDocsAddons } from './addons'; export * from './components'; export { useEntityMetadata, - useMetadata, + useTechDocsMetadata, useShadowRoot, useShadowRootElements, } from './context'; -export type { TechDocsAddonLocations, TechDocsAddonOptions } from './types'; +export type { + TechDocsAddonAsyncMetadata, + TechDocsAddonLocations, + TechDocsAddonOptions, +} from './types'; diff --git a/plugins/techdocs-addons/src/types.ts b/plugins/techdocs-addons/src/types.ts index 9cb095577f..8e42e0a6bc 100644 --- a/plugins/techdocs-addons/src/types.ts +++ b/plugins/techdocs-addons/src/types.ts @@ -15,6 +15,7 @@ */ import { ComponentType } from 'react'; +import { AsyncState } from 'react-use/lib/useAsyncFn'; /** * Locations for which TechDocs addons may be declared and rendered. @@ -70,3 +71,9 @@ export type TechDocsAddonOptions = { location: TechDocsAddonLocations; component: ComponentType; }; + +/** + * Common response envelope for addon-related hooks. + * @public + */ +export type TechDocsAddonAsyncMetadata = AsyncState;