feat(date-picker): enhance DatePicker component with new features and styling updates
- Added a portal option for rendering the calendar in a portal, improving usability in modals and overflow containers. - Introduced new utility functions for converting form values to picker values, enhancing date handling for single and multiple selections. - Refactored DatePickerRHFInput to utilize memoization for performance optimization and improved value management. - Updated CSS styles for the date picker to ensure better visibility and interaction in both light and dark modes.
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import { CalendarIcon } from "@/assets/icons";
|
import { CalendarIcon } from "@/assets/icons";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
import { useMemo } from "react";
|
||||||
import {
|
import {
|
||||||
Control,
|
Control,
|
||||||
Controller,
|
Controller,
|
||||||
@@ -25,12 +26,187 @@ interface IProps<T extends FieldValues> {
|
|||||||
maxDate?: number;
|
maxDate?: number;
|
||||||
timePicker?: boolean;
|
timePicker?: boolean;
|
||||||
clearable?: boolean;
|
clearable?: boolean;
|
||||||
|
/** Renders the calendar in a portal (recommended inside modals / overflow containers). */
|
||||||
|
portal?: boolean;
|
||||||
rules?: Omit<
|
rules?: Omit<
|
||||||
RegisterOptions<T, Path<T>>,
|
RegisterOptions<T, Path<T>>,
|
||||||
"valueAsNumber" | "valueAsDate" | "setValueAs" | "disabled"
|
"valueAsNumber" | "valueAsDate" | "setValueAs" | "disabled"
|
||||||
>;
|
>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const toUnixSeconds = (v: unknown): number | null => {
|
||||||
|
if (v === "" || v === undefined || v === null) return null;
|
||||||
|
const n = typeof v === "number" ? v : Number(v);
|
||||||
|
return Number.isFinite(n) ? n : null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const convertFormValueToPickerValue = (
|
||||||
|
value: unknown,
|
||||||
|
range: boolean,
|
||||||
|
multiple: boolean,
|
||||||
|
): DateObject | DateObject[] | undefined => {
|
||||||
|
if (value === "" || value === undefined || value === null) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (multiple && Array.isArray(value)) {
|
||||||
|
const secs = value
|
||||||
|
.map(toUnixSeconds)
|
||||||
|
.filter((s): s is number => s !== null);
|
||||||
|
if (!secs.length) return undefined;
|
||||||
|
return secs.map((unix) => new DateObject(new Date(unix * 1000)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (range && Array.isArray(value)) {
|
||||||
|
const secs = value
|
||||||
|
.map(toUnixSeconds)
|
||||||
|
.filter((s): s is number => s !== null);
|
||||||
|
if (!secs.length) return undefined;
|
||||||
|
return secs.map((unix) => new DateObject(new Date(unix * 1000)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (range && !Array.isArray(value)) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const unix = toUnixSeconds(value);
|
||||||
|
if (unix === null) return undefined;
|
||||||
|
return new DateObject(new Date(unix * 1000));
|
||||||
|
};
|
||||||
|
|
||||||
|
type PickerInputProps<T extends FieldValues> = {
|
||||||
|
name: Path<T>;
|
||||||
|
value: unknown;
|
||||||
|
onChange: (...event: unknown[]) => void;
|
||||||
|
error?: { message?: string };
|
||||||
|
range: boolean;
|
||||||
|
multiple: boolean;
|
||||||
|
onlyMonthPicker: boolean;
|
||||||
|
onlyYearPicker: boolean;
|
||||||
|
minDate?: number;
|
||||||
|
maxDate?: number;
|
||||||
|
timePicker: boolean;
|
||||||
|
clearable: boolean;
|
||||||
|
portal: boolean;
|
||||||
|
placeholder?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DatePickerRHFInput = <T extends FieldValues>({
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
onChange,
|
||||||
|
error,
|
||||||
|
range,
|
||||||
|
multiple,
|
||||||
|
onlyMonthPicker,
|
||||||
|
onlyYearPicker,
|
||||||
|
minDate,
|
||||||
|
maxDate,
|
||||||
|
timePicker,
|
||||||
|
clearable,
|
||||||
|
portal,
|
||||||
|
placeholder,
|
||||||
|
}: PickerInputProps<T>) => {
|
||||||
|
const valueFingerprint = useMemo(
|
||||||
|
() =>
|
||||||
|
JSON.stringify({
|
||||||
|
value,
|
||||||
|
range,
|
||||||
|
multiple,
|
||||||
|
}),
|
||||||
|
[value, range, multiple],
|
||||||
|
);
|
||||||
|
|
||||||
|
const pickerValue = useMemo(
|
||||||
|
() => convertFormValueToPickerValue(value, range, multiple),
|
||||||
|
[valueFingerprint, range, multiple],
|
||||||
|
);
|
||||||
|
|
||||||
|
const hasValue =
|
||||||
|
pickerValue !== undefined &&
|
||||||
|
(Array.isArray(pickerValue) ? pickerValue.length > 0 : true);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="relative">
|
||||||
|
<MultiDatePicker
|
||||||
|
range={range}
|
||||||
|
minDate={minDate}
|
||||||
|
maxDate={maxDate}
|
||||||
|
onlyMonthPicker={onlyMonthPicker}
|
||||||
|
plugins={
|
||||||
|
timePicker ? [<TimePicker key={String(name)} position="bottom" />] : []
|
||||||
|
}
|
||||||
|
onlyYearPicker={onlyYearPicker}
|
||||||
|
multiple={multiple}
|
||||||
|
{...(portal ? { portal: true } : {})}
|
||||||
|
value={pickerValue}
|
||||||
|
onChange={(date: DateObject | DateObject[] | null) => {
|
||||||
|
if (!date) {
|
||||||
|
onChange("");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(date)) {
|
||||||
|
const unixTimestamps = date.map((d) => d.toUnix());
|
||||||
|
onChange(unixTimestamps);
|
||||||
|
} else if (date instanceof DateObject) {
|
||||||
|
onChange(date.isValid ? date.toUnix() : "");
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
format={`YYYY/MM/DD ${timePicker ? "HH:mm" : ""}`}
|
||||||
|
containerClassName="w-full"
|
||||||
|
inputClass={cn(
|
||||||
|
"w-full rounded-xl border border-stroke/70 bg-white/90 px-5.5 py-3 pl-12.5 text-dark shadow-[0_1px_2px_rgba(16,24,40,0.04),0_8px_20px_rgba(16,24,40,0.04)] outline-none backdrop-blur-[1px] transition-all duration-200 focus:border-primary/70 focus:bg-white focus:shadow-[0_0_0_2px_rgba(59,130,246,0.14),0_10px_24px_rgba(59,130,246,0.08)] disabled:cursor-default disabled:bg-gray-2/70 dark:border-dark-3/80 dark:bg-dark-2/85 dark:text-white dark:focus:border-primary/80 dark:focus:shadow-[0_0_0_2px_rgba(59,130,246,0.2),0_10px_24px_rgba(15,23,42,0.45)] dark:disabled:bg-dark",
|
||||||
|
clearable && hasValue && "pr-11",
|
||||||
|
error &&
|
||||||
|
"border-red/80 focus:border-red focus:shadow-[0_0_0_2px_rgba(239,68,68,0.16),0_10px_24px_rgba(239,68,68,0.1)] dark:border-red/80 dark:focus:shadow-[0_0_0_2px_rgba(239,68,68,0.24),0_10px_24px_rgba(127,29,29,0.45)]",
|
||||||
|
)}
|
||||||
|
placeholder={placeholder}
|
||||||
|
/>
|
||||||
|
<span className="pointer-events-none absolute left-4.5 top-1/2 -translate-y-1/2 text-dark-5 transition-colors dark:text-dark-6">
|
||||||
|
<CalendarIcon />
|
||||||
|
</span>
|
||||||
|
{clearable && hasValue && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
aria-label="Clear date"
|
||||||
|
className="absolute right-3 top-1/2 z-10 -translate-y-1/2 rounded-md p-1 text-dark-5 transition hover:bg-gray-2 hover:text-dark dark:text-dark-6 dark:hover:bg-dark-3 dark:hover:text-white"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
onChange("");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
aria-hidden
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M12 4L4 12M4 4L12 12"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="2"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{error && (
|
||||||
|
<p className="mt-1.5 text-sm font-medium text-error">
|
||||||
|
{error.message as string}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const DatePicker = <T extends FieldValues>({
|
const DatePicker = <T extends FieldValues>({
|
||||||
control,
|
control,
|
||||||
name,
|
name,
|
||||||
@@ -46,11 +222,12 @@ const DatePicker = <T extends FieldValues>({
|
|||||||
maxDate,
|
maxDate,
|
||||||
minDate,
|
minDate,
|
||||||
clearable = false,
|
clearable = false,
|
||||||
|
portal = false,
|
||||||
}: IProps<T>) => {
|
}: IProps<T>) => {
|
||||||
return (
|
return (
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<label
|
<label
|
||||||
htmlFor={name}
|
htmlFor={String(name)}
|
||||||
className="block text-body-sm font-semibold capitalize tracking-[0.01em] text-dark dark:text-white"
|
className="block text-body-sm font-semibold capitalize tracking-[0.01em] text-dark dark:text-white"
|
||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
@@ -62,137 +239,24 @@ const DatePicker = <T extends FieldValues>({
|
|||||||
control={control}
|
control={control}
|
||||||
name={name}
|
name={name}
|
||||||
rules={rules}
|
rules={rules}
|
||||||
render={({
|
render={({ field: { onChange, name: fieldName, value }, formState: { errors } }) => (
|
||||||
field: { onChange, name, value },
|
<DatePickerRHFInput<T>
|
||||||
formState: { errors },
|
name={fieldName}
|
||||||
}) => {
|
value={value}
|
||||||
const error = errors[name];
|
onChange={onChange}
|
||||||
|
error={errors[fieldName] as { message?: string } | undefined}
|
||||||
const toUnixSeconds = (v: unknown): number | null => {
|
range={range}
|
||||||
if (v === "" || v === undefined || v === null) return null;
|
multiple={multiple}
|
||||||
const n = typeof v === "number" ? v : Number(v);
|
onlyMonthPicker={onlyMonthPicker}
|
||||||
return Number.isFinite(n) ? n : null;
|
onlyYearPicker={onlyYearPicker}
|
||||||
};
|
minDate={minDate}
|
||||||
|
maxDate={maxDate}
|
||||||
const toPickerValue = ():
|
timePicker={timePicker}
|
||||||
| DateObject
|
clearable={clearable}
|
||||||
| DateObject[]
|
portal={portal}
|
||||||
| undefined => {
|
placeholder={placeholder}
|
||||||
if (value === "" || value === undefined || value === null) {
|
/>
|
||||||
return undefined;
|
)}
|
||||||
}
|
|
||||||
|
|
||||||
if (multiple && Array.isArray(value)) {
|
|
||||||
const secs = value
|
|
||||||
.map(toUnixSeconds)
|
|
||||||
.filter((s): s is number => s !== null);
|
|
||||||
if (!secs.length) return undefined;
|
|
||||||
return secs.map((unix) => new DateObject(new Date(unix * 1000)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (range && Array.isArray(value)) {
|
|
||||||
const secs = value
|
|
||||||
.map(toUnixSeconds)
|
|
||||||
.filter((s): s is number => s !== null);
|
|
||||||
if (!secs.length) return undefined;
|
|
||||||
return secs.map((unix) => new DateObject(new Date(unix * 1000)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (range && !Array.isArray(value)) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
const unix = toUnixSeconds(value);
|
|
||||||
if (unix === null) return undefined;
|
|
||||||
return new DateObject(new Date(unix * 1000));
|
|
||||||
};
|
|
||||||
|
|
||||||
const pickerValue = toPickerValue();
|
|
||||||
const hasValue =
|
|
||||||
pickerValue !== undefined &&
|
|
||||||
(Array.isArray(pickerValue) ? pickerValue.length > 0 : true);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className="relative">
|
|
||||||
<MultiDatePicker
|
|
||||||
range={range}
|
|
||||||
minDate={minDate}
|
|
||||||
maxDate={maxDate}
|
|
||||||
onlyMonthPicker={onlyMonthPicker}
|
|
||||||
plugins={
|
|
||||||
timePicker
|
|
||||||
? [<TimePicker key={name} position="bottom" />]
|
|
||||||
: []
|
|
||||||
}
|
|
||||||
onlyYearPicker={onlyYearPicker}
|
|
||||||
multiple={multiple}
|
|
||||||
value={pickerValue}
|
|
||||||
onChange={(date: DateObject | DateObject[] | null) => {
|
|
||||||
if (!date) {
|
|
||||||
onChange("");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Array.isArray(date)) {
|
|
||||||
const unixTimestamps = date.map((d) => d.toUnix());
|
|
||||||
onChange(unixTimestamps);
|
|
||||||
} else if (date instanceof DateObject) {
|
|
||||||
onChange(date.isValid ? date.toUnix() : "");
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
format={`YYYY/MM/DD ${timePicker ? "HH:mm" : ""}`}
|
|
||||||
containerClassName="w-full"
|
|
||||||
inputClass={cn(
|
|
||||||
"w-full rounded-xl border border-stroke/70 bg-white/90 px-5.5 py-3 pl-12.5 text-dark shadow-[0_1px_2px_rgba(16,24,40,0.04),0_8px_20px_rgba(16,24,40,0.04)] outline-none backdrop-blur-[1px] transition-all duration-200 focus:border-primary/70 focus:bg-white focus:shadow-[0_0_0_2px_rgba(59,130,246,0.14),0_10px_24px_rgba(59,130,246,0.08)] disabled:cursor-default disabled:bg-gray-2/70 dark:border-dark-3/80 dark:bg-dark-2/85 dark:text-white dark:focus:border-primary/80 dark:focus:shadow-[0_0_0_2px_rgba(59,130,246,0.2),0_10px_24px_rgba(15,23,42,0.45)] dark:disabled:bg-dark",
|
|
||||||
clearable && hasValue && "pr-11",
|
|
||||||
error &&
|
|
||||||
"border-red/80 focus:border-red focus:shadow-[0_0_0_2px_rgba(239,68,68,0.16),0_10px_24px_rgba(239,68,68,0.1)] dark:border-red/80 dark:focus:shadow-[0_0_0_2px_rgba(239,68,68,0.24),0_10px_24px_rgba(127,29,29,0.45)]",
|
|
||||||
)}
|
|
||||||
placeholder={placeholder}
|
|
||||||
/>
|
|
||||||
<span className="pointer-events-none absolute left-4.5 top-1/2 -translate-y-1/2 text-dark-5 transition-colors dark:text-dark-6">
|
|
||||||
<CalendarIcon />
|
|
||||||
</span>
|
|
||||||
{clearable && hasValue && (
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
aria-label="Clear date"
|
|
||||||
className="absolute right-3 top-1/2 z-10 -translate-y-1/2 rounded-md p-1 text-dark-5 transition hover:bg-gray-2 hover:text-dark dark:text-dark-6 dark:hover:bg-dark-3 dark:hover:text-white"
|
|
||||||
onClick={(e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
onChange("");
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
width="16"
|
|
||||||
height="16"
|
|
||||||
viewBox="0 0 16 16"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
aria-hidden
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M12 4L4 12M4 4L12 12"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeWidth="2"
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{error && (
|
|
||||||
<p className="mt-1.5 text-sm font-medium text-error">
|
|
||||||
{error.message as string}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+33
-18
@@ -47,7 +47,7 @@
|
|||||||
/* third-party libraries CSS */
|
/* third-party libraries CSS */
|
||||||
|
|
||||||
.rmdp-wrapper {
|
.rmdp-wrapper {
|
||||||
@apply !overflow-hidden !rounded-2xl !border !border-stroke/60 !bg-white/95 !shadow-[0_10px_30px_rgba(16,24,40,0.12)] dark:!border-dark-3/80 dark:!bg-dark-2/95 dark:!shadow-[0_20px_40px_rgba(2,6,23,0.55)];
|
@apply !overflow-visible !rounded-2xl !border !border-stroke/60 !bg-white/95 !shadow-[0_10px_30px_rgba(16,24,40,0.12)] dark:!border-dark-3/80 dark:!bg-dark-2/95 dark:!shadow-[0_20px_40px_rgba(2,6,23,0.55)];
|
||||||
}
|
}
|
||||||
|
|
||||||
.rmdp-calendar {
|
.rmdp-calendar {
|
||||||
@@ -63,11 +63,11 @@
|
|||||||
.rmdp-time-picker div input {
|
.rmdp-time-picker div input {
|
||||||
@apply !rounded-lg !border !border-stroke/70 !bg-white !text-dark !shadow-sm focus:!border-primary/70 dark:!border-dark-3/80 dark:!bg-dark-2 dark:!text-gray-5;
|
@apply !rounded-lg !border !border-stroke/70 !bg-white !text-dark !shadow-sm focus:!border-primary/70 dark:!border-dark-3/80 dark:!bg-dark-2 dark:!text-gray-5;
|
||||||
}
|
}
|
||||||
.rmdp-month-picker {
|
/* Month/year panels sit on top of the day grid (absolute inset). They must stay
|
||||||
@apply dark:!bg-transparent;
|
opaque in dark mode — transparent lets the day cells show through underneath. */
|
||||||
}
|
.rmdp-month-picker,
|
||||||
.rmdp-year-picker {
|
.rmdp-year-picker {
|
||||||
@apply dark:!bg-transparent;
|
@apply !z-[2] !rounded-xl !bg-white/95 dark:!bg-dark-2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rmdp-header-values,
|
.rmdp-header-values,
|
||||||
@@ -91,19 +91,21 @@
|
|||||||
@apply !rounded-lg transition-colors duration-200 hover:!bg-gray-2 dark:hover:!bg-dark-3;
|
@apply !rounded-lg transition-colors duration-200 hover:!bg-gray-2 dark:hover:!bg-dark-3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rmdp-day {
|
/* Day grid only — month/year pickers reuse .rmdp-day inside .rmdp-ym; fixed w/h
|
||||||
|
here would clip long month names (e.g. "February"). */
|
||||||
|
.rmdp-day-picker .rmdp-day {
|
||||||
@apply !m-0 !p-0 dark:!text-dark-6;
|
@apply !m-0 !p-0 dark:!text-dark-6;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rmdp-day span {
|
.rmdp-day-picker .rmdp-day span {
|
||||||
@apply !h-8 !w-8 !rounded-lg !font-medium;
|
@apply !h-8 !w-8 !rounded-lg !font-medium;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rmdp-day:not(.rmdp-disabled):not(.rmdp-day-hidden) span:hover {
|
.rmdp-day-picker .rmdp-day:not(.rmdp-disabled):not(.rmdp-day-hidden) span:hover {
|
||||||
@apply !border-primary/20 !bg-primary/10 !text-primary dark:!border-primary/30 dark:!bg-primary/20 dark:!text-white;
|
@apply !border-primary/20 !bg-primary/10 !text-primary dark:!border-primary/30 dark:!bg-primary/20 dark:!text-white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rmdp-day.rmdp-today span {
|
.rmdp-day-picker .rmdp-day.rmdp-today span {
|
||||||
@apply !border !border-primary/35 !bg-transparent !text-primary dark:!border-primary/45 dark:!bg-transparent dark:!text-primary;
|
@apply !border !border-primary/35 !bg-transparent !text-primary dark:!border-primary/45 dark:!bg-transparent dark:!text-primary;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,33 +114,46 @@
|
|||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rmdp-day.rmdp-range {
|
.rmdp-day-picker .rmdp-day.rmdp-range {
|
||||||
@apply !bg-transparent !shadow-none;
|
@apply !bg-transparent !shadow-none;
|
||||||
color: inherit !important;
|
color: inherit !important;
|
||||||
}
|
}
|
||||||
.rmdp-day.rmdp-range span {
|
.rmdp-day-picker .rmdp-day.rmdp-range span {
|
||||||
@apply !h-8 !w-full !rounded-none !border-transparent !bg-primary/10 !text-primary dark:!bg-primary/20 dark:!text-white;
|
@apply !h-8 !w-full !rounded-none !border-transparent !bg-primary/10 !text-primary dark:!bg-primary/20 dark:!text-white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rmdp-day.rmdp-range.start span,
|
.rmdp-day-picker .rmdp-day.rmdp-range.start span,
|
||||||
.rmdp-day.rmdp-range.end span {
|
.rmdp-day-picker .rmdp-day.rmdp-range.end span {
|
||||||
@apply !h-8 !w-full !border-primary !bg-primary !text-white;
|
@apply !h-8 !w-full !border-primary !bg-primary !text-white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rmdp-day.rmdp-range.start span {
|
.rmdp-day-picker .rmdp-day.rmdp-range.start span {
|
||||||
@apply !rounded-l-lg !rounded-r-none;
|
@apply !rounded-l-lg !rounded-r-none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rmdp-day.rmdp-range.end span {
|
.rmdp-day-picker .rmdp-day.rmdp-range.end span {
|
||||||
@apply !rounded-l-none !rounded-r-lg;
|
@apply !rounded-l-none !rounded-r-lg;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rmdp-day.rmdp-today.rmdp-range.start span,
|
.rmdp-day-picker .rmdp-day.rmdp-today.rmdp-range.start span,
|
||||||
.rmdp-day.rmdp-today.rmdp-range.end span,
|
.rmdp-day-picker .rmdp-day.rmdp-today.rmdp-range.end span,
|
||||||
.rmdp-day.rmdp-today.rmdp-selected span {
|
.rmdp-day-picker .rmdp-day.rmdp-today.rmdp-selected span {
|
||||||
@apply !border-primary !bg-primary !text-white;
|
@apply !border-primary !bg-primary !text-white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Month/year cells: center label; let highlight grow with text (library uses
|
||||||
|
position:absolute on .rmdp-day span — reset so flex + padding size the pill). */
|
||||||
|
.rmdp-month-picker .rmdp-ym .rmdp-day,
|
||||||
|
.rmdp-year-picker .rmdp-ym .rmdp-day {
|
||||||
|
/* Library defaults color:#000 on .rmdp-day — scope readable labels off the day grid */
|
||||||
|
@apply !relative !min-w-0 !text-dark/90 dark:!text-gray-5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rmdp-month-picker .rmdp-ym .rmdp-day span,
|
||||||
|
.rmdp-year-picker .rmdp-ym .rmdp-day span {
|
||||||
|
@apply !relative !inset-auto !inline-flex !h-auto !min-h-8 !w-auto !min-w-0 !max-w-none !items-center !justify-center !px-2 !py-1;
|
||||||
|
}
|
||||||
|
|
||||||
.rmdp-disabled {
|
.rmdp-disabled {
|
||||||
@apply !opacity-45;
|
@apply !opacity-45;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user