feat(dashboard,ui,types,admin-shared): Add more extension zones + pass data to widgets (#7465)

This commit is contained in:
Kasper Fabricius Kristensen authored and GitHub committed 2024-05-27 12:47:12 +02:00
1 parent 0b0e210f67
commit ab2e8fcd45
19 files changed
+195 -84

No files matched your search

+1
View File
@@ -57,6 +57,7 @@
"@medusajs/admin-sdk": patch "@medusajs/admin-sdk": patch
"@medusajs/admin-shared": patch "@medusajs/admin-shared": patch
"@medusajs/admin-vite-plugin": patch "@medusajs/admin-vite-plugin": patch
"@medusajs/ui": patch
--- ---
chore: Preview release changeset chore: Preview release changeset
@@ -58,20 +58,17 @@ const PRODUCT_CATEGORY_INJECTION_ZONES = [
const PRICE_LIST_INJECTION_ZONES = [ const PRICE_LIST_INJECTION_ZONES = [
"price_list.details.before", "price_list.details.before",
"price_list.details.after", "price_list.details.after",
"price_list.details.side.before",
"price_list.details.side.after",
"price_list.list.before", "price_list.list.before",
"price_list.list.after", "price_list.list.after",
] as const ] as const
const DISCOUNT_INJECTION_ZONES = [
"discount.details.before",
"discount.details.after",
"discount.list.before",
"discount.list.after",
] as const
const PROMOTION_INJECTION_ZONES = [ const PROMOTION_INJECTION_ZONES = [
"promotion.details.before", "promotion.details.before",
"promotion.details.after", "promotion.details.after",
"promotion.details.side.before",
"promotion.details.side.after",
"promotion.list.before", "promotion.list.before",
"promotion.list.after", "promotion.list.after",
] as const ] as const
@@ -123,7 +120,6 @@ export const INJECTION_ZONES = [
...PRODUCT_COLLECTION_INJECTION_ZONES, ...PRODUCT_COLLECTION_INJECTION_ZONES,
...PRODUCT_CATEGORY_INJECTION_ZONES, ...PRODUCT_CATEGORY_INJECTION_ZONES,
...PRICE_LIST_INJECTION_ZONES, ...PRICE_LIST_INJECTION_ZONES,
...DISCOUNT_INJECTION_ZONES,
...PROMOTION_INJECTION_ZONES, ...PROMOTION_INJECTION_ZONES,
...GIFT_CARD_INJECTION_ZONES, ...GIFT_CARD_INJECTION_ZONES,
...REGION_INJECTION_ZONES, ...REGION_INJECTION_ZONES,
+3 -1
View File
@@ -1,5 +1,7 @@
declare module "virtual:medusa/widgets/*" { declare module "virtual:medusa/widgets/*" {
const widgets: { Component: () => JSX.Element }[] import type { ComponentType } from "react"
const widgets: { Component: ComponentType<any> }[]
export default { export default {
widgets, widgets,
@@ -95,7 +95,6 @@ export const CreateCampaignForm = () => {
{t("actions.cancel")} {t("actions.cancel")}
</Button> </Button>
</RouteFocusModal.Close> </RouteFocusModal.Close>
<Button <Button
size="small" size="small"
variant="primary" variant="primary"
@@ -1,5 +1,4 @@
import { import {
clx,
CurrencyInput, CurrencyInput,
DatePicker, DatePicker,
Heading, Heading,
@@ -7,10 +6,12 @@ import {
RadioGroup, RadioGroup,
Select, Select,
Text, Text,
Textarea,
} from "@medusajs/ui" } from "@medusajs/ui"
import { useEffect } from "react" import { useEffect } from "react"
import { useWatch } from "react-hook-form" import { useWatch } from "react-hook-form"
import { useTranslation } from "react-i18next" import { useTranslation } from "react-i18next"
import { Form } from "../../../../../components/common/form" import { Form } from "../../../../../components/common/form"
import { useStore } from "../../../../../hooks/api/store" import { useStore } from "../../../../../hooks/api/store"
import { currencies, getCurrencySymbol } from "../../../../../lib/currencies" import { currencies, getCurrencySymbol } from "../../../../../lib/currencies"
@@ -70,6 +71,7 @@ export const CreateCampaignFormFields = ({ form, fieldScope = "" }) => {
</Text> </Text>
</div> </div>
<div className="flex flex-col gap-y-4">
<div className="grid grid-cols-1 gap-4 md:grid-cols-2"> <div className="grid grid-cols-1 gap-4 md:grid-cols-2">
<Form.Field <Form.Field
control={form.control} control={form.control}
@@ -89,24 +91,6 @@ export const CreateCampaignFormFields = ({ form, fieldScope = "" }) => {
}} }}
/> />
<Form.Field
control={form.control}
name={`${fieldScope}description`}
render={({ field }) => {
return (
<Form.Item>
<Form.Label>{t("fields.description")}</Form.Label>
<Form.Control>
<Input {...field} />
</Form.Control>
<Form.ErrorMessage />
</Form.Item>
)
}}
/>
<Form.Field <Form.Field
control={form.control} control={form.control}
name={`${fieldScope}campaign_identifier`} name={`${fieldScope}campaign_identifier`}
@@ -124,9 +108,28 @@ export const CreateCampaignFormFields = ({ form, fieldScope = "" }) => {
) )
}} }}
/> />
</div>
<div></div> <Form.Field
control={form.control}
name={`${fieldScope}description`}
render={({ field }) => {
return (
<Form.Item>
<Form.Label>{t("fields.description")}</Form.Label>
<Form.Control>
<Textarea {...field} />
</Form.Control>
<Form.ErrorMessage />
</Form.Item>
)
}}
/>
</div>
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
<Form.Field <Form.Field
control={form.control} control={form.control}
name={`${fieldScope}starts_at`} name={`${fieldScope}starts_at`}
@@ -198,20 +201,12 @@ export const CreateCampaignFormFields = ({ form, fieldScope = "" }) => {
onValueChange={field.onChange} onValueChange={field.onChange}
> >
<RadioGroup.ChoiceBox <RadioGroup.ChoiceBox
className={clx("basis-1/2 border", {
"border border-ui-border-interactive":
"spend" === field.value,
})}
value={"spend"} value={"spend"}
label={t("campaigns.budget.type.spend.title")} label={t("campaigns.budget.type.spend.title")}
description={t("campaigns.budget.type.spend.description")} description={t("campaigns.budget.type.spend.description")}
/> />
<RadioGroup.ChoiceBox <RadioGroup.ChoiceBox
className={clx("basis-1/2 border", {
"border border-ui-border-interactive":
"usage" === field.value,
})}
value={"usage"} value={"usage"}
label={t("campaigns.budget.type.usage.title")} label={t("campaigns.budget.type.usage.title")}
description={t("campaigns.budget.type.usage.description")} description={t("campaigns.budget.type.usage.description")}
@@ -39,7 +39,7 @@ export const CategoryDetail = () => {
{before.widgets.map((w, i) => { {before.widgets.map((w, i) => {
return ( return (
<div key={i}> <div key={i}>
<w.Component /> <w.Component data={product_category} />
</div> </div>
) )
})} })}
@@ -50,7 +50,7 @@ export const CategoryDetail = () => {
{after.widgets.map((w, i) => { {after.widgets.map((w, i) => {
return ( return (
<div key={i}> <div key={i}>
<w.Component /> <w.Component data={product_category} />
</div> </div>
) )
})} })}
@@ -62,7 +62,7 @@ export const CategoryDetail = () => {
{sideBefore.widgets.map((w, i) => { {sideBefore.widgets.map((w, i) => {
return ( return (
<div key={i}> <div key={i}>
<w.Component /> <w.Component data={product_category} />
</div> </div>
) )
})} })}
@@ -70,7 +70,7 @@ export const CategoryDetail = () => {
{sideAfter.widgets.map((w, i) => { {sideAfter.widgets.map((w, i) => {
return ( return (
<div key={i}> <div key={i}>
<w.Component /> <w.Component data={product_category} />
</div> </div>
) )
})} })}
@@ -36,7 +36,7 @@ export const CollectionDetail = () => {
{before.widgets.map((w, i) => { {before.widgets.map((w, i) => {
return ( return (
<div key={i}> <div key={i}>
<w.Component /> <w.Component data={collection} />
</div> </div>
) )
})} })}
@@ -45,7 +45,7 @@ export const CollectionDetail = () => {
{after.widgets.map((w, i) => { {after.widgets.map((w, i) => {
return ( return (
<div key={i}> <div key={i}>
<w.Component /> <w.Component data={collection} />
</div> </div>
) )
})} })}
@@ -36,7 +36,7 @@ export const CustomerGroupDetail = () => {
{before.widgets.map((w, i) => { {before.widgets.map((w, i) => {
return ( return (
<div key={i}> <div key={i}>
<w.Component /> <w.Component data={customer_group} />
</div> </div>
) )
})} })}
@@ -45,7 +45,7 @@ export const CustomerGroupDetail = () => {
{after.widgets.map((w, i) => { {after.widgets.map((w, i) => {
return ( return (
<div key={i}> <div key={i}>
<w.Component /> <w.Component data={customer_group} />
</div> </div>
) )
})} })}
@@ -32,7 +32,7 @@ export const CustomerDetail = () => {
{before.widgets.map((w, i) => { {before.widgets.map((w, i) => {
return ( return (
<div key={i}> <div key={i}>
<w.Component /> <w.Component data={customer} />
</div> </div>
) )
})} })}
@@ -44,7 +44,7 @@ export const CustomerDetail = () => {
{after.widgets.map((w, i) => { {after.widgets.map((w, i) => {
return ( return (
<div key={i}> <div key={i}>
<w.Component /> <w.Component data={customer} />
</div> </div>
) )
})} })}
@@ -43,7 +43,7 @@ export const OrderDetail = () => {
{before.widgets.map((w, i) => { {before.widgets.map((w, i) => {
return ( return (
<div key={i}> <div key={i}>
<w.Component /> <w.Component data={order} />
</div> </div>
) )
})} })}
@@ -56,7 +56,7 @@ export const OrderDetail = () => {
{after.widgets.map((w, i) => { {after.widgets.map((w, i) => {
return ( return (
<div key={i}> <div key={i}>
<w.Component /> <w.Component data={order} />
</div> </div>
) )
})} })}
@@ -68,7 +68,7 @@ export const OrderDetail = () => {
{sideBefore.widgets.map((w, i) => { {sideBefore.widgets.map((w, i) => {
return ( return (
<div key={i}> <div key={i}>
<w.Component /> <w.Component data={order} />
</div> </div>
) )
})} })}
@@ -77,7 +77,7 @@ export const OrderDetail = () => {
{sideAfter.widgets.map((w, i) => { {sideAfter.widgets.map((w, i) => {
return ( return (
<div key={i}> <div key={i}>
<w.Component /> <w.Component data={order} />
</div> </div>
) )
})} })}
@@ -1,10 +1,16 @@
import { Outlet, useParams } from "react-router-dom" import { Outlet, useParams } from "react-router-dom"
import { JsonViewSection } from "../../../components/common/json-view-section" import { JsonViewSection } from "../../../components/common/json-view-section"
import { usePriceList } from "../../../hooks/api/price-lists" import { usePriceList } from "../../../hooks/api/price-lists"
import { PricingConfigurationSection } from "./components/pricing-configuration-section" import { PricingConfigurationSection } from "./components/pricing-configuration-section"
import { PricingGeneralSection } from "./components/pricing-general-section" import { PricingGeneralSection } from "./components/pricing-general-section"
import { PricingProductSection } from "./components/pricing-product-section" import { PricingProductSection } from "./components/pricing-product-section"
import after from "virtual:medusa/widgets/price_list/details/after"
import before from "virtual:medusa/widgets/price_list/details/before"
import sideAfter from "virtual:medusa/widgets/price_list/details/side/after"
import sideBefore from "virtual:medusa/widgets/price_list/details/side/before"
export const PricingDetail = () => { export const PricingDetail = () => {
const { id } = useParams() const { id } = useParams()
@@ -19,19 +25,51 @@ export const PricingDetail = () => {
} }
return ( return (
<div className="flex flex-col gap-x-4 xl:flex-row xl:items-start"> <div className="flex flex-col gap-y-2">
{before.widgets.map((w, i) => {
return (
<div key={i}>
<w.Component data={price_list} />
</div>
)
})}
<div className="flex flex-col gap-x-4 lg:flex-row xl:items-start">
<div className="flex w-full flex-col gap-y-2"> <div className="flex w-full flex-col gap-y-2">
<PricingGeneralSection priceList={price_list} /> <PricingGeneralSection priceList={price_list} />
<PricingProductSection priceList={price_list} /> <PricingProductSection priceList={price_list} />
<div className="flex w-full flex-col gap-y-2 xl:hidden"> {after.widgets.map((w, i) => {
<PricingConfigurationSection priceList={price_list} /> return (
<div key={i}>
<w.Component data={price_list} />
</div> </div>
)
})}
<div className="hidden xl:block">
<JsonViewSection data={price_list} /> <JsonViewSection data={price_list} />
</div> </div>
<div className="hidden w-full max-w-[400px] flex-col gap-y-2 xl:flex"> </div>
<div className="mt-2 flex w-full max-w-[100%] flex-col gap-y-2 xl:mt-0 xl:max-w-[400px]">
{sideBefore.widgets.map((w, i) => {
return (
<div key={i}>
<w.Component data={price_list} />
</div>
)
})}
<PricingConfigurationSection priceList={price_list} /> <PricingConfigurationSection priceList={price_list} />
{sideAfter.widgets.map((w, i) => {
return (
<div key={i}>
<w.Component data={price_list} />
</div>
)
})}
<div className="xl:hidden">
<JsonViewSection data={price_list} />
</div>
</div> </div>
<Outlet /> <Outlet />
</div> </div>
</div>
) )
} }
@@ -1,10 +1,28 @@
import { Outlet } from "react-router-dom" import { Outlet } from "react-router-dom"
import { PricingListTable } from "./components/pricing-list-table" import { PricingListTable } from "./components/pricing-list-table"
import after from "virtual:medusa/widgets/price_list/list/after"
import before from "virtual:medusa/widgets/price_list/list/before"
export const PricingList = () => { export const PricingList = () => {
return ( return (
<div className="flex flex-col gap-y-2"> <div className="flex flex-col gap-y-2">
{before.widgets.map((w, i) => {
return (
<div key={i}>
<w.Component />
</div>
)
})}
<PricingListTable /> <PricingListTable />
{after.widgets.map((w, i) => {
return (
<div key={i}>
<w.Component />
</div>
)
})}
<Outlet /> <Outlet />
</div> </div>
) )
@@ -40,7 +40,7 @@ export const ProductDetail = () => {
{before.widgets.map((w, i) => { {before.widgets.map((w, i) => {
return ( return (
<div key={i}> <div key={i}>
<w.Component /> <w.Component data={product} />
</div> </div>
) )
})} })}
@@ -53,7 +53,7 @@ export const ProductDetail = () => {
{after.widgets.map((w, i) => { {after.widgets.map((w, i) => {
return ( return (
<div key={i}> <div key={i}>
<w.Component /> <w.Component data={product} />
</div> </div>
) )
})} })}
@@ -65,7 +65,7 @@ export const ProductDetail = () => {
{sideBefore.widgets.map((w, i) => { {sideBefore.widgets.map((w, i) => {
return ( return (
<div key={i}> <div key={i}>
<w.Component /> <w.Component data={product} />
</div> </div>
) )
})} })}
@@ -75,7 +75,7 @@ export const ProductDetail = () => {
{sideAfter.widgets.map((w, i) => { {sideAfter.widgets.map((w, i) => {
return ( return (
<div key={i}> <div key={i}>
<w.Component /> <w.Component data={product} />
</div> </div>
) )
})} })}
@@ -7,6 +7,9 @@ import { PromotionConditionsSection } from "./components/promotion-conditions-se
import { PromotionGeneralSection } from "./components/promotion-general-section" import { PromotionGeneralSection } from "./components/promotion-general-section"
import { promotionLoader } from "./loader" import { promotionLoader } from "./loader"
import after from "virtual:medusa/widgets/promotion/details/after"
import before from "virtual:medusa/widgets/promotion/details/before"
export const PromotionDetail = () => { export const PromotionDetail = () => {
const initialData = useLoaderData() as Awaited< const initialData = useLoaderData() as Awaited<
ReturnType<typeof promotionLoader> ReturnType<typeof promotionLoader>
@@ -24,33 +27,43 @@ export const PromotionDetail = () => {
return ( return (
<div className="flex flex-col gap-y-2"> <div className="flex flex-col gap-y-2">
{before.widgets.map((w, i) => {
return (
<div key={i}>
<w.Component data={promotion} />
</div>
)
})}
<div className="flex flex-col gap-x-4 xl:flex-row xl:items-start"> <div className="flex flex-col gap-x-4 xl:flex-row xl:items-start">
<div className="flex w-full flex-col gap-y-2"> <div className="flex w-full flex-col gap-y-2">
<PromotionGeneralSection promotion={promotion} /> <PromotionGeneralSection promotion={promotion} />
<PromotionConditionsSection rules={rules || []} ruleType={"rules"} /> <PromotionConditionsSection rules={rules || []} ruleType={"rules"} />
<PromotionConditionsSection <PromotionConditionsSection
rules={targetRules || []} rules={targetRules || []}
ruleType={"target-rules"} ruleType={"target-rules"}
/> />
{promotion.type === "buyget" && ( {promotion.type === "buyget" && (
<PromotionConditionsSection <PromotionConditionsSection
rules={buyRules || []} rules={buyRules || []}
ruleType={"buy-rules"} ruleType={"buy-rules"}
/> />
)} )}
{after.widgets.map((w, i) => {
<div className="flex w-full flex-col gap-y-2 xl:hidden"> return (
<CampaignSection campaign={promotion.campaign!} /> <div key={i}>
<w.Component data={promotion} />
</div> </div>
)
<JsonViewSection data={promotion as any} /> })}
<div className="hidden xl:block">
<JsonViewSection data={promotion} />
</div> </div>
</div>
<div className="hidden w-full max-w-[400px] flex-col gap-y-2 xl:flex"> <div className="mt-2 flex w-full max-w-[100%] flex-col gap-y-2 xl:mt-0 xl:max-w-[400px]">
<CampaignSection campaign={promotion.campaign!} /> <CampaignSection campaign={promotion.campaign!} />
<div className="xl:hidden">
<JsonViewSection data={promotion} />
</div>
</div> </div>
</div> </div>
<Outlet /> <Outlet />
@@ -1,9 +1,26 @@
import { PromotionListTable } from "./components/promotion-list-table" import { PromotionListTable } from "./components/promotion-list-table"
import after from "virtual:medusa/widgets/promotion/list/after"
import before from "virtual:medusa/widgets/promotion/list/before"
export const PromotionsList = () => { export const PromotionsList = () => {
return ( return (
<div className="flex flex-col gap-y-2"> <div className="flex flex-col gap-y-2">
{before.widgets.map((w, i) => {
return (
<div key={i}>
<w.Component />
</div>
)
})}
<PromotionListTable /> <PromotionListTable />
{after.widgets.map((w, i) => {
return (
<div key={i}>
<w.Component />
</div>
)
})}
</div> </div>
) )
} }
@@ -0,0 +1,27 @@
/**
* The props for detail widgets. All widgets that are rendered in a detail view,
* e.g. the product detail view, should implement this interface.
*
* The type of the data prop should be the same as the data that is passed to the widget.
* If the widget is rendered in the product detail view, the data prop should be of
* type AdminProduct.
*
* @example
* ```tsx
* import type { DetailWidgetProps, AdminProduct } from "@medusajs/types"
* import { defineConfig } from "@medusajs/admin-shared"
*
* const ProductWidget = ({ data }: DetailWidgetProps<AdminProduct>) => {
* return <div>{data.title}</div>
* }
*
* export const config = defineConfig({
* zone: "product.details.after",
* })
*
* export default ProductWidget
* ```
*/
export interface DetailWidgetProps<TData> {
data: TData
}
+1
View File
@@ -0,0 +1 @@
export * from "./extensions"
+2 -1
View File
@@ -1,4 +1,5 @@
export * from "./address" export * from "./address"
// export * from "./admin"
export * from "./api-key" export * from "./api-key"
export * from "./auth" export * from "./auth"
export * from "./bundles" export * from "./bundles"
@@ -19,6 +20,7 @@ export * from "./joiner"
export * from "./link-modules" export * from "./link-modules"
export * from "./logger" export * from "./logger"
export * from "./modules-sdk" export * from "./modules-sdk"
export * from "./notification"
export * from "./order" export * from "./order"
export * from "./payment" export * from "./payment"
export * from "./pricing" export * from "./pricing"
@@ -38,4 +40,3 @@ export * from "./transaction-base"
export * from "./user" export * from "./user"
export * from "./workflow" export * from "./workflow"
export * from "./workflows" export * from "./workflows"
export * from "./notification"
@@ -343,7 +343,7 @@ interface SingleProps extends PickerProps {
onChange?: (date: Date | undefined) => void onChange?: (date: Date | undefined) => void
} }
const SingleDatePicker = ({ const SingleDatePicker = React.forwardRef<HTMLButtonElement, SingleProps>(({
defaultValue, defaultValue,
value, value,
size = "base", size = "base",
@@ -355,7 +355,7 @@ const SingleDatePicker = ({
placeholder, placeholder,
translations, translations,
...props ...props
}: SingleProps) => { }, ref) => {
const [open, setOpen] = React.useState(false) const [open, setOpen] = React.useState(false)
const [date, setDate] = React.useState<Date | undefined>( const [date, setDate] = React.useState<Date | undefined>(
value ?? defaultValue ?? undefined value ?? defaultValue ?? undefined
@@ -480,7 +480,7 @@ const SingleDatePicker = ({
} }
return ( return (
<Primitives.Root open={open} onOpenChange={onOpenChange}> <Primitives.Root modal open={open} onOpenChange={onOpenChange}>
<Display <Display
placeholder={placeholder} placeholder={placeholder}
disabled={disabled} disabled={disabled}
@@ -490,6 +490,7 @@ const SingleDatePicker = ({
aria-label={props["aria-label"]} aria-label={props["aria-label"]}
aria-labelledby={props["aria-labelledby"]} aria-labelledby={props["aria-labelledby"]}
size={size} size={size}
ref={ref}
> >
{formattedDate} {formattedDate}
</Display> </Display>
@@ -554,7 +555,7 @@ const SingleDatePicker = ({
</Flyout> </Flyout>
</Primitives.Root> </Primitives.Root>
) )
} })
interface RangeProps extends PickerProps { interface RangeProps extends PickerProps {
presets?: DateRangePreset[] presets?: DateRangePreset[]
@@ -563,7 +564,7 @@ interface RangeProps extends PickerProps {
onChange?: (dateRange: DateRange | undefined) => void onChange?: (dateRange: DateRange | undefined) => void
} }
const RangeDatePicker = ({ const RangeDatePicker = React.forwardRef<HTMLButtonElement, RangeProps>(({
/** /**
* The date range selected by default. * The date range selected by default.
*/ */
@@ -587,7 +588,7 @@ const RangeDatePicker = ({
placeholder, placeholder,
translations, translations,
...props ...props
}: RangeProps) => { }, ref) => {
const [open, setOpen] = React.useState(false) const [open, setOpen] = React.useState(false)
const [range, setRange] = React.useState<DateRange | undefined>( const [range, setRange] = React.useState<DateRange | undefined>(
value ?? defaultValue ?? undefined value ?? defaultValue ?? undefined
@@ -756,7 +757,7 @@ const RangeDatePicker = ({
} }
return ( return (
<Primitives.Root open={open} onOpenChange={onOpenChange}> <Primitives.Root modal open={open} onOpenChange={onOpenChange}>
<Display <Display
placeholder={placeholder} placeholder={placeholder}
disabled={disabled} disabled={disabled}
@@ -766,6 +767,7 @@ const RangeDatePicker = ({
aria-label={props["aria-label"]} aria-label={props["aria-label"]}
aria-labelledby={props["aria-labelledby"]} aria-labelledby={props["aria-labelledby"]}
size={size} size={size}
ref={ref}
> >
{displayRange} {displayRange}
</Display> </Display>
@@ -858,7 +860,7 @@ const RangeDatePicker = ({
</Flyout> </Flyout>
</Primitives.Root> </Primitives.Root>
) )
} })
/** /**
* @interface * @interface
@@ -1031,22 +1033,23 @@ const validatePresets = (
* This component is based on the [Calendar](https://docs.medusajs.com/ui/components/calendar) * This component is based on the [Calendar](https://docs.medusajs.com/ui/components/calendar)
* component and [Radix UI Popover](https://www.radix-ui.com/primitives/docs/components/popover). * component and [Radix UI Popover](https://www.radix-ui.com/primitives/docs/components/popover).
*/ */
const DatePicker = ({ const DatePicker = React.forwardRef<HTMLButtonElement, DatePickerProps>(({
/** /**
* The date picker's mode. * The date picker's mode.
*/ */
mode = "single", mode = "single",
...props ...props
}: DatePickerProps) => { }, ref) => {
if (props.presets) { if (props.presets) {
validatePresets(props.presets, props) validatePresets(props.presets, props)
} }
if (mode === "single") { if (mode === "single") {
return <SingleDatePicker {...(props as SingleProps)} /> return <SingleDatePicker ref={ref} {...(props as SingleProps)} />
} }
return <RangeDatePicker {...(props as RangeProps)} /> return <RangeDatePicker ref={ref} {...(props as RangeProps)} />
} })
DatePicker.displayName = "DatePicker"
export { DatePicker } export { DatePicker }