Repository: gpbl/react-day-picker
Pull request #2181 (2024-06-02 11:49:40)

fix: replace data- attribute with WeekNumberFlag feature


Patch:
diff --git a/src/UI.ts b/src/UI.ts
index 4c76f2d3d..c46f37113 100644
--- a/src/UI.ts
+++ b/src/UI.ts
@@ -51,7 +51,10 @@ export enum UI {
   Weekday = "weekday",
   /** The row grouping the weekdays in the column headers. */
   Weekdays = "weekdays",
-  /** The row header containing the week number. */
+  /**
+   * The row header containing the week number. Extended by
+   * {@link WeekNumberFlag}.
+   */
   WeekNumber = "week_number",
   /** The dropdown with the years. */
   YearsDropdown = "years_dropdown"
@@ -96,3 +99,12 @@ export enum ChevronFlag {
   /** Assigned when the week numbers are show. */
   disabled = "chevron_disabled"
 }
+
+/** Flags that can be applied to the {@link UI.WeekNumber} element. */
+export enum WeekNumberFlag {
+  /**
+   * Assigned when the week number is interactive, i.e. has an
+   * `onWeekNumberClick` event attached to it.
+   */
+  isInteractive = "week_number_interactive"
+}
diff --git a/src/components/WeekNumber.tsx b/src/components/WeekNumber.tsx
index e47693d67..1087ba888 100644
--- a/src/components/WeekNumber.tsx
+++ b/src/components/WeekNumber.tsx
@@ -1,6 +1,6 @@
 import React from "react";
 
-import { UI } from "../UI";
+import { UI, WeekNumberFlag } from "../UI";
 import type { CalendarWeek } from "../classes";
 import { useProps } from "../contexts/props";
 
@@ -21,15 +21,20 @@ export function WeekNumber(props: { week: CalendarWeek }) {
     styles,
     onWeekNumberClick
   } = useProps();
+
+  const isInteractive = Boolean(onWeekNumberClick);
+
   return (
     <div
       role="rowheader"
       aria-colindex={1}
       aria-label={labelWeekNumber(props.week.weekNumber, { locale })}
-      className={classNames[UI.WeekNumber]}
+      className={[
+        classNames[UI.WeekNumber],
+        isInteractive ? classNames[WeekNumberFlag.isInteractive] : ""
+      ].join(" ")}
       style={styles?.[UI.WeekNumber]}
-      tabIndex={onWeekNumberClick ? 0 : undefined}
-      data-onclick={onWeekNumberClick ? true : undefined}
+      tabIndex={isInteractive ? 0 : undefined}
       onClick={(e) =>
         onWeekNumberClick?.(
           props.week.weekNumber,
diff --git a/src/helpers/getDefaultClassNames.ts b/src/helpers/getDefaultClassNames.ts
index a2f4c7b26..61f3ae02c 100644
--- a/src/helpers/getDefaultClassNames.ts
+++ b/src/helpers/getDefaultClassNames.ts
@@ -1,4 +1,10 @@
-import { UI, DayModifier, CalendarFlag, ChevronFlag } from "../UI";
+import {
+  UI,
+  DayModifier,
+  CalendarFlag,
+  ChevronFlag,
+  WeekNumberFlag
+} from "../UI";
 import type { ClassNames } from "../types";
 
 /**
@@ -24,6 +30,11 @@ export function getDefaultClassNames(): Required<ClassNames> {
       `rdp-${ChevronFlag[key as keyof typeof ChevronFlag]}`;
   }
 
+  for (const key in WeekNumberFlag) {
+    classNames[WeekNumberFlag[key as keyof typeof WeekNumberFlag]] =
+      `rdp-${WeekNumberFlag[key as keyof typeof WeekNumberFlag]}`;
+  }
+
   for (const key in DayModifier) {
     classNames[DayModifier[key as keyof typeof DayModifier]] =
       `rdp-${DayModifier[key as keyof typeof DayModifier]}`;
diff --git a/src/style.css b/src/style.css
index c4b20523b..2b2088d2f 100644
--- a/src/style.css
+++ b/src/style.css
@@ -311,21 +311,12 @@
   border: var(--rdp-week_number-border);
   border-radius: var(--rdp-week_number-border-radius);
 }
-.rdp-week_number[data-onclick] {
-  cursor: pointer;
-}
-
-.rdp-week_number[data-interactive] .rdp-weekday {
-  display: inline-flex;
-  align-items: center;
-  justify-content: center;
 
-  width: var(--rdp-weekday-width);
-  height: var(--rdp-weekday-height);
+.rdp-week_number_interactive {
+  cursor: pointer;
 }
 
 /* DAY MODIFIERS */
-
 .rdp-today:not(.rdp-outside) {
   color: var(--rdp-today-color);
 }
diff --git a/src/style.css.d.ts b/src/style.css.d.ts
index acc1fe317..24caf6d40 100644
--- a/src/style.css.d.ts
+++ b/src/style.css.d.ts
@@ -6,6 +6,7 @@ declare const styles: {
   readonly "rdp-chevron": string;
   readonly "rdp-chevron_disabled": string;
   readonly "rdp-day": string;
+  readonly "rdp-day_date": string;
   readonly "rdp-disabled": string;
   readonly "rdp-dropdown": string;
   readonly "rdp-dropdown_nav": string;
@@ -29,6 +30,7 @@ declare const styles: {
   readonly "rdp-today": string;
   readonly "rdp-week": string;
   readonly "rdp-week_number": string;
+  readonly "rdp-week_number_interactive": string;
   readonly "rdp-weekday": string;
   readonly "rdp-weekdays": string;
   readonly "rdp-weeks": string;
diff --git a/src/style.module.css b/src/style.module.css
index 75f5eb88f..4f8ab23c7 100644
--- a/src/style.module.css
+++ b/src/style.module.css
@@ -86,12 +86,29 @@
   /* The font of the month caption. */
   --rdp-month-caption-font: bold larger var(--rdp-font-family);
 
-  /* The color of the range background. */
-  --rdp-range-background-color: var(--rdp-accent-color);
+  /* The color of the background for days in the middle of a range. */
+  --rdp-range-middle-background-color: #ababff;
+
+  /* The font for days in the middle of a range. */
+  --rdp-range-middle-font: normal medium var(--rdp-font-family);
 
   /* The color of the range text. */
   --rdp-range-color: white;
 
+  /* Used for the background of the start of the selected range. */
+  --rdp-range-start-background: linear-gradient(
+    90deg,
+    transparent 50%,
+    var(--rdp-range-middle-background-color) 50%
+  );
+
+  /* Used for the background of the end of the selected range. */
+  --rdp-range-end-background: linear-gradient(
+    90deg,
+    var(--rdp-range-middle-background-color) 50%,
+    transparent 50%
+  );
+
   /* The gap between the dropdown. */
   --rdp-dropdown-gap: 0.5rem;
 
@@ -144,9 +161,20 @@
 
   width: var(--rdp-day-width);
   height: var(--rdp-day-height);
+
+  font: var(--rdp-day-font);
+}
+
+.day_date {
+  justify-content: center;
+  align-items: center;
+  display: flex;
+
+  width: var(--rdp-day-width);
+  height: var(--rdp-day-height);
+
   border: var(--rdp-day-border);
   border-radius: var(--rdp-day-border-radius);
-  font: var(--rdp-day-font);
 }
 
 .caption_label {
@@ -283,28 +311,21 @@
   border: var(--rdp-week_number-border);
   border-radius: var(--rdp-week_number-border-radius);
 }
-.week_number[data-onclick] {
-  cursor: pointer;
-}
 
-.week_number[data-interactive] .weekday {
-  display: inline-flex;
-  align-items: center;
-  justify-content: center;
-
-  width: var(--rdp-weekday-width);
-  height: var(--rdp-weekday-height);
+.week_number_interactive {
+  cursor: pointer;
 }
 
 /* DAY MODIFIERS */
-
 .today:not(.outside) {
   color: var(--rdp-today-color);
 }
 
-.selected,
-.selected.outside {
+.selected {
   font: var(--rdp-selected-font);
+}
+
+.selected .day_date {
   border: var(--rdp-selected-border);
 }
 
@@ -322,29 +343,30 @@
 }
 
 .range_start {
-  border-start-end-radius: 0;
-  border-end-end-radius: 0;
+  background: var(--rdp-range-start-background);
 }
 
-.range_start.selected,
-.range_end.selected,
-.range_middle.selected {
-  border-color: transparent;
+.range_start .day_date {
   background-color: var(--rdp-range-background-color);
   color: var(--rdp-range-color);
 }
 
-.range_end {
-  border-start-start-radius: 0;
-  border-end-start-radius: 0;
+.range_middle .day_date {
+  border-color: transparent;
+  border: unset;
+  border-radius: unset;
+  background-color: var(--rdp-range-middle-background-color);
+  color: var(--rdp-range-color);
+  font: var(--rdp-range-middle-font);
 }
 
-.range_end.range_start {
-  border-radius: var(--rdp-day-border-radius);
+.range_end {
+  background: var(--rdp-range-end-background);
 }
 
-.range_middle {
-  border-radius: 0;
+.range_end .day_date {
+  background-color: var(--rdp-range-background-color);
+  color: var(--rdp-range-color);
 }
 
 .focusable {
diff --git a/src/style.module.css.d.ts b/src/style.module.css.d.ts
index 61bee380e..99658c7b5 100644
--- a/src/style.module.css.d.ts
+++ b/src/style.module.css.d.ts
@@ -6,6 +6,7 @@ declare const styles: {
   readonly "chevron": string;
   readonly "chevron_disabled": string;
   readonly "day": string;
+  readonly "day_date": string;
   readonly "disabled": string;
   readonly "dropdown": string;
   readonly "dropdown_nav": string;
@@ -29,6 +30,7 @@ declare const styles: {
   readonly "today": string;
   readonly "week": string;
   readonly "week_number": string;
+  readonly "week_number_interactive": string;
   readonly "weekday": string;
   readonly "weekdays": string;
   readonly "weeks": string;
diff --git a/src/types.ts b/src/types.ts
index f15625917..544e6f9f6 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -10,7 +10,13 @@ import type {
 
 import type { Locale } from "date-fns";
 
-import { UI, DayModifier, CalendarFlag, ChevronFlag } from "./UI";
+import {
+  UI,
+  DayModifier,
+  CalendarFlag,
+  ChevronFlag,
+  WeekNumberFlag
+} from "./UI";
 import { CalendarDay } from "./classes";
 import * as components from "./components/custom-components";
 import {
@@ -581,6 +587,8 @@ export type ClassNames = {
   [flag in CalendarFlag]: string;
 } & {
   [flag in ChevronFlag]: string;
+} & {
+  [flag in WeekNumberFlag]: string;
 };
 
 /** The modifiers that are internally used by DayPicker. */


Test patch:
diff --git a/src/helpers/getDefaultClassNames.test.ts b/src/helpers/getDefaultClassNames.test.ts
index e33be6c8c..caa9bb59b 100644
--- a/src/helpers/getDefaultClassNames.test.ts
+++ b/src/helpers/getDefaultClassNames.test.ts
@@ -35,6 +35,7 @@ test("should return the default classnames", () => {
     selected: "rdp-selected",
     today: "rdp-today",
     week_number: "rdp-week_number",
+    week_number_interactive: "rdp-week_number_interactive",
     week: "rdp-week",
     weekday: "rdp-weekday",
     weekdays: "rdp-weekdays",