diff --git a/packages/admin-next/dashboard/package.json b/packages/admin-next/dashboard/package.json index 5d6cb4ffb8..477473f7fa 100644 --- a/packages/admin-next/dashboard/package.json +++ b/packages/admin-next/dashboard/package.json @@ -35,14 +35,14 @@ "@medusajs/icons": "1.2.1", "@medusajs/js-sdk": "0.0.1", "@medusajs/ui": "3.0.0", - "@radix-ui/react-collapsible": "1.0.3", - "@radix-ui/react-hover-card": "^1.0.7", + "@radix-ui/react-collapsible": "1.1.0", + "@radix-ui/react-hover-card": "1.1.1", "@tanstack/react-query": "^5.28.14", "@tanstack/react-table": "8.10.7", "@tanstack/react-virtual": "^3.0.4", "@uiw/react-json-view": "^2.0.0-alpha.17", "cmdk": "^0.2.0", - "date-fns": "^3.2.0", + "date-fns": "^3.6.0", "framer-motion": "^11.0.3", "i18next": "23.7.11", "i18next-browser-languagedetector": "7.2.0", diff --git a/packages/admin-next/dashboard/src/app.tsx b/packages/admin-next/dashboard/src/app.tsx index def2787f4b..e1a0ffd4ac 100644 --- a/packages/admin-next/dashboard/src/app.tsx +++ b/packages/admin-next/dashboard/src/app.tsx @@ -3,6 +3,7 @@ import { QueryClientProvider } from "@tanstack/react-query" import { I18n } from "./components/utilities/i18n" import { queryClient } from "./lib/query-client" +import { I18nProvider } from "./providers/i18n-provider" import { RouterProvider } from "./providers/router-provider" import { ThemeProvider } from "./providers/theme-provider" @@ -14,7 +15,9 @@ function App() { - + + + diff --git a/packages/admin-next/dashboard/src/components/common/date-range-display/date-range-display.tsx b/packages/admin-next/dashboard/src/components/common/date-range-display/date-range-display.tsx index 8243e41b54..738c9d9f5e 100644 --- a/packages/admin-next/dashboard/src/components/common/date-range-display/date-range-display.tsx +++ b/packages/admin-next/dashboard/src/components/common/date-range-display/date-range-display.tsx @@ -27,7 +27,7 @@ export const DateRangeDisplay = ({ {t("fields.startDate")} - + {startDate ? getFullDate({ date: startDate, @@ -44,7 +44,7 @@ export const DateRangeDisplay = ({ {t("fields.endDate")} - + {endDate ? getFullDate({ date: endDate, diff --git a/packages/admin-next/dashboard/src/components/common/form/form.tsx b/packages/admin-next/dashboard/src/components/common/form/form.tsx index 9799136d8f..877946d59f 100644 --- a/packages/admin-next/dashboard/src/components/common/form/form.tsx +++ b/packages/admin-next/dashboard/src/components/common/form/form.tsx @@ -78,6 +78,7 @@ const useFormField = () => { id, name: fieldContext.name, formItemId: `${id}-form-item`, + formLabelId: `${id}-form-item-label`, formDescriptionId: `${id}-form-item-description`, formErrorMessageId: `${id}-form-item-message`, ...fieldState, @@ -109,12 +110,13 @@ const Label = forwardRef< icon?: ReactNode } >(({ className, optional = false, tooltip, icon, ...props }, ref) => { - const { formItemId } = useFormField() + const { formLabelId, formItemId } = useFormField() const { t } = useTranslation() return (
, React.ComponentPropsWithoutRef >(({ ...props }, ref) => { - const { error, formItemId, formDescriptionId, formErrorMessageId } = - useFormField() + const { + error, + formItemId, + formDescriptionId, + formErrorMessageId, + formLabelId, + } = useFormField() return ( ) diff --git a/packages/admin-next/dashboard/src/components/localization/localized-date-picker/index.ts b/packages/admin-next/dashboard/src/components/localization/localized-date-picker/index.ts deleted file mode 100644 index 3b64d8f60f..0000000000 --- a/packages/admin-next/dashboard/src/components/localization/localized-date-picker/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./localized-date-picker" diff --git a/packages/admin-next/dashboard/src/components/localization/localized-date-picker/localized-date-picker.tsx b/packages/admin-next/dashboard/src/components/localization/localized-date-picker/localized-date-picker.tsx deleted file mode 100644 index b84f047a11..0000000000 --- a/packages/admin-next/dashboard/src/components/localization/localized-date-picker/localized-date-picker.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { DatePicker } from "@medusajs/ui" -import { ComponentPropsWithoutRef } from "react" -import { useTranslation } from "react-i18next" -import { languages } from "../../../i18n/languages" - -type LocalizedDatePickerProps = Omit< - ComponentPropsWithoutRef, - "translations" | "locale" -> - -export const LocalizedDatePicker = ({ - mode = "single", - ...props -}: LocalizedDatePickerProps) => { - const { i18n, t } = useTranslation() - - const locale = languages.find( - (lang) => lang.code === i18n.language - )?.date_locale - - const translations = { - cancel: t("actions.cancel"), - apply: t("general.apply"), - end: t("general.end"), - start: t("general.start"), - range: t("general.range"), - } - - return ( - - ) -} diff --git a/packages/admin-next/dashboard/src/components/modals/stacked-focus-modal/index.ts b/packages/admin-next/dashboard/src/components/modals/stacked-focus-modal/index.ts index e130e6356a..e1c5081749 100644 --- a/packages/admin-next/dashboard/src/components/modals/stacked-focus-modal/index.ts +++ b/packages/admin-next/dashboard/src/components/modals/stacked-focus-modal/index.ts @@ -1 +1 @@ -export * from "./stacked-foucs-modal" +export * from "./stacked-focus-modal" diff --git a/packages/admin-next/dashboard/src/components/modals/stacked-focus-modal/stacked-foucs-modal.tsx b/packages/admin-next/dashboard/src/components/modals/stacked-focus-modal/stacked-focus-modal.tsx similarity index 100% rename from packages/admin-next/dashboard/src/components/modals/stacked-focus-modal/stacked-foucs-modal.tsx rename to packages/admin-next/dashboard/src/components/modals/stacked-focus-modal/stacked-focus-modal.tsx diff --git a/packages/admin-next/dashboard/src/components/table/data-table/data-table-filter/date-filter.tsx b/packages/admin-next/dashboard/src/components/table/data-table/data-table-filter/date-filter.tsx index 255285ddff..5533633cea 100644 --- a/packages/admin-next/dashboard/src/components/table/data-table/data-table-filter/date-filter.tsx +++ b/packages/admin-next/dashboard/src/components/table/data-table/data-table-filter/date-filter.tsx @@ -65,10 +65,7 @@ export const DateFilter = ({ const customStartValue = getDateFromComparison(currentDateComparison, "$gte") const customEndValue = getDateFromComparison(currentDateComparison, "$lte") - const handleCustomDateChange = ( - value: Date | undefined, - pos: "start" | "end" - ) => { + const handleCustomDateChange = (value: Date | null, pos: "start" | "end") => { const key = pos === "start" ? "$gte" : "$lte" const dateValue = value ? value.toISOString() : undefined @@ -201,8 +198,7 @@ export const DateFilter = ({
handleCustomDateChange(d, "start")} /> @@ -216,8 +212,7 @@ export const DateFilter = ({
{ handleCustomDateChange(d, "end") diff --git a/packages/admin-next/dashboard/src/hooks/use-date.tsx b/packages/admin-next/dashboard/src/hooks/use-date.tsx index af8769f712..15e40541f5 100644 --- a/packages/admin-next/dashboard/src/hooks/use-date.tsx +++ b/packages/admin-next/dashboard/src/hooks/use-date.tsx @@ -4,6 +4,8 @@ import { useTranslation } from "react-i18next" import { languages } from "../i18n/languages" +// TODO: We rely on the current language to determine the date locale. This is not ideal, as we use en-US for the english translation. +// We either need to also have an en-GB translation or we need to separate the date locale from the translation language. export const useDate = () => { const { i18n } = useTranslation() diff --git a/packages/admin-next/dashboard/src/providers/i18n-provider/i18n-provider.tsx b/packages/admin-next/dashboard/src/providers/i18n-provider/i18n-provider.tsx new file mode 100644 index 0000000000..6da3118eb8 --- /dev/null +++ b/packages/admin-next/dashboard/src/providers/i18n-provider/i18n-provider.tsx @@ -0,0 +1,16 @@ +import { I18nProvider as Provider } from "@medusajs/ui" +import { PropsWithChildren } from "react" +import { useTranslation } from "react-i18next" +import { languages } from "../../i18n/languages" + +type I18nProviderProps = PropsWithChildren + +export const I18nProvider = ({ children }: I18nProviderProps) => { + const { i18n } = useTranslation() + + const locale = + languages.find((lan) => lan.code === i18n.language)?.code || + languages[0].code + + return {children} +} diff --git a/packages/admin-next/dashboard/src/providers/i18n-provider/index.ts b/packages/admin-next/dashboard/src/providers/i18n-provider/index.ts new file mode 100644 index 0000000000..ed399e5acf --- /dev/null +++ b/packages/admin-next/dashboard/src/providers/i18n-provider/index.ts @@ -0,0 +1 @@ +export * from "./i18n-provider" diff --git a/packages/admin-next/dashboard/src/routes/campaigns/campaign-edit/components/edit-campaign-form/edit-campaign-form.tsx b/packages/admin-next/dashboard/src/routes/campaigns/campaign-edit/components/edit-campaign-form/edit-campaign-form.tsx index 6482bd74b9..9eb49155b6 100644 --- a/packages/admin-next/dashboard/src/routes/campaigns/campaign-edit/components/edit-campaign-form/edit-campaign-form.tsx +++ b/packages/admin-next/dashboard/src/routes/campaigns/campaign-edit/components/edit-campaign-form/edit-campaign-form.tsx @@ -5,10 +5,7 @@ import { useForm } from "react-hook-form" import { useTranslation } from "react-i18next" import * as zod from "zod" import { Form } from "../../../../../components/common/form" -import { - RouteDrawer, - useRouteModal, -} from "../../../../../components/modals" +import { RouteDrawer, useRouteModal } from "../../../../../components/modals" import { useUpdateCampaign } from "../../../../../hooks/api/campaigns" type EditCampaignFormProps = { @@ -133,18 +130,16 @@ export const EditCampaignForm = ({ campaign }: EditCampaignFormProps) => { { + render={({ field }) => { return ( {t("campaigns.fields.start_date")} { - onChange(v ?? null) - }} + granularity="minute" + hourCycle={12} + shouldCloseOnSelect={false} {...field} /> @@ -158,16 +153,15 @@ export const EditCampaignForm = ({ campaign }: EditCampaignFormProps) => { { + render={({ field }) => { return ( {t("campaigns.fields.end_date")} onChange(v ?? null)} + granularity="minute" + shouldCloseOnSelect={false} {...field} /> diff --git a/packages/admin-next/dashboard/src/routes/campaigns/common/components/create-campaign-form-fields/create-campaign-form-fields.tsx b/packages/admin-next/dashboard/src/routes/campaigns/common/components/create-campaign-form-fields/create-campaign-form-fields.tsx index ceadd2b5a5..1403aa55ad 100644 --- a/packages/admin-next/dashboard/src/routes/campaigns/common/components/create-campaign-form-fields/create-campaign-form-fields.tsx +++ b/packages/admin-next/dashboard/src/routes/campaigns/common/components/create-campaign-form-fields/create-campaign-form-fields.tsx @@ -138,18 +138,15 @@ export const CreateCampaignFormFields = ({ form, fieldScope = "" }) => { { + render={({ field }) => { return ( {t("campaigns.fields.start_date")} { - onChange(v ?? null) - }} + granularity="minute" + shouldCloseOnSelect={false} {...field} /> @@ -163,16 +160,15 @@ export const CreateCampaignFormFields = ({ form, fieldScope = "" }) => { { + render={({ field }) => { return ( {t("campaigns.fields.end_date")} onChange(v ?? null)} + granularity="minute" + shouldCloseOnSelect={false} {...field} /> diff --git a/packages/admin-next/dashboard/src/routes/price-lists/price-list-configuration/components/price-list-configuration-form/price-list-configuration-form.tsx b/packages/admin-next/dashboard/src/routes/price-lists/price-list-configuration/components/price-list-configuration-form/price-list-configuration-form.tsx index f26d34a69f..1ef624c33b 100644 --- a/packages/admin-next/dashboard/src/routes/price-lists/price-list-configuration/components/price-list-configuration-form/price-list-configuration-form.tsx +++ b/packages/admin-next/dashboard/src/routes/price-lists/price-list-configuration/components/price-list-configuration-form/price-list-configuration-form.tsx @@ -41,7 +41,6 @@ const PriceListConfigurationSchema = z.object({ const STACKED_MODAL_ID = "cg" -// TODO: Fix DatePickers once new version is merged. export const PriceListConfigurationForm = ({ priceList, customerGroups, @@ -122,7 +121,7 @@ export const PriceListConfigurationForm = ({ { + render={({ field }) => { return (
@@ -135,12 +134,10 @@ export const PriceListConfigurationForm = ({
- {/* TODO: Add timepicker see CORE-2382 */} onChange(value ?? null)} - value={value ?? undefined} />
@@ -153,7 +150,7 @@ export const PriceListConfigurationForm = ({ { + render={({ field }) => { return (
@@ -167,10 +164,9 @@ export const PriceListConfigurationForm = ({
onChange(value ?? null)} - value={value ?? undefined} /> diff --git a/packages/admin-next/dashboard/src/routes/price-lists/price-list-create/components/price-list-create-form/price-list-create-form.tsx b/packages/admin-next/dashboard/src/routes/price-lists/price-list-create/components/price-list-create-form/price-list-create-form.tsx index 2476028c72..82abdb79aa 100644 --- a/packages/admin-next/dashboard/src/routes/price-lists/price-list-create/components/price-list-create-form/price-list-create-form.tsx +++ b/packages/admin-next/dashboard/src/routes/price-lists/price-list-create/components/price-list-create-form/price-list-create-form.tsx @@ -46,7 +46,6 @@ type PriceListCreateFormProps = { currencies: HttpTypes.AdminStoreCurrency[] } -// TODO: Fix DatePickers once new version is merged. export const PriceListCreateForm = ({ regions, currencies, diff --git a/packages/admin-next/dashboard/src/routes/price-lists/price-list-create/components/price-list-create-form/price-list-details-form.tsx b/packages/admin-next/dashboard/src/routes/price-lists/price-list-create/components/price-list-create-form/price-list-details-form.tsx index 63631690de..17c9ec3d41 100644 --- a/packages/admin-next/dashboard/src/routes/price-lists/price-list-create/components/price-list-create-form/price-list-details-form.tsx +++ b/packages/admin-next/dashboard/src/routes/price-lists/price-list-create/components/price-list-create-form/price-list-details-form.tsx @@ -173,7 +173,7 @@ export const PriceListDetailsForm = ({ form }: PriceListDetailsFormProps) => { { + render={({ field }) => { return (
@@ -186,11 +186,10 @@ export const PriceListDetailsForm = ({ form }: PriceListDetailsFormProps) => {
- {/* TODO: Add timepicker see CORE-2382 */} @@ -203,7 +202,7 @@ export const PriceListDetailsForm = ({ form }: PriceListDetailsFormProps) => { { + render={({ field }) => { return (
@@ -215,9 +214,9 @@ export const PriceListDetailsForm = ({ form }: PriceListDetailsFormProps) => {
diff --git a/packages/admin-next/dashboard/src/routes/price-lists/price-list-detail/price-list-detail.tsx b/packages/admin-next/dashboard/src/routes/price-lists/price-list-detail/price-list-detail.tsx index af0ae3a37e..d6e4a0da91 100644 --- a/packages/admin-next/dashboard/src/routes/price-lists/price-list-detail/price-list-detail.tsx +++ b/packages/admin-next/dashboard/src/routes/price-lists/price-list-detail/price-list-detail.tsx @@ -34,7 +34,7 @@ export const PriceListDetails = () => { ) })}
-
+
{after.widgets.map((w, i) => { @@ -48,7 +48,7 @@ export const PriceListDetails = () => {
-
+
{sideBefore.widgets.map((w, i) => { return (
diff --git a/packages/design-system/ui/package.json b/packages/design-system/ui/package.json index fb7f3c0897..208818c76b 100644 --- a/packages/design-system/ui/package.json +++ b/packages/design-system/ui/package.json @@ -81,34 +81,35 @@ }, "dependencies": { "@medusajs/icons": "^1.2.1", - "@radix-ui/react-accordion": "^1.1.2", - "@radix-ui/react-alert-dialog": "1.0.4", - "@radix-ui/react-avatar": "^1.0.3", - "@radix-ui/react-checkbox": "^1.0.4", - "@radix-ui/react-dialog": "1.0.4", - "@radix-ui/react-dropdown-menu": "^2.0.5", - "@radix-ui/react-label": "^2.0.2", - "@radix-ui/react-popover": "^1.0.6", - "@radix-ui/react-portal": "^1.0.3", - "@radix-ui/react-radio-group": "^1.1.3", - "@radix-ui/react-scroll-area": "^1.0.4", - "@radix-ui/react-select": "^2.0.0", - "@radix-ui/react-slot": "^1.0.2", - "@radix-ui/react-switch": "^1.0.3", - "@radix-ui/react-tabs": "^1.0.4", - "@radix-ui/react-tooltip": "^1.0.6", - "@react-aria/datepicker": "^3.5.0", - "@react-stately/datepicker": "^3.5.0", + "@radix-ui/react-accordion": "1.2.0", + "@radix-ui/react-alert-dialog": "1.1.1", + "@radix-ui/react-avatar": "1.1.0", + "@radix-ui/react-checkbox": "1.1.1", + "@radix-ui/react-dialog": "1.1.1", + "@radix-ui/react-dropdown-menu": "2.1.1", + "@radix-ui/react-label": "2.1.0", + "@radix-ui/react-popover": "1.1.1", + "@radix-ui/react-portal": "1.1.1", + "@radix-ui/react-radio-group": "1.2.0", + "@radix-ui/react-scroll-area": "1.1.0", + "@radix-ui/react-select": "2.1.1", + "@radix-ui/react-slot": "1.1.0", + "@radix-ui/react-switch": "1.1.0", + "@radix-ui/react-tabs": "1.1.0", + "@radix-ui/react-tooltip": "1.1.2", "clsx": "^1.2.1", "copy-to-clipboard": "^3.3.3", "cva": "1.0.0-beta.1", "date-fns": "^2.30.0", "prism-react-renderer": "^2.0.6", "prismjs": "^1.29.0", + "react-aria": "^3.33.1", "react-currency-input-field": "^3.6.11", - "react-day-picker": "^8.8.0", + "react-stately": "^3.31.1", "sonner": "^1.4.41", - "tailwind-merge": "^2.2.1" + "tailwind-merge": "^2.2.1", + "upgrade": "^1.1.0", + "yarn": "^1.22.22" }, "peerDependencies": { "react": "^18.0.0", diff --git a/packages/design-system/ui/src/components/calendar/calendar.stories.tsx b/packages/design-system/ui/src/components/calendar/calendar.stories.tsx deleted file mode 100644 index ed24ea624d..0000000000 --- a/packages/design-system/ui/src/components/calendar/calendar.stories.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import type { Meta, StoryObj } from "@storybook/react" -import * as React from "react" - -import { Text } from "@/components/text" -import { DateRange } from "react-day-picker" -import { Calendar } from "./calendar" - -const Demo = ({ mode, ...args }: Parameters[0]) => { - const [date, setDate] = React.useState(new Date()) - const [dateRange, setDateRange] = React.useState( - undefined - ) - - return ( -
- - - {mode === "single" && ( - - Selected Date: {date ? date.toDateString() : "None"} - - )} - {mode === "range" && ( - - Selected Range:{" "} - {dateRange - ? `${dateRange.from?.toDateString()} – ${ - dateRange.to?.toDateString() ?? "" - }` - : "None"} - - )} -
- ) -} - -const meta: Meta = { - title: "Components/Calendar", - component: Calendar, - render: Demo, - parameters: { - layout: "centered", - }, -} - -export default meta - -type Story = StoryObj - -export const Single: Story = { - args: { - mode: "single", - }, -} - -export const TwoMonthSingle: Story = { - args: { - mode: "single", - numberOfMonths: 2, - }, -} - -export const Range: Story = { - args: { - mode: "range", - }, -} - -export const TwoMonthRange: Story = { - args: { - mode: "range", - numberOfMonths: 2, - }, -} diff --git a/packages/design-system/ui/src/components/calendar/calendar.tsx b/packages/design-system/ui/src/components/calendar/calendar.tsx deleted file mode 100644 index 7a8364635a..0000000000 --- a/packages/design-system/ui/src/components/calendar/calendar.tsx +++ /dev/null @@ -1,174 +0,0 @@ -"use client" - -import { TriangleLeftMini, TriangleRightMini } from "@medusajs/icons" -import * as React from "react" -import { - DayPicker, - useDayRender, - type DayPickerRangeProps, - type DayPickerSingleProps, - type DayProps, -} from "react-day-picker" - -import { clx } from "@/utils/clx" -import { iconButtonVariants } from "../icon-button" - -type OmitKeys = { - [P in keyof T as P extends K ? never : P]: T[P] -} - -type KeysToOmit = "showWeekNumber" | "captionLayout" | "mode" - -type SingleProps = OmitKeys -type RangeProps = OmitKeys - -/** - * @interface - */ -type CalendarProps = - | ({ - mode: "single" - } & SingleProps) - | ({ - mode?: undefined - } & SingleProps) - | ({ - mode: "range" - } & RangeProps) - -/** - * This component is based on the [react-date-picker](https://www.npmjs.com/package/react-date-picker) package. - * - * @excludeExternal - */ -const Calendar = ({ - /** - * @ignore - */ - className, - /** - * @ignore - */ - classNames, - /** - * The calendar's mode. - */ - mode = "single", - /** - * Whether to show days of previous and next months. - * - * @keep - */ - showOutsideDays = true, - /** - * The locale to use for formatting dates. To change the locale pass a date-fns locale object. - * - * @keep - */ - locale, - ...props -}: CalendarProps) => { - return ( - , - IconRight: () => , - Day: Day, - }} - {...(props as SingleProps & RangeProps)} - /> - ) -} -Calendar.displayName = "Calendar" - -const Day = ({ date, displayMonth }: DayProps) => { - const ref = React.useRef(null) - const { activeModifiers, buttonProps, divProps, isButton, isHidden } = - useDayRender(date, displayMonth, ref) - - const { selected, today, disabled, range_middle } = activeModifiers - - React.useEffect(() => { - if (selected) { - ref.current?.focus() - } - }, [selected]) - - if (isHidden) { - return <> - } - - if (!isButton) { - return ( -
- ) - } - - const { - children: buttonChildren, - className: buttonClassName, - ...buttonPropsRest - } = buttonProps - - return ( - - ) -} - -export { Calendar } diff --git a/packages/design-system/ui/src/components/calendar/index.ts b/packages/design-system/ui/src/components/calendar/index.ts deleted file mode 100644 index 33dfcd855d..0000000000 --- a/packages/design-system/ui/src/components/calendar/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./calendar" diff --git a/packages/design-system/ui/src/components/calender/_internal-calendar.tsx b/packages/design-system/ui/src/components/calender/_internal-calendar.tsx new file mode 100644 index 0000000000..230190b3c8 --- /dev/null +++ b/packages/design-system/ui/src/components/calender/_internal-calendar.tsx @@ -0,0 +1,53 @@ +"use client" + +import { createCalendar } from "@internationalized/date" +import { TriangleLeftMini, TriangleRightMini } from "@medusajs/icons" +import * as React from "react" +import { + DateValue, + useCalendar, + useLocale, + type CalendarProps, +} from "react-aria" +import { useCalendarState } from "react-stately" + +import { CalendarButton } from "./calendar-button" +import { CalendarGrid } from "./calendar-grid" + +/** + * InternalCalendar is the internal implementation of the Calendar component. + * It's not for public use, but only used for other components like DatePicker. + */ +const InternalCalendar = ( + props: CalendarProps +) => { + const { locale } = useLocale() + + const state = useCalendarState({ + ...props, + locale, + createCalendar, + }) + + const { calendarProps, prevButtonProps, nextButtonProps, title } = + useCalendar(props, state) + + return ( +
+
+ + + +
+

{title}

+
+ + + +
+ +
+ ) +} + +export { InternalCalendar } diff --git a/packages/design-system/ui/src/components/calender/calendar-button.tsx b/packages/design-system/ui/src/components/calender/calendar-button.tsx new file mode 100644 index 0000000000..e6575475fe --- /dev/null +++ b/packages/design-system/ui/src/components/calender/calendar-button.tsx @@ -0,0 +1,29 @@ +import * as React from "react" +import { AriaButtonProps, useButton } from "react-aria" + +import { IconButton } from "@/components/icon-button" + +interface CalendarButtonProps extends AriaButtonProps<"button"> {} + +const CalendarButton = React.forwardRef( + ({ children, ...props }, ref) => { + const innerRef = React.useRef(null) + React.useImperativeHandle(ref, () => innerRef.current as HTMLButtonElement) + + const { buttonProps } = useButton(props, innerRef) + + return ( + + {children} + + ) + } +) +CalendarButton.displayName = "CalendarButton" + +export { CalendarButton } diff --git a/packages/design-system/ui/src/components/calender/calendar-cell.tsx b/packages/design-system/ui/src/components/calender/calendar-cell.tsx new file mode 100644 index 0000000000..31a83006e5 --- /dev/null +++ b/packages/design-system/ui/src/components/calender/calendar-cell.tsx @@ -0,0 +1,75 @@ +"use client" + +import { CalendarDate } from "@internationalized/date" +import * as React from "react" +import { useCalendarCell } from "react-aria" +import { CalendarState } from "react-stately" + +import { clx } from "@/utils/clx" + +interface CalendarCellProps { + date: CalendarDate + state: CalendarState +} + +const CalendarCell = ({ state, date }: CalendarCellProps) => { + const ref = React.useRef(null) + const { + cellProps, + buttonProps, + isSelected, + isOutsideVisibleRange, + isDisabled, + isUnavailable, + formattedDate, + } = useCalendarCell({ date }, state, ref) + + const isToday = getIsToday(date) + + return ( + +