periplo-ui 3.44.0 → 3.45.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/DatePicker/DatePicker.d.ts +4 -4
- package/dist/components/DatePicker/DatePicker.js.map +1 -1
- package/dist/components/DatePickerLite/DatePickerLite.d.ts +3 -3
- package/dist/components/DatePickerLite/DatePickerLite.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/lib/dateUtils.d.ts +1 -1
- package/dist/lib/dateUtils.js.map +1 -1
- package/dist/shared/datePicker/types.d.ts +3 -3
- package/package.json +1 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Locale } from 'date-fns';
|
|
2
2
|
import { PropsBase } from 'react-day-picker';
|
|
3
3
|
import { ValueFormat } from '../../lib/dateUtils';
|
|
4
|
-
import {
|
|
5
|
-
export type
|
|
6
|
-
from?:
|
|
7
|
-
to?:
|
|
4
|
+
import { IsoDateRange, SupportedLocaleString } from '../../shared/datePicker/types';
|
|
5
|
+
export type DateRange = {
|
|
6
|
+
from?: Date;
|
|
7
|
+
to?: Date;
|
|
8
8
|
};
|
|
9
9
|
type DatePickerOutput<Variant extends 'single' | 'range', Format extends ValueFormat> = Variant extends 'single' ? Format extends 'date' ? Date | null : string | null : Format extends 'date' ? DateRange | null : IsoDateRange | null;
|
|
10
10
|
type DatePickerInput<V extends 'single' | 'range'> = V extends 'single' ? Date | string | null : {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DatePicker.js","sources":["../../../src/components/DatePicker/DatePicker.tsx"],"sourcesContent":["'use client'\n\nimport { CalendarBlank, X } from '@phosphor-icons/react'\nimport { format as formatFn, Locale } from 'date-fns'\nimport * as React from 'react'\nimport { PropsBase, PropsRangeRequired, PropsSingleRequired } from 'react-day-picker'\n\nimport { Button, buttonVariants } from '../Button'\nimport { Calendar } from '../Calendar'\nimport { PopoverContent, PopoverRoot, PopoverTrigger } from '../Popover'\n\nimport {\n formatOutputDate,\n formatOutputRange,\n InputDate,\n InputRange,\n parseInputDate,\n parseInputRange,\n ValueFormat,\n} from '@/lib/dateUtils'\nimport { useIsMobile } from '@/lib/useMobile'\nimport { cn } from '@/lib/utils'\nimport { useLocale } from '@/shared/datePicker/hooks/useLocale'\nimport { DateRange, SupportedLocaleString } from '@/shared/datePicker/types'\n\nexport type IsoDateRange = {\n from?: string\n to?: string\n}\n\ntype DatePickerOutput<Variant extends 'single' | 'range', Format extends ValueFormat> = Variant extends 'single'\n ? Format extends 'date'\n ? Date | null\n : string | null\n : Format extends 'date'\n ? DateRange | null\n : IsoDateRange | null\n\ntype DatePickerInput<V extends 'single' | 'range'> = V extends 'single'\n ? Date | string | null\n : { from?: Date | string; to?: Date | string } | null\n\nexport type DatePickerProps<V extends 'single' | 'range' = 'single', F extends ValueFormat = 'iso'> = {\n /**\n * Placeholder text displayed when no date is selected\n * @default 'Pick a date' for single mode, 'Pick a date range' for range mode\n */\n readonly placeholder?: string\n\n /**\n * Format string to use when displaying the selected date in the button\n * @default 'MMM d, yyyy'\n */\n readonly displayFormat?: string\n\n /**\n * ClassName for the button\n */\n readonly buttonClassName?: string\n\n /**\n * Whether to allow the user to show the year switcher menu\n * @default true for single mode, false for range mode\n */\n readonly showYearSwitcher?: boolean\n\n /**\n * Initial value for the date picker\n * Accepts both Date objects and ISO strings regardless of valueFormat setting\n */\n readonly initialValue?: DatePickerInput<V>\n\n /**\n * Current value for the date picker\n * Accepts both Date objects and ISO strings regardless of valueFormat setting\n */\n readonly value?: DatePickerInput<V>\n\n /**\n * Determines if the picker should close after a selection\n * @default true for single mode, false for range mode\n */\n readonly closeOnSelect?: boolean\n\n /**\n * Determines the format of the value provided to the onChange callback\n * - 'iso' (default): onChange receives ISO string(s) ('yyyy-MM-dd') or empty string for cleared values\n * - 'date': onChange receives JavaScript Date object(s) or null for cleared values\n *\n * Note: The component accepts both Date objects and ISO strings for value/initialValue\n * regardless of this setting. Empty values are sent as null (date format) or '' (iso format)\n * instead of undefined to work properly with React Hook Form.\n * @default 'iso'\n */\n readonly valueFormat?: F\n\n /**\n * Callback when date or date range changes\n */\n readonly onChange?: (value: DatePickerOutput<V, F>) => void\n\n /**\n * DatePicker mode - single date or date range\n * @default 'single'\n */\n readonly variant?: V\n\n /**\n * The locale to use for formatting dates and determining the start of the week.\n * Can be a string identifier for supported locales ('enUS', 'es', 'pt', 'enGB', 'de', 'it', 'fr')\n * or a Locale object from date-fns/locale for other languages.\n * @default 'enUS'\n */\n readonly locale?: SupportedLocaleString | Locale\n\n /**\n * Callback function executed when the clear button is clicked.\n * When provided, an X button will appear on hover to clear the selected date.\n */\n readonly onClear?: boolean | (() => void)\n\n /**\n * Weather the picker is inside a modal (needed for pointer events to work at mobile)\n */\n modal?: boolean\n\n /**\n * Container element to position the popover relative to.\n * @default document.body\n */\n container?: HTMLElement\n} & Omit<PropsBase, 'mode' | 'selected' | 'onSelect' | 'locale'>\n\nfunction DatePicker<V extends 'single' | 'range' = 'single', F extends ValueFormat = 'iso'>({\n variant = 'single' as V,\n placeholder = variant === 'single' ? 'Pick a date' : 'Pick a date range',\n valueFormat = 'iso' as F,\n initialValue: initialValueProp,\n value: valueProp,\n onChange,\n buttonClassName,\n displayFormat = 'MMM d, yyyy',\n closeOnSelect = variant === 'single',\n showYearSwitcher = variant === 'single',\n locale: localeProp = 'enUS',\n defaultMonth,\n onClear,\n modal = false,\n container = document.body,\n ...rest\n}: DatePickerProps<V, F>) {\n const [isOpen, setIsOpen] = React.useState(false)\n const [isHovered, setIsHovered] = React.useState(false)\n const [isClicked, setIsClicked] = React.useState(false)\n const isMobile = useIsMobile()\n const calendarRef = React.useRef<HTMLDivElement>(null)\n\n const resolvedLocale = useLocale(localeProp)\n\n const [internalSingleDate, setInternalSingleDate] = React.useState<Date | undefined>(() => {\n if (variant === 'single') {\n return parseInputDate(initialValueProp as InputDate)\n }\n return undefined\n })\n\n const [internalDateRange, setInternalDateRange] = React.useState<DateRange | undefined>(() => {\n if (variant === 'range') {\n return parseInputRange(initialValueProp as InputRange)\n }\n return undefined\n })\n\n React.useEffect(() => {\n const handleWindowMouseUp = () => setIsClicked(false)\n window.addEventListener('mouseup', handleWindowMouseUp)\n return () => window.removeEventListener('mouseup', handleWindowMouseUp)\n }, [])\n\n React.useEffect(() => {\n if (variant === 'single') {\n const newDate = parseInputDate(valueProp as InputDate)\n setInternalSingleDate(newDate)\n } else {\n const newRange = parseInputRange(valueProp as InputRange)\n setInternalDateRange(newRange)\n }\n }, [valueProp, variant])\n\n React.useEffect(() => {\n if (isOpen && isMobile && calendarRef.current) {\n const timeoutId = setTimeout(() => {\n const calendarElement = calendarRef.current?.querySelector('[id=\"calendar\"]') as HTMLElement | null\n\n calendarElement?.focus()\n }, 100)\n\n return () => clearTimeout(timeoutId)\n }\n }, [isOpen, isMobile])\n\n const singleDate = internalSingleDate\n const dateRange = internalDateRange\n\n const getEmptyValue = React.useCallback((): DatePickerOutput<V, F> => {\n if (variant === 'single') {\n return (valueFormat === 'date' ? null : '') as DatePickerOutput<V, F>\n } else {\n return (valueFormat === 'date' ? null : { from: '', to: '' }) as DatePickerOutput<V, F>\n }\n }, [variant, valueFormat])\n\n const handleSelect = React.useCallback(\n (selectedDate: Date | DateRange | undefined) => {\n if (variant === 'single') {\n const date = selectedDate as Date | undefined\n\n setInternalSingleDate(date)\n\n if (onChange) {\n if (date) {\n const output = valueFormat === 'date' ? date : formatOutputDate(date, 'iso')\n onChange(output as DatePickerOutput<V, F>)\n } else {\n onChange(getEmptyValue())\n }\n }\n\n if (closeOnSelect) {\n setIsOpen(false)\n }\n } else {\n const range = selectedDate as DateRange | undefined\n setInternalDateRange(range)\n if (onChange) {\n if (range) {\n const output = valueFormat === 'date' ? range : formatOutputRange(range, 'iso')\n onChange(output as DatePickerOutput<V, F>)\n } else {\n onChange(getEmptyValue())\n }\n }\n }\n },\n [variant, valueFormat, onChange, closeOnSelect, getEmptyValue],\n )\n\n const handleClear = React.useCallback(\n (event: React.MouseEvent) => {\n if (isMobile) return\n\n event.preventDefault()\n event.stopPropagation()\n\n if (variant === 'single') {\n setInternalSingleDate(undefined)\n } else {\n setInternalDateRange(undefined)\n }\n\n if (onChange) {\n onChange(getEmptyValue())\n }\n\n if (typeof onClear === 'function') {\n onClear()\n }\n },\n [variant, onChange, onClear, getEmptyValue, isMobile],\n )\n\n const formatForDisplay = () => {\n const formatOptions = { locale: resolvedLocale }\n if (variant === 'single') {\n return singleDate ? formatFn(singleDate, displayFormat, formatOptions) : placeholder\n }\n\n if (!dateRange) return placeholder\n const fromStr = dateRange.from ? formatFn(dateRange.from, displayFormat, formatOptions) : '...'\n const toStr = dateRange.to ? formatFn(dateRange.to, displayFormat, formatOptions) : '...'\n if (!dateRange.from && !dateRange.to) return placeholder\n if (!dateRange.from) return `... - ${toStr}`\n if (!dateRange.to) return `${fromStr} - ...`\n return `${fromStr} - ${toStr}`\n }\n\n const renderClearIcon = (showClearIcon: boolean) => {\n if (!showClearIcon) return null\n const clearIconClassName =\n 'pointer-events-none absolute right-4 z-10 flex h-full w-10 items-center justify-end rounded-r-lg bg-gradient-to-l from-60% via-80% to-transparent'\n\n return (\n <>\n <div\n className={cn(\n clearIconClassName,\n 'from-neutral-50 via-neutral-50/80',\n isHovered ? 'opacity-100' : 'opacity-0',\n )}\n />\n <div\n className={cn(\n clearIconClassName,\n 'from-neutral-100 via-neutral-100/80',\n isClicked ? 'opacity-100' : 'opacity-0',\n )}\n />\n <div className=\"absolute right-4 z-20 flex h-full w-10 items-center justify-end\">\n <X\n data-testid=\"clear-button\"\n className={cn(\n 'h-4 w-4 shrink-0 cursor-pointer opacity-100 transition-opacity duration-150 hover:opacity-70',\n )}\n onClick={handleClear}\n />\n </div>\n </>\n )\n }\n\n const calendarProps = React.useMemo(() => {\n const baseProps = {\n defaultMonth: (variant === 'single' ? singleDate : dateRange?.from) ?? defaultMonth,\n locale: resolvedLocale,\n initialFocus: true,\n ...rest,\n } as PropsBase\n\n if (variant === 'single') {\n return {\n ...baseProps,\n mode: 'single' as const,\n selected: singleDate,\n onSelect: (date: Date | undefined) => handleSelect(date),\n } as PropsSingleRequired\n }\n\n return {\n ...baseProps,\n mode: 'range' as const,\n selected: dateRange,\n onSelect: (range: DateRange | undefined) => handleSelect(range),\n numberOfMonths: rest.numberOfMonths ?? 2,\n } as PropsRangeRequired\n }, [variant, rest, singleDate, dateRange, handleSelect, resolvedLocale, defaultMonth])\n\n const hasValue = variant === 'single' ? singleDate : dateRange\n const showClearButton = onClear && hasValue && isHovered\n\n return (\n <PopoverRoot open={isOpen} onOpenChange={setIsOpen} modal={modal}>\n <PopoverTrigger asChild>\n <Button\n id={rest.id}\n variant=\"ghost\"\n className={cn(\n 'relative flex w-fit items-center justify-start text-left font-normal hover:transition-opacity',\n !hasValue && 'text-muted-foreground',\n buttonVariants({ variant: 'input', size: 'lg' }),\n buttonClassName,\n )}\n disabled={typeof rest.disabled === 'boolean' ? rest.disabled : false}\n onMouseEnter={() => !isMobile && setIsHovered(true)}\n onMouseLeave={() => !isMobile && setIsHovered(false)}\n onMouseDown={() => !isMobile && setIsClicked(true)}\n >\n <div className=\"flex items-center justify-center gap-2\">\n <CalendarBlank className={cn('h-4 w-4 shrink-0 transition-opacity duration-150')} />\n <span className=\"w-full text-center\">{formatForDisplay()}</span>\n {onClear && hasValue && renderClearIcon(showClearButton ?? false)}\n </div>\n </Button>\n </PopoverTrigger>\n <PopoverContent container={container} className=\"w-auto p-0\" align=\"center\" ref={calendarRef}>\n <Calendar\n {...calendarProps}\n className=\"border-0\"\n showYearSwitcher={variant === 'single' ? showYearSwitcher : false}\n />\n </PopoverContent>\n </PopoverRoot>\n )\n}\n\nDatePicker.displayName = 'DatePicker'\n\nexport { DatePicker }\n"],"names":[],"mappings":";;;;;;;;;;;;;AAqIA;AAA4F;AAChF;AAC2C;AACvC;AACA;AACP;AACP;AACA;AACgB;AACY;AACG;AACV;AACrB;AACA;AACQ;AACa;AAEvB;AACE;AACA;AACA;AACA;AACA;AAEA;AAEA;AACE;AACE;AAAmD;AAErD;AAAO;AAGT;AACE;AACE;AAAqD;AAEvD;AAAO;AAGT;AACE;AACA;AACA;AAAsE;AAGxE;AACE;AACE;AACA;AAA6B;AAE7B;AACA;AAA6B;AAC/B;AAGF;AACE;AACE;AACE;AAEA;AAAuB;AAGzB;AAAmC;AACrC;AAGF;AACA;AAEA;AACE;AACE;AAAwC;AAExC;AAA2D;AAC7D;AAGF;AAA2B;AAEvB;AACE;AAEA;AAEA;AACE;AACE;AACA;AAAyC;AAEzC;AAAwB;AAC1B;AAGF;AACE;AAAe;AACjB;AAEA;AACA;AACA;AACE;AACE;AACA;AAAyC;AAEzC;AAAwB;AAC1B;AACF;AACF;AACF;AAC6D;AAG/D;AAA0B;AAEtB;AAEA;AACA;AAEA;AACE;AAA+B;AAE/B;AAA8B;AAGhC;AACE;AAAwB;AAG1B;AACE;AAAQ;AACV;AACF;AACoD;AAGtD;AACE;AACA;AACE;AAAyE;AAG3E;AACA;AACA;AACA;AACA;AACA;AACA;AAA4B;AAG9B;AACE;AACA;AAGA;AAEI;AAAA;AAAC;AAAA;AACY;AACT;AACA;AAC4B;AAC9B;AAAA;AACF;AACA;AAAC;AAAA;AACY;AACT;AACA;AAC4B;AAC9B;AAAA;AACF;AAEE;AAAC;AAAA;AACa;AACD;AACT;AACF;AACS;AAAA;AAEb;AACF;AAIJ;AACE;AAAkB;AACuD;AAC/D;AACM;AACX;AAGL;AACE;AAAO;AACF;AACG;AACI;AAC6C;AACzD;AAGF;AAAO;AACF;AACG;AACI;AACoD;AACvB;AACzC;AAGF;AACA;AAEA;AAEI;AACE;AAAC;AAAA;AACU;AACD;AACG;AACT;AACa;AACkC;AAC/C;AACF;AAC+D;AACb;AACC;AACF;AAG/C;AAAkF;AACzB;AACO;AAClE;AAAA;AAEJ;AAEE;AAAC;AAAA;AACK;AACM;AACkD;AAAA;AAEhE;AAGN;AAEA;;"}
|
|
1
|
+
{"version":3,"file":"DatePicker.js","sources":["../../../src/components/DatePicker/DatePicker.tsx"],"sourcesContent":["'use client'\n\nimport { CalendarBlank, X } from '@phosphor-icons/react'\nimport { format as formatFn, Locale } from 'date-fns'\nimport * as React from 'react'\nimport { PropsBase, PropsRangeRequired, PropsSingleRequired } from 'react-day-picker'\n\nimport { Button, buttonVariants } from '../Button'\nimport { Calendar } from '../Calendar'\nimport { PopoverContent, PopoverRoot, PopoverTrigger } from '../Popover'\n\nimport {\n formatOutputDate,\n formatOutputRange,\n InputDate,\n InputRange,\n parseInputDate,\n parseInputRange,\n ValueFormat,\n} from '@/lib/dateUtils'\nimport { useIsMobile } from '@/lib/useMobile'\nimport { cn } from '@/lib/utils'\nimport { useLocale } from '@/shared/datePicker/hooks/useLocale'\nimport { IsoDateRange, SupportedLocaleString } from '@/shared/datePicker/types'\n\nexport type DateRange = {\n from?: Date\n to?: Date\n}\n\ntype DatePickerOutput<Variant extends 'single' | 'range', Format extends ValueFormat> = Variant extends 'single'\n ? Format extends 'date'\n ? Date | null\n : string | null\n : Format extends 'date'\n ? DateRange | null\n : IsoDateRange | null\n\ntype DatePickerInput<V extends 'single' | 'range'> = V extends 'single'\n ? Date | string | null\n : { from?: Date | string; to?: Date | string } | null\n\nexport type DatePickerProps<V extends 'single' | 'range' = 'single', F extends ValueFormat = 'iso'> = {\n /**\n * Placeholder text displayed when no date is selected\n * @default 'Pick a date' for single mode, 'Pick a date range' for range mode\n */\n readonly placeholder?: string\n\n /**\n * Format string to use when displaying the selected date in the button\n * @default 'MMM d, yyyy'\n */\n readonly displayFormat?: string\n\n /**\n * ClassName for the button\n */\n readonly buttonClassName?: string\n\n /**\n * Whether to allow the user to show the year switcher menu\n * @default true for single mode, false for range mode\n */\n readonly showYearSwitcher?: boolean\n\n /**\n * Initial value for the date picker\n * Accepts both Date objects and ISO strings regardless of valueFormat setting\n */\n readonly initialValue?: DatePickerInput<V>\n\n /**\n * Current value for the date picker\n * Accepts both Date objects and ISO strings regardless of valueFormat setting\n */\n readonly value?: DatePickerInput<V>\n\n /**\n * Determines if the picker should close after a selection\n * @default true for single mode, false for range mode\n */\n readonly closeOnSelect?: boolean\n\n /**\n * Determines the format of the value provided to the onChange callback\n * - 'iso' (default): onChange receives ISO string(s) ('yyyy-MM-dd') or empty string for cleared values\n * - 'date': onChange receives JavaScript Date object(s) or null for cleared values\n *\n * Note: The component accepts both Date objects and ISO strings for value/initialValue\n * regardless of this setting. Empty values are sent as null (date format) or '' (iso format)\n * instead of undefined to work properly with React Hook Form.\n * @default 'iso'\n */\n readonly valueFormat?: F\n\n /**\n * Callback when date or date range changes\n */\n readonly onChange?: (value: DatePickerOutput<V, F>) => void\n\n /**\n * DatePicker mode - single date or date range\n * @default 'single'\n */\n readonly variant?: V\n\n /**\n * The locale to use for formatting dates and determining the start of the week.\n * Can be a string identifier for supported locales ('enUS', 'es', 'pt', 'enGB', 'de', 'it', 'fr')\n * or a Locale object from date-fns/locale for other languages.\n * @default 'enUS'\n */\n readonly locale?: SupportedLocaleString | Locale\n\n /**\n * Callback function executed when the clear button is clicked.\n * When provided, an X button will appear on hover to clear the selected date.\n */\n readonly onClear?: boolean | (() => void)\n\n /**\n * Weather the picker is inside a modal (needed for pointer events to work at mobile)\n */\n modal?: boolean\n\n /**\n * Container element to position the popover relative to.\n * @default document.body\n */\n container?: HTMLElement\n} & Omit<PropsBase, 'mode' | 'selected' | 'onSelect' | 'locale'>\n\nfunction DatePicker<V extends 'single' | 'range' = 'single', F extends ValueFormat = 'iso'>({\n variant = 'single' as V,\n placeholder = variant === 'single' ? 'Pick a date' : 'Pick a date range',\n valueFormat = 'iso' as F,\n initialValue: initialValueProp,\n value: valueProp,\n onChange,\n buttonClassName,\n displayFormat = 'MMM d, yyyy',\n closeOnSelect = variant === 'single',\n showYearSwitcher = variant === 'single',\n locale: localeProp = 'enUS',\n defaultMonth,\n onClear,\n modal = false,\n container = document.body,\n ...rest\n}: DatePickerProps<V, F>) {\n const [isOpen, setIsOpen] = React.useState(false)\n const [isHovered, setIsHovered] = React.useState(false)\n const [isClicked, setIsClicked] = React.useState(false)\n const isMobile = useIsMobile()\n const calendarRef = React.useRef<HTMLDivElement>(null)\n\n const resolvedLocale = useLocale(localeProp)\n\n const [internalSingleDate, setInternalSingleDate] = React.useState<Date | undefined>(() => {\n if (variant === 'single') {\n return parseInputDate(initialValueProp as InputDate)\n }\n return undefined\n })\n\n const [internalDateRange, setInternalDateRange] = React.useState<DateRange | undefined>(() => {\n if (variant === 'range') {\n return parseInputRange(initialValueProp as InputRange)\n }\n return undefined\n })\n\n React.useEffect(() => {\n const handleWindowMouseUp = () => setIsClicked(false)\n window.addEventListener('mouseup', handleWindowMouseUp)\n return () => window.removeEventListener('mouseup', handleWindowMouseUp)\n }, [])\n\n React.useEffect(() => {\n if (variant === 'single') {\n const newDate = parseInputDate(valueProp as InputDate)\n setInternalSingleDate(newDate)\n } else {\n const newRange = parseInputRange(valueProp as InputRange)\n setInternalDateRange(newRange)\n }\n }, [valueProp, variant])\n\n React.useEffect(() => {\n if (isOpen && isMobile && calendarRef.current) {\n const timeoutId = setTimeout(() => {\n const calendarElement = calendarRef.current?.querySelector('[id=\"calendar\"]') as HTMLElement | null\n\n calendarElement?.focus()\n }, 100)\n\n return () => clearTimeout(timeoutId)\n }\n }, [isOpen, isMobile])\n\n const singleDate = internalSingleDate\n const dateRange = internalDateRange\n\n const getEmptyValue = React.useCallback((): DatePickerOutput<V, F> => {\n if (variant === 'single') {\n return (valueFormat === 'date' ? null : '') as DatePickerOutput<V, F>\n } else {\n return (valueFormat === 'date' ? null : { from: '', to: '' }) as DatePickerOutput<V, F>\n }\n }, [variant, valueFormat])\n\n const handleSelect = React.useCallback(\n (selectedDate: Date | DateRange | undefined) => {\n if (variant === 'single') {\n const date = selectedDate as Date | undefined\n\n setInternalSingleDate(date)\n\n if (onChange) {\n if (date) {\n const output = valueFormat === 'date' ? date : formatOutputDate(date, 'iso')\n onChange(output as DatePickerOutput<V, F>)\n } else {\n onChange(getEmptyValue())\n }\n }\n\n if (closeOnSelect) {\n setIsOpen(false)\n }\n } else {\n const range = selectedDate as DateRange | undefined\n setInternalDateRange(range)\n if (onChange) {\n if (range) {\n const output = valueFormat === 'date' ? range : formatOutputRange(range, 'iso')\n onChange(output as DatePickerOutput<V, F>)\n } else {\n onChange(getEmptyValue())\n }\n }\n }\n },\n [variant, valueFormat, onChange, closeOnSelect, getEmptyValue],\n )\n\n const handleClear = React.useCallback(\n (event: React.MouseEvent) => {\n if (isMobile) return\n\n event.preventDefault()\n event.stopPropagation()\n\n if (variant === 'single') {\n setInternalSingleDate(undefined)\n } else {\n setInternalDateRange(undefined)\n }\n\n if (onChange) {\n onChange(getEmptyValue())\n }\n\n if (typeof onClear === 'function') {\n onClear()\n }\n },\n [variant, onChange, onClear, getEmptyValue, isMobile],\n )\n\n const formatForDisplay = () => {\n const formatOptions = { locale: resolvedLocale }\n if (variant === 'single') {\n return singleDate ? formatFn(singleDate, displayFormat, formatOptions) : placeholder\n }\n\n if (!dateRange) return placeholder\n const fromStr = dateRange.from ? formatFn(dateRange.from, displayFormat, formatOptions) : '...'\n const toStr = dateRange.to ? formatFn(dateRange.to, displayFormat, formatOptions) : '...'\n if (!dateRange.from && !dateRange.to) return placeholder\n if (!dateRange.from) return `... - ${toStr}`\n if (!dateRange.to) return `${fromStr} - ...`\n return `${fromStr} - ${toStr}`\n }\n\n const renderClearIcon = (showClearIcon: boolean) => {\n if (!showClearIcon) return null\n const clearIconClassName =\n 'pointer-events-none absolute right-4 z-10 flex h-full w-10 items-center justify-end rounded-r-lg bg-gradient-to-l from-60% via-80% to-transparent'\n\n return (\n <>\n <div\n className={cn(\n clearIconClassName,\n 'from-neutral-50 via-neutral-50/80',\n isHovered ? 'opacity-100' : 'opacity-0',\n )}\n />\n <div\n className={cn(\n clearIconClassName,\n 'from-neutral-100 via-neutral-100/80',\n isClicked ? 'opacity-100' : 'opacity-0',\n )}\n />\n <div className=\"absolute right-4 z-20 flex h-full w-10 items-center justify-end\">\n <X\n data-testid=\"clear-button\"\n className={cn(\n 'h-4 w-4 shrink-0 cursor-pointer opacity-100 transition-opacity duration-150 hover:opacity-70',\n )}\n onClick={handleClear}\n />\n </div>\n </>\n )\n }\n\n const calendarProps = React.useMemo(() => {\n const baseProps = {\n defaultMonth: (variant === 'single' ? singleDate : dateRange?.from) ?? defaultMonth,\n locale: resolvedLocale,\n initialFocus: true,\n ...rest,\n } as PropsBase\n\n if (variant === 'single') {\n return {\n ...baseProps,\n mode: 'single' as const,\n selected: singleDate,\n onSelect: (date: Date | undefined) => handleSelect(date),\n } as PropsSingleRequired\n }\n\n return {\n ...baseProps,\n mode: 'range' as const,\n selected: dateRange,\n onSelect: (range: DateRange | undefined) => handleSelect(range),\n numberOfMonths: rest.numberOfMonths ?? 2,\n } as PropsRangeRequired\n }, [variant, rest, singleDate, dateRange, handleSelect, resolvedLocale, defaultMonth])\n\n const hasValue = variant === 'single' ? singleDate : dateRange\n const showClearButton = onClear && hasValue && isHovered\n\n return (\n <PopoverRoot open={isOpen} onOpenChange={setIsOpen} modal={modal}>\n <PopoverTrigger asChild>\n <Button\n id={rest.id}\n variant=\"ghost\"\n className={cn(\n 'relative flex w-fit items-center justify-start text-left font-normal hover:transition-opacity',\n !hasValue && 'text-muted-foreground',\n buttonVariants({ variant: 'input', size: 'lg' }),\n buttonClassName,\n )}\n disabled={typeof rest.disabled === 'boolean' ? rest.disabled : false}\n onMouseEnter={() => !isMobile && setIsHovered(true)}\n onMouseLeave={() => !isMobile && setIsHovered(false)}\n onMouseDown={() => !isMobile && setIsClicked(true)}\n >\n <div className=\"flex items-center justify-center gap-2\">\n <CalendarBlank className={cn('h-4 w-4 shrink-0 transition-opacity duration-150')} />\n <span className=\"w-full text-center\">{formatForDisplay()}</span>\n {onClear && hasValue && renderClearIcon(showClearButton ?? false)}\n </div>\n </Button>\n </PopoverTrigger>\n <PopoverContent container={container} className=\"w-auto p-0\" align=\"center\" ref={calendarRef}>\n <Calendar\n {...calendarProps}\n className=\"border-0\"\n showYearSwitcher={variant === 'single' ? showYearSwitcher : false}\n />\n </PopoverContent>\n </PopoverRoot>\n )\n}\n\nDatePicker.displayName = 'DatePicker'\n\nexport { DatePicker }\n"],"names":[],"mappings":";;;;;;;;;;;;;AAqIA;AAA4F;AAChF;AAC2C;AACvC;AACA;AACP;AACP;AACA;AACgB;AACY;AACG;AACV;AACrB;AACA;AACQ;AACa;AAEvB;AACE;AACA;AACA;AACA;AACA;AAEA;AAEA;AACE;AACE;AAAmD;AAErD;AAAO;AAGT;AACE;AACE;AAAqD;AAEvD;AAAO;AAGT;AACE;AACA;AACA;AAAsE;AAGxE;AACE;AACE;AACA;AAA6B;AAE7B;AACA;AAA6B;AAC/B;AAGF;AACE;AACE;AACE;AAEA;AAAuB;AAGzB;AAAmC;AACrC;AAGF;AACA;AAEA;AACE;AACE;AAAwC;AAExC;AAA2D;AAC7D;AAGF;AAA2B;AAEvB;AACE;AAEA;AAEA;AACE;AACE;AACA;AAAyC;AAEzC;AAAwB;AAC1B;AAGF;AACE;AAAe;AACjB;AAEA;AACA;AACA;AACE;AACE;AACA;AAAyC;AAEzC;AAAwB;AAC1B;AACF;AACF;AACF;AAC6D;AAG/D;AAA0B;AAEtB;AAEA;AACA;AAEA;AACE;AAA+B;AAE/B;AAA8B;AAGhC;AACE;AAAwB;AAG1B;AACE;AAAQ;AACV;AACF;AACoD;AAGtD;AACE;AACA;AACE;AAAyE;AAG3E;AACA;AACA;AACA;AACA;AACA;AACA;AAA4B;AAG9B;AACE;AACA;AAGA;AAEI;AAAA;AAAC;AAAA;AACY;AACT;AACA;AAC4B;AAC9B;AAAA;AACF;AACA;AAAC;AAAA;AACY;AACT;AACA;AAC4B;AAC9B;AAAA;AACF;AAEE;AAAC;AAAA;AACa;AACD;AACT;AACF;AACS;AAAA;AAEb;AACF;AAIJ;AACE;AAAkB;AACuD;AAC/D;AACM;AACX;AAGL;AACE;AAAO;AACF;AACG;AACI;AAC6C;AACzD;AAGF;AAAO;AACF;AACG;AACI;AACoD;AACvB;AACzC;AAGF;AACA;AAEA;AAEI;AACE;AAAC;AAAA;AACU;AACD;AACG;AACT;AACa;AACkC;AAC/C;AACF;AAC+D;AACb;AACC;AACF;AAG/C;AAAkF;AACzB;AACO;AAClE;AAAA;AAEJ;AAEE;AAAC;AAAA;AACK;AACM;AACkD;AAAA;AAEhE;AAGN;AAEA;;"}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { Matcher, PropsBase } from 'react-day-picker';
|
|
2
|
-
import {
|
|
2
|
+
import { IsoDateRange, SupportedLocaleString } from '../../shared/datePicker/types';
|
|
3
3
|
type DatePickerLiteProps = {
|
|
4
|
-
value?:
|
|
4
|
+
value?: IsoDateRange | undefined;
|
|
5
5
|
buttonClassName?: string;
|
|
6
6
|
container?: HTMLElement;
|
|
7
7
|
displayFormat?: string;
|
|
8
8
|
placeholder?: string;
|
|
9
9
|
locale?: SupportedLocaleString;
|
|
10
10
|
defaultMonth?: Date;
|
|
11
|
-
onChange?: (date:
|
|
11
|
+
onChange?: (date: IsoDateRange | undefined) => void;
|
|
12
12
|
disabled?: boolean;
|
|
13
13
|
disabledDates?: Matcher;
|
|
14
14
|
} & Omit<PropsBase, 'mode' | 'selected' | 'onSelect' | 'locale' | 'disabled'>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DatePickerLite.js","sources":["../../../src/components/DatePickerLite/DatePickerLite.tsx"],"sourcesContent":["import { CalendarBlank } from '@phosphor-icons/react'\nimport { format } from 'date-fns'\nimport { useEffect, useMemo, useState } from 'react'\nimport { Matcher, PropsBase, PropsRangeRequired } from 'react-day-picker'\n\nimport { Button, buttonVariants } from '../Button'\nimport { Calendar } from '../Calendar'\nimport { PopoverContent, PopoverRoot, PopoverTrigger } from '../Popover'\n\nimport { useIsMobile } from '@/lib/useMobile'\nimport { cn } from '@/lib/utils'\nimport { useLocale } from '@/shared/datePicker/hooks/useLocale'\nimport {
|
|
1
|
+
{"version":3,"file":"DatePickerLite.js","sources":["../../../src/components/DatePickerLite/DatePickerLite.tsx"],"sourcesContent":["import { CalendarBlank } from '@phosphor-icons/react'\nimport { format } from 'date-fns'\nimport { useEffect, useMemo, useState } from 'react'\nimport { Matcher, PropsBase, PropsRangeRequired } from 'react-day-picker'\n\nimport { Button, buttonVariants } from '../Button'\nimport { Calendar } from '../Calendar'\nimport { PopoverContent, PopoverRoot, PopoverTrigger } from '../Popover'\n\nimport { useIsMobile } from '@/lib/useMobile'\nimport { cn } from '@/lib/utils'\nimport { useLocale } from '@/shared/datePicker/hooks/useLocale'\nimport { IsoDateRange, SupportedLocaleString } from '@/shared/datePicker/types'\n\ntype DatePickerLiteProps = {\n value?: IsoDateRange | undefined\n buttonClassName?: string\n container?: HTMLElement\n displayFormat?: string\n placeholder?: string\n locale?: SupportedLocaleString\n defaultMonth?: Date\n onChange?: (date: IsoDateRange | undefined) => void\n disabled?: boolean\n disabledDates?: Matcher\n} & Omit<PropsBase, 'mode' | 'selected' | 'onSelect' | 'locale' | 'disabled'>\n\nconst DatePickerLite = ({\n value,\n buttonClassName,\n container,\n displayFormat = 'MMM d, yyyy',\n placeholder = 'Select a date range',\n locale: localeProp = 'enUS',\n defaultMonth,\n onChange,\n disabled,\n disabledDates,\n ...rest\n}: DatePickerLiteProps) => {\n const [dateRange, setDateRange] = useState<IsoDateRange | undefined>(value)\n const isMobile = useIsMobile()\n const resolvedLocale = useLocale(localeProp)\n\n useEffect(() => {\n setDateRange(value)\n }, [value])\n\n const displayText = useMemo(() => {\n const formatOptions = { locale: resolvedLocale }\n\n if (!dateRange) return placeholder\n const fromStr = dateRange.from ? format(dateRange.from, displayFormat, formatOptions) : '...'\n const toStr = dateRange.to ? format(dateRange.to, displayFormat, formatOptions) : '...'\n\n return `${fromStr} - ${toStr}`\n }, [dateRange, resolvedLocale, displayFormat, placeholder])\n\n const calendarProps = useMemo(() => {\n const baseProps = {\n defaultMonth: dateRange?.from ?? defaultMonth,\n locale: resolvedLocale,\n initialFocus: true,\n disabled: disabledDates,\n ...rest,\n } as PropsBase\n\n return {\n ...baseProps,\n mode: 'range' as const,\n selected: dateRange,\n onSelect: (range: IsoDateRange | undefined) => {\n setDateRange(range)\n onChange?.(range)\n },\n numberOfMonths: isMobile ? 1 : (rest.numberOfMonths ?? 2),\n } as PropsRangeRequired\n }, [dateRange, resolvedLocale, rest, defaultMonth, onChange, disabledDates, isMobile])\n\n return (\n <PopoverRoot>\n <PopoverTrigger asChild>\n <Button\n variant=\"ghost\"\n className={cn(\n 'relative flex w-fit items-center justify-start text-left font-normal hover:transition-opacity',\n buttonVariants({ variant: 'input', size: 'lg' }),\n buttonClassName,\n )}\n disabled={disabled}\n >\n <div className=\"flex items-center justify-center gap-2\">\n <CalendarBlank className={cn('h-4 w-4 shrink-0 transition-opacity duration-150')} />\n <span className={cn('w-full text-center', !dateRange && 'text-neutral-500')}>{displayText}</span>\n </div>\n </Button>\n </PopoverTrigger>\n <PopoverContent container={container} className=\"w-auto p-0\" align=\"center\">\n <Calendar className=\"border-0\" {...calendarProps} />\n </PopoverContent>\n </PopoverRoot>\n )\n}\n\nexport { DatePickerLite, type DatePickerLiteProps }\n"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
package/dist/lib/dateUtils.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dateUtils.js","sources":["../../src/lib/dateUtils.ts"],"sourcesContent":["import { format as formatFn, isValid, parseISO } from 'date-fns' // Used for parsing, formatting, and validating dates\n\nimport { DateRange } from '@/
|
|
1
|
+
{"version":3,"file":"dateUtils.js","sources":["../../src/lib/dateUtils.ts"],"sourcesContent":["import { format as formatFn, isValid, parseISO } from 'date-fns' // Used for parsing, formatting, and validating dates\n\nimport { DateRange } from '@/components/DatePicker/DatePicker'\n\n/**\n * Format options for date values returned by onChange callbacks\n */\nexport type ValueFormat = 'iso' | 'date'\n\n/**\n * Type for single date input that can be a Date object, ISO string, or undefined\n */\nexport type InputDate = Date | string | undefined\n\n/**\n * Type for date range input that can be a DateRange object, an object with from/to properties, or undefined\n */\nexport type InputRange = DateRange | { from?: Date | string; to?: Date | string } | undefined\n\nexport type OutputDate<TFormat extends ValueFormat> = TFormat extends 'iso' ? string | undefined : Date | undefined\nexport type OutputRange<TFormat extends ValueFormat> = TFormat extends 'iso'\n ? { from?: string; to?: string } | undefined\n : DateRange | undefined\n\n/**\n * Parses an input value (Date or ISO string) into a valid Date object.\n * Returns undefined if the input is invalid or cannot be parsed.\n */\nexport const parseInputDate = (input: InputDate): Date | undefined => {\n if (!input) return undefined\n\n if (input instanceof Date && isValid(input)) {\n return input\n }\n\n if (typeof input === 'string') {\n try {\n const parsedDate = parseISO(input)\n return isValid(parsedDate) ? parsedDate : undefined\n } catch {\n return undefined\n }\n }\n\n return undefined\n}\n\n/**\n * Formats a Date object into the specified output format (Date or ISO string).\n * Returns undefined if the input date is undefined or invalid.\n */\nexport const formatOutputDate = <TFormat extends 'iso' | 'date'>(\n date: Date | string | undefined,\n format: TFormat,\n): OutputDate<TFormat> => {\n if (date === undefined || !isValid(date)) return undefined\n\n if (format === 'date') {\n return date as OutputDate<TFormat>\n }\n\n try {\n return formatFn(date, 'yyyy-MM-dd') as OutputDate<TFormat>\n } catch {\n return undefined\n }\n}\n\n/**\n * Parses an input range value (containing Dates or ISO strings) into a DateRange object.\n * Returns undefined if the input is invalid.\n */\nexport const parseInputRange = (input: InputRange): DateRange | undefined => {\n if (!input) return undefined\n\n const fromDate = parseInputDate(input.from)\n const toDate = parseInputDate(input.to)\n\n if (fromDate === undefined && toDate === undefined) return undefined\n\n return { from: fromDate, to: toDate }\n}\n\n/**\n * Formats a DateRange object into the specified output format (DateRange or object with ISO strings).\n * Returns undefined if the input range is undefined.\n */\nexport const formatOutputRange = <TFormat extends 'iso' | 'date'>(\n range: DateRange | undefined,\n format: TFormat,\n): OutputRange<TFormat> => {\n if (!range) return undefined\n\n if (format === 'date') {\n return range as OutputRange<TFormat>\n }\n\n const fromString = formatOutputDate(range.from, 'iso')\n const toString = formatOutputDate(range.to, 'iso')\n\n return {\n from: fromString,\n to: toString,\n } as OutputRange<TFormat>\n}\n"],"names":["format","formatFn"],"mappings":";;AA4BO,MAAM,cAAA,GAAiB,CAAC,KAAA,KAAuC;AACpE,EAAA,IAAI,CAAC,OAAO,OAAO,MAAA;AAEnB,EAAA,IAAI,KAAA,YAAiB,IAAA,IAAQ,OAAA,CAAQ,KAAK,CAAA,EAAG;AAC3C,IAAA,OAAO,KAAA;AAAA;AAGT,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,IAAA,IAAI;AACF,MAAA,MAAM,UAAA,GAAa,SAAS,KAAK,CAAA;AACjC,MAAA,OAAO,OAAA,CAAQ,UAAU,CAAA,GAAI,UAAA,GAAa,KAAA,CAAA;AAAA,KAC5C,CAAA,MAAQ;AACN,MAAA,OAAO,MAAA;AAAA;AACT;AAGF,EAAA,OAAO,MAAA;AACT;AAMO,MAAM,gBAAA,GAAmB,CAC9B,IAAA,EACAA,QAAA,KACwB;AACxB,EAAA,IAAI,SAAS,MAAA,IAAa,CAAC,OAAA,CAAQ,IAAI,GAAG,OAAO,MAAA;AAEjD,EAAA,IAAIA,aAAW,MAAA,EAAQ;AACrB,IAAA,OAAO,IAAA;AAAA;AAGT,EAAA,IAAI;AACF,IAAA,OAAOC,MAAA,CAAS,MAAM,YAAY,CAAA;AAAA,GACpC,CAAA,MAAQ;AACN,IAAA,OAAO,MAAA;AAAA;AAEX;AAMO,MAAM,eAAA,GAAkB,CAAC,KAAA,KAA6C;AAC3E,EAAA,IAAI,CAAC,OAAO,OAAO,MAAA;AAEnB,EAAA,MAAM,QAAA,GAAW,cAAA,CAAe,KAAA,CAAM,IAAI,CAAA;AAC1C,EAAA,MAAM,MAAA,GAAS,cAAA,CAAe,KAAA,CAAM,EAAE,CAAA;AAEtC,EAAA,IAAI,QAAA,KAAa,MAAA,IAAa,MAAA,KAAW,MAAA,EAAW,OAAO,MAAA;AAE3D,EAAA,OAAO,EAAE,IAAA,EAAM,QAAA,EAAU,EAAA,EAAI,MAAA,EAAO;AACtC;AAMO,MAAM,iBAAA,GAAoB,CAC/B,KAAA,EACA,MAAA,KACyB;AACzB,EAAA,IAAI,CAAC,OAAO,OAAO,MAAA;AAEnB,EAAA,IAAI,WAAW,MAAA,EAAQ;AACrB,IAAA,OAAO,KAAA;AAAA;AAGT,EAAA,MAAM,UAAA,GAAa,gBAAA,CAAiB,KAAA,CAAM,IAAA,EAAM,KAAK,CAAA;AACrD,EAAA,MAAM,QAAA,GAAW,gBAAA,CAAiB,KAAA,CAAM,EAAA,EAAI,KAAK,CAAA;AAEjD,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,UAAA;AAAA,IACN,EAAA,EAAI;AAAA,GACN;AACF;;;;"}
|