feat(dashboard,ui,types,admin-shared): Add more extension zones + pass data to widgets (#7465)
This commit is contained in:
committed by
GitHub
parent
0b0e210f67
commit
ab2e8fcd45
@@ -57,6 +57,7 @@
|
||||
"@medusajs/admin-sdk": patch
|
||||
"@medusajs/admin-shared": patch
|
||||
"@medusajs/admin-vite-plugin": patch
|
||||
"@medusajs/ui": patch
|
||||
---
|
||||
|
||||
chore: Preview release changeset
|
||||
|
||||
@@ -58,20 +58,17 @@ const PRODUCT_CATEGORY_INJECTION_ZONES = [
|
||||
const PRICE_LIST_INJECTION_ZONES = [
|
||||
"price_list.details.before",
|
||||
"price_list.details.after",
|
||||
"price_list.details.side.before",
|
||||
"price_list.details.side.after",
|
||||
"price_list.list.before",
|
||||
"price_list.list.after",
|
||||
] as const
|
||||
|
||||
const DISCOUNT_INJECTION_ZONES = [
|
||||
"discount.details.before",
|
||||
"discount.details.after",
|
||||
"discount.list.before",
|
||||
"discount.list.after",
|
||||
] as const
|
||||
|
||||
const PROMOTION_INJECTION_ZONES = [
|
||||
"promotion.details.before",
|
||||
"promotion.details.after",
|
||||
"promotion.details.side.before",
|
||||
"promotion.details.side.after",
|
||||
"promotion.list.before",
|
||||
"promotion.list.after",
|
||||
] as const
|
||||
@@ -123,7 +120,6 @@ export const INJECTION_ZONES = [
|
||||
...PRODUCT_COLLECTION_INJECTION_ZONES,
|
||||
...PRODUCT_CATEGORY_INJECTION_ZONES,
|
||||
...PRICE_LIST_INJECTION_ZONES,
|
||||
...DISCOUNT_INJECTION_ZONES,
|
||||
...PROMOTION_INJECTION_ZONES,
|
||||
...GIFT_CARD_INJECTION_ZONES,
|
||||
...REGION_INJECTION_ZONES,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
declare module "virtual:medusa/widgets/*" {
|
||||
const widgets: { Component: () => JSX.Element }[]
|
||||
import type { ComponentType } from "react"
|
||||
|
||||
const widgets: { Component: ComponentType<any> }[]
|
||||
|
||||
export default {
|
||||
widgets,
|
||||
|
||||
@@ -95,7 +95,6 @@ export const CreateCampaignForm = () => {
|
||||
{t("actions.cancel")}
|
||||
</Button>
|
||||
</RouteFocusModal.Close>
|
||||
|
||||
<Button
|
||||
size="small"
|
||||
variant="primary"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import {
|
||||
clx,
|
||||
CurrencyInput,
|
||||
DatePicker,
|
||||
Heading,
|
||||
@@ -7,10 +6,12 @@ import {
|
||||
RadioGroup,
|
||||
Select,
|
||||
Text,
|
||||
Textarea,
|
||||
} from "@medusajs/ui"
|
||||
import { useEffect } from "react"
|
||||
import { useWatch } from "react-hook-form"
|
||||
import { useTranslation } from "react-i18next"
|
||||
|
||||
import { Form } from "../../../../../components/common/form"
|
||||
import { useStore } from "../../../../../hooks/api/store"
|
||||
import { currencies, getCurrencySymbol } from "../../../../../lib/currencies"
|
||||
@@ -70,24 +71,44 @@ export const CreateCampaignFormFields = ({ form, fieldScope = "" }) => {
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<Form.Field
|
||||
control={form.control}
|
||||
name={`${fieldScope}name`}
|
||||
render={({ field }) => {
|
||||
return (
|
||||
<Form.Item>
|
||||
<Form.Label>{t("fields.name")}</Form.Label>
|
||||
<div className="flex flex-col gap-y-4">
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<Form.Field
|
||||
control={form.control}
|
||||
name={`${fieldScope}name`}
|
||||
render={({ field }) => {
|
||||
return (
|
||||
<Form.Item>
|
||||
<Form.Label>{t("fields.name")}</Form.Label>
|
||||
|
||||
<Form.Control>
|
||||
<Input {...field} />
|
||||
</Form.Control>
|
||||
<Form.Control>
|
||||
<Input {...field} />
|
||||
</Form.Control>
|
||||
|
||||
<Form.ErrorMessage />
|
||||
</Form.Item>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
<Form.ErrorMessage />
|
||||
</Form.Item>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
|
||||
<Form.Field
|
||||
control={form.control}
|
||||
name={`${fieldScope}campaign_identifier`}
|
||||
render={({ field }) => {
|
||||
return (
|
||||
<Form.Item>
|
||||
<Form.Label>{t("campaigns.fields.identifier")}</Form.Label>
|
||||
|
||||
<Form.Control>
|
||||
<Input {...field} />
|
||||
</Form.Control>
|
||||
|
||||
<Form.ErrorMessage />
|
||||
</Form.Item>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Form.Field
|
||||
control={form.control}
|
||||
@@ -98,7 +119,7 @@ export const CreateCampaignFormFields = ({ form, fieldScope = "" }) => {
|
||||
<Form.Label>{t("fields.description")}</Form.Label>
|
||||
|
||||
<Form.Control>
|
||||
<Input {...field} />
|
||||
<Textarea {...field} />
|
||||
</Form.Control>
|
||||
|
||||
<Form.ErrorMessage />
|
||||
@@ -106,27 +127,9 @@ export const CreateCampaignFormFields = ({ form, fieldScope = "" }) => {
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Form.Field
|
||||
control={form.control}
|
||||
name={`${fieldScope}campaign_identifier`}
|
||||
render={({ field }) => {
|
||||
return (
|
||||
<Form.Item>
|
||||
<Form.Label>{t("campaigns.fields.identifier")}</Form.Label>
|
||||
|
||||
<Form.Control>
|
||||
<Input {...field} />
|
||||
</Form.Control>
|
||||
|
||||
<Form.ErrorMessage />
|
||||
</Form.Item>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
|
||||
<div></div>
|
||||
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<Form.Field
|
||||
control={form.control}
|
||||
name={`${fieldScope}starts_at`}
|
||||
@@ -198,20 +201,12 @@ export const CreateCampaignFormFields = ({ form, fieldScope = "" }) => {
|
||||
onValueChange={field.onChange}
|
||||
>
|
||||
<RadioGroup.ChoiceBox
|
||||
className={clx("basis-1/2 border", {
|
||||
"border border-ui-border-interactive":
|
||||
"spend" === field.value,
|
||||
})}
|
||||
value={"spend"}
|
||||
label={t("campaigns.budget.type.spend.title")}
|
||||
description={t("campaigns.budget.type.spend.description")}
|
||||
/>
|
||||
|
||||
<RadioGroup.ChoiceBox
|
||||
className={clx("basis-1/2 border", {
|
||||
"border border-ui-border-interactive":
|
||||
"usage" === field.value,
|
||||
})}
|
||||
value={"usage"}
|
||||
label={t("campaigns.budget.type.usage.title")}
|
||||
description={t("campaigns.budget.type.usage.description")}
|
||||
|
||||
@@ -39,7 +39,7 @@ export const CategoryDetail = () => {
|
||||
{before.widgets.map((w, i) => {
|
||||
return (
|
||||
<div key={i}>
|
||||
<w.Component />
|
||||
<w.Component data={product_category} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
@@ -50,7 +50,7 @@ export const CategoryDetail = () => {
|
||||
{after.widgets.map((w, i) => {
|
||||
return (
|
||||
<div key={i}>
|
||||
<w.Component />
|
||||
<w.Component data={product_category} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
@@ -62,7 +62,7 @@ export const CategoryDetail = () => {
|
||||
{sideBefore.widgets.map((w, i) => {
|
||||
return (
|
||||
<div key={i}>
|
||||
<w.Component />
|
||||
<w.Component data={product_category} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
@@ -70,7 +70,7 @@ export const CategoryDetail = () => {
|
||||
{sideAfter.widgets.map((w, i) => {
|
||||
return (
|
||||
<div key={i}>
|
||||
<w.Component />
|
||||
<w.Component data={product_category} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
|
||||
@@ -36,7 +36,7 @@ export const CollectionDetail = () => {
|
||||
{before.widgets.map((w, i) => {
|
||||
return (
|
||||
<div key={i}>
|
||||
<w.Component />
|
||||
<w.Component data={collection} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
@@ -45,7 +45,7 @@ export const CollectionDetail = () => {
|
||||
{after.widgets.map((w, i) => {
|
||||
return (
|
||||
<div key={i}>
|
||||
<w.Component />
|
||||
<w.Component data={collection} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
|
||||
@@ -36,7 +36,7 @@ export const CustomerGroupDetail = () => {
|
||||
{before.widgets.map((w, i) => {
|
||||
return (
|
||||
<div key={i}>
|
||||
<w.Component />
|
||||
<w.Component data={customer_group} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
@@ -45,7 +45,7 @@ export const CustomerGroupDetail = () => {
|
||||
{after.widgets.map((w, i) => {
|
||||
return (
|
||||
<div key={i}>
|
||||
<w.Component />
|
||||
<w.Component data={customer_group} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
|
||||
@@ -32,7 +32,7 @@ export const CustomerDetail = () => {
|
||||
{before.widgets.map((w, i) => {
|
||||
return (
|
||||
<div key={i}>
|
||||
<w.Component />
|
||||
<w.Component data={customer} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
@@ -44,7 +44,7 @@ export const CustomerDetail = () => {
|
||||
{after.widgets.map((w, i) => {
|
||||
return (
|
||||
<div key={i}>
|
||||
<w.Component />
|
||||
<w.Component data={customer} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
|
||||
@@ -43,7 +43,7 @@ export const OrderDetail = () => {
|
||||
{before.widgets.map((w, i) => {
|
||||
return (
|
||||
<div key={i}>
|
||||
<w.Component />
|
||||
<w.Component data={order} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
@@ -56,7 +56,7 @@ export const OrderDetail = () => {
|
||||
{after.widgets.map((w, i) => {
|
||||
return (
|
||||
<div key={i}>
|
||||
<w.Component />
|
||||
<w.Component data={order} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
@@ -68,7 +68,7 @@ export const OrderDetail = () => {
|
||||
{sideBefore.widgets.map((w, i) => {
|
||||
return (
|
||||
<div key={i}>
|
||||
<w.Component />
|
||||
<w.Component data={order} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
@@ -77,7 +77,7 @@ export const OrderDetail = () => {
|
||||
{sideAfter.widgets.map((w, i) => {
|
||||
return (
|
||||
<div key={i}>
|
||||
<w.Component />
|
||||
<w.Component data={order} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
import { Outlet, useParams } from "react-router-dom"
|
||||
|
||||
import { JsonViewSection } from "../../../components/common/json-view-section"
|
||||
import { usePriceList } from "../../../hooks/api/price-lists"
|
||||
import { PricingConfigurationSection } from "./components/pricing-configuration-section"
|
||||
import { PricingGeneralSection } from "./components/pricing-general-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 = () => {
|
||||
const { id } = useParams()
|
||||
|
||||
@@ -19,19 +25,51 @@ export const PricingDetail = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-x-4 xl:flex-row xl:items-start">
|
||||
<div className="flex w-full flex-col gap-y-2">
|
||||
<PricingGeneralSection priceList={price_list} />
|
||||
<PricingProductSection priceList={price_list} />
|
||||
<div className="flex w-full flex-col gap-y-2 xl:hidden">
|
||||
<PricingConfigurationSection priceList={price_list} />
|
||||
<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">
|
||||
<PricingGeneralSection priceList={price_list} />
|
||||
<PricingProductSection priceList={price_list} />
|
||||
{after.widgets.map((w, i) => {
|
||||
return (
|
||||
<div key={i}>
|
||||
<w.Component data={price_list} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
<div className="hidden xl:block">
|
||||
<JsonViewSection data={price_list} />
|
||||
</div>
|
||||
</div>
|
||||
<JsonViewSection data={price_list} />
|
||||
<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} />
|
||||
{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>
|
||||
<Outlet />
|
||||
</div>
|
||||
<div className="hidden w-full max-w-[400px] flex-col gap-y-2 xl:flex">
|
||||
<PricingConfigurationSection priceList={price_list} />
|
||||
</div>
|
||||
<Outlet />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,10 +1,28 @@
|
||||
import { Outlet } from "react-router-dom"
|
||||
|
||||
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 = () => {
|
||||
return (
|
||||
<div className="flex flex-col gap-y-2">
|
||||
{before.widgets.map((w, i) => {
|
||||
return (
|
||||
<div key={i}>
|
||||
<w.Component />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
<PricingListTable />
|
||||
{after.widgets.map((w, i) => {
|
||||
return (
|
||||
<div key={i}>
|
||||
<w.Component />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
<Outlet />
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -40,7 +40,7 @@ export const ProductDetail = () => {
|
||||
{before.widgets.map((w, i) => {
|
||||
return (
|
||||
<div key={i}>
|
||||
<w.Component />
|
||||
<w.Component data={product} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
@@ -53,7 +53,7 @@ export const ProductDetail = () => {
|
||||
{after.widgets.map((w, i) => {
|
||||
return (
|
||||
<div key={i}>
|
||||
<w.Component />
|
||||
<w.Component data={product} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
@@ -65,7 +65,7 @@ export const ProductDetail = () => {
|
||||
{sideBefore.widgets.map((w, i) => {
|
||||
return (
|
||||
<div key={i}>
|
||||
<w.Component />
|
||||
<w.Component data={product} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
@@ -75,7 +75,7 @@ export const ProductDetail = () => {
|
||||
{sideAfter.widgets.map((w, i) => {
|
||||
return (
|
||||
<div key={i}>
|
||||
<w.Component />
|
||||
<w.Component data={product} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
|
||||
@@ -7,6 +7,9 @@ import { PromotionConditionsSection } from "./components/promotion-conditions-se
|
||||
import { PromotionGeneralSection } from "./components/promotion-general-section"
|
||||
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 = () => {
|
||||
const initialData = useLoaderData() as Awaited<
|
||||
ReturnType<typeof promotionLoader>
|
||||
@@ -24,33 +27,43 @@ export const PromotionDetail = () => {
|
||||
|
||||
return (
|
||||
<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 w-full flex-col gap-y-2">
|
||||
<PromotionGeneralSection promotion={promotion} />
|
||||
|
||||
<PromotionConditionsSection rules={rules || []} ruleType={"rules"} />
|
||||
|
||||
<PromotionConditionsSection
|
||||
rules={targetRules || []}
|
||||
ruleType={"target-rules"}
|
||||
/>
|
||||
|
||||
{promotion.type === "buyget" && (
|
||||
<PromotionConditionsSection
|
||||
rules={buyRules || []}
|
||||
ruleType={"buy-rules"}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className="flex w-full flex-col gap-y-2 xl:hidden">
|
||||
<CampaignSection campaign={promotion.campaign!} />
|
||||
{after.widgets.map((w, i) => {
|
||||
return (
|
||||
<div key={i}>
|
||||
<w.Component data={promotion} />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
<div className="hidden xl:block">
|
||||
<JsonViewSection data={promotion} />
|
||||
</div>
|
||||
|
||||
<JsonViewSection data={promotion as any} />
|
||||
</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!} />
|
||||
<div className="xl:hidden">
|
||||
<JsonViewSection data={promotion} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Outlet />
|
||||
|
||||
@@ -1,9 +1,26 @@
|
||||
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 = () => {
|
||||
return (
|
||||
<div className="flex flex-col gap-y-2">
|
||||
{before.widgets.map((w, i) => {
|
||||
return (
|
||||
<div key={i}>
|
||||
<w.Component />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
<PromotionListTable />
|
||||
{after.widgets.map((w, i) => {
|
||||
return (
|
||||
<div key={i}>
|
||||
<w.Component />
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
27
packages/core/types/src/admin/extensions.ts
Normal file
27
packages/core/types/src/admin/extensions.ts
Normal file
@@ -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
packages/core/types/src/admin/index.ts
Normal file
1
packages/core/types/src/admin/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./extensions"
|
||||
@@ -1,4 +1,5 @@
|
||||
export * from "./address"
|
||||
// export * from "./admin"
|
||||
export * from "./api-key"
|
||||
export * from "./auth"
|
||||
export * from "./bundles"
|
||||
@@ -19,6 +20,7 @@ export * from "./joiner"
|
||||
export * from "./link-modules"
|
||||
export * from "./logger"
|
||||
export * from "./modules-sdk"
|
||||
export * from "./notification"
|
||||
export * from "./order"
|
||||
export * from "./payment"
|
||||
export * from "./pricing"
|
||||
@@ -38,4 +40,3 @@ export * from "./transaction-base"
|
||||
export * from "./user"
|
||||
export * from "./workflow"
|
||||
export * from "./workflows"
|
||||
export * from "./notification"
|
||||
|
||||
@@ -343,7 +343,7 @@ interface SingleProps extends PickerProps {
|
||||
onChange?: (date: Date | undefined) => void
|
||||
}
|
||||
|
||||
const SingleDatePicker = ({
|
||||
const SingleDatePicker = React.forwardRef<HTMLButtonElement, SingleProps>(({
|
||||
defaultValue,
|
||||
value,
|
||||
size = "base",
|
||||
@@ -355,7 +355,7 @@ const SingleDatePicker = ({
|
||||
placeholder,
|
||||
translations,
|
||||
...props
|
||||
}: SingleProps) => {
|
||||
}, ref) => {
|
||||
const [open, setOpen] = React.useState(false)
|
||||
const [date, setDate] = React.useState<Date | undefined>(
|
||||
value ?? defaultValue ?? undefined
|
||||
@@ -480,7 +480,7 @@ const SingleDatePicker = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<Primitives.Root open={open} onOpenChange={onOpenChange}>
|
||||
<Primitives.Root modal open={open} onOpenChange={onOpenChange}>
|
||||
<Display
|
||||
placeholder={placeholder}
|
||||
disabled={disabled}
|
||||
@@ -490,6 +490,7 @@ const SingleDatePicker = ({
|
||||
aria-label={props["aria-label"]}
|
||||
aria-labelledby={props["aria-labelledby"]}
|
||||
size={size}
|
||||
ref={ref}
|
||||
>
|
||||
{formattedDate}
|
||||
</Display>
|
||||
@@ -554,7 +555,7 @@ const SingleDatePicker = ({
|
||||
</Flyout>
|
||||
</Primitives.Root>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
interface RangeProps extends PickerProps {
|
||||
presets?: DateRangePreset[]
|
||||
@@ -563,7 +564,7 @@ interface RangeProps extends PickerProps {
|
||||
onChange?: (dateRange: DateRange | undefined) => void
|
||||
}
|
||||
|
||||
const RangeDatePicker = ({
|
||||
const RangeDatePicker = React.forwardRef<HTMLButtonElement, RangeProps>(({
|
||||
/**
|
||||
* The date range selected by default.
|
||||
*/
|
||||
@@ -587,7 +588,7 @@ const RangeDatePicker = ({
|
||||
placeholder,
|
||||
translations,
|
||||
...props
|
||||
}: RangeProps) => {
|
||||
}, ref) => {
|
||||
const [open, setOpen] = React.useState(false)
|
||||
const [range, setRange] = React.useState<DateRange | undefined>(
|
||||
value ?? defaultValue ?? undefined
|
||||
@@ -756,7 +757,7 @@ const RangeDatePicker = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<Primitives.Root open={open} onOpenChange={onOpenChange}>
|
||||
<Primitives.Root modal open={open} onOpenChange={onOpenChange}>
|
||||
<Display
|
||||
placeholder={placeholder}
|
||||
disabled={disabled}
|
||||
@@ -766,6 +767,7 @@ const RangeDatePicker = ({
|
||||
aria-label={props["aria-label"]}
|
||||
aria-labelledby={props["aria-labelledby"]}
|
||||
size={size}
|
||||
ref={ref}
|
||||
>
|
||||
{displayRange}
|
||||
</Display>
|
||||
@@ -858,7 +860,7 @@ const RangeDatePicker = ({
|
||||
</Flyout>
|
||||
</Primitives.Root>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* @interface
|
||||
@@ -1031,22 +1033,23 @@ const validatePresets = (
|
||||
* 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).
|
||||
*/
|
||||
const DatePicker = ({
|
||||
const DatePicker = React.forwardRef<HTMLButtonElement, DatePickerProps>(({
|
||||
/**
|
||||
* The date picker's mode.
|
||||
*/
|
||||
mode = "single",
|
||||
...props
|
||||
}: DatePickerProps) => {
|
||||
}, ref) => {
|
||||
if (props.presets) {
|
||||
validatePresets(props.presets, props)
|
||||
}
|
||||
|
||||
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 }
|
||||
|
||||
Reference in New Issue
Block a user