@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 +6 -0
- package/CLAUDE.md +2 -2
- package/dist/RawDatePicker/RawDatePicker.js +6 -21
- package/dist/utils.d.ts +0 -1
- package/dist/utils.js +1 -9
- package/package.json +12 -11
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 —
|
|
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** —
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
|
|
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 =
|
|
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
|
|
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.
|
|
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.
|
|
46
|
-
"@synerise/ds-dropdown": "^2.0
|
|
47
|
-
"@synerise/ds-icon": "^2.1.
|
|
48
|
-
"@synerise/ds-input": "^2.0.
|
|
49
|
-
"@synerise/ds-time-picker": "^2.0.
|
|
50
|
-
"@synerise/ds-tooltip": "^2.0.
|
|
51
|
-
"@synerise/ds-typography": "^2.0.
|
|
52
|
-
"@synerise/ds-utils": "^2.
|
|
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": "
|
|
70
|
+
"gitHead": "71f08fdaba8e7b80731e29a03883dc6a33f2b9db"
|
|
70
71
|
}
|