feat(dashboard,ui): DateFilter should open correctly (#9775)
This commit is contained in:
committed by
GitHub
parent
92bbd7953b
commit
59e6747800
6
.changeset/perfect-ravens-allow.md
Normal file
6
.changeset/perfect-ravens-allow.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@medusajs/dashboard": patch
|
||||
"@medusajs/ui": patch
|
||||
---
|
||||
|
||||
fix(dashboard,ui): DateFilter should remain open
|
||||
@@ -9,8 +9,8 @@ import { useTranslation } from "react-i18next"
|
||||
import { useDate } from "../../../../hooks/use-date"
|
||||
import { useSelectedParams } from "../hooks"
|
||||
import { useDataTableFilterContext } from "./context"
|
||||
import { IFilter } from "./types"
|
||||
import FilterChip from "./filter-chip"
|
||||
import { IFilter } from "./types"
|
||||
|
||||
type DateFilterProps = IFilter
|
||||
|
||||
@@ -97,7 +97,9 @@ export const DateFilter = ({
|
||||
|
||||
const displayValue = getDisplayValueFromPresets() || getCustomDisplayValue()
|
||||
|
||||
const [previousValue, setPreviousValue] = useState<string | undefined>(displayValue)
|
||||
const [previousValue, setPreviousValue] = useState<string | undefined>(
|
||||
displayValue
|
||||
)
|
||||
|
||||
const handleRemove = () => {
|
||||
selectedParams.delete()
|
||||
@@ -210,6 +212,7 @@ export const DateFilter = ({
|
||||
</div>
|
||||
<div className="px-2 py-1">
|
||||
<DatePicker
|
||||
modal
|
||||
maxValue={customEndValue}
|
||||
value={customStartValue}
|
||||
onChange={(d) => handleCustomDateChange(d, "start")}
|
||||
@@ -224,6 +227,7 @@ export const DateFilter = ({
|
||||
</div>
|
||||
<div className="px-2 py-1">
|
||||
<DatePicker
|
||||
modal
|
||||
minValue={customStartValue}
|
||||
value={customEndValue || undefined}
|
||||
onChange={(d) => {
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
"use client"
|
||||
|
||||
import { CalendarDate, CalendarDateTime, getLocalTimeZone } from "@internationalized/date"
|
||||
import {
|
||||
CalendarDate,
|
||||
CalendarDateTime,
|
||||
getLocalTimeZone,
|
||||
} from "@internationalized/date"
|
||||
import { CalendarMini, Clock, XMarkMini } from "@medusajs/icons"
|
||||
import { cva } from "cva"
|
||||
import * as React from "react"
|
||||
@@ -38,10 +42,14 @@ type DatePickerValueProps = {
|
||||
granularity?: Granularity
|
||||
size?: "base" | "small"
|
||||
className?: string
|
||||
modal?: boolean
|
||||
}
|
||||
|
||||
interface DatePickerProps
|
||||
extends Omit<BaseDatePickerProps<CalendarDateTime | CalendarDate>, keyof DatePickerValueProps>,
|
||||
extends Omit<
|
||||
BaseDatePickerProps<CalendarDateTime | CalendarDate>,
|
||||
keyof DatePickerValueProps
|
||||
>,
|
||||
DatePickerValueProps {}
|
||||
|
||||
const datePickerStyles = (
|
||||
@@ -72,103 +80,123 @@ const datePickerStyles = (
|
||||
},
|
||||
})
|
||||
|
||||
const HAS_TIME = new Set<Granularity>(["hour","minute", "second"])
|
||||
const HAS_TIME = new Set<Granularity>(["hour", "minute", "second"])
|
||||
|
||||
const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(({
|
||||
size = "base",
|
||||
shouldCloseOnSelect = true,
|
||||
className,
|
||||
...props
|
||||
}, ref) => {
|
||||
const [value, setValue] = React.useState<CalendarDateTime | CalendarDate | null | undefined>(
|
||||
getDefaultCalendarDateFromDate(props.value, props.defaultValue, props.granularity)
|
||||
)
|
||||
|
||||
const innerRef = React.useRef<HTMLDivElement>(null)
|
||||
React.useImperativeHandle(ref, () => innerRef.current as HTMLDivElement)
|
||||
|
||||
const contentRef = React.useRef<HTMLDivElement>(null)
|
||||
|
||||
const _props = convertProps(props, setValue)
|
||||
|
||||
const state = useDatePickerState({
|
||||
..._props,
|
||||
shouldCloseOnSelect,
|
||||
})
|
||||
|
||||
const { groupProps, fieldProps, buttonProps, dialogProps, calendarProps } =
|
||||
useDatePicker(_props, state, innerRef)
|
||||
|
||||
React.useEffect(() => {
|
||||
setValue(props.value ? updateCalendarDateFromDate(value, props.value, props.granularity) : null)
|
||||
state.setValue(props.value ? updateCalendarDateFromDate(value, props.value, props.granularity) : null)
|
||||
}, [props.value])
|
||||
|
||||
function clear(e: React.MouseEvent<HTMLButtonElement>) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
|
||||
props.onChange?.(null)
|
||||
state.setValue(null)
|
||||
}
|
||||
|
||||
useInteractOutside({
|
||||
ref: contentRef,
|
||||
onInteractOutside: () => {
|
||||
state.setOpen(false)
|
||||
const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>(
|
||||
(
|
||||
{
|
||||
size = "base",
|
||||
shouldCloseOnSelect = true,
|
||||
className,
|
||||
modal = false,
|
||||
...props
|
||||
},
|
||||
})
|
||||
ref
|
||||
) => {
|
||||
const [value, setValue] = React.useState<
|
||||
CalendarDateTime | CalendarDate | null | undefined
|
||||
>(
|
||||
getDefaultCalendarDateFromDate(
|
||||
props.value,
|
||||
props.defaultValue,
|
||||
props.granularity
|
||||
)
|
||||
)
|
||||
|
||||
const hasTime = props.granularity && HAS_TIME.has(props.granularity)
|
||||
const Icon = hasTime ? Clock : CalendarMini
|
||||
const innerRef = React.useRef<HTMLDivElement>(null)
|
||||
React.useImperativeHandle(ref, () => innerRef.current as HTMLDivElement)
|
||||
|
||||
return (
|
||||
<Popover open={state.isOpen} onOpenChange={state.setOpen}>
|
||||
<Popover.Anchor asChild>
|
||||
<div
|
||||
ref={ref}
|
||||
className={clx(
|
||||
datePickerStyles(
|
||||
state.isOpen,
|
||||
state.isInvalid,
|
||||
state.value
|
||||
)({ size }),
|
||||
className
|
||||
)}
|
||||
{...groupProps}
|
||||
>
|
||||
<DatePickerButton {...buttonProps} size={size}>
|
||||
<Icon />
|
||||
</DatePickerButton>
|
||||
<DatePickerField {...fieldProps} size={size} />
|
||||
{!!state.value && (
|
||||
<DatePickerClearButton onClick={clear}>
|
||||
<XMarkMini />
|
||||
</DatePickerClearButton>
|
||||
)}
|
||||
</div>
|
||||
</Popover.Anchor>
|
||||
<Popover.Content
|
||||
ref={contentRef}
|
||||
{...dialogProps}
|
||||
className="flex flex-col divide-y p-0"
|
||||
>
|
||||
<div className="p-3">
|
||||
<InternalCalendar autoFocus {...calendarProps} />
|
||||
</div>
|
||||
{state.hasTime && (
|
||||
<div className="p-3">
|
||||
<TimeInput
|
||||
value={state.timeValue}
|
||||
onChange={state.setTimeValue}
|
||||
hourCycle={props.hourCycle}
|
||||
/>
|
||||
const contentRef = React.useRef<HTMLDivElement>(null)
|
||||
|
||||
const _props = convertProps(props, setValue)
|
||||
|
||||
const state = useDatePickerState({
|
||||
..._props,
|
||||
shouldCloseOnSelect,
|
||||
})
|
||||
|
||||
const { groupProps, fieldProps, buttonProps, dialogProps, calendarProps } =
|
||||
useDatePicker(_props, state, innerRef)
|
||||
|
||||
React.useEffect(() => {
|
||||
setValue(
|
||||
props.value
|
||||
? updateCalendarDateFromDate(value, props.value, props.granularity)
|
||||
: null
|
||||
)
|
||||
state.setValue(
|
||||
props.value
|
||||
? updateCalendarDateFromDate(value, props.value, props.granularity)
|
||||
: null
|
||||
)
|
||||
}, [props.value])
|
||||
|
||||
function clear(e: React.MouseEvent<HTMLButtonElement>) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
|
||||
props.onChange?.(null)
|
||||
state.setValue(null)
|
||||
}
|
||||
|
||||
useInteractOutside({
|
||||
ref: contentRef,
|
||||
onInteractOutside: () => {
|
||||
state.setOpen(false)
|
||||
},
|
||||
})
|
||||
|
||||
const hasTime = props.granularity && HAS_TIME.has(props.granularity)
|
||||
const Icon = hasTime ? Clock : CalendarMini
|
||||
|
||||
return (
|
||||
<Popover modal={modal} open={state.isOpen} onOpenChange={state.setOpen}>
|
||||
<Popover.Anchor asChild>
|
||||
<div
|
||||
ref={ref}
|
||||
className={clx(
|
||||
datePickerStyles(
|
||||
state.isOpen,
|
||||
state.isInvalid,
|
||||
state.value
|
||||
)({ size }),
|
||||
className
|
||||
)}
|
||||
{...groupProps}
|
||||
>
|
||||
<DatePickerButton {...buttonProps} size={size}>
|
||||
<Icon />
|
||||
</DatePickerButton>
|
||||
<DatePickerField {...fieldProps} size={size} />
|
||||
{!!state.value && (
|
||||
<DatePickerClearButton onClick={clear}>
|
||||
<XMarkMini />
|
||||
</DatePickerClearButton>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</Popover.Content>
|
||||
</Popover>
|
||||
)
|
||||
})
|
||||
</Popover.Anchor>
|
||||
<Popover.Content
|
||||
ref={contentRef}
|
||||
{...dialogProps}
|
||||
className="flex flex-col divide-y p-0"
|
||||
>
|
||||
<div className="p-3">
|
||||
<InternalCalendar autoFocus {...calendarProps} />
|
||||
</div>
|
||||
{state.hasTime && (
|
||||
<div className="p-3">
|
||||
<TimeInput
|
||||
value={state.timeValue}
|
||||
onChange={state.setTimeValue}
|
||||
hourCycle={props.hourCycle}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</Popover.Content>
|
||||
</Popover>
|
||||
)
|
||||
}
|
||||
)
|
||||
DatePicker.displayName = "DatePicker"
|
||||
|
||||
function convertProps(
|
||||
@@ -200,10 +228,16 @@ function convertProps(
|
||||
|
||||
return {
|
||||
...rest,
|
||||
onChange: onChange as BaseDatePickerProps<CalendarDateTime | CalendarDate>["onChange"],
|
||||
onChange: onChange as BaseDatePickerProps<
|
||||
CalendarDateTime | CalendarDate
|
||||
>["onChange"],
|
||||
isDateUnavailable,
|
||||
minValue: minValue ? createCalendarDateFromDate(minValue, props.granularity) : minValue,
|
||||
maxValue: maxValue ? createCalendarDateFromDate(maxValue, props.granularity) : maxValue,
|
||||
minValue: minValue
|
||||
? createCalendarDateFromDate(minValue, props.granularity)
|
||||
: minValue,
|
||||
maxValue: maxValue
|
||||
? createCalendarDateFromDate(maxValue, props.granularity)
|
||||
: maxValue,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user