⚡️ feat: add onReset
prop
This commit is contained in:
parent
630af612a2
commit
e0c5895e9c
@ -19,6 +19,7 @@ import {
|
||||
|
||||
import './Calendar.css';
|
||||
import { format } from 'date-fns';
|
||||
import { cn } from 'utils/classnames';
|
||||
|
||||
type ValuePiece = Date | null;
|
||||
export type Value = ValuePiece | [ValuePiece, ValuePiece];
|
||||
@ -63,6 +64,11 @@ export interface CalendarProps extends CustomReactCalendarProps, CalendarTheme {
|
||||
* @returns None
|
||||
*/
|
||||
onCancel?: () => void;
|
||||
/**
|
||||
* Optional callback function that is called when a reset action is triggered.
|
||||
* @returns None
|
||||
*/
|
||||
onReset?: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -80,6 +86,7 @@ export const Calendar = ({
|
||||
actions,
|
||||
onSelect,
|
||||
onCancel,
|
||||
onReset,
|
||||
onChange: onChangeProp,
|
||||
...props
|
||||
}: CalendarProps): JSX.Element => {
|
||||
@ -217,6 +224,11 @@ export const Calendar = ({
|
||||
[setValue, setActiveDate, changeNavigationLabel, selectRange],
|
||||
);
|
||||
|
||||
const handleReset = useCallback(() => {
|
||||
setValue(null);
|
||||
onReset?.();
|
||||
}, [setValue, onReset]);
|
||||
|
||||
return (
|
||||
<div
|
||||
{...wrapperProps}
|
||||
@ -276,21 +288,30 @@ export const Calendar = ({
|
||||
{/* Footer or CTA */}
|
||||
<div
|
||||
{...footerProps}
|
||||
className={footer({ className: footerProps?.className })}
|
||||
className={cn(footer({ className: footerProps?.className }), {
|
||||
'justify-between': value,
|
||||
})}
|
||||
>
|
||||
{actions ? (
|
||||
actions
|
||||
) : (
|
||||
<>
|
||||
<Button variant="tertiary" onClick={onCancel}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
disabled={!value}
|
||||
onClick={() => (value ? onSelect?.(value) : null)}
|
||||
>
|
||||
Select
|
||||
</Button>
|
||||
{value && (
|
||||
<Button variant="danger" onClick={handleReset}>
|
||||
Reset
|
||||
</Button>
|
||||
)}
|
||||
<div className="space-x-3">
|
||||
<Button variant="tertiary" onClick={onCancel}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
disabled={!value}
|
||||
onClick={() => (value ? onSelect?.(value) : null)}
|
||||
>
|
||||
Select
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
@ -2,7 +2,7 @@ import { VariantProps, tv } from 'tailwind-variants';
|
||||
|
||||
export const datePickerTheme = tv({
|
||||
slots: {
|
||||
input: [],
|
||||
input: ['w-full'],
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import { Input, InputProps } from 'components/shared/Input';
|
||||
import * as Popover from '@radix-ui/react-popover';
|
||||
import { datePickerTheme } from './DatePicker.theme';
|
||||
@ -27,6 +27,10 @@ export interface DatePickerProps
|
||||
* Whether to allow the selection of a date range.
|
||||
*/
|
||||
selectRange?: boolean;
|
||||
/**
|
||||
* Optional callback function that is called when the date picker is reset.
|
||||
*/
|
||||
onReset?: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -39,6 +43,7 @@ export const DatePicker = ({
|
||||
calendarProps,
|
||||
value,
|
||||
onChange,
|
||||
onReset,
|
||||
selectRange = false,
|
||||
...props
|
||||
}: DatePickerProps) => {
|
||||
@ -50,16 +55,16 @@ export const DatePicker = ({
|
||||
* Renders the value of the date based on the current state of `props.value`.
|
||||
* @returns {string | undefined} - The formatted date value or `undefined` if `props.value` is falsy.
|
||||
*/
|
||||
const renderValue = useCallback(() => {
|
||||
if (!value) return undefined;
|
||||
const renderValue = useMemo(() => {
|
||||
if (!value) return '';
|
||||
if (Array.isArray(value)) {
|
||||
return value
|
||||
.map((date) => format(date as Date, 'dd/MM/yyyy'))
|
||||
.join(' - ');
|
||||
}
|
||||
return format(value, 'dd/MM/yyyy');
|
||||
}, [value]);
|
||||
|
||||
}, [value, onReset]);
|
||||
console.log(renderValue);
|
||||
/**
|
||||
* Handles the selection of a date from the calendar.
|
||||
*/
|
||||
@ -71,15 +76,20 @@ export const DatePicker = ({
|
||||
[setOpen, onChange],
|
||||
);
|
||||
|
||||
const handleReset = useCallback(() => {
|
||||
setOpen(false);
|
||||
onReset?.();
|
||||
}, [setOpen, onReset]);
|
||||
|
||||
return (
|
||||
<Popover.Root open={open}>
|
||||
<Popover.Trigger>
|
||||
<Popover.Trigger className="w-full">
|
||||
<Input
|
||||
{...props}
|
||||
rightIcon={<CalendarIcon onClick={() => setOpen(true)} />}
|
||||
readOnly
|
||||
placeholder="Select a date..."
|
||||
value={renderValue()}
|
||||
value={renderValue}
|
||||
className={input({ className })}
|
||||
onClick={() => setOpen(true)}
|
||||
/>
|
||||
@ -93,6 +103,7 @@ export const DatePicker = ({
|
||||
{...calendarProps}
|
||||
selectRange={selectRange}
|
||||
value={value}
|
||||
onReset={handleReset}
|
||||
onCancel={() => setOpen(false)}
|
||||
onSelect={handleSelect}
|
||||
/>
|
||||
|
@ -2,7 +2,7 @@ import { VariantProps, tv } from 'tailwind-variants';
|
||||
|
||||
export const selectTheme = tv({
|
||||
slots: {
|
||||
container: ['flex', 'flex-col', 'relative', 'gap-2'],
|
||||
container: ['flex', 'flex-col', 'relative', 'gap-2', 'w-full'],
|
||||
label: ['text-sm', 'text-elements-high-em'],
|
||||
description: ['text-xs', 'text-elements-low-em'],
|
||||
inputWrapper: [
|
||||
|
@ -3,7 +3,6 @@ import React, {
|
||||
useState,
|
||||
ComponentPropsWithoutRef,
|
||||
useMemo,
|
||||
useCallback,
|
||||
MouseEvent,
|
||||
useRef,
|
||||
useEffect,
|
||||
@ -12,7 +11,7 @@ import { useMultipleSelection, useCombobox } from 'downshift';
|
||||
import { SelectTheme, selectTheme } from './Select.theme';
|
||||
import {
|
||||
ChevronDownIcon,
|
||||
CrossIcon,
|
||||
CrossCircleIcon,
|
||||
WarningIcon,
|
||||
} from 'components/shared/CustomIcon';
|
||||
import { cloneIcon } from 'utils/cloneIcon';
|
||||
@ -270,11 +269,8 @@ export const Select = ({
|
||||
itemToString: (item) => (item && !multiple ? item.label : ''),
|
||||
});
|
||||
|
||||
const isSelected = useCallback(
|
||||
(item: SelectOption) =>
|
||||
multiple ? selectedItems.includes(item) : selectedItem === item,
|
||||
[selectedItems, selectedItem, multiple],
|
||||
);
|
||||
const isSelected = (item: SelectOption) =>
|
||||
multiple ? selectedItems.includes(item) : selectedItem === item;
|
||||
|
||||
const handleClear = (e: MouseEvent<SVGSVGElement, globalThis.MouseEvent>) => {
|
||||
e.stopPropagation();
|
||||
@ -306,7 +302,7 @@ export const Select = ({
|
||||
return (
|
||||
<div className={theme.iconContainer({ class: 'pr-4 right-0' })}>
|
||||
{clearable && (selectedItems.length > 0 || selectedItem) && (
|
||||
<CrossIcon
|
||||
<CrossCircleIcon
|
||||
className={theme.icon({ class: 'h-4 w-4' })}
|
||||
onClick={handleClear}
|
||||
/>
|
||||
@ -318,7 +314,7 @@ export const Select = ({
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}, [cloneIcon, theme, rightIcon]);
|
||||
}, [cloneIcon, theme, rightIcon, selectedItem, selectedItems, clearable]);
|
||||
|
||||
const renderHelperText = useMemo(
|
||||
() => (
|
||||
|
@ -62,7 +62,9 @@ const SelectItem = forwardRef<HTMLLIElement, SelectItemProps>(
|
||||
<p className={theme.label()} data-disabled={disabled}>
|
||||
{label}
|
||||
</p>
|
||||
{orientation === 'horizontal' && <span className={theme.dot()} />}
|
||||
{orientation === 'horizontal' && description && (
|
||||
<span className={theme.dot()} />
|
||||
)}
|
||||
{description && (
|
||||
<p className={theme.description()} data-disabled={disabled}>
|
||||
{description}
|
||||
|
Loading…
Reference in New Issue
Block a user