@synerise/ds-date-picker 2.1.0 → 2.1.1

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/CHANGELOG.md CHANGED
@@ -3,6 +3,12 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [2.1.1](https://github.com/Synerise/synerise-design/compare/@synerise/ds-date-picker@2.1.0...@synerise/ds-date-picker@2.1.1) (2026-09-16)
7
+
8
+ ### Bug Fixes
9
+
10
+ - **date-picker:** keep the local clock when a day click crosses a DST boundary ([81fb588](https://github.com/Synerise/synerise-design/commit/81fb5883286faa1a938d3ec5909a1e48a6cb68b7))
11
+
6
12
  # [2.1.0](https://github.com/Synerise/synerise-design/compare/@synerise/ds-date-picker@2.0.3...@synerise/ds-date-picker@2.1.0) (2026-09-10)
7
13
 
8
14
  ### Features
package/CLAUDE.md CHANGED
@@ -30,7 +30,7 @@ src/
30
30
  fns.tsx — date-fns re-exports (named, from the package root)
31
31
  format.ts — fnsFormat wrapper
32
32
  localeUtils.ts — weekday/month name tables; adapted into react-day-picker formatters/labels
33
- utils.ts — changeDayWithHoursPreserved and other helpers
33
+ utils.ts — range / getDecadeRange / getCenturyRange helpers
34
34
  index.ts — public exports
35
35
  ```
36
36
 
@@ -140,7 +140,7 @@ import { RawDatePicker } from '@synerise/ds-date-picker';
140
140
  - **`readOnly` short-circuits the Dropdown** — when `readOnly={true}`, the component renders only the `PickerInput` (or `renderTrigger` output) with no calendar attached.
141
141
  - **Mode switching** — clicking the month name in `DayPicker` switches to `'month'` mode; clicking the year name switches to `'year'` mode. The back navigation in those modes returns to `'date'`. Selecting a day when `showTime=true` switches to `'time'` mode automatically.
142
142
  - **`useStartOfDay` / `useEndOfDay`** — applied on day click, before `onValueChange` fires. `useStartOfDay` takes precedence if both are set (implemented as `if/else if` in `handleDayClick`).
143
- - **Time preserved on day change** — when changing the day while already having a time selected (`changed=true`), hours/minutes/seconds from the previous value are preserved (`changeDayWithHoursPreserved`).
143
+ - **Time preserved on day change** — clicking a day rewrites only the calendar fields of the current `value` (`setYear`/`setMonth`/`setDate`), so its local clock carries over. Local fields are the whole mechanism, and they are what makes this correct across a DST boundary; do not reintroduce a seconds-difference round-trip here. The removed `changeDayWithHoursPreserved` did exactly that and multiplied a calendar-day count by a hard-coded `86400`, so any pair of dates straddling a transition came out an hour wrong — and with `useStartOfDay`/`useEndOfDay` that hour crossed midnight and moved the day.
144
144
  - **Apply vs onChange** — `onValueChange` fires on every day/time interaction. `onApply` fires only when the user explicitly clicks Apply (or selects a quick pick), and also closes the dropdown.
145
145
  - **`dropdownProps.open`** — if provided, it OR-s with internal `dropVisible` state: `open={(dropdownProps?.open || dropVisible) && !disabled}`. This means both sources can open the dropdown independently.
146
146
  - **`format` has been removed** — use `valueFormatOptions: DateToFormatOptions` (from `@synerise/ds-core`). It took a token pattern, which no consumer passed and which disagreed with `formatValue` for every locale. `PickerInput` now renders a `Date` and an ISO string identically; whether a value is an *instant* is signalled by `isInstantValue`, not inferred from its runtime type.
@@ -11,7 +11,6 @@ import TimePicker from "../Elements/TimePicker/TimePicker.js";
11
11
  import YearPicker from "../Elements/YearPicker/YearPicker.js";
12
12
  import { setYear, setMonth, setDate, startOfDay, endOfDay, addDays, startOfMonth } from "date-fns";
13
13
  import toDateValue from "../toDateValue.js";
14
- import { changeDayWithHoursPreserved } from "../utils.js";
15
14
  import { getDefaultTexts } from "../utils/getDefaultTexts.js";
16
15
  const _RawDatePicker = class _RawDatePicker extends React.Component {
17
16
  constructor(props) {
@@ -20,24 +19,11 @@ const _RawDatePicker = class _RawDatePicker extends React.Component {
20
19
  const {
21
20
  onValueChange
22
21
  } = this.props;
23
- const {
24
- mode,
25
- value: valueFromState
26
- } = this.state;
27
- if (mode === "date" && !!valueFromState && !!value) {
28
- const dateToBeUpdated = changeDayWithHoursPreserved(valueFromState, value);
29
- this.setState({
30
- value: dateToBeUpdated,
31
- changed: true
32
- });
33
- onValueChange && onValueChange(dateToBeUpdated);
34
- } else {
35
- this.setState({
36
- value,
37
- changed: true
38
- });
39
- onValueChange && onValueChange(value);
40
- }
22
+ this.setState({
23
+ value,
24
+ changed: true
25
+ });
26
+ onValueChange && onValueChange(value);
41
27
  };
42
28
  this.handleDayMouseEnter = (day) => this.setState({
43
29
  enteredTo: day
@@ -47,7 +33,6 @@ const _RawDatePicker = class _RawDatePicker extends React.Component {
47
33
  });
48
34
  this.handleDayClick = (day, modifiers) => {
49
35
  const {
50
- changed: isChanged,
51
36
  value
52
37
  } = this.state;
53
38
  const {
@@ -58,7 +43,7 @@ const _RawDatePicker = class _RawDatePicker extends React.Component {
58
43
  if (modifiers.disabled) {
59
44
  return;
60
45
  }
61
- let nextDateWithCurrentTime = isChanged && value ? value : /* @__PURE__ */ new Date();
46
+ let nextDateWithCurrentTime = value || /* @__PURE__ */ new Date();
62
47
  nextDateWithCurrentTime = setYear(nextDateWithCurrentTime, day.getFullYear());
63
48
  nextDateWithCurrentTime = setMonth(nextDateWithCurrentTime, day.getMonth());
64
49
  nextDateWithCurrentTime = setDate(nextDateWithCurrentTime, day.getDate());
package/dist/utils.d.ts CHANGED
@@ -1,4 +1,3 @@
1
1
  export declare const range: (start: number, end: number) => number[];
2
2
  export declare function getDecadeRange(cursor: Date): number[];
3
3
  export declare function getCenturyRange(cursor: Date): number[];
4
- export declare function changeDayWithHoursPreserved(oldDate: Date, chosenDate: Date): Date;
package/dist/utils.js CHANGED
@@ -1,5 +1,4 @@
1
- import { getYear, differenceInCalendarDays, differenceInSeconds, addSeconds } from "date-fns";
2
- import toDateValue from "./toDateValue.js";
1
+ import { getYear } from "date-fns";
3
2
  const range = (start, end) => {
4
3
  if (end <= start) {
5
4
  return [];
@@ -17,14 +16,7 @@ function getCenturyRange(cursor) {
17
16
  const endYear = startYear + 99;
18
17
  return [startYear, endYear];
19
18
  }
20
- function changeDayWithHoursPreserved(oldDate, chosenDate) {
21
- const dayDifferenceInSeconds = differenceInCalendarDays(toDateValue(oldDate), toDateValue(chosenDate)) * 24 * 60 * 60;
22
- const difference = differenceInSeconds(oldDate, chosenDate) - dayDifferenceInSeconds;
23
- const dateToBeUpdated = addSeconds(chosenDate, difference);
24
- return dateToBeUpdated;
25
- }
26
19
  export {
27
- changeDayWithHoursPreserved,
28
20
  getCenturyRange,
29
21
  getDecadeRange,
30
22
  range
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synerise/ds-date-picker",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "description": "DatePicker UI Component for the Synerise Design System",
5
5
  "license": "ISC",
6
6
  "repository": "Synerise/synerise-design",
@@ -30,7 +30,8 @@
30
30
  "build:watch": "vite build --watch",
31
31
  "pack:ci": "pnpm pack --pack-destination ../../storybook/storybook-static/static",
32
32
  "prepublish": "pnpm run build",
33
- "test": "vitest run",
33
+ "test": "vitest run && pnpm test:dst",
34
+ "test:dst": "TZ=Europe/Warsaw vitest run -t DaylightSavings",
34
35
  "test:watch": "vitest",
35
36
  "types": "tsc --noEmit",
36
37
  "check:circular-dependencies": "madge --circular --extensions ts,tsx,js,jsx --ts-config tsconfig.json src/ --exclude '/dist/'",
@@ -42,14 +43,14 @@
42
43
  ],
43
44
  "types": "dist/index.d.ts",
44
45
  "dependencies": {
45
- "@synerise/ds-button": "^2.0.2",
46
- "@synerise/ds-dropdown": "^2.0.3",
47
- "@synerise/ds-icon": "^2.1.0",
48
- "@synerise/ds-input": "^2.0.3",
49
- "@synerise/ds-time-picker": "^2.0.3",
50
- "@synerise/ds-tooltip": "^2.0.2",
51
- "@synerise/ds-typography": "^2.0.2",
52
- "@synerise/ds-utils": "^2.0.0",
46
+ "@synerise/ds-button": "^2.0.3",
47
+ "@synerise/ds-dropdown": "^2.1.0",
48
+ "@synerise/ds-icon": "^2.1.1",
49
+ "@synerise/ds-input": "^2.0.4",
50
+ "@synerise/ds-time-picker": "^2.0.4",
51
+ "@synerise/ds-tooltip": "^2.0.3",
52
+ "@synerise/ds-typography": "^2.0.3",
53
+ "@synerise/ds-utils": "^2.1.0",
53
54
  "classnames": "^2.5.1",
54
55
  "date-fns": "^4.1.0",
55
56
  "lodash.range": "^3.2.0",
@@ -66,5 +67,5 @@
66
67
  "react-intl": ">=3.12.0 <= 6.8",
67
68
  "styled-components": "^5.3.3"
68
69
  },
69
- "gitHead": "a49acd96b6f71f5617548ae5ce6126cb9b0985dc"
70
+ "gitHead": "71f08fdaba8e7b80731e29a03883dc6a33f2b9db"
70
71
  }