Repository: gpbl/react-day-picker
Pull request #2168 (2024-05-30 00:38:29)

build: fix CSS module support, added missing class names


Patch:
diff --git a/package.json b/package.json
index 3717f9578..26652a04a 100644
--- a/package.json
+++ b/package.json
@@ -44,16 +44,16 @@
       "types": "./src/style.css.d.ts"
     },
     "./style.module.css": {
-      "require": "./src/style.css",
-      "import": "./src/style.css",
-      "default": "./src/style.css",
-      "types": "./src/style.css.d.ts"
+      "require": "./src/style.module.css",
+      "import": "./src/style.module.css",
+      "default": "./src/style.module.css",
+      "types": "./src/style.module.css.d.ts"
     },
     "./dist/style.module.css": {
-      "require": "./src/style.css",
-      "import": "./src/style.css",
-      "default": "./src/style.css",
-      "types": "./src/style.css.d.ts"
+      "require": "./src/style.module.css",
+      "import": "./src/style.module.css",
+      "default": "./src/style.module.css",
+      "types": "./src/style.module.css.d.ts"
     },
     "./package.json": {
       "require": "./package.json",
@@ -66,6 +66,7 @@
     "build": "pnpm build:cjs && pnpm build:esm",
     "build:cjs": "tsc --project tsconfig-cjs.json",
     "build:esm": "tsc --project tsconfig-esm.json",
+    "build:css": "tcm src",
     "lint": "eslint .",
     "test": "jest",
     "test-watch": "jest --watch",
@@ -111,7 +112,8 @@
     "ts-jest": "^29.1.3",
     "ts-node": "^10.9.2",
     "tslib": "^2.6.2",
-    "typescript": "~5.4.5"
+    "typescript": "~5.4.5",
+    "typescript-css-modules": "^1.0.4"
   },
   "peerDependencies": {
     "date-fns": "^2.28.0 || ^3.0.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index ddc20e0f8..a58b9e015 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -100,7 +100,7 @@ importers:
         version: 18.3.1(react@18.3.1)
       ts-jest:
         specifier: ^29.1.3
-        version: 29.1.3(@babel/core@7.23.6)(@jest/types@29.6.3)(jest@29.7.0)(typescript@5.4.5)
+        version: 29.1.3(@babel/core@7.23.0)(@jest/types@29.6.3)(jest@29.7.0)(typescript@5.4.5)
       ts-node:
         specifier: ^10.9.2
         version: 10.9.2(@types/node@20.12.12)(typescript@5.4.5)
@@ -110,6 +110,9 @@ importers:
       typescript:
         specifier: ~5.4.5
         version: 5.4.5
+      typescript-css-modules:
+        specifier: ^1.0.4
+        version: 1.0.4
 
   website:
     dependencies:
@@ -3896,6 +3899,10 @@ packages:
       '@types/node': 20.12.12
     dev: false
 
+  /@types/css@0.0.30:
+    resolution: {integrity: sha512-7q091Zj54s9A3RVUeeHNhV4dSqJOomMUwp33P5gccw3IioHCIb0eK/q7+MqpnCRy9JNpisf9b4yG0r4d1sT0Gw==}
+    dev: true
+
   /@types/debug@4.1.12:
     resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
     dependencies:
@@ -4129,16 +4136,35 @@ packages:
     resolution: {integrity: sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==}
     dev: true
 
+  /@types/tapable@0.2.9:
+    resolution: {integrity: sha512-SBDYUqhRCLeIEBedB+NAzFpxvst6rYFkxLjpQnqBPfXHsihSgSNhBwqxcIVJenwXvYkxxIRucFLKY87zq5lLlw==}
+    dev: true
+
   /@types/tough-cookie@4.0.2:
     resolution: {integrity: sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==}
     dev: true
 
+  /@types/uglify-js@3.17.5:
+    resolution: {integrity: sha512-TU+fZFBTBcXj/GpDpDaBmgWk/gn96kMZ+uocaFUlV2f8a6WdMzzI44QBCmGcCiYR0Y6ZlNRiyUyKKt5nl/lbzQ==}
+    dependencies:
+      source-map: 0.6.1
+    dev: true
+
   /@types/unist@2.0.8:
     resolution: {integrity: sha512-d0XxK3YTObnWVp6rZuev3c49+j4Lo8g4L1ZRm9z5L0xpoZycUPshHgczK5gsUMaZOstjVYYi09p5gYvUtfChYw==}
 
   /@types/unist@3.0.2:
     resolution: {integrity: sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==}
 
+  /@types/webpack@3.8.27:
+    resolution: {integrity: sha512-nqLESI6KtyNYeT25TMxL4FQ0Z+1aItPIXAyfphMH0bOohjq8FVJtk8RKSu0YqoIEyWRyzpd4UA7yc9VPN4Defw==}
+    dependencies:
+      '@types/node': 20.12.12
+      '@types/tapable': 0.2.9
+      '@types/uglify-js': 3.17.5
+      source-map: 0.6.1
+    dev: true
+
   /@types/ws@8.5.10:
     resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==}
     dependencies:
@@ -4930,6 +4956,12 @@ packages:
     engines: {node: '>= 4.0.0'}
     dev: false
 
+  /atob@2.1.2:
+    resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==}
+    engines: {node: '>= 4.5.0'}
+    hasBin: true
+    dev: true
+
   /autoprefixer@10.4.19(postcss@8.4.38):
     resolution: {integrity: sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==}
     engines: {node: ^10 || ^12 || >=14}
@@ -5932,6 +5964,15 @@ packages:
     resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==}
     dev: true
 
+  /css@2.2.4:
+    resolution: {integrity: sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==}
+    dependencies:
+      inherits: 2.0.4
+      source-map: 0.6.1
+      source-map-resolve: 0.5.3
+      urix: 0.1.0
+    dev: true
+
   /cssesc@3.0.0:
     resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
     engines: {node: '>=4'}
@@ -6123,6 +6164,11 @@ packages:
     dependencies:
       character-entities: 2.0.2
 
+  /decode-uri-component@0.2.2:
+    resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==}
+    engines: {node: '>=0.10'}
+    dev: true
+
   /decompress-response@6.0.0:
     resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==}
     engines: {node: '>=10'}
@@ -11808,6 +11854,11 @@ packages:
     resolution: {integrity: sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==}
     dev: false
 
+  /resolve-url@0.2.1:
+    resolution: {integrity: sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==}
+    deprecated: https://github.com/lydell/resolve-url#deprecated
+    dev: true
+
   /resolve.exports@2.0.2:
     resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==}
     engines: {node: '>=10'}
@@ -12251,6 +12302,17 @@ packages:
     engines: {node: '>=0.10.0'}
     dev: false
 
+  /source-map-resolve@0.5.3:
+    resolution: {integrity: sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==}
+    deprecated: See https://github.com/lydell/source-map-resolve#deprecated
+    dependencies:
+      atob: 2.1.2
+      decode-uri-component: 0.2.2
+      resolve-url: 0.2.1
+      source-map-url: 0.4.1
+      urix: 0.1.0
+    dev: true
+
   /source-map-support@0.5.13:
     resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==}
     dependencies:
@@ -12264,6 +12326,11 @@ packages:
       buffer-from: 1.1.2
       source-map: 0.6.1
 
+  /source-map-url@0.4.1:
+    resolution: {integrity: sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==}
+    deprecated: See https://github.com/lydell/source-map-url#deprecated
+    dev: true
+
   /source-map@0.5.7:
     resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==}
     engines: {node: '>=0.10.0'}
@@ -12717,6 +12784,44 @@ packages:
       typescript: 5.4.5
     dev: true
 
+  /ts-jest@29.1.3(@babel/core@7.23.0)(@jest/types@29.6.3)(jest@29.7.0)(typescript@5.4.5):
+    resolution: {integrity: sha512-6L9qz3ginTd1NKhOxmkP0qU3FyKjj5CPoY+anszfVn6Pmv/RIKzhiMCsH7Yb7UvJR9I2A64rm4zQl531s2F1iw==}
+    engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0}
+    hasBin: true
+    peerDependencies:
+      '@babel/core': '>=7.0.0-beta.0 <8'
+      '@jest/transform': ^29.0.0
+      '@jest/types': ^29.0.0
+      babel-jest: ^29.0.0
+      esbuild: '*'
+      jest: ^29.0.0
+      typescript: '>=4.3 <6'
+    peerDependenciesMeta:
+      '@babel/core':
+        optional: true
+      '@jest/transform':
+        optional: true
+      '@jest/types':
+        optional: true
+      babel-jest:
+        optional: true
+      esbuild:
+        optional: true
+    dependencies:
+      '@babel/core': 7.23.0
+      '@jest/types': 29.6.3
+      bs-logger: 0.2.6
+      fast-json-stable-stringify: 2.1.0
+      jest: 29.7.0(@types/node@20.12.12)(ts-node@10.9.2)
+      jest-util: 29.7.0
+      json5: 2.2.3
+      lodash.memoize: 4.1.2
+      make-error: 1.3.6
+      semver: 7.6.0
+      typescript: 5.4.5
+      yargs-parser: 21.1.1
+    dev: true
+
   /ts-jest@29.1.3(@babel/core@7.23.6)(@jest/types@29.6.3)(jest@29.7.0)(typescript@5.4.5):
     resolution: {integrity: sha512-6L9qz3ginTd1NKhOxmkP0qU3FyKjj5CPoY+anszfVn6Pmv/RIKzhiMCsH7Yb7UvJR9I2A64rm4zQl531s2F1iw==}
     engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0}
@@ -12976,6 +13081,14 @@ packages:
       typescript: 5.4.5
     dev: true
 
+  /typescript-css-modules@1.0.4:
+    resolution: {integrity: sha512-r2vUBeCnvAMTQeA7FgZkyz219dpVeWWT/DVkMU3/gfFNzf346LZdTXDB6vQrHRpetCjcw5s9uPy/NV79V7B7Jw==}
+    dependencies:
+      '@types/css': 0.0.30
+      '@types/webpack': 3.8.27
+      css: 2.2.4
+    dev: true
+
   /typescript@5.4.5:
     resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==}
     engines: {node: '>=14.17'}
@@ -13155,6 +13268,11 @@ packages:
     dependencies:
       punycode: 2.1.1
 
+  /urix@0.1.0:
+    resolution: {integrity: sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==}
+    deprecated: Please see https://github.com/lydell/urix#deprecated
+    dev: true
+
   /url-loader@4.1.1(file-loader@6.2.0)(webpack@5.89.0):
     resolution: {integrity: sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==}
     engines: {node: '>= 10.13.0'}
diff --git a/src/UI.ts b/src/UI.ts
index f5a0ea0f9..578230945 100644
--- a/src/UI.ts
+++ b/src/UI.ts
@@ -1,3 +1,8 @@
+/**
+ * The UI elements composing DayPicker.
+ *
+ * These elements are mapped to the components directory.
+ */
 /**
  * The UI elements composing DayPicker.
  *
@@ -10,12 +15,12 @@ export enum UI {
   ButtonNext = "button_next",
   /** The calendar element, the root of the component. */
   Calendar = "calendar",
+  /** The Chevron SVG element used by navigation buttons and dropdowns. */
+  Chevron = "chevron",
   /** The gridcell with the day's date. */
   Day = "day",
   /** The label of a caption. */
   CaptionLabel = "caption_label",
-  /** The Chevron SVG element used by navigation buttons and dropdowns. */
-  Chevron = "chevron",
   /** The container of the dropdown navigation.. */
   DropdownNav = "dropdown_nav",
   /** The dropdown used for years and months. */
@@ -24,22 +29,22 @@ export enum UI {
   DropdownRoot = "dropdown_root",
   /** The root element of the {@link Footer} component. */
   Footer = "footer",
+  /** The month grid. */
+  Month = "month",
   /** The caption of a month. */
   MonthCaption = "month_caption",
   /** The dropdown of months. */
   MonthsDropdown = "months_dropdown",
   /** Wrapper of the month grid. */
   MonthWrapper = "month_wrapper",
-  /** The month grid. */
-  Month = "month",
-  /** The group of weeks in a month. */
-  Weeks = "weeks",
   /** Container containing the months. */
   Months = "months",
   /** The navigation element. */
   Nav = "nav",
   /** The row in a week. */
   Week = "week",
+  /** The group of weeks in a month. */
+  Weeks = "weeks",
   /** The column's header with the weekday. */
   Weekday = "weekday",
   /** The row grouping the weekdays. */
@@ -77,9 +82,9 @@ export enum DayModifier {
 /** Flags that can be applied to the {@link UI.Calendar} element. */
 export enum CalendarFlag {
   /** Assigned when the week numbers are show. */
-  hasWeekNumbers = "week_numbers",
+  hasWeekNumbers = "has_week_numbers",
   /** Assigned when the weekdays are hidden. */
   noWeekdays = "no_weekdays",
   /** Assigned when the calendar has multiple months. */
-  hasMultipleMonths = "multiple_months"
+  hasMultipleMonths = "has_multiple_months"
 }
diff --git a/src/style.css b/src/style.css
index 55d505be3..573c8101f 100644
--- a/src/style.css
+++ b/src/style.css
@@ -159,11 +159,11 @@
   fill: var(--rdp-accent-color);
 }
 
-.rdp[dir="rtl"] .rdp-chevron {
+.rdp-calendar[dir="rtl"] .rdp-chevron {
   transform: rotate(180deg);
 }
 
-.rdp[dir="rtl"] .rdp-chevron {
+.rdp-calendar[dir="rtl"] .rdp-chevron {
   transform: rotate(180deg);
   transform-origin: 50%;
 }
@@ -241,7 +241,7 @@
   grid-template-columns: repeat(7, 1fr);
 }
 
-.rdp-week_numbers .rdp-week {
+.rdp-has_week_numbers .rdp-week {
   grid-template-columns: repeat(8, 1fr);
 }
 
@@ -258,7 +258,7 @@
   grid-template-columns: repeat(7, 1fr);
 }
 
-.rdp-week_numbers .rdp-weekdays {
+.rdp-has_week_numbers .rdp-weekdays {
   grid-template-columns: repeat(8, 1fr);
 }
 
@@ -278,7 +278,7 @@
   cursor: pointer;
 }
 
-.rdp-weeknumber[data-interactive] .rdp-weekday {
+.rdp-week_number[data-interactive] .rdp-weekday {
   display: inline-flex;
   align-items: center;
   justify-content: center;
@@ -341,3 +341,14 @@
 .rdp-focusable {
   cursor: pointer;
 }
+
+.rdp-footer,
+.rdp-months_dropdown,
+.rdp-month_wrapper,
+.rdp-month,
+.rdp-weeks,
+.rdp-no_weekdays,
+.rdp-years_dropdown {
+  /* These classes are not used by the default style, but are available to use */
+  /* Keep anyway for the CSS type definition. */
+}
diff --git a/src/style.css.d.ts b/src/style.css.d.ts
new file mode 100644
index 000000000..47b01bf71
--- /dev/null
+++ b/src/style.css.d.ts
@@ -0,0 +1,37 @@
+declare const styles: {
+  readonly "rdp-button_next": string;
+  readonly "rdp-button_previous": string;
+  readonly "rdp-calendar": string;
+  readonly "rdp-caption_label": string;
+  readonly "rdp-chevron": string;
+  readonly "rdp-day": string;
+  readonly "rdp-disabled": string;
+  readonly "rdp-dropdown": string;
+  readonly "rdp-dropdown_nav": string;
+  readonly "rdp-dropdown_root": string;
+  readonly "rdp-focusable": string;
+  readonly "rdp-footer": string;
+  readonly "rdp-has_week_numbers": string;
+  readonly "rdp-hidden": string;
+  readonly "rdp-month": string;
+  readonly "rdp-month_caption": string;
+  readonly "rdp-month_wrapper": string;
+  readonly "rdp-months": string;
+  readonly "rdp-months_dropdown": string;
+  readonly "rdp-nav": string;
+  readonly "rdp-no_weekdays": string;
+  readonly "rdp-outside": string;
+  readonly "rdp-range_end": string;
+  readonly "rdp-range_middle": string;
+  readonly "rdp-range_start": string;
+  readonly "rdp-selected": string;
+  readonly "rdp-today": string;
+  readonly "rdp-week": string;
+  readonly "rdp-week_number": string;
+  readonly "rdp-weekday": string;
+  readonly "rdp-weekdays": string;
+  readonly "rdp-weeks": string;
+  readonly "rdp-years_dropdown": string;
+};
+export = styles;
+
diff --git a/src/style.d.ts b/src/style.d.ts
deleted file mode 100644
index e385bf774..000000000
--- a/src/style.d.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import { UI } from "./types";
-
-/** The class names that can passed to DayPicker's `classNames` prop. */
-const classNames: {
-  [uiElement in UI]: string;
-// eslint-disable-next-line prettier/prettier
-}
-
-export default classNames;
diff --git a/src/style.module.css b/src/style.module.css
new file mode 100644
index 000000000..04d0f825a
--- /dev/null
+++ b/src/style.module.css
@@ -0,0 +1,354 @@
+:root {
+  /* The accent color used for selected days and ui elements. */
+  --rdp-accent-color: blue;
+
+  /* The font family used by the calendar. (`inherited` won't work here) */
+  --rdp-font-family: system-ui;
+
+  /* The gap between the months in the multi-month view. */
+  --rdp-months-gap: 2rem;
+
+  /* The font used for the day cells. */
+  --rdp-day-font: inherit;
+
+  /* The width of the day cells. */
+  --rdp-day-width: 2.75rem;
+
+  /* The height of the day cells. */
+  --rdp-day-height: 2.75rem;
+
+  /* The border of the day cells. */
+  --rdp-day-border: 2px solid transparent;
+
+  /* The border radius of the day cells. */
+  --rdp-day-border-radius: 100%;
+
+  /* The opacity of the days outside the current month. */
+  --rdp-outside-opacity: 0.75;
+
+  /* The opacity of the disabled days. */
+  --rdp-disabled-opacity: 0.5;
+
+  /* The border of the selected days. */
+  --rdp-selected-border: 2px solid var(--rdp-accent-color);
+
+  /* The font of the selected days. */
+  --rdp-selected-font: bold large var(--rdp-font-family);
+
+  /* The color of the today's date. */
+  --rdp-today-color: var(--rdp-accent-color);
+
+  /* The height of the navigation bar. */
+  --rdp-nav-height: 2.75rem;
+
+  /* The width of the navigation buttons. */
+  --rdp-nav-button-width: 2.25rem;
+
+  /* The height of the navigation buttons. */
+  --rdp-nav-button-height: 2.25rem;
+
+  /* The opacity of the disabled navigation buttons. */
+  --rdp-nav-button-disabled-opacity: 0.5;
+
+  /* The border radius of the navigation buttons. */
+  --rdp-nav-button-border-radius: 100%;
+
+  /* The height of the week number cells. */
+  --rdp-week_number-height: var(--rdp-day-height);
+
+  /* The width of the week number cells. */
+  --rdp-week_number-width: var(--rdp-day-width);
+
+  /* The font of the week number cells. */
+  --rdp-week_number-font: 400 small var(--rdp-font-family);
+
+  /* The border radius of the week number. */
+  --rdp-week_number-border-radius: 100%;
+
+  /* The border of the week number. */
+  --rdp-week_number-border: 2px solid transparent;
+
+  /* The opacity of the week number. */
+  --rdp-week_number-opacity: 0.75;
+
+  /* The font of the weekday. */
+  --rdp-weekday-font: 500 smaller var(--rdp-font-family);
+
+  /* The opacity of the weekday. */
+  --rdp-weekday-opacity: 0.75;
+
+  /* THe padding of the weekday. */
+  --rdp-weekday-padding: 0.25rem 0.75rem;
+
+  /* The text alignment of the weekday cells. */
+  --rdp-weekday-text-align: center;
+
+  /* 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 range text. */
+  --rdp-range-color: white;
+}
+
+.button_next,
+.button_previous {
+  -moz-appearance: none;
+  -webkit-appearance: none;
+  display: inline-flex;
+  align-items: center;
+  justify-content: center;
+  margin: 0;
+  padding: 0;
+  position: relative;
+  font: inherit;
+  appearance: none;
+  background: none;
+  border: 0;
+  color: inherit;
+  cursor: pointer;
+
+  border-radius: var(--rdp-nav-button-border-radius);
+  width: var(--rdp-nav-button-width);
+  height: var(--rdp-nav-button-height);
+}
+
+.button_next:disabled,
+.button_previous:disabled {
+  opacity: var(--rdp-nav-button-disabled-opacity);
+  cursor: revert;
+}
+
+.calendar {
+  display: inline-block;
+  position: relative;
+}
+
+.calendar,
+.calendar * {
+  box-sizing: border-box;
+}
+
+.day {
+  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 {
+  z-index: 1;
+
+  position: relative;
+  display: inline-flex;
+  align-items: center;
+
+  white-space: nowrap;
+  border: 0;
+}
+
+.chevron {
+  display: inline-block;
+  fill: var(--rdp-accent-color);
+}
+
+.calendar[dir="rtl"] .chevron {
+  transform: rotate(180deg);
+}
+
+.calendar[dir="rtl"] .chevron {
+  transform: rotate(180deg);
+  transform-origin: 50%;
+}
+
+.dropdown_nav {
+  position: relative;
+  display: inline-flex;
+}
+.dropdown {
+  z-index: 2; /* Remove ? */
+
+  /* Reset */
+  appearance: none;
+  position: absolute;
+  inset-block-start: 0;
+  inset-block-end: 0;
+  inset-inline-start: 0;
+  width: 100%;
+  margin: 0;
+  padding: 0;
+  cursor: inherit;
+  opacity: 0;
+  border: none;
+  background-color: transparent;
+  line-height: inherit;
+  /* font: 1rem; */
+}
+
+.dropdown[disabled] {
+  opacity: unset;
+  color: unset;
+}
+
+.dropdown_root {
+  position: relative;
+  display: inline-flex;
+  align-items: center;
+}
+
+.dropdown_root::after {
+  position: absolute;
+  inset-block-start: 50%;
+  inset-inline-end: 5px;
+  transform: translateY(-50%);
+  pointer-events: none;
+}
+
+.month_caption {
+  display: flex;
+  align-content: center;
+  height: var(--rdp-nav-height);
+  font: var(--rdp-month-caption-font);
+}
+
+.months {
+  display: flex;
+  flex-wrap: wrap;
+  gap: var(--rdp-months-gap);
+  justify-content: center;
+}
+
+.nav {
+  position: absolute;
+  inset-block-start: 0;
+  inset-inline-end: 0;
+
+  display: flex;
+  align-items: center;
+
+  height: var(--rdp-nav-height);
+}
+
+.week {
+  display: grid;
+  grid-template-columns: repeat(7, 1fr);
+}
+
+.has_week_numbers .week {
+  grid-template-columns: repeat(8, 1fr);
+}
+
+.weekday {
+  opacity: var(--rdp-weekday-opacity);
+  padding-block: var(--rdp-weekday-padding);
+  font: var(--rdp-weekday-font);
+  text-align: var(--rdp-weekday-text-align);
+  text-transform: var(--rdp-weekday-text-transform);
+}
+
+.weekdays {
+  display: grid;
+  grid-template-columns: repeat(7, 1fr);
+}
+
+.has_week_numbers .weekdays {
+  grid-template-columns: repeat(8, 1fr);
+}
+
+.week_number {
+  justify-content: center;
+  align-items: center;
+  display: flex;
+
+  opacity: var(--rdp-week_number-opacity);
+  font: var(--rdp-week_number-font);
+  height: var(--rdp-week_number-height);
+  width: var(--rdp-week_number-width);
+  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);
+}
+
+/* DAY MODIFIERS */
+
+.today:not(.outside) {
+  color: var(--rdp-today-color);
+}
+
+.selected,
+.selected.outside {
+  font: var(--rdp-selected-font);
+  border: var(--rdp-selected-border);
+}
+
+.outside {
+  opacity: var(--rdp-outside-opacity);
+}
+
+.disabled {
+  opacity: var(--rdp-disabled-opacity);
+  cursor: revert;
+}
+
+.hidden {
+  visibility: hidden;
+}
+
+.range_start {
+  border-start-end-radius: 0;
+  border-end-end-radius: 0;
+}
+
+.range_start.selected,
+.range_end.selected,
+.range_middle.selected {
+  border-color: transparent;
+  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_end.range_start {
+  border-radius: var(--rdp-day-border-radius);
+}
+
+.range_middle {
+  border-radius: 0;
+}
+
+.focusable {
+  cursor: pointer;
+}
+
+.footer,
+.months_dropdown,
+.month_wrapper,
+.month,
+.weeks,
+.no_weekdays,
+.years_dropdown {
+  /* These classes are not used by the default style, but are available to use */
+  /* Keep anyway for the CSS type definition. */
+}
diff --git a/src/style.module.css.d.ts b/src/style.module.css.d.ts
new file mode 100644
index 000000000..cf27a447d
--- /dev/null
+++ b/src/style.module.css.d.ts
@@ -0,0 +1,37 @@
+declare const styles: {
+  readonly "button_next": string;
+  readonly "button_previous": string;
+  readonly "calendar": string;
+  readonly "caption_label": string;
+  readonly "chevron": string;
+  readonly "day": string;
+  readonly "disabled": string;
+  readonly "dropdown": string;
+  readonly "dropdown_nav": string;
+  readonly "dropdown_root": string;
+  readonly "focusable": string;
+  readonly "footer": string;
+  readonly "has_week_numbers": string;
+  readonly "hidden": string;
+  readonly "month": string;
+  readonly "month_caption": string;
+  readonly "month_wrapper": string;
+  readonly "months": string;
+  readonly "months_dropdown": string;
+  readonly "nav": string;
+  readonly "no_weekdays": string;
+  readonly "outside": string;
+  readonly "range_end": string;
+  readonly "range_middle": string;
+  readonly "range_start": string;
+  readonly "selected": string;
+  readonly "today": string;
+  readonly "week": string;
+  readonly "week_number": string;
+  readonly "weekday": string;
+  readonly "weekdays": string;
+  readonly "weeks": string;
+  readonly "years_dropdown": string;
+};
+export = styles;
+
diff --git a/website/docs/using-daypicker/styling.mdx b/website/docs/using-daypicker/styling.mdx
index e60728a07..1c5a31c25 100644
--- a/website/docs/using-daypicker/styling.mdx
+++ b/website/docs/using-daypicker/styling.mdx
@@ -23,21 +23,24 @@ import "react-day-picker/style.css";
 
 </details>
 
-<details>
-<summary>Importing the CSS Module</summary>
+### Importing the CSS Module
 
-When using CSS modules, you can import `style.module.css`. Pass the class names to the `classNames` prop.
+You can import `style.module.css` if you want your CSS pre-processor to parse it. Pass the imported styles to the `classNames` prop.
 
-```tsx title="./DatePicker.jsx"
+```tsx title="./MyDatePicker.jsx"
 import { DayPicker } from "react-day-picker";
-import { default as defaultStyles } from "react-day-picker/style.module.css";
+import styles from "react-day-picker/style.module.css";
+
+console.log(styles); // Output the class names as parsed by CSS modules.
 
-export function DatePicker() {
-  return <DayPicker classNames={defaultStyles} />;
+export function MyDatePicker() {
+  return <DayPicker classNames={styles} />;
 }
 ```
 
-</details>
+<BrowserWindow>
+  <Examples.CssModules />
+</BrowserWindow>
 
 ### CSS Variables
 
@@ -107,10 +110,12 @@ Use the `classNames` prop to use other classnames instead of the default ones.
 
 ### Tailwind CSS
 
-> TODO: this section is still incomplete.
+...
 
 ### Custom CSS
 
+...
+
 ### Inline Styles
 
 To change the appearance of any DayPicker element via inline-styles use the `styles` prop.
diff --git a/website/docusaurus.config.ts b/website/docusaurus.config.ts
index 6cfaf2eb4..4e2f5180f 100644
--- a/website/docusaurus.config.ts
+++ b/website/docusaurus.config.ts
@@ -97,10 +97,6 @@ const config: Config = {
           "date picker, react component, calendar component, react datepicker, daypicker, react day picker, date-fns date picker, typescript date picker"
       }
     ],
-    // announcementBar: {
-    // id: "announcement-v9", // Increment on change
-    // content: ``,
-    // },
     navbar: {
       title: "React DayPicker",
       logo: {
@@ -166,23 +162,6 @@ const config: Config = {
     colorMode: {
       defaultMode: "light",
       respectPrefersColorScheme: true
-    },
-    webpack: {
-      configure: (webpackConfig) => {
-        // Alias 'react-day-picker-v8' to the npm package installed with the alias
-        webpackConfig.resolve.alias["react-day-picker-v8"] = path.resolve(
-          __dirname,
-          "node_modules/react-day-picker-v8"
-        );
-
-        // Possibly ensure that all instances of 'react-day-picker' are resolved to your custom package
-        webpackConfig.resolve.alias["react-day-picker"] = path.resolve(
-          __dirname,
-          "../packages/react-day-picker"
-        );
-
-        return webpackConfig;
-      }
     }
   } satisfies Preset.ThemeConfig
 };
diff --git a/website/examples-v9/CssModules.tsx b/website/examples-v9/CssModules.tsx
new file mode 100644
index 000000000..e84bfc205
--- /dev/null
+++ b/website/examples-v9/CssModules.tsx
@@ -0,0 +1,6 @@
+import { DayPicker } from "react-day-picker";
+import classNames from "react-day-picker/style.module.css";
+
+export function CssModules() {
+  return <DayPicker classNames={classNames} />;
+}
diff --git a/website/examples-v9/StylingCssModules.module.css b/website/examples-v9/StylingCssModules.module.css
deleted file mode 100644
index 8b928cdf9..000000000
--- a/website/examples-v9/StylingCssModules.module.css
+++ /dev/null
@@ -1,7 +0,0 @@
-.month_caption {
-  margin-bottom: 0.5em;
-  font-size: var(--rdp-font-large);
-  font-family: Georgia, "Times New Roman", Times, serif;
-  padding-bottom: 0.5rem;
-  border-bottom: 1px solid currentcolor;
-}
diff --git a/website/examples-v9/StylingCssModules.tsx b/website/examples-v9/StylingCssModules.tsx
deleted file mode 100644
index ce186c83d..000000000
--- a/website/examples-v9/StylingCssModules.tsx
+++ /dev/null
@@ -1,6 +0,0 @@
-import { DayPicker } from "react-day-picker";
-import defaultStyles from "react-day-picker/style.module.css";
-
-export function StylingCssModules() {
-  return <DayPicker classNames={{ ...defaultStyles }} />;
-}
diff --git a/website/examples-v9/index.ts b/website/examples-v9/index.ts
index c067fb399..af6ee7eba 100644
--- a/website/examples-v9/index.ts
+++ b/website/examples-v9/index.ts
@@ -2,6 +2,7 @@ export * from "./ContainerAttributes";
 export * from "./Controlled";
 
 export * from "./CssVariables";
+export * from "./CssModules";
 export * from "./CustomCaption";
 export * from "./CustomDay";
 export * from "./CustomMultiple";
@@ -49,7 +50,6 @@ export * from "./Spanish";
 export * from "./SpanishWeekStartsOn";
 export * from "./Start";
 export * from "./StylingCss";
-export * from "./StylingCssModules";
 export * from "./StylingInline";
 export * from "./StylingModifiers";
 export * from "./Testcase1567";


Test patch:
diff --git a/src/components/Calendar.test.tsx b/src/components/Calendar.test.tsx
index fd501c6a0..847564f12 100644
--- a/src/components/Calendar.test.tsx
+++ b/src/components/Calendar.test.tsx
@@ -21,8 +21,8 @@ it("should apply classnames and style according to props", () => {
   });
 
   expect(container.firstChild).toHaveClass("rdp-calendar");
-  expect(container.firstChild).toHaveClass("rdp-multiple_months");
-  expect(container.firstChild).toHaveClass("rdp-week_numbers");
+  expect(container.firstChild).toHaveClass("rdp-has_multiple_months");
+  expect(container.firstChild).toHaveClass("rdp-has_week_numbers");
   expect(container.firstChild).toHaveClass("custom-class");
   expect(container.firstChild).toHaveStyle({ color: "red" });
 });
diff --git a/src/helpers/getDefaultClassNames.test.ts b/src/helpers/getDefaultClassNames.test.ts
index 65864e390..fb1f1376c 100644
--- a/src/helpers/getDefaultClassNames.test.ts
+++ b/src/helpers/getDefaultClassNames.test.ts
@@ -15,8 +15,8 @@ test("should return the default classnames", () => {
     focusable: "rdp-focusable",
     focused: "rdp-focused",
     footer: "rdp-footer",
-    multiple_months: "rdp-multiple_months",
-    week_numbers: "rdp-week_numbers",
+    has_multiple_months: "rdp-has_multiple_months",
+    has_week_numbers: "rdp-has_week_numbers",
     hidden: "rdp-hidden",
     month_caption: "rdp-month_caption",
     month_wrapper: "rdp-month_wrapper",
diff --git a/src/helpers/useControlledValue.test.ts b/src/helpers/useControlledValue.test.ts
index e1cc7b02e..0a6358fff 100644
--- a/src/helpers/useControlledValue.test.ts
+++ b/src/helpers/useControlledValue.test.ts
@@ -1,5 +1,4 @@
-import { renderHook } from "@testing-library/react";
-import { act } from "react-dom/test-utils";
+import { act, renderHook } from "@testing-library/react";
 
 import { useControlledValue } from "./useControlledValue";
 
diff --git a/website/examples-v9/StylingCssModules.test.tsx b/website/examples-v9/StylingCssModules.test.tsx
index 6184dd2a8..bba242cbc 100644
--- a/website/examples-v9/StylingCssModules.test.tsx
+++ b/website/examples-v9/StylingCssModules.test.tsx
@@ -1,12 +1,12 @@
 import { app, mockDate, renderApp } from "@/test";
 
-import { StylingCssModules } from "./StylingCssModules";
+import { CssModules } from "./CssModules";
 
 const today = new Date(2021, 10, 25);
 mockDate(today);
 
 beforeEach(() => {
-  renderApp(<StylingCssModules />);
+  renderApp(<CssModules />);
 });
 
 test("should match the snapshot", () => {