@trackunit/react-date-and-time-components 1.4.11 → 1.4.13

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/index.cjs.js CHANGED
@@ -8,9 +8,8 @@ var uiDesignTokens = require('@trackunit/ui-design-tokens');
8
8
  var react = require('react');
9
9
  var reactComponents = require('@trackunit/react-components');
10
10
  var sharedUtils = require('@trackunit/shared-utils');
11
- var reactDayPicker = require('react-day-picker');
11
+ var Calendar = require('react-calendar');
12
12
  var tailwindMerge = require('tailwind-merge');
13
- var locale = require('date-fns/locale');
14
13
  var reactFormComponents = require('@trackunit/react-form-components');
15
14
  var cssClassVarianceUtilities = require('@trackunit/css-class-variance-utilities');
16
15
  var stringTs = require('string-ts');
@@ -138,75 +137,33 @@ const DateTimeHumanized = ({ value }) => {
138
137
  return (jsxRuntime.jsx(reactComponents.Tooltip, { label: jsxRuntime.jsx(DateTime, { format: tooltipFormat, value: value }), children: jsxRuntime.jsx(DateTime, { className: "underline decoration-neutral-300 decoration-dotted", fromNow: true, value: value }) }));
139
138
  };
140
139
 
141
- const localeLookup = {
142
- en: locale.enGB,
143
- "en-US": locale.enUS,
144
- "en-GB": locale.enGB,
145
- da: locale.da,
146
- de: locale.de,
147
- cs: locale.cs,
148
- nl: locale.nl,
149
- fr: locale.fr,
150
- fi: locale.fi,
151
- hu: locale.hu,
152
- it: locale.it,
153
- nb: locale.nb,
154
- pl: locale.pl,
155
- pt: locale.pt,
156
- ru: locale.ru,
157
- ro: locale.ro,
158
- es: locale.es,
159
- sv: locale.sv,
160
- ja: locale.ja,
161
- th: locale.th,
162
- };
163
- /**
164
- * A helper function to get the matching Locale object for a given language.
165
- *
166
- * @param {string} language The language to match
167
- * @returns {Locale} The corresponding Locale object
168
- */
169
- const useLocale = (language) => {
170
- return localeLookup[language] || localeLookup.en || locale.enGB;
171
- };
172
-
173
- /**
174
- * The DayPicker component is used when the user needs to select a date.
175
-
176
- * @param {DayPickerProps} props - The props for the DayPicker component
177
- * @returns {ReactElement} DayPicker component
178
- */
179
- const DayPicker = ({ onDaySelect, disabledDays, selectedDays, language, className, dataTestId, max, }) => {
180
- const locale = useLocale(language);
181
- return (jsxRuntime.jsx(reactDayPicker.DayPicker, { className: tailwindMerge.twMerge("custom-day-picker", className), disabled: disabledDays, footer: jsxRuntime.jsx("div", { "data-testid": dataTestId }), locale: locale, max: max, onDayClick: onDaySelect, selected: selectedDays }));
182
- };
183
-
184
140
  /**
185
141
  * The DayRangePicker component should be used when the user needs to select a range of dates.
186
142
  *
187
143
  * @param {DayRangePickerProps} props - The props for the DayRangePicker component
188
144
  * @returns {ReactElement} DayRangePicker component
189
145
  */
190
- const DayRangePicker = ({ onRangeSelect, selectedDays, disabledDays, dataTestId, language, className, max, timezone, cancelButtonLabel, onClose, }) => {
191
- const [newRange, setNewRange] = react.useState(selectedDays ?? { from: undefined, to: undefined });
146
+ const DayRangePicker = ({ onRangeSelect, selectedDays, disabledDays, dataTestId, language, className, timezone, cancelButtonLabel, onClose, }) => {
147
+ const [newRange, setNewRange] = react.useState(selectedDays ?? { start: undefined, end: undefined });
192
148
  const [t] = useTranslation();
193
- const locale = useLocale(language);
149
+ const { subtract } = reactDateAndTimeHooks.useDateAndTime();
150
+ const calculateDateRange = useCalculateDateRange();
194
151
  react.useEffect(() => {
195
152
  if (selectedDays) {
196
153
  setNewRange(selectedDays);
197
154
  }
198
155
  }, [selectedDays]);
199
156
  const handleOnRangeSelect = react.useCallback((range) => {
200
- if (range && range.from) {
201
- if (range.to === undefined) {
202
- setNewRange({ from: range.from, to: range.from });
157
+ if (range && range.start) {
158
+ if (range.end === undefined) {
159
+ setNewRange({ start: range.start, end: range.start });
203
160
  }
204
161
  else {
205
- setNewRange({ from: range.from, to: range.to });
162
+ setNewRange({ start: range.start, end: range.end });
206
163
  }
207
164
  }
208
165
  else {
209
- setNewRange({ from: undefined, to: undefined });
166
+ setNewRange({ start: undefined, end: undefined });
210
167
  }
211
168
  }, []);
212
169
  const handleCancel = react.useCallback(() => {
@@ -216,13 +173,47 @@ const DayRangePicker = ({ onRangeSelect, selectedDays, disabledDays, dataTestId,
216
173
  onClose && onClose();
217
174
  }, [selectedDays, onClose]);
218
175
  const clearSelectedDays = () => {
219
- setNewRange({ from: undefined, to: undefined });
176
+ setNewRange({ start: undefined, end: undefined });
220
177
  };
221
178
  const handleApply = react.useCallback(() => {
222
179
  onRangeSelect && onRangeSelect(newRange);
223
180
  onClose && onClose();
224
181
  }, [onRangeSelect, newRange, onClose]);
225
- return (jsxRuntime.jsxs("div", { className: "flex w-min flex-col gap-4 p-2", children: [jsxRuntime.jsx(reactDayPicker.DayPicker, { className: tailwindMerge.twMerge("custom-day-picker", "range-picker", className, "p-0"), defaultMonth: selectedDays ? selectedDays.from : undefined, disabled: disabledDays, footer: jsxRuntime.jsx("div", { "data-testid": dataTestId }), locale: locale, max: max, mode: "range", onSelect: handleOnRangeSelect, selected: newRange }), jsxRuntime.jsxs("div", { className: "flex w-full gap-2", children: [jsxRuntime.jsx(reactComponents.Button, { className: "mr-auto", dataTestId: "range-popover-clear-button", onClick: clearSelectedDays, variant: "secondary", children: t("layout.actions.clear") }), jsxRuntime.jsx(reactComponents.Button, { dataTestId: "range-popover-cancel-button", onClick: () => handleCancel(), variant: "ghost-neutral", children: cancelButtonLabel ? cancelButtonLabel : t("layout.actions.cancel") }), jsxRuntime.jsx(reactComponents.Button, { dataTestId: "range-popover-apply-button", disabled: !newRange.from || !newRange.to, onClick: () => handleApply(), children: t("layout.actions.apply") })] })] }));
182
+ return (jsxRuntime.jsxs("div", { className: "flex w-min flex-col gap-4 p-2", "data-testid": dataTestId, children: [jsxRuntime.jsx(Calendar, { activeStartDate: newRange.start ?? undefined, allowPartialRange: true, className: tailwindMerge.twMerge("custom-day-picker", "range-picker", className, "p-0"), locale: language, onChange: value => {
183
+ if (Array.isArray(value) && value[0] && value[1]) {
184
+ handleOnRangeSelect({ start: value[0], end: value[1] });
185
+ }
186
+ }, selectRange: true, tileDisabled: ({ date, view }) => {
187
+ if (view === "month") {
188
+ if (typeof disabledDays === "function") {
189
+ return disabledDays(date);
190
+ }
191
+ if (Array.isArray(disabledDays)) {
192
+ return disabledDays.some(dateToCheck => {
193
+ return dateToCheck.toDateString() === date.toDateString();
194
+ });
195
+ }
196
+ if (typeof disabledDays === "object" && "after" in disabledDays && "before" in disabledDays) {
197
+ return !(date.getTime() >
198
+ (disabledDays.before ? subtract(disabledDays.before, 1, "days").getTime() : date.getTime()) &&
199
+ date.getTime() < (disabledDays.after?.getTime() ?? date.getTime()));
200
+ }
201
+ if (typeof disabledDays === "object" && "furtherBackThanDays" in disabledDays) {
202
+ const dateRange = calculateDateRange({
203
+ direction: "last",
204
+ count: disabledDays.furtherBackThanDays,
205
+ unit: "day",
206
+ });
207
+ if (dateRange.start && dateRange.end) {
208
+ return date < dateRange.start || date > dateRange.end;
209
+ }
210
+ }
211
+ }
212
+ return false;
213
+ }, value:
214
+ // type is wrong here if we add array of 2 elements if end is undefined and set to null it will not highlight the start date
215
+ // eslint-disable-next-line local-rules/no-typescript-assertion, @typescript-eslint/no-explicit-any
216
+ newRange.end ? [newRange.start ?? null, newRange.end ?? null] : (newRange.start ?? null) }), jsxRuntime.jsxs("div", { className: "flex w-full gap-2", children: [jsxRuntime.jsx(reactComponents.Button, { className: "mr-auto", dataTestId: "range-popover-clear-button", onClick: clearSelectedDays, variant: "secondary", children: t("layout.actions.clear") }), jsxRuntime.jsx(reactComponents.Button, { dataTestId: "range-popover-cancel-button", onClick: () => handleCancel(), variant: "ghost-neutral", children: cancelButtonLabel ? cancelButtonLabel : t("layout.actions.cancel") }), jsxRuntime.jsx(reactComponents.Button, { dataTestId: "range-popover-apply-button", disabled: !newRange.start || !newRange.end, onClick: () => handleApply(), children: t("layout.actions.apply") })] })] }));
226
217
  };
227
218
 
228
219
  const temporalArithmeticTypeMapping = {
@@ -250,8 +241,8 @@ const useCalculateDateRange = () => {
250
241
  const endDate = add(nowDate, count, unitType);
251
242
  const adjustedEndDate = subtract(endDate, 1, "days");
252
243
  return {
253
- from: startOf(nowDate, "day"),
254
- to: endOf(adjustedEndDate, "day"),
244
+ start: startOf(nowDate, "day"),
245
+ end: endOf(adjustedEndDate, "day"),
255
246
  };
256
247
  }
257
248
  else {
@@ -259,8 +250,8 @@ const useCalculateDateRange = () => {
259
250
  const startDate = subtract(nowDate, count, unitType);
260
251
  const adjustedStartDate = add(startDate, 1, "days");
261
252
  return {
262
- from: startOf(adjustedStartDate, "day"),
263
- to: endOf(nowDate, "day"),
253
+ start: startOf(adjustedStartDate, "day"),
254
+ end: endOf(nowDate, "day"),
264
255
  };
265
256
  }
266
257
  }, [nowDate, startOf, endOf, subtract, add]);
@@ -386,8 +377,8 @@ const useFilterTemporalPeriodsInRange = () => {
386
377
  const { difference } = reactDateAndTimeHooks.useDateAndTime();
387
378
  const calculateDateRange = useCalculateDateRange();
388
379
  const getDayCountInRange = react.useCallback((temporalPeriod) => {
389
- const { from, to } = calculateDateRange(temporalPeriod);
390
- return difference(from, to, "day");
380
+ const { start, end } = calculateDateRange(temporalPeriod);
381
+ return difference(start ?? new Date(), end ?? new Date(), "day");
391
382
  }, [calculateDateRange, difference]);
392
383
  return react.useCallback(({ temporalPeriods, maxDaysInRange, }) => {
393
384
  if (!maxDaysInRange) {
@@ -516,9 +507,9 @@ const createTemporalPeriodCombinations = ({ direction, count, unit, }) => {
516
507
  * formatCustomDateRangeLabel({ from: new Date("2025-06-16"), to: new Date("2025-06-17") }); // "June 16, 2025 - June 17, 2025"
517
508
  */
518
509
  const formatCustomDateRangeLabel = (dateRange) => {
519
- return (dateAndTimeUtils.formatDateUtil(dateRange.from, { dateFormat: "medium", selectFormat: "dateOnly" }) +
510
+ return (dateAndTimeUtils.formatDateUtil(dateRange.start ?? new Date(), { dateFormat: "medium", selectFormat: "dateOnly" }) +
520
511
  " - " +
521
- dateAndTimeUtils.formatDateUtil(dateRange.to, { dateFormat: "medium", selectFormat: "dateOnly" }));
512
+ dateAndTimeUtils.formatDateUtil(dateRange.end ?? new Date(), { dateFormat: "medium", selectFormat: "dateOnly" }));
522
513
  };
523
514
 
524
515
  /**
@@ -614,13 +605,13 @@ const DayRangeSelect = ({ className, dataTestId, disabled, selectedDateRange, on
614
605
  onRangeSelect(value);
615
606
  }, [onRangeSelect]);
616
607
  const handleCustomDateRangeSelect = react.useCallback((dateRange, closeMenu) => {
617
- if (!dateRange || !dateRange.from || !dateRange.to) {
608
+ if (!dateRange || !dateRange.start || !dateRange.end) {
618
609
  handleReset();
619
610
  return;
620
611
  }
621
612
  closeMenu();
622
613
  const _selectedDateRange = {
623
- dateRange: { from: dateRange.from, to: dateRange.to },
614
+ dateRange: { start: dateRange.start, end: dateRange.end },
624
615
  temporalPeriod: undefined,
625
616
  };
626
617
  setSelectedRange(_selectedDateRange);
@@ -629,10 +620,58 @@ const DayRangeSelect = ({ className, dataTestId, disabled, selectedDateRange, on
629
620
  return (jsxRuntime.jsxs(reactComponents.Popover, { onOpenStateChange: state => !state && setIsCustomDateRangeOpen(false), placement: "bottom-start", children: [jsxRuntime.jsx(reactComponents.PopoverTrigger, { children: jsxRuntime.jsx(reactComponents.Button, { className: cvaTriggerButton({ active: !!selectedDateRange, className }), dataTestId: dataTestId, disabled: disabled, fullWidth: fullWidth, prefix: jsxRuntime.jsx(reactComponents.Icon, { ariaLabel: t("input.icon.tooltip.calendar"), color: disabled ? "secondary" : selectedDateRange ? "primary" : undefined, name: "Calendar", size: size === "large" ? "medium" : "small" }), size: size, variant: "secondary", children: popoverTriggerLabel ?? t("trigger.selectDateRange") }) }), jsxRuntime.jsx(reactComponents.PopoverContent, { dataTestId: dataTestId ? `${dataTestId}-popover-content` : undefined, children: closeMenu => {
630
621
  return !isCustomDateRangeOpen ? (jsxRuntime.jsxs(reactComponents.MenuList, { className: "min-w-[280px]", children: [jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [showDateRangeSearch ? (jsxRuntime.jsx(reactFormComponents.Search, { className: "w-full", dataTestId: dataTestId ? `${dataTestId}-search-input` : undefined, onChange: event => handleDateRangeSearch(event.target.value), onClear: () => handleDateRangeSearch(""), placeholder: allowedDirection === "last"
631
622
  ? t("input.placeholder.customRange.last")
632
- : t("input.placeholder.customRange.next"), value: dateRangeSearchValue })) : null, jsxRuntime.jsx(reactComponents.Button, { className: "ml-auto", dataTestId: dataTestId ? `${dataTestId}-reset-button` : undefined, disabled: !selectedDateRange, onClick: handleReset, size: "small", variant: "ghost", children: t("layout.actions.reset") })] }), jsxRuntime.jsx("hr", { className: "border-secondary-200 my-1", role: "separator" }), jsxRuntime.jsx(DayRangeSelectOptions, { dataTestId: dataTestId ? `${dataTestId}-options` : undefined, onSelect: value => handleOptionsSelect(value, closeMenu), selectedDateRange: currentSelectedRange, temporalPeriods: temporalPeriods }), showCustomDateRangeOption ? (jsxRuntime.jsxs("section", { children: [jsxRuntime.jsx(reactComponents.MenuDivider, {}), jsxRuntime.jsx(reactComponents.MenuItem, { dataTestId: dataTestId ? `${dataTestId}-custom-range` : undefined, label: t("trigger.customRange"), onClick: () => setIsCustomDateRangeOpen(true), selected: isCustomDateRangeSelected, suffix: jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [isCustomDateRangeSelected ? jsxRuntime.jsx(reactComponents.Icon, { color: "primary", name: "Check", size: "small" }) : null, jsxRuntime.jsx(reactComponents.Icon, { name: "ChevronRight", size: "small" })] }) })] })) : null] })) : (jsxRuntime.jsx(reactComponents.Card, { children: jsxRuntime.jsx(DayRangePicker, { cancelButtonLabel: t("layout.actions.back"), disabledDays: customDateRangeDisabledDays, language: "en", max: maxDaysInRange, onClose: () => setIsCustomDateRangeOpen(false), onRangeSelect: dateRange => handleCustomDateRangeSelect(dateRange, closeMenu), selectedDays: currentSelectedRange?.dateRange, timezone: timezone }) }));
623
+ : t("input.placeholder.customRange.next"), value: dateRangeSearchValue })) : null, jsxRuntime.jsx(reactComponents.Button, { className: "ml-auto", dataTestId: dataTestId ? `${dataTestId}-reset-button` : undefined, disabled: !selectedDateRange, onClick: handleReset, size: "small", variant: "ghost", children: t("layout.actions.reset") })] }), jsxRuntime.jsx("hr", { className: "border-secondary-200 my-1", role: "separator" }), jsxRuntime.jsx(DayRangeSelectOptions, { dataTestId: dataTestId ? `${dataTestId}-options` : undefined, onSelect: value => handleOptionsSelect(value, closeMenu), selectedDateRange: currentSelectedRange, temporalPeriods: temporalPeriods }), showCustomDateRangeOption ? (jsxRuntime.jsxs("section", { children: [jsxRuntime.jsx(reactComponents.MenuDivider, {}), jsxRuntime.jsx(reactComponents.MenuItem, { dataTestId: dataTestId ? `${dataTestId}-custom-range` : undefined, label: t("trigger.customRange"), onClick: () => setIsCustomDateRangeOpen(true), selected: isCustomDateRangeSelected, suffix: jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [isCustomDateRangeSelected ? jsxRuntime.jsx(reactComponents.Icon, { color: "primary", name: "Check", size: "small" }) : null, jsxRuntime.jsx(reactComponents.Icon, { name: "ChevronRight", size: "small" })] }) })] })) : null] })) : (jsxRuntime.jsx(reactComponents.Card, { children: jsxRuntime.jsx(DayRangePicker, { cancelButtonLabel: t("layout.actions.back"), disabledDays: customDateRangeDisabledDays, language: "en", onClose: () => setIsCustomDateRangeOpen(false), onRangeSelect: dateRange => handleCustomDateRangeSelect(dateRange
624
+ ? {
625
+ start: dateRange.start ?? undefined,
626
+ end: dateRange.end ?? undefined,
627
+ }
628
+ : undefined, closeMenu), selectedDays: currentSelectedRange?.dateRange, timezone: timezone }) }));
633
629
  } })] }));
634
630
  };
635
631
 
632
+ /**
633
+ * The DayPicker component is used when the user needs to select a date.
634
+
635
+ * @param {DayPickerProps} props - The props for the DayPicker component
636
+ * @returns {React.ReactElement} DayPicker component
637
+ */
638
+ const DayPicker = ({ onDaySelect, disabledDays, selectedDay, language, className, dataTestId, }) => {
639
+ const { subtract } = reactDateAndTimeHooks.useDateAndTime();
640
+ const calculateDateRange = useCalculateDateRange();
641
+ return (jsxRuntime.jsx("div", { "data-testid": dataTestId, children: jsxRuntime.jsx(Calendar, { activeStartDate: selectedDay ?? undefined, allowPartialRange: true, className: tailwindMerge.twMerge("custom-day-picker", "range-picker", className, "p-0"), locale: language, onChange: value => {
642
+ if (value) {
643
+ onDaySelect && onDaySelect(value);
644
+ }
645
+ }, selectRange: false, tileDisabled: ({ date, view }) => {
646
+ if (view === "month") {
647
+ if (typeof disabledDays === "function") {
648
+ return disabledDays(date);
649
+ }
650
+ if (Array.isArray(disabledDays)) {
651
+ return disabledDays.some(dateToCheck => {
652
+ return dateToCheck instanceof Date && dateToCheck.toDateString() === date.toDateString();
653
+ });
654
+ }
655
+ if (typeof disabledDays === "object" && "after" in disabledDays && "before" in disabledDays) {
656
+ return !(date.getTime() >
657
+ (disabledDays.before ? subtract(disabledDays.before, 1, "days").getTime() : date.getTime()) &&
658
+ date.getTime() < (disabledDays.after?.getTime() ?? date.getTime()));
659
+ }
660
+ if (typeof disabledDays === "object" && "furtherBackThanDays" in disabledDays) {
661
+ const dateRange = calculateDateRange({
662
+ direction: "last",
663
+ count: disabledDays.furtherBackThanDays,
664
+ unit: "day",
665
+ });
666
+ if (dateRange.start && dateRange.end) {
667
+ return date < dateRange.start || date > dateRange.end;
668
+ }
669
+ }
670
+ }
671
+ return false;
672
+ }, value: selectedDay ?? null }) }));
673
+ };
674
+
636
675
  const cvaTimelineElement = cssClassVarianceUtilities.cvaMerge([
637
676
  "flex",
638
677
  "group/timeline",
package/index.esm.js CHANGED
@@ -1,14 +1,13 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import { registerTranslations, useNamespaceTranslation } from '@trackunit/i18n-library-translation';
3
3
  import { toDateUtil, formatDateUtil, isEqualUtil, timeSinceAuto, getHourCycle } from '@trackunit/date-and-time-utils';
4
- import { useLocale as useLocale$1, useDateAndTime } from '@trackunit/react-date-and-time-hooks';
4
+ import { useLocale, useDateAndTime } from '@trackunit/react-date-and-time-hooks';
5
5
  import { color } from '@trackunit/ui-design-tokens';
6
6
  import { useMemo, useCallback, useState, useEffect, useRef, Children, isValidElement } from 'react';
7
7
  import { Tooltip, Button, MenuItem, Icon, Popover, PopoverTrigger, PopoverContent, MenuList, MenuDivider, Card, Text } from '@trackunit/react-components';
8
8
  import { DateTimeFormat, nonNullable, objectKeys } from '@trackunit/shared-utils';
9
- import { DayPicker as DayPicker$1 } from 'react-day-picker';
9
+ import Calendar from 'react-calendar';
10
10
  import { twMerge } from 'tailwind-merge';
11
- import { enGB, enUS, da, de, cs, nl, fr, fi, hu, it, nb, pl, pt, ru, ro, es, sv, ja, th } from 'date-fns/locale';
12
11
  import { Search } from '@trackunit/react-form-components';
13
12
  import { cvaMerge } from '@trackunit/css-class-variance-utilities';
14
13
  import { lowerCase } from 'string-ts';
@@ -107,7 +106,7 @@ const MS_PER_HOUR = 60 * 60 * 1000;
107
106
  */
108
107
  const DateTime = ({ value, format, className, fromNow, withTitle, titleFormat, timezone, subtle, calendar, }) => {
109
108
  const { t } = useTranslation();
110
- const locale = useLocale$1();
109
+ const locale = useLocale();
111
110
  const nowDate = useMemo(() => new Date(), []);
112
111
  const date = value ? toDateUtil(value) : nowDate;
113
112
  const newDateTime = formatDateUtil(date, format, timezone?.id, locale);
@@ -136,75 +135,33 @@ const DateTimeHumanized = ({ value }) => {
136
135
  return (jsx(Tooltip, { label: jsx(DateTime, { format: tooltipFormat, value: value }), children: jsx(DateTime, { className: "underline decoration-neutral-300 decoration-dotted", fromNow: true, value: value }) }));
137
136
  };
138
137
 
139
- const localeLookup = {
140
- en: enGB,
141
- "en-US": enUS,
142
- "en-GB": enGB,
143
- da,
144
- de,
145
- cs,
146
- nl,
147
- fr,
148
- fi,
149
- hu,
150
- it,
151
- nb,
152
- pl,
153
- pt,
154
- ru,
155
- ro,
156
- es,
157
- sv,
158
- ja,
159
- th,
160
- };
161
- /**
162
- * A helper function to get the matching Locale object for a given language.
163
- *
164
- * @param {string} language The language to match
165
- * @returns {Locale} The corresponding Locale object
166
- */
167
- const useLocale = (language) => {
168
- return localeLookup[language] || localeLookup.en || enGB;
169
- };
170
-
171
- /**
172
- * The DayPicker component is used when the user needs to select a date.
173
-
174
- * @param {DayPickerProps} props - The props for the DayPicker component
175
- * @returns {ReactElement} DayPicker component
176
- */
177
- const DayPicker = ({ onDaySelect, disabledDays, selectedDays, language, className, dataTestId, max, }) => {
178
- const locale = useLocale(language);
179
- return (jsx(DayPicker$1, { className: twMerge("custom-day-picker", className), disabled: disabledDays, footer: jsx("div", { "data-testid": dataTestId }), locale: locale, max: max, onDayClick: onDaySelect, selected: selectedDays }));
180
- };
181
-
182
138
  /**
183
139
  * The DayRangePicker component should be used when the user needs to select a range of dates.
184
140
  *
185
141
  * @param {DayRangePickerProps} props - The props for the DayRangePicker component
186
142
  * @returns {ReactElement} DayRangePicker component
187
143
  */
188
- const DayRangePicker = ({ onRangeSelect, selectedDays, disabledDays, dataTestId, language, className, max, timezone, cancelButtonLabel, onClose, }) => {
189
- const [newRange, setNewRange] = useState(selectedDays ?? { from: undefined, to: undefined });
144
+ const DayRangePicker = ({ onRangeSelect, selectedDays, disabledDays, dataTestId, language, className, timezone, cancelButtonLabel, onClose, }) => {
145
+ const [newRange, setNewRange] = useState(selectedDays ?? { start: undefined, end: undefined });
190
146
  const [t] = useTranslation();
191
- const locale = useLocale(language);
147
+ const { subtract } = useDateAndTime();
148
+ const calculateDateRange = useCalculateDateRange();
192
149
  useEffect(() => {
193
150
  if (selectedDays) {
194
151
  setNewRange(selectedDays);
195
152
  }
196
153
  }, [selectedDays]);
197
154
  const handleOnRangeSelect = useCallback((range) => {
198
- if (range && range.from) {
199
- if (range.to === undefined) {
200
- setNewRange({ from: range.from, to: range.from });
155
+ if (range && range.start) {
156
+ if (range.end === undefined) {
157
+ setNewRange({ start: range.start, end: range.start });
201
158
  }
202
159
  else {
203
- setNewRange({ from: range.from, to: range.to });
160
+ setNewRange({ start: range.start, end: range.end });
204
161
  }
205
162
  }
206
163
  else {
207
- setNewRange({ from: undefined, to: undefined });
164
+ setNewRange({ start: undefined, end: undefined });
208
165
  }
209
166
  }, []);
210
167
  const handleCancel = useCallback(() => {
@@ -214,13 +171,47 @@ const DayRangePicker = ({ onRangeSelect, selectedDays, disabledDays, dataTestId,
214
171
  onClose && onClose();
215
172
  }, [selectedDays, onClose]);
216
173
  const clearSelectedDays = () => {
217
- setNewRange({ from: undefined, to: undefined });
174
+ setNewRange({ start: undefined, end: undefined });
218
175
  };
219
176
  const handleApply = useCallback(() => {
220
177
  onRangeSelect && onRangeSelect(newRange);
221
178
  onClose && onClose();
222
179
  }, [onRangeSelect, newRange, onClose]);
223
- return (jsxs("div", { className: "flex w-min flex-col gap-4 p-2", children: [jsx(DayPicker$1, { className: twMerge("custom-day-picker", "range-picker", className, "p-0"), defaultMonth: selectedDays ? selectedDays.from : undefined, disabled: disabledDays, footer: jsx("div", { "data-testid": dataTestId }), locale: locale, max: max, mode: "range", onSelect: handleOnRangeSelect, selected: newRange }), jsxs("div", { className: "flex w-full gap-2", children: [jsx(Button, { className: "mr-auto", dataTestId: "range-popover-clear-button", onClick: clearSelectedDays, variant: "secondary", children: t("layout.actions.clear") }), jsx(Button, { dataTestId: "range-popover-cancel-button", onClick: () => handleCancel(), variant: "ghost-neutral", children: cancelButtonLabel ? cancelButtonLabel : t("layout.actions.cancel") }), jsx(Button, { dataTestId: "range-popover-apply-button", disabled: !newRange.from || !newRange.to, onClick: () => handleApply(), children: t("layout.actions.apply") })] })] }));
180
+ return (jsxs("div", { className: "flex w-min flex-col gap-4 p-2", "data-testid": dataTestId, children: [jsx(Calendar, { activeStartDate: newRange.start ?? undefined, allowPartialRange: true, className: twMerge("custom-day-picker", "range-picker", className, "p-0"), locale: language, onChange: value => {
181
+ if (Array.isArray(value) && value[0] && value[1]) {
182
+ handleOnRangeSelect({ start: value[0], end: value[1] });
183
+ }
184
+ }, selectRange: true, tileDisabled: ({ date, view }) => {
185
+ if (view === "month") {
186
+ if (typeof disabledDays === "function") {
187
+ return disabledDays(date);
188
+ }
189
+ if (Array.isArray(disabledDays)) {
190
+ return disabledDays.some(dateToCheck => {
191
+ return dateToCheck.toDateString() === date.toDateString();
192
+ });
193
+ }
194
+ if (typeof disabledDays === "object" && "after" in disabledDays && "before" in disabledDays) {
195
+ return !(date.getTime() >
196
+ (disabledDays.before ? subtract(disabledDays.before, 1, "days").getTime() : date.getTime()) &&
197
+ date.getTime() < (disabledDays.after?.getTime() ?? date.getTime()));
198
+ }
199
+ if (typeof disabledDays === "object" && "furtherBackThanDays" in disabledDays) {
200
+ const dateRange = calculateDateRange({
201
+ direction: "last",
202
+ count: disabledDays.furtherBackThanDays,
203
+ unit: "day",
204
+ });
205
+ if (dateRange.start && dateRange.end) {
206
+ return date < dateRange.start || date > dateRange.end;
207
+ }
208
+ }
209
+ }
210
+ return false;
211
+ }, value:
212
+ // type is wrong here if we add array of 2 elements if end is undefined and set to null it will not highlight the start date
213
+ // eslint-disable-next-line local-rules/no-typescript-assertion, @typescript-eslint/no-explicit-any
214
+ newRange.end ? [newRange.start ?? null, newRange.end ?? null] : (newRange.start ?? null) }), jsxs("div", { className: "flex w-full gap-2", children: [jsx(Button, { className: "mr-auto", dataTestId: "range-popover-clear-button", onClick: clearSelectedDays, variant: "secondary", children: t("layout.actions.clear") }), jsx(Button, { dataTestId: "range-popover-cancel-button", onClick: () => handleCancel(), variant: "ghost-neutral", children: cancelButtonLabel ? cancelButtonLabel : t("layout.actions.cancel") }), jsx(Button, { dataTestId: "range-popover-apply-button", disabled: !newRange.start || !newRange.end, onClick: () => handleApply(), children: t("layout.actions.apply") })] })] }));
224
215
  };
225
216
 
226
217
  const temporalArithmeticTypeMapping = {
@@ -248,8 +239,8 @@ const useCalculateDateRange = () => {
248
239
  const endDate = add(nowDate, count, unitType);
249
240
  const adjustedEndDate = subtract(endDate, 1, "days");
250
241
  return {
251
- from: startOf(nowDate, "day"),
252
- to: endOf(adjustedEndDate, "day"),
242
+ start: startOf(nowDate, "day"),
243
+ end: endOf(adjustedEndDate, "day"),
253
244
  };
254
245
  }
255
246
  else {
@@ -257,8 +248,8 @@ const useCalculateDateRange = () => {
257
248
  const startDate = subtract(nowDate, count, unitType);
258
249
  const adjustedStartDate = add(startDate, 1, "days");
259
250
  return {
260
- from: startOf(adjustedStartDate, "day"),
261
- to: endOf(nowDate, "day"),
251
+ start: startOf(adjustedStartDate, "day"),
252
+ end: endOf(nowDate, "day"),
262
253
  };
263
254
  }
264
255
  }, [nowDate, startOf, endOf, subtract, add]);
@@ -384,8 +375,8 @@ const useFilterTemporalPeriodsInRange = () => {
384
375
  const { difference } = useDateAndTime();
385
376
  const calculateDateRange = useCalculateDateRange();
386
377
  const getDayCountInRange = useCallback((temporalPeriod) => {
387
- const { from, to } = calculateDateRange(temporalPeriod);
388
- return difference(from, to, "day");
378
+ const { start, end } = calculateDateRange(temporalPeriod);
379
+ return difference(start ?? new Date(), end ?? new Date(), "day");
389
380
  }, [calculateDateRange, difference]);
390
381
  return useCallback(({ temporalPeriods, maxDaysInRange, }) => {
391
382
  if (!maxDaysInRange) {
@@ -514,9 +505,9 @@ const createTemporalPeriodCombinations = ({ direction, count, unit, }) => {
514
505
  * formatCustomDateRangeLabel({ from: new Date("2025-06-16"), to: new Date("2025-06-17") }); // "June 16, 2025 - June 17, 2025"
515
506
  */
516
507
  const formatCustomDateRangeLabel = (dateRange) => {
517
- return (formatDateUtil(dateRange.from, { dateFormat: "medium", selectFormat: "dateOnly" }) +
508
+ return (formatDateUtil(dateRange.start ?? new Date(), { dateFormat: "medium", selectFormat: "dateOnly" }) +
518
509
  " - " +
519
- formatDateUtil(dateRange.to, { dateFormat: "medium", selectFormat: "dateOnly" }));
510
+ formatDateUtil(dateRange.end ?? new Date(), { dateFormat: "medium", selectFormat: "dateOnly" }));
520
511
  };
521
512
 
522
513
  /**
@@ -612,13 +603,13 @@ const DayRangeSelect = ({ className, dataTestId, disabled, selectedDateRange, on
612
603
  onRangeSelect(value);
613
604
  }, [onRangeSelect]);
614
605
  const handleCustomDateRangeSelect = useCallback((dateRange, closeMenu) => {
615
- if (!dateRange || !dateRange.from || !dateRange.to) {
606
+ if (!dateRange || !dateRange.start || !dateRange.end) {
616
607
  handleReset();
617
608
  return;
618
609
  }
619
610
  closeMenu();
620
611
  const _selectedDateRange = {
621
- dateRange: { from: dateRange.from, to: dateRange.to },
612
+ dateRange: { start: dateRange.start, end: dateRange.end },
622
613
  temporalPeriod: undefined,
623
614
  };
624
615
  setSelectedRange(_selectedDateRange);
@@ -627,10 +618,58 @@ const DayRangeSelect = ({ className, dataTestId, disabled, selectedDateRange, on
627
618
  return (jsxs(Popover, { onOpenStateChange: state => !state && setIsCustomDateRangeOpen(false), placement: "bottom-start", children: [jsx(PopoverTrigger, { children: jsx(Button, { className: cvaTriggerButton({ active: !!selectedDateRange, className }), dataTestId: dataTestId, disabled: disabled, fullWidth: fullWidth, prefix: jsx(Icon, { ariaLabel: t("input.icon.tooltip.calendar"), color: disabled ? "secondary" : selectedDateRange ? "primary" : undefined, name: "Calendar", size: size === "large" ? "medium" : "small" }), size: size, variant: "secondary", children: popoverTriggerLabel ?? t("trigger.selectDateRange") }) }), jsx(PopoverContent, { dataTestId: dataTestId ? `${dataTestId}-popover-content` : undefined, children: closeMenu => {
628
619
  return !isCustomDateRangeOpen ? (jsxs(MenuList, { className: "min-w-[280px]", children: [jsxs("div", { className: "flex flex-col gap-1", children: [showDateRangeSearch ? (jsx(Search, { className: "w-full", dataTestId: dataTestId ? `${dataTestId}-search-input` : undefined, onChange: event => handleDateRangeSearch(event.target.value), onClear: () => handleDateRangeSearch(""), placeholder: allowedDirection === "last"
629
620
  ? t("input.placeholder.customRange.last")
630
- : t("input.placeholder.customRange.next"), value: dateRangeSearchValue })) : null, jsx(Button, { className: "ml-auto", dataTestId: dataTestId ? `${dataTestId}-reset-button` : undefined, disabled: !selectedDateRange, onClick: handleReset, size: "small", variant: "ghost", children: t("layout.actions.reset") })] }), jsx("hr", { className: "border-secondary-200 my-1", role: "separator" }), jsx(DayRangeSelectOptions, { dataTestId: dataTestId ? `${dataTestId}-options` : undefined, onSelect: value => handleOptionsSelect(value, closeMenu), selectedDateRange: currentSelectedRange, temporalPeriods: temporalPeriods }), showCustomDateRangeOption ? (jsxs("section", { children: [jsx(MenuDivider, {}), jsx(MenuItem, { dataTestId: dataTestId ? `${dataTestId}-custom-range` : undefined, label: t("trigger.customRange"), onClick: () => setIsCustomDateRangeOpen(true), selected: isCustomDateRangeSelected, suffix: jsxs(Fragment, { children: [isCustomDateRangeSelected ? jsx(Icon, { color: "primary", name: "Check", size: "small" }) : null, jsx(Icon, { name: "ChevronRight", size: "small" })] }) })] })) : null] })) : (jsx(Card, { children: jsx(DayRangePicker, { cancelButtonLabel: t("layout.actions.back"), disabledDays: customDateRangeDisabledDays, language: "en", max: maxDaysInRange, onClose: () => setIsCustomDateRangeOpen(false), onRangeSelect: dateRange => handleCustomDateRangeSelect(dateRange, closeMenu), selectedDays: currentSelectedRange?.dateRange, timezone: timezone }) }));
621
+ : t("input.placeholder.customRange.next"), value: dateRangeSearchValue })) : null, jsx(Button, { className: "ml-auto", dataTestId: dataTestId ? `${dataTestId}-reset-button` : undefined, disabled: !selectedDateRange, onClick: handleReset, size: "small", variant: "ghost", children: t("layout.actions.reset") })] }), jsx("hr", { className: "border-secondary-200 my-1", role: "separator" }), jsx(DayRangeSelectOptions, { dataTestId: dataTestId ? `${dataTestId}-options` : undefined, onSelect: value => handleOptionsSelect(value, closeMenu), selectedDateRange: currentSelectedRange, temporalPeriods: temporalPeriods }), showCustomDateRangeOption ? (jsxs("section", { children: [jsx(MenuDivider, {}), jsx(MenuItem, { dataTestId: dataTestId ? `${dataTestId}-custom-range` : undefined, label: t("trigger.customRange"), onClick: () => setIsCustomDateRangeOpen(true), selected: isCustomDateRangeSelected, suffix: jsxs(Fragment, { children: [isCustomDateRangeSelected ? jsx(Icon, { color: "primary", name: "Check", size: "small" }) : null, jsx(Icon, { name: "ChevronRight", size: "small" })] }) })] })) : null] })) : (jsx(Card, { children: jsx(DayRangePicker, { cancelButtonLabel: t("layout.actions.back"), disabledDays: customDateRangeDisabledDays, language: "en", onClose: () => setIsCustomDateRangeOpen(false), onRangeSelect: dateRange => handleCustomDateRangeSelect(dateRange
622
+ ? {
623
+ start: dateRange.start ?? undefined,
624
+ end: dateRange.end ?? undefined,
625
+ }
626
+ : undefined, closeMenu), selectedDays: currentSelectedRange?.dateRange, timezone: timezone }) }));
631
627
  } })] }));
632
628
  };
633
629
 
630
+ /**
631
+ * The DayPicker component is used when the user needs to select a date.
632
+
633
+ * @param {DayPickerProps} props - The props for the DayPicker component
634
+ * @returns {React.ReactElement} DayPicker component
635
+ */
636
+ const DayPicker = ({ onDaySelect, disabledDays, selectedDay, language, className, dataTestId, }) => {
637
+ const { subtract } = useDateAndTime();
638
+ const calculateDateRange = useCalculateDateRange();
639
+ return (jsx("div", { "data-testid": dataTestId, children: jsx(Calendar, { activeStartDate: selectedDay ?? undefined, allowPartialRange: true, className: twMerge("custom-day-picker", "range-picker", className, "p-0"), locale: language, onChange: value => {
640
+ if (value) {
641
+ onDaySelect && onDaySelect(value);
642
+ }
643
+ }, selectRange: false, tileDisabled: ({ date, view }) => {
644
+ if (view === "month") {
645
+ if (typeof disabledDays === "function") {
646
+ return disabledDays(date);
647
+ }
648
+ if (Array.isArray(disabledDays)) {
649
+ return disabledDays.some(dateToCheck => {
650
+ return dateToCheck instanceof Date && dateToCheck.toDateString() === date.toDateString();
651
+ });
652
+ }
653
+ if (typeof disabledDays === "object" && "after" in disabledDays && "before" in disabledDays) {
654
+ return !(date.getTime() >
655
+ (disabledDays.before ? subtract(disabledDays.before, 1, "days").getTime() : date.getTime()) &&
656
+ date.getTime() < (disabledDays.after?.getTime() ?? date.getTime()));
657
+ }
658
+ if (typeof disabledDays === "object" && "furtherBackThanDays" in disabledDays) {
659
+ const dateRange = calculateDateRange({
660
+ direction: "last",
661
+ count: disabledDays.furtherBackThanDays,
662
+ unit: "day",
663
+ });
664
+ if (dateRange.start && dateRange.end) {
665
+ return date < dateRange.start || date > dateRange.end;
666
+ }
667
+ }
668
+ }
669
+ return false;
670
+ }, value: selectedDay ?? null }) }));
671
+ };
672
+
634
673
  const cvaTimelineElement = cvaMerge([
635
674
  "flex",
636
675
  "group/timeline",
@@ -726,7 +765,7 @@ const Timeline = ({ className, dataTestId, children, dateHeader, customHeader, t
726
765
  const [visibleCount, setVisibleCount] = useState(ITEMS_PER_PAGE);
727
766
  const [isLoadingMore, setIsLoadingMore] = useState(false);
728
767
  const { formatDate, formatRange } = useDateAndTime();
729
- const locale = useLocale$1();
768
+ const locale = useLocale();
730
769
  const hourCycle = getHourCycle(locale);
731
770
  const { t } = useTranslation();
732
771
  const childrenArray = useMemo(() => Children.toArray(children), [children]);
@@ -799,7 +838,7 @@ const Timeline = ({ className, dataTestId, children, dateHeader, customHeader, t
799
838
  const TimelineElement = ({ date, children, className, dataTestId = "timeline-element", header, onClick, actionButton, selected, customDot, lineStyle = "solid", hoverBehavior = false, }) => {
800
839
  const [isHovered, setIsHovered] = useState(false);
801
840
  const { formatDate } = useDateAndTime();
802
- const locale = useLocale$1();
841
+ const locale = useLocale();
803
842
  const formattedDate = date ? formatDate(date, { selectFormat: "timeOnly", timeFormat: "short" }) : null;
804
843
  const handleMouseEnter = () => {
805
844
  if (hoverBehavior) {
package/package.json CHANGED
@@ -1,27 +1,26 @@
1
1
  {
2
2
  "name": "@trackunit/react-date-and-time-components",
3
- "version": "1.4.11",
3
+ "version": "1.4.13",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "engines": {
7
7
  "node": ">=22.x"
8
8
  },
9
9
  "dependencies": {
10
- "date-fns": "^2.30.0",
11
- "react-day-picker": "9.5.1",
12
10
  "react": "19.0.0",
13
- "@trackunit/react-components": "1.4.202",
14
- "@trackunit/react-date-and-time-hooks": "1.3.195",
15
- "@trackunit/date-and-time-utils": "1.3.165",
16
- "@trackunit/css-class-variance-utilities": "1.3.165",
17
- "@trackunit/ui-icons": "1.3.166",
18
- "@trackunit/ui-design-tokens": "1.3.163",
19
- "@trackunit/shared-utils": "1.5.165",
20
- "@trackunit/i18n-library-translation": "1.3.189",
21
- "@trackunit/react-test-setup": "1.0.55",
22
- "@trackunit/react-form-components": "1.3.228",
11
+ "@trackunit/react-components": "1.4.204",
12
+ "@trackunit/react-date-and-time-hooks": "1.3.196",
13
+ "@trackunit/date-and-time-utils": "1.3.166",
14
+ "@trackunit/css-class-variance-utilities": "1.3.166",
15
+ "@trackunit/ui-icons": "1.3.167",
16
+ "@trackunit/ui-design-tokens": "1.3.164",
17
+ "@trackunit/shared-utils": "1.5.166",
18
+ "@trackunit/i18n-library-translation": "1.3.190",
19
+ "@trackunit/react-test-setup": "1.0.56",
20
+ "@trackunit/react-form-components": "1.3.230",
23
21
  "string-ts": "^2.0.0",
24
- "tailwind-merge": "^2.0.0"
22
+ "tailwind-merge": "^2.0.0",
23
+ "react-calendar": "^6.0.0"
25
24
  },
26
25
  "module": "./index.esm.js",
27
26
  "main": "./index.cjs.js",
@@ -1,5 +1,14 @@
1
1
  import { CommonProps } from "@trackunit/react-components";
2
- import { DateRange, Matcher } from "react-day-picker";
2
+ export type FurtherBackThanDays = {
3
+ /**
4
+ * This disables dates that are further back than the number of days specified from today.
5
+ */
6
+ furtherBackThanDays: number;
7
+ };
8
+ export type DisabledDaysMatcher = ((date: Date) => boolean) | {
9
+ before?: Date;
10
+ after?: Date;
11
+ } | Array<Date> | FurtherBackThanDays;
3
12
  export interface DayPickerProps extends CommonProps {
4
13
  /**
5
14
  * A callback function for when a date is selected
@@ -8,24 +17,20 @@ export interface DayPickerProps extends CommonProps {
8
17
  /**
9
18
  * Define any days which may not be selected
10
19
  */
11
- disabledDays?: Matcher | Array<Matcher>;
20
+ disabledDays?: DisabledDaysMatcher | Array<DisabledDaysMatcher>;
12
21
  /**
13
- * Set any days which are selected
22
+ * Set any day which are selected
14
23
  */
15
- selectedDays?: DateRange;
24
+ selectedDay?: Date;
16
25
  /**
17
26
  * Set the language
18
27
  */
19
28
  language: string;
20
- /**
21
- * The maximum amount of days that can be selected
22
- */
23
- max?: number;
24
29
  }
25
30
  /**
26
31
  * The DayPicker component is used when the user needs to select a date.
27
32
 
28
33
  * @param {DayPickerProps} props - The props for the DayPicker component
29
- * @returns {ReactElement} DayPicker component
34
+ * @returns {React.ReactElement} DayPicker component
30
35
  */
31
- export declare const DayPicker: ({ onDaySelect, disabledDays, selectedDays, language, className, dataTestId, max, }: DayPickerProps) => import("react/jsx-runtime").JSX.Element;
36
+ export declare const DayPicker: ({ onDaySelect, disabledDays, selectedDay, language, className, dataTestId, }: DayPickerProps) => import("react/jsx-runtime").JSX.Element;
@@ -1,7 +1,7 @@
1
1
  import { CommonProps } from "@trackunit/react-components";
2
+ import { DateRange } from "@trackunit/date-and-time-utils";
2
3
  import { ReactElement } from "react";
3
- import { DateRange, Matcher } from "react-day-picker";
4
- import { TimeZone } from "./index";
4
+ import { DisabledDaysMatcher, TimeZone } from "./index";
5
5
  export interface DayRangePickerProps extends CommonProps {
6
6
  /**
7
7
  * A callback function for when a range is selected
@@ -10,7 +10,7 @@ export interface DayRangePickerProps extends CommonProps {
10
10
  /**
11
11
  * Define any days which may not be selected
12
12
  */
13
- disabledDays?: Matcher | Array<Matcher>;
13
+ disabledDays?: DisabledDaysMatcher;
14
14
  /**
15
15
  * Set any days which are selected
16
16
  */
@@ -19,10 +19,6 @@ export interface DayRangePickerProps extends CommonProps {
19
19
  * Set the language
20
20
  */
21
21
  language: string;
22
- /**
23
- * The maximum amount of days that can be selected
24
- */
25
- max?: number;
26
22
  /**
27
23
  * Shown time ranges will take timezone into consideration
28
24
  */
@@ -42,4 +38,4 @@ export interface DayRangePickerProps extends CommonProps {
42
38
  * @param {DayRangePickerProps} props - The props for the DayRangePicker component
43
39
  * @returns {ReactElement} DayRangePicker component
44
40
  */
45
- export declare const DayRangePicker: ({ onRangeSelect, selectedDays, disabledDays, dataTestId, language, className, max, timezone, cancelButtonLabel, onClose, }: DayRangePickerProps) => ReactElement;
41
+ export declare const DayRangePicker: ({ onRangeSelect, selectedDays, disabledDays, dataTestId, language, className, timezone, cancelButtonLabel, onClose, }: DayRangePickerProps) => ReactElement;
@@ -8,3 +8,4 @@ export declare const packageName: () => import("react/jsx-runtime").JSX.Element;
8
8
  export declare const DefaultSDA: () => import("react/jsx-runtime").JSX.Element;
9
9
  export declare const VariantWithMax: () => import("react/jsx-runtime").JSX.Element;
10
10
  export declare const VariantWithDisabledDays: () => import("react/jsx-runtime").JSX.Element;
11
+ export declare const VariantWithDisableRange: () => import("react/jsx-runtime").JSX.Element;
@@ -1,7 +1,8 @@
1
+ import { DateRange } from "@trackunit/date-and-time-utils";
1
2
  import { CommonProps } from "@trackunit/react-components";
2
3
  import { Size } from "@trackunit/shared-utils";
3
4
  import { DayRangePickerProps } from "../DayPicker/DayRangePicker";
4
- import { DateRange, SelectedDateRange, TemporalDirection, TemporalPeriod } from "./types";
5
+ import { SelectedDateRange, TemporalDirection, TemporalPeriod } from "./types";
5
6
  export type DayRangeSelectProps = CommonProps & {
6
7
  /**
7
8
  * Whether the component is disabled.
@@ -1,4 +1,5 @@
1
- import { DateRange, TemporalPeriod } from "../../types";
1
+ import { DateRange } from "@trackunit/date-and-time-utils";
2
+ import { TemporalPeriod } from "../../types";
2
3
  /**
3
4
  * Calculate a date range based on a temporal period.
4
5
  *
@@ -1,8 +1,5 @@
1
+ import { DateRange } from "@trackunit/date-and-time-utils";
1
2
  import { TemporalArithmeticType, TemporalSameType } from "@trackunit/react-date-and-time-hooks";
2
- export type DateRange = {
3
- from: Date;
4
- to: Date;
5
- };
6
3
  export type TemporalUnit = Exclude<TemporalArithmeticType | TemporalSameType, "year" | "hours" | "minutes" | "years">;
7
4
  export type TemporalDirection = "next" | "last";
8
5
  export type TemporalPeriod = {
@@ -1,4 +1,4 @@
1
- import { DateRange } from "../../types";
1
+ import { DateRange } from "@trackunit/date-and-time-utils";
2
2
  /**
3
3
  * Format a label representing the provided date range.
4
4
  *
@@ -1,4 +1,5 @@
1
- import { DateRange, TemporalPeriod } from "../../types";
1
+ import { DateRange } from "@trackunit/date-and-time-utils";
2
+ import { TemporalPeriod } from "../../types";
2
3
  /**
3
4
  * Check if a value is a temporal period.
4
5
  *
@@ -3,5 +3,5 @@ import { DateTime } from "./DateTime";
3
3
  type Story = StoryObj<typeof DateTime>;
4
4
  declare const meta: Meta<typeof DateTime>;
5
5
  export default meta;
6
- export declare const packageName: () => import("react/jsx-runtime").JSX.Element;
7
6
  export declare const Default: Story;
7
+ export declare const packageName: () => import("react/jsx-runtime").JSX.Element;
@@ -1,8 +0,0 @@
1
- import { Locale } from "date-fns";
2
- /**
3
- * A helper function to get the matching Locale object for a given language.
4
- *
5
- * @param {string} language The language to match
6
- * @returns {Locale} The corresponding Locale object
7
- */
8
- export declare const useLocale: (language: string) => Locale;