@entur/datepicker 11.6.2 → 11.7.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.
@@ -0,0 +1,69 @@
1
+ import { default as React } from 'react';
2
+ import { AriaRangeCalendarProps } from '@react-aria/calendar';
3
+ import { CalendarDate, DateDuration, DateValue } from '@internationalized/date';
4
+ import { RangeValue } from '@react-types/shared';
5
+ import { MappedDateValue } from '@react-types/datepicker';
6
+ type BaseRangeCalendarProps<DateType extends DateValue> = {
7
+ /** Det valgte datoperioden. Null hvis ingen periode er valgt. */
8
+ value: RangeValue<MappedDateValue<DateType>> | null;
9
+ /** Callback som kalles når valgt periode endres. */
10
+ onChange?: (value: RangeValue<MappedDateValue<DateType>> | null) => void;
11
+ navigationDescription?: string;
12
+ style?: React.CSSProperties;
13
+ /** Ekstra klassenavn */
14
+ className?: string;
15
+ /** Tidligste gyldige datovalg.
16
+ * Eks: today(getLocalTimeZone()) == i dag i lokal tidssone.
17
+ *
18
+ * OBS: Hvis du bruker dato med tid vil tidspunktet også tas hensyn til.
19
+ * Gyldig fra og med den tiden som legges inn som minDate.
20
+ * Dato uten tid vil være gyldig hele minDate-dagen */
21
+ minDate?: DateValue;
22
+ /** Seneste gyldige datovalg.
23
+ * Eks: today(getLocalTimeZone()).add({days: 1}) == i morgen i lokal tidssone
24
+ *
25
+ * OBS: Hvis du bruker dato med tid vil tidspunktet også tas hensyn til.
26
+ * Gyldig til og med den tiden som legges inn som maxDate.
27
+ * Dato uten tid vil være gyldig hele maxDate-dagen */
28
+ maxDate?: DateValue;
29
+ /** Slå på visning av ukenummere i kalenderen. Overskriften for ukenummer-kolonnen
30
+ * kan endres med prop-en 'weekNumberHeader'
31
+ * @default false */
32
+ showWeekNumbers?: boolean;
33
+ /** Overskrift som vises for ukenummer-kolonnen. Vises kun hvis 'showWeekNumbers' er true.
34
+ * @default 'uke' */
35
+ weekNumberHeader?: string;
36
+ /** Vis datoer som ligger utenfor den viste måneden.
37
+ * @example Hvis uken starter på onsdag vises de to siste datoene i forrige måned i ruten til mandagen og tirsdagen før.
38
+ * @default false */
39
+ showOutsideMonth?: boolean;
40
+ /** Brukes for å legge til klassenavn på spesifikke datoer i kalenderen.
41
+ * Tar inn en dato og skal returnere klassenavnet som skal legges til den datoen.
42
+ * @default undefined
43
+ * @example (date) => isWeekend(date, 'no-NO') ? 'weekend' : ''
44
+ *
45
+ * OBS: hvis stylingen er meningsbærende bør du bruke ariaLabelForDate i tillegg for å beskrive
46
+ * meningen til skjermlesere o.l.
47
+ */
48
+ classNameForDate?: (date: CalendarDate) => string;
49
+ /** Legger til teksten som returneres på datoen i kalenderen sin aria-label.
50
+ * Bør brukes sammen med classNameForDate hvis styling-endringene gjort der er meningsbærende.
51
+ * @default undefined
52
+ * @example (date) => isWeekend(date, 'no-NO') ? 'helgedag' : ''
53
+ */
54
+ ariaLabelForDate?: (date: CalendarDate) => string;
55
+ /** Callback-funksjon for når valideringen til datovelgeren endrer seg */
56
+ onValidate?: (isValid?: boolean) => void;
57
+ disabled?: boolean;
58
+ locale?: string;
59
+ calendarRef?: React.MutableRefObject<HTMLDivElement | null>;
60
+ /** Vis flere måneder samtidig i kalenderen.
61
+ * @default {months: 1}
62
+ * @example {months: 2}
63
+ */
64
+ visibleDuration?: Pick<DateDuration, 'months'>;
65
+ };
66
+ type ExtendedRangeCalendarProps<DateType extends DateValue> = Omit<AriaRangeCalendarProps<DateType>, keyof BaseRangeCalendarProps<DateType> | 'value' | 'label' | 'hideTimeZone' | 'placeholder' | 'placeholderValue' | 'defaultValue' | 'minValue' | 'maxValue'>;
67
+ export type RangeCalendarProps<DateType extends DateValue> = BaseRangeCalendarProps<DateType> & ExtendedRangeCalendarProps<DateType>;
68
+ export declare const RangeCalendar: <DateType extends DateValue>({ locale: localOverride, ...rest }: RangeCalendarProps<DateType>) => React.JSX.Element;
69
+ export {};
@@ -0,0 +1,14 @@
1
+ import { default as React } from 'react';
2
+ import { RangeCalendarState } from '@react-stately/calendar';
3
+ import { CalendarDate } from '@internationalized/date';
4
+ type RangeCalendarCellProps = {
5
+ state: RangeCalendarState;
6
+ date: CalendarDate;
7
+ currentMonth: CalendarDate;
8
+ weekNumberString: string;
9
+ showOutsideMonth?: boolean;
10
+ classNameForDate?: (date: CalendarDate) => string;
11
+ ariaLabelForDate?: (date: CalendarDate) => string;
12
+ };
13
+ export declare const RangeCalendarCell: ({ state, date, currentMonth, showOutsideMonth, weekNumberString, classNameForDate, ariaLabelForDate, ...rest }: RangeCalendarCellProps) => React.JSX.Element;
14
+ export {};
@@ -0,0 +1,15 @@
1
+ import { default as React } from 'react';
2
+ import { RangeCalendarState } from '@react-stately/calendar';
3
+ import { CalendarDate } from '@internationalized/date';
4
+ type RangeCalendarGridProps = {
5
+ state: RangeCalendarState;
6
+ startDate?: CalendarDate;
7
+ navigationDescription?: string;
8
+ showWeekNumbers: boolean;
9
+ weekNumberHeader: string;
10
+ showOutsideMonth?: boolean;
11
+ classNameForDate?: (date: CalendarDate) => string;
12
+ ariaLabelForDate?: (date: CalendarDate) => string;
13
+ };
14
+ export declare const RangeCalendarGrid: ({ state, startDate, navigationDescription, showWeekNumbers, weekNumberHeader, showOutsideMonth, classNameForDate, ariaLabelForDate, ...rest }: RangeCalendarGridProps) => React.JSX.Element;
15
+ export {};
@@ -1,4 +1,5 @@
1
1
  export * from './DateField';
2
2
  export * from './Calendar';
3
+ export * from './RangeCalendar';
3
4
  export * from './DatePicker';
4
5
  export * from './NativeDatePicker';
@@ -577,6 +577,270 @@ const CalendarBase = ({
577
577
  }
578
578
  );
579
579
  };
580
+ const RangeCalendarCell = ({
581
+ state,
582
+ date: date$1,
583
+ currentMonth,
584
+ showOutsideMonth = false,
585
+ weekNumberString,
586
+ classNameForDate,
587
+ ariaLabelForDate,
588
+ ...rest
589
+ }) => {
590
+ const cellRef = React.useRef(null);
591
+ const {
592
+ cellProps,
593
+ buttonProps,
594
+ isSelected,
595
+ isOutsideVisibleRange,
596
+ isDisabled,
597
+ isUnavailable,
598
+ formattedDate
599
+ } = calendar.useCalendarCell({ date: date$1 }, state, cellRef);
600
+ const ariaLabel = `${buttonProps["aria-label"]}${weekNumberString} ${ariaLabelForDate?.(date$1) ?? ""}`;
601
+ const highlightedRange = state.highlightedRange;
602
+ const isSelectionStart = isSelected && highlightedRange ? date.isSameDay(date$1, highlightedRange.start) : isSelected;
603
+ const isSelectionEnd = isSelected && highlightedRange ? date.isSameDay(date$1, highlightedRange.end) : isSelected;
604
+ const isInRange = isSelected && !isSelectionStart && !isSelectionEnd;
605
+ const isOverflowDate = date$1.month !== currentMonth.month || date$1.year !== currentMonth.year;
606
+ const isBetweenVisibleMonths = isOverflowDate && !isOutsideVisibleRange;
607
+ const shouldHideDate = !showOutsideMonth && isOutsideVisibleRange;
608
+ const extendedButtonProps = {
609
+ ...buttonProps,
610
+ ...showOutsideMonth && isOutsideVisibleRange && {
611
+ onClick: () => state.selectDate(date$1),
612
+ onKeyUp: (e) => {
613
+ if (e.key === "Enter") state.selectDate(date$1);
614
+ }
615
+ },
616
+ ...isBetweenVisibleMonths && {
617
+ tabIndex: -1,
618
+ role: "presentation",
619
+ onClick: void 0,
620
+ onKeyDown: void 0,
621
+ onKeyUp: void 0,
622
+ onPointerDown: void 0,
623
+ onFocus: void 0
624
+ }
625
+ };
626
+ return /* @__PURE__ */ jsxRuntime.jsx("td", { ...cellProps, className: "eds-datepicker__calendar__grid__cell__td", children: /* @__PURE__ */ jsxRuntime.jsx(
627
+ "div",
628
+ {
629
+ ...extendedButtonProps,
630
+ "aria-label": isBetweenVisibleMonths ? void 0 : ariaLabel,
631
+ "aria-hidden": shouldHideDate || isBetweenVisibleMonths,
632
+ ref: cellRef,
633
+ hidden: shouldHideDate,
634
+ className: classNames("eds-datepicker__calendar__grid__cell", {
635
+ [classNameForDate?.(date$1) ?? ""]: !shouldHideDate,
636
+ "eds-datepicker__calendar__grid__cell--selected": isSelected && !isOverflowDate,
637
+ "eds-datepicker__calendar__grid__cell--selection-start": isSelectionStart && !isOverflowDate,
638
+ "eds-datepicker__calendar__grid__cell--selection-end": isSelectionEnd && !isOverflowDate,
639
+ "eds-datepicker__calendar__grid__cell--in-range": isInRange && !isOverflowDate,
640
+ "eds-datepicker__calendar__grid__cell--disabled": isDisabled || isUnavailable,
641
+ "eds-datepicker__calendar__grid__cell--outside-month": isOutsideVisibleRange && !showOutsideMonth,
642
+ "eds-datepicker__calendar__grid__cell--between-months": isBetweenVisibleMonths,
643
+ "eds-datepicker__calendar__grid__cell--outside-month--visible": isOutsideVisibleRange && showOutsideMonth,
644
+ "eds-datepicker__calendar__grid__cell--today": date.isEqualDay(
645
+ date$1,
646
+ date.now(state.timeZone ?? date.getLocalTimeZone())
647
+ )
648
+ }),
649
+ ...rest,
650
+ children: formattedDate
651
+ }
652
+ ) });
653
+ };
654
+ const RangeCalendarGrid = ({
655
+ state,
656
+ startDate,
657
+ navigationDescription,
658
+ showWeekNumbers,
659
+ weekNumberHeader,
660
+ showOutsideMonth = false,
661
+ classNameForDate,
662
+ ariaLabelForDate,
663
+ ...rest
664
+ }) => {
665
+ const calendarGridId = utils.useRandomId("eds-calendar");
666
+ const { locale } = i18n.useLocale();
667
+ const gridStartDate = startDate ?? state.visibleRange.start;
668
+ const { gridProps, headerProps, weekDays } = calendar.useCalendarGrid(
669
+ { ...rest, startDate: gridStartDate },
670
+ state
671
+ );
672
+ const weeksInMonth = date.getWeeksInMonth(gridStartDate, locale);
673
+ const weeksArray = Array.from(Array(weeksInMonth).keys());
674
+ const weekDaysMapped = () => {
675
+ if (locale.toLowerCase().includes("no"))
676
+ return ["ma", "ti", "on", "to", "fr", "lø", "sø"];
677
+ if (locale.toLowerCase().includes("en")) {
678
+ if (weekDays[0] === "M")
679
+ return ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"];
680
+ if (weekDays[0] === "S")
681
+ return ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
682
+ }
683
+ return weekDays.map((day) => day.toLowerCase());
684
+ };
685
+ const getNavigationDescription = () => {
686
+ if (navigationDescription) return navigationDescription;
687
+ if (locale.toLowerCase().includes("en"))
688
+ return "Use the arrow keys to navigate between dates";
689
+ return "Bruk piltastene til å navigere mellom datoer";
690
+ };
691
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
692
+ /* @__PURE__ */ jsxRuntime.jsxs(
693
+ "table",
694
+ {
695
+ ...gridProps,
696
+ cellSpacing: "0",
697
+ className: "eds-datepicker__calendar__grid",
698
+ children: [
699
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { ...headerProps, children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
700
+ showWeekNumbers && /* @__PURE__ */ jsxRuntime.jsx("th", { className: "eds-datepicker__calendar__grid__weeknumber-header", children: weekNumberHeader }),
701
+ weekDaysMapped().map((day) => /* @__PURE__ */ jsxRuntime.jsx("th", { children: day }, day))
702
+ ] }) }),
703
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: weeksArray.map((weekIndex) => {
704
+ const weekNumber = getWeekNumberForDate(
705
+ state.getDatesInWeek(weekIndex, gridStartDate)[0]
706
+ );
707
+ return /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
708
+ showWeekNumbers && /* @__PURE__ */ jsxRuntime.jsx(
709
+ "th",
710
+ {
711
+ "aria-label": `${weekNumberHeader} ${weekNumber}`,
712
+ className: "eds-datepicker__calendar__grid__weeknumber",
713
+ children: weekNumber
714
+ }
715
+ ),
716
+ state.getDatesInWeek(weekIndex, gridStartDate).map(
717
+ (date2, i) => date2 ? /* @__PURE__ */ jsxRuntime.jsx(
718
+ RangeCalendarCell,
719
+ {
720
+ state,
721
+ date: date2,
722
+ currentMonth: gridStartDate,
723
+ "aria-describedby": calendarGridId + "description",
724
+ weekNumberString: showWeekNumbers ? `, ${weekNumberHeader} ${weekNumber},` : "",
725
+ classNameForDate,
726
+ ariaLabelForDate,
727
+ showOutsideMonth
728
+ },
729
+ `${date2.month}.${date2.day}`
730
+ ) : /* @__PURE__ */ jsxRuntime.jsx("td", {}, i)
731
+ )
732
+ ] }, weekIndex);
733
+ }) })
734
+ ]
735
+ }
736
+ ),
737
+ /* @__PURE__ */ jsxRuntime.jsx(a11y.VisuallyHidden, { id: calendarGridId + "description", children: getNavigationDescription() })
738
+ ] });
739
+ };
740
+ const RangeCalendar = ({
741
+ locale: localOverride,
742
+ ...rest
743
+ }) => {
744
+ const props = { isDisabled: rest.disabled, ...rest };
745
+ const { locale } = i18n.useLocale();
746
+ return /* @__PURE__ */ jsxRuntime.jsx(i18n.I18nProvider, { locale: localOverride ?? locale, children: /* @__PURE__ */ jsxRuntime.jsx(RangeCalendarBase, { ...props }) });
747
+ };
748
+ const RangeCalendarBase = ({
749
+ value,
750
+ onChange,
751
+ minDate,
752
+ maxDate,
753
+ showWeekNumbers = false,
754
+ weekNumberHeader = "uke",
755
+ showOutsideMonth = false,
756
+ visibleDuration,
757
+ style,
758
+ className,
759
+ navigationDescription,
760
+ classNameForDate,
761
+ ariaLabelForDate,
762
+ calendarRef,
763
+ ...rest
764
+ }) => {
765
+ const { locale } = i18n.useLocale();
766
+ const internalRef = React.useRef(null);
767
+ const ref = calendarRef ?? internalRef;
768
+ const _props = {
769
+ ...rest,
770
+ value,
771
+ onChange,
772
+ locale,
773
+ createCalendar,
774
+ minValue: minDate,
775
+ maxValue: getAdjustedMaxDate(maxDate),
776
+ visibleDuration
777
+ };
778
+ const state = calendar$1.useRangeCalendarState(_props);
779
+ const { calendarProps, prevButtonProps, nextButtonProps, title } = calendar.useRangeCalendar(_props, state, ref);
780
+ React.useEffect(
781
+ () => rest.onValidate?.(!state.isValueInvalid),
782
+ [state.isValueInvalid]
783
+ );
784
+ const monthCount = state.visibleRange.end.month - state.visibleRange.start.month + 1 + (state.visibleRange.end.year - state.visibleRange.start.year) * 12;
785
+ const getMonthTitle = (startDate) => new Intl.DateTimeFormat(locale, { month: "long", year: "numeric" }).format(
786
+ new Date(startDate.year, startDate.month - 1)
787
+ );
788
+ return /* @__PURE__ */ jsxRuntime.jsx(
789
+ "div",
790
+ {
791
+ ...calendarProps,
792
+ ref,
793
+ className: classNames("eds-datepicker__calendar", className),
794
+ style,
795
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "eds-datepicker__calendar__grids", children: Array.from({ length: monthCount }, (_, i) => {
796
+ const startDate = state.visibleRange.start.add({ months: i });
797
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "eds-datepicker__calendar__month", children: [
798
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "eds-datepicker__calendar__header", children: [
799
+ i === 0 && /* @__PURE__ */ jsxRuntime.jsx(
800
+ CalendarButton,
801
+ {
802
+ ...prevButtonProps,
803
+ "aria-label": ariaLabelIfNorwegian(
804
+ "Forrige måned",
805
+ locale,
806
+ prevButtonProps
807
+ ),
808
+ children: /* @__PURE__ */ jsxRuntime.jsx(icons.LeftArrowIcon, { size: 20 })
809
+ }
810
+ ),
811
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { children: monthCount > 1 ? getMonthTitle(startDate) : title }),
812
+ i === monthCount - 1 && /* @__PURE__ */ jsxRuntime.jsx(
813
+ CalendarButton,
814
+ {
815
+ ...nextButtonProps,
816
+ "aria-label": ariaLabelIfNorwegian(
817
+ "Neste måned",
818
+ locale,
819
+ nextButtonProps
820
+ ),
821
+ children: /* @__PURE__ */ jsxRuntime.jsx(icons.RightArrowIcon, { size: 20 })
822
+ }
823
+ )
824
+ ] }),
825
+ /* @__PURE__ */ jsxRuntime.jsx(
826
+ RangeCalendarGrid,
827
+ {
828
+ ...rest,
829
+ state,
830
+ startDate,
831
+ navigationDescription,
832
+ classNameForDate,
833
+ ariaLabelForDate,
834
+ showWeekNumbers,
835
+ weekNumberHeader,
836
+ showOutsideMonth
837
+ }
838
+ )
839
+ ] }, i);
840
+ }) })
841
+ }
842
+ );
843
+ };
580
844
  const DatePicker = ({
581
845
  selectedDate,
582
846
  locale,
@@ -1267,6 +1531,7 @@ exports.DateField = DateField;
1267
1531
  exports.DatePicker = DatePicker;
1268
1532
  exports.NativeDatePicker = NativeDatePicker;
1269
1533
  exports.NativeTimePicker = NativeTimePicker;
1534
+ exports.RangeCalendar = RangeCalendar;
1270
1535
  exports.SimpleTimePicker = SimpleTimePicker;
1271
1536
  exports.TimePicker = TimePicker;
1272
1537
  exports.ariaLabelIfNorwegian = ariaLabelIfNorwegian;