From ab82e9670d36fb533044e071481d1a7e3c2c7317 Mon Sep 17 00:00:00 2001 From: Angelo Ashmore Date: Thu, 7 Oct 2021 16:21:33 -1000 Subject: [PATCH] feat: support intrinsic props from link components --- src/PrismicLink.tsx | 74 +++++++++++++++++++++++++++++---------------- 1 file changed, 48 insertions(+), 26 deletions(-) diff --git a/src/PrismicLink.tsx b/src/PrismicLink.tsx index a2a207d..c5b6160 100644 --- a/src/PrismicLink.tsx +++ b/src/PrismicLink.tsx @@ -33,10 +33,23 @@ export interface LinkProps { children?: React.ReactNode; } +type ComponentProps = T extends React.ComponentType + ? U + : T extends keyof JSX.IntrinsicElements + ? React.ComponentProps + : unknown; + /** * Props for ``. */ -export type PrismicLinkProps = { +export type PrismicLinkProps< + InternalComponent extends string | React.ComponentType = + | string + | React.ComponentType, + ExternalComponent extends string | React.ComponentType = + | string + | React.ComponentType, +> = ComponentProps & { /** * The Link Resolver used to resolve links. * @@ -53,12 +66,12 @@ export type PrismicLinkProps = { * If your app uses a client-side router that requires a special Link * component, provide the Link component to this prop. */ - internalComponent?: string | React.ComponentType; + internalComponent?: InternalComponent; /** * The component rendered for external URLs. Defaults to ``. */ - externalComponent?: string | React.ComponentType; + externalComponent?: ExternalComponent; /** * The `target` attribute for anchor elements. If the Prismic field is @@ -77,27 +90,27 @@ export type PrismicLinkProps = { */ children?: React.ReactNode; } & ( - | { - /** - * The Prismic Link field containing the URL or document to link. - * - * @see Learn about Prismic Link fields {@link https://prismic.io/docs/core-concepts/link-content-relationship} - */ - field?: prismicT.LinkField; - } - | { - /** - * The Prismic document to link. - */ - document?: prismicT.PrismicDocument; - } - | { - /** - * The URL to link. - */ - href?: string; - } -); + | { + /** + * The Prismic Link field containing the URL or document to link. + * + * @see Learn about Prismic Link fields {@link https://prismic.io/docs/core-concepts/link-content-relationship} + */ + field?: prismicT.LinkField; + } + | { + /** + * The Prismic document to link. + */ + document?: prismicT.PrismicDocument; + } + | { + /** + * The URL to link. + */ + href?: string; + } + ); /** * The default component rendered for internal URLs. @@ -124,7 +137,16 @@ const defaultExternalComponent = "a"; * @returns The internal or external link component depending on whether the * link is internal or external. */ -export const PrismicLink = (props: PrismicLinkProps): JSX.Element | null => { +export const PrismicLink = < + InternalComponent extends + | string + | React.ComponentType = typeof defaultInternalComponent, + ExternalComponent extends + | string + | React.ComponentType = typeof defaultExternalComponent, +>( + props: PrismicLinkProps, +): JSX.Element | null => { const context = usePrismicContext(); const linkResolver = props.linkResolver || context.linkResolver; @@ -164,7 +186,7 @@ export const PrismicLink = (props: PrismicLinkProps): JSX.Element | null => { const Component = isInternal ? InternalComponent : ExternalComponent; return href ? ( - + {props.children} ) : null;