}
-
- );
- }
-
- const { children, ...buttonProps } = props as ButtonAsButton;
-
return (
-
+
);
-}
+};
-export const Button = React.forwardRef(ButtonComponent);
+export const Button: ButtonComponent = forwardRef(ButtonComponent);
diff --git a/packages/shared-ui/components/Card/Card.tsx b/packages/shared-ui/components/Card/Card.tsx
index b071019..401245d 100644
--- a/packages/shared-ui/components/Card/Card.tsx
+++ b/packages/shared-ui/components/Card/Card.tsx
@@ -1,31 +1,34 @@
import classNames from "classnames";
import { currencyFormatter } from "../../utils/currencyFormatter";
-import { UrlObject } from "url";
+import { PolymorphicComponentProps } from "../../uitls/polymorphicComponent";
-export interface CardProps {
+export interface BaseProps {
title: string;
price?: number;
- Link?: React.ElementType;
Image?: React.ElementType;
subTitle?: string;
- to: string | UrlObject;
- className?: string;
imageContainerClass?: string;
}
-export const Card = ({
- to,
+type CardProps = PolymorphicComponentProps;
+
+export const Card = ({
subTitle,
title,
price,
- Link = "a",
- className = "",
+ as,
imageContainerClass,
children,
-}: React.PropsWithChildren) => {
+ ...linkProps
+}: React.PropsWithChildren>) => {
+ const RenderedLink = as || "a";
+
return (
-
+ {title}
{price && {currencyFormatter.format(price)}}
{subTitle && {subTitle}}
-
+
);
};
diff --git a/packages/shared-ui/uitls/polymorphicComponent.ts b/packages/shared-ui/uitls/polymorphicComponent.ts
new file mode 100644
index 0000000..c13059a
--- /dev/null
+++ b/packages/shared-ui/uitls/polymorphicComponent.ts
@@ -0,0 +1,57 @@
+// Taken from: https://www.benmvp.com/blog/forwarding-refs-polymorphic-react-component-typescript/
+
+// A more precise version of just React.ComponentPropsWithoutRef on its own
+export type PropsOf<
+ C extends keyof JSX.IntrinsicElements | React.JSXElementConstructor
+> = JSX.LibraryManagedAttributes>
+
+type AsProp = {
+ /**
+ * An override of the default HTML tag.
+ * Can also be another React component.
+ */
+ as?: C
+}
+
+/**
+ * Allows for extending a set of props (`ExtendedProps`) by an overriding set of props
+ * (`OverrideProps`), ensuring that any duplicates are overridden by the overriding
+ * set of props.
+ */
+export type ExtendableProps<
+ ExtendedProps = {},
+ OverrideProps = {}
+> = OverrideProps & Omit
+
+/**
+ * Allows for inheriting the props from the specified element type so that
+ * props like children, className & style work, as well as element-specific
+ * attributes like aria roles. The component (`C`) must be passed in.
+ */
+export type InheritableElementProps<
+ C extends React.ElementType,
+ Props = {}
+> = ExtendableProps, Props>
+
+export type PolymorphicComponentProps<
+ C extends React.ElementType,
+ Props = {}
+> = InheritableElementProps>
+
+/**
+ * Utility type to extract the `ref` prop from a polymorphic component
+ */
+export type PolymorphicRef<
+ C extends React.ElementType
+>
+ = React.ComponentPropsWithRef['ref']
+
+/**
+ * A wrapper of `PolymorphicComponentProps` that also includes the `ref`
+ * prop for the polymorphic component
+ */
+export type PolymorphicComponentPropsWithRef<
+ C extends React.ElementType,
+ Props = {}
+>
+ = PolymorphicComponentProps & { ref?: PolymorphicRef }
\ No newline at end of file