@uxf/ui 11.110.0 → 11.111.0-canary.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/date-picker/date-picker.spec.js +1 -1
- package/date-picker/date-picker.stories.d.ts +42 -1
- package/date-picker/date-picker.stories.js +205 -49
- package/date-range-picker/date-range-picker-decade.js +7 -10
- package/date-range-picker/date-range-picker-month.js +5 -8
- package/date-range-picker/date-range-picker-year.js +5 -8
- package/date-range-picker/date-range-picker.spec.js +1 -1
- package/date-range-picker/date-range-picker.stories.d.ts +57 -1
- package/date-range-picker/date-range-picker.stories.js +224 -23
- package/package.json +3 -3
|
@@ -6,4 +6,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const react_1 = __importDefault(require("react"));
|
|
7
7
|
const snap_test_1 = require("../utils/snap-test");
|
|
8
8
|
const date_picker_stories_1 = require("./date-picker.stories");
|
|
9
|
-
(0, snap_test_1.snapTest)("render stories", react_1.default.createElement(date_picker_stories_1.
|
|
9
|
+
(0, snap_test_1.snapTest)("render stories", react_1.default.createElement(date_picker_stories_1.Basic, null));
|
|
@@ -1,2 +1,43 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
|
|
2
|
+
/** Minimal date picker with no constraints. Select any date and it is logged to console. */
|
|
3
|
+
export declare function Basic(): React.JSX.Element;
|
|
4
|
+
/** Opens with today pre-selected so the user can see the highlighted state immediately. */
|
|
5
|
+
export declare function PreSelected(): React.JSX.Element;
|
|
6
|
+
/**
|
|
7
|
+
* Only dates within the selectable range are available.
|
|
8
|
+
* Dates outside appear dimmed and cannot be chosen.
|
|
9
|
+
*/
|
|
10
|
+
export declare function MinMaxDates(): React.JSX.Element;
|
|
11
|
+
/**
|
|
12
|
+
* Today and a cluster of dates next week are marked as unavailable.
|
|
13
|
+
* They appear crossed-out and cannot be selected even though they are within min/max.
|
|
14
|
+
*/
|
|
15
|
+
export declare function UnavailableDates(): React.JSX.Element;
|
|
16
|
+
/**
|
|
17
|
+
* datesConfig lets you attach custom CSS flags to date cells and disable whole groups.
|
|
18
|
+
*
|
|
19
|
+
* - flag-1 (selectable): +1 / +2
|
|
20
|
+
* - flag-2 (disabled): +4 / +5
|
|
21
|
+
* - no flag (disabled): +8
|
|
22
|
+
*/
|
|
23
|
+
export declare function DatesConfigFlags(): React.JSX.Element;
|
|
24
|
+
/**
|
|
25
|
+
* Combines a tight date window with several unavailable dates inside that window.
|
|
26
|
+
* Useful for availability calendars where only a handful of slots remain.
|
|
27
|
+
*/
|
|
28
|
+
export declare function MinMaxWithUnavailable(): React.JSX.Element;
|
|
29
|
+
/**
|
|
30
|
+
* The `bottomContent` prop renders arbitrary JSX below the calendar grid.
|
|
31
|
+
* Useful for legends, CTAs, or pricing summaries.
|
|
32
|
+
*/
|
|
33
|
+
export declare function WithBottomContent(): React.JSX.Element;
|
|
34
|
+
/**
|
|
35
|
+
* `onMonthChange` fires whenever the user navigates to a different month.
|
|
36
|
+
* The currently visible month is displayed below the description.
|
|
37
|
+
*/
|
|
38
|
+
export declare function OnMonthChange(): React.JSX.Element;
|
|
39
|
+
/**
|
|
40
|
+
* Kitchen-sink story combining min/max, unavailable dates, datesConfig flags,
|
|
41
|
+
* bottom content, and onMonthChange — useful for regression testing the full API.
|
|
42
|
+
*/
|
|
43
|
+
export declare function AllFeatures(): React.JSX.Element;
|
|
@@ -33,57 +33,213 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.
|
|
37
|
-
|
|
36
|
+
exports.Basic = Basic;
|
|
37
|
+
exports.PreSelected = PreSelected;
|
|
38
|
+
exports.MinMaxDates = MinMaxDates;
|
|
39
|
+
exports.UnavailableDates = UnavailableDates;
|
|
40
|
+
exports.DatesConfigFlags = DatesConfigFlags;
|
|
41
|
+
exports.MinMaxWithUnavailable = MinMaxWithUnavailable;
|
|
42
|
+
exports.WithBottomContent = WithBottomContent;
|
|
43
|
+
exports.OnMonthChange = OnMonthChange;
|
|
44
|
+
exports.AllFeatures = AllFeatures;
|
|
45
|
+
const date_string_1 = require("@uxf/datepicker/utils/date-string");
|
|
38
46
|
const react_1 = __importStar(require("react"));
|
|
39
47
|
const action_1 = require("../utils/action");
|
|
40
48
|
const date_picker_1 = require("./date-picker");
|
|
41
|
-
|
|
42
|
-
const
|
|
43
|
-
const
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
today.add(7, "days").toDate(),
|
|
49
|
-
today.add(11, "days").toDate(),
|
|
50
|
-
today.add(12, "days").toDate(),
|
|
51
|
-
];
|
|
52
|
-
const datesConfig = [
|
|
53
|
-
{
|
|
54
|
-
flag: "flag-1",
|
|
55
|
-
dates: [today.add(5, "days").toDate(), today.add(6, "days").toDate()],
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
flag: "flag-2",
|
|
59
|
-
dates: [today.add(3, "days").toDate(), today.add(4, "days").toDate()],
|
|
60
|
-
isDisabled: true,
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
dates: [today.add(8, "days").toDate()],
|
|
64
|
-
isDisabled: true,
|
|
65
|
-
},
|
|
66
|
-
];
|
|
67
|
-
function Default() {
|
|
49
|
+
// Build all demo dates relative to today using timezone-safe arithmetic
|
|
50
|
+
const todayStr = (0, date_string_1.todayDateString)();
|
|
51
|
+
const d = (n) => (0, date_string_1.fromDateString)((0, date_string_1.addDays)(todayStr, n));
|
|
52
|
+
const s = (n) => (0, date_string_1.addDays)(todayStr, n); // DateString for use in descriptions
|
|
53
|
+
// ─── Basic usage ───────────────────────────────────────────────────────────────
|
|
54
|
+
/** Minimal date picker with no constraints. Select any date and it is logged to console. */
|
|
55
|
+
function Basic() {
|
|
68
56
|
const [value, setValue] = (0, react_1.useState)(null);
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
react_1.default.createElement(date_picker_1.DatePicker, {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
57
|
+
return (react_1.default.createElement("div", { className: "space-y-2 p-8" },
|
|
58
|
+
react_1.default.createElement("p", { className: "text-sm text-gray-500" }, "Select any date \u2014 no constraints applied."),
|
|
59
|
+
react_1.default.createElement(date_picker_1.DatePicker, { onChange: (0, action_1.action)("onChange", setValue), selectedDate: value })));
|
|
60
|
+
}
|
|
61
|
+
// ─── Pre-selected date ─────────────────────────────────────────────────────────
|
|
62
|
+
/** Opens with today pre-selected so the user can see the highlighted state immediately. */
|
|
63
|
+
function PreSelected() {
|
|
64
|
+
const [value, setValue] = (0, react_1.useState)(d(0));
|
|
65
|
+
return (react_1.default.createElement("div", { className: "space-y-2 p-8" },
|
|
66
|
+
react_1.default.createElement("p", { className: "text-sm text-gray-500" },
|
|
67
|
+
s(0),
|
|
68
|
+
" (today) is pre-selected on mount."),
|
|
69
|
+
react_1.default.createElement(date_picker_1.DatePicker, { onChange: (0, action_1.action)("onChange", setValue), selectedDate: value })));
|
|
70
|
+
}
|
|
71
|
+
// ─── Min / max date constraints ────────────────────────────────────────────────
|
|
72
|
+
/**
|
|
73
|
+
* Only dates within the selectable range are available.
|
|
74
|
+
* Dates outside appear dimmed and cannot be chosen.
|
|
75
|
+
*/
|
|
76
|
+
function MinMaxDates() {
|
|
77
|
+
const [value, setValue] = (0, react_1.useState)(null);
|
|
78
|
+
return (react_1.default.createElement("div", { className: "space-y-2 p-8" },
|
|
79
|
+
react_1.default.createElement("p", { className: "text-sm text-gray-500" },
|
|
80
|
+
"Selectable range: ",
|
|
81
|
+
s(-2),
|
|
82
|
+
" \u2192 ",
|
|
83
|
+
s(28),
|
|
84
|
+
". Dates outside are dimmed."),
|
|
85
|
+
react_1.default.createElement(date_picker_1.DatePicker, { maxDate: d(28), minDate: d(-2), onChange: (0, action_1.action)("onChange", setValue), selectedDate: value })));
|
|
86
|
+
}
|
|
87
|
+
// ─── Unavailable (blocked) dates ───────────────────────────────────────────────
|
|
88
|
+
/**
|
|
89
|
+
* Today and a cluster of dates next week are marked as unavailable.
|
|
90
|
+
* They appear crossed-out and cannot be selected even though they are within min/max.
|
|
91
|
+
*/
|
|
92
|
+
function UnavailableDates() {
|
|
93
|
+
const [value, setValue] = (0, react_1.useState)(null);
|
|
94
|
+
const unavailableDates = [d(0), d(5), d(6), d(7), d(11), d(12)];
|
|
95
|
+
return (react_1.default.createElement("div", { className: "space-y-2 p-8" },
|
|
96
|
+
react_1.default.createElement("p", { className: "text-sm text-gray-500" },
|
|
97
|
+
"Blocked dates: ",
|
|
98
|
+
s(0),
|
|
99
|
+
", ",
|
|
100
|
+
s(5),
|
|
101
|
+
", ",
|
|
102
|
+
s(6),
|
|
103
|
+
", ",
|
|
104
|
+
s(7),
|
|
105
|
+
", ",
|
|
106
|
+
s(11),
|
|
107
|
+
", ",
|
|
108
|
+
s(12),
|
|
109
|
+
"."),
|
|
110
|
+
react_1.default.createElement(date_picker_1.DatePicker, { onChange: (0, action_1.action)("onChange", setValue), selectedDate: value, unavailableDates: unavailableDates })));
|
|
111
|
+
}
|
|
112
|
+
// ─── DatesConfig — custom flags and disabled groups ───────────────────────────
|
|
113
|
+
/**
|
|
114
|
+
* datesConfig lets you attach custom CSS flags to date cells and disable whole groups.
|
|
115
|
+
*
|
|
116
|
+
* - flag-1 (selectable): +1 / +2
|
|
117
|
+
* - flag-2 (disabled): +4 / +5
|
|
118
|
+
* - no flag (disabled): +8
|
|
119
|
+
*/
|
|
120
|
+
function DatesConfigFlags() {
|
|
121
|
+
const [value, setValue] = (0, react_1.useState)(null);
|
|
122
|
+
const datesConfig = [
|
|
123
|
+
{
|
|
124
|
+
flag: "flag-1",
|
|
125
|
+
dates: [d(1), d(2)],
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
flag: "flag-2",
|
|
129
|
+
dates: [d(4), d(5)],
|
|
130
|
+
isDisabled: true,
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
dates: [d(8)],
|
|
134
|
+
isDisabled: true,
|
|
135
|
+
},
|
|
136
|
+
];
|
|
137
|
+
return (react_1.default.createElement("div", { className: "space-y-2 p-8" },
|
|
138
|
+
react_1.default.createElement("p", { className: "text-sm text-gray-500" },
|
|
139
|
+
react_1.default.createElement("code", null, "flag-1"),
|
|
140
|
+
" (selectable): ",
|
|
141
|
+
s(1),
|
|
142
|
+
", ",
|
|
143
|
+
s(2),
|
|
144
|
+
" \u00B7 ",
|
|
145
|
+
react_1.default.createElement("code", null, "flag-2"),
|
|
146
|
+
" (disabled): ",
|
|
147
|
+
s(4),
|
|
148
|
+
", ",
|
|
149
|
+
s(5),
|
|
150
|
+
" \u00B7",
|
|
151
|
+
" ",
|
|
152
|
+
"disabled (no flag): ",
|
|
153
|
+
s(8)),
|
|
154
|
+
react_1.default.createElement(date_picker_1.DatePicker, { datesConfig: datesConfig, onChange: (0, action_1.action)("onChange", setValue), selectedDate: value })));
|
|
155
|
+
}
|
|
156
|
+
// ─── Min / max + unavailable combined ─────────────────────────────────────────
|
|
157
|
+
/**
|
|
158
|
+
* Combines a tight date window with several unavailable dates inside that window.
|
|
159
|
+
* Useful for availability calendars where only a handful of slots remain.
|
|
160
|
+
*/
|
|
161
|
+
function MinMaxWithUnavailable() {
|
|
162
|
+
const [value, setValue] = (0, react_1.useState)(null);
|
|
163
|
+
return (react_1.default.createElement("div", { className: "space-y-2 p-8" },
|
|
164
|
+
react_1.default.createElement("p", { className: "text-sm text-gray-500" },
|
|
165
|
+
"Window: ",
|
|
166
|
+
s(-5),
|
|
167
|
+
" \u2192 ",
|
|
168
|
+
s(20),
|
|
169
|
+
". Additionally blocked: ",
|
|
170
|
+
s(0),
|
|
171
|
+
", ",
|
|
172
|
+
s(3),
|
|
173
|
+
", ",
|
|
174
|
+
s(9),
|
|
175
|
+
", ",
|
|
176
|
+
s(15),
|
|
177
|
+
"."),
|
|
178
|
+
react_1.default.createElement(date_picker_1.DatePicker, { maxDate: d(20), minDate: d(-5), onChange: (0, action_1.action)("onChange", setValue), selectedDate: value, unavailableDates: [d(0), d(3), d(9), d(15)] })));
|
|
179
|
+
}
|
|
180
|
+
// ─── Bottom content slot ───────────────────────────────────────────────────────
|
|
181
|
+
/**
|
|
182
|
+
* The `bottomContent` prop renders arbitrary JSX below the calendar grid.
|
|
183
|
+
* Useful for legends, CTAs, or pricing summaries.
|
|
184
|
+
*/
|
|
185
|
+
function WithBottomContent() {
|
|
186
|
+
const [value, setValue] = (0, react_1.useState)(null);
|
|
187
|
+
return (react_1.default.createElement("div", { className: "space-y-2 p-8" },
|
|
188
|
+
react_1.default.createElement("p", { className: "text-sm text-gray-500" }, "Custom content rendered below the calendar grid."),
|
|
189
|
+
react_1.default.createElement(date_picker_1.DatePicker, { bottomContent: react_1.default.createElement("div", { className: "border-t pt-2 text-sm text-gray-600" },
|
|
190
|
+
react_1.default.createElement("p", null, "Legend: highlighted = special offer")), onChange: (0, action_1.action)("onChange", setValue), selectedDate: value })));
|
|
191
|
+
}
|
|
192
|
+
// ─── onMonthChange callback ────────────────────────────────────────────────────
|
|
193
|
+
/**
|
|
194
|
+
* `onMonthChange` fires whenever the user navigates to a different month.
|
|
195
|
+
* The currently visible month is displayed below the description.
|
|
196
|
+
*/
|
|
197
|
+
function OnMonthChange() {
|
|
198
|
+
const [value, setValue] = (0, react_1.useState)(null);
|
|
199
|
+
const [lastMonth, setLastMonth] = (0, react_1.useState)("—");
|
|
200
|
+
return (react_1.default.createElement("div", { className: "space-y-2 p-8" },
|
|
201
|
+
react_1.default.createElement("p", { className: "text-sm text-gray-500" },
|
|
202
|
+
"Navigate with the arrows. Last reported month: ",
|
|
203
|
+
react_1.default.createElement("strong", null, lastMonth)),
|
|
204
|
+
react_1.default.createElement(date_picker_1.DatePicker, { onChange: (0, action_1.action)("onChange", setValue), onMonthChange: (months) => {
|
|
205
|
+
const m = months.at(0);
|
|
206
|
+
setLastMonth(m ? `${m.year}-${String(m.month + 1).padStart(2, "0")}` : "—");
|
|
207
|
+
}, selectedDate: value })));
|
|
208
|
+
}
|
|
209
|
+
// ─── All features together ─────────────────────────────────────────────────────
|
|
210
|
+
/**
|
|
211
|
+
* Kitchen-sink story combining min/max, unavailable dates, datesConfig flags,
|
|
212
|
+
* bottom content, and onMonthChange — useful for regression testing the full API.
|
|
213
|
+
*/
|
|
214
|
+
function AllFeatures() {
|
|
215
|
+
const [value, setValue] = (0, react_1.useState)(null);
|
|
216
|
+
const datesConfig = [
|
|
217
|
+
{ flag: "flag-1", dates: [d(3), d(4)] },
|
|
218
|
+
{ flag: "flag-2", dates: [d(6), d(7)], isDisabled: true },
|
|
219
|
+
];
|
|
220
|
+
return (react_1.default.createElement("div", { className: "space-y-2 p-8" },
|
|
221
|
+
react_1.default.createElement("p", { className: "text-sm text-gray-500" },
|
|
222
|
+
"Window: ",
|
|
223
|
+
s(-3),
|
|
224
|
+
" \u2192 ",
|
|
225
|
+
s(25),
|
|
226
|
+
". Blocked: ",
|
|
227
|
+
s(0),
|
|
228
|
+
", ",
|
|
229
|
+
s(10),
|
|
230
|
+
". ",
|
|
231
|
+
react_1.default.createElement("code", null, "flag-1"),
|
|
232
|
+
": ",
|
|
233
|
+
s(3),
|
|
234
|
+
", ",
|
|
235
|
+
s(4),
|
|
236
|
+
".",
|
|
237
|
+
" ",
|
|
238
|
+
react_1.default.createElement("code", null, "flag-2"),
|
|
239
|
+
" (disabled): ",
|
|
240
|
+
s(6),
|
|
241
|
+
", ",
|
|
242
|
+
s(7),
|
|
243
|
+
"."),
|
|
244
|
+
react_1.default.createElement(date_picker_1.DatePicker, { bottomContent: react_1.default.createElement("div", { className: "border-t pt-2 text-xs text-gray-500" }, "flag-1 = highlighted \u00B7 flag-2 = disabled highlight"), datesConfig: datesConfig, maxDate: d(25), minDate: d(-3), onChange: (0, action_1.action)("onChange", setValue), onMonthChange: (months) => { var _a; return console.log("month changed", (_a = months.at(0)) === null || _a === void 0 ? void 0 : _a.month); }, selectedDate: value, unavailableDates: [d(0), d(10)] })));
|
|
89
245
|
}
|
|
@@ -32,9 +32,6 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
32
32
|
return result;
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
36
|
exports.DateRangePickerDecade = void 0;
|
|
40
37
|
const translations_1 = require("@uxf/core-react/translations");
|
|
@@ -44,7 +41,7 @@ const date_range_picker_context_1 = require("@uxf/datepicker/contexts/date-range
|
|
|
44
41
|
const use_decade_1 = require("@uxf/datepicker/hooks/use-decade");
|
|
45
42
|
const use_month_1 = require("@uxf/datepicker/hooks/use-month");
|
|
46
43
|
const use_year_1 = require("@uxf/datepicker/hooks/use-year");
|
|
47
|
-
const
|
|
44
|
+
const date_1 = require("@uxf/localize/src/date");
|
|
48
45
|
const react_1 = __importStar(require("react"));
|
|
49
46
|
const calendar_1 = require("../calendar");
|
|
50
47
|
exports.DateRangePickerDecade = (0, react_1.memo)((props) => {
|
|
@@ -58,17 +55,17 @@ exports.DateRangePickerDecade = (0, react_1.memo)((props) => {
|
|
|
58
55
|
});
|
|
59
56
|
const { yearLabel } = (0, use_year_1.useYear)({
|
|
60
57
|
year: currentYear,
|
|
61
|
-
yearLabelFormat: (date) => (0,
|
|
62
|
-
monthLabelFormat: (date) => (0,
|
|
58
|
+
yearLabelFormat: (date) => (0, date_1.dayjsTz)(date).format("YYYY"),
|
|
59
|
+
monthLabelFormat: (date) => (0, date_1.dayjsTz)(date).format("MMMM"),
|
|
63
60
|
});
|
|
64
61
|
const { monthLabel } = (0, use_month_1.useMonth)({
|
|
65
62
|
firstDayOfWeek,
|
|
66
63
|
month: currentMonth,
|
|
67
|
-
monthLabelFormat: (date) => (0,
|
|
64
|
+
monthLabelFormat: (date) => (0, date_1.dayjsTz)(date).format("MMMM"),
|
|
68
65
|
year: currentYear,
|
|
69
66
|
});
|
|
70
|
-
const canGoToPrevDecade = canGoToYear((0,
|
|
71
|
-
const canGoToNextDecade = canGoToYear((0,
|
|
67
|
+
const canGoToPrevDecade = canGoToYear((0, date_1.dayjsTz)(new Date(currentYear, 0)).subtract(5, "years").toDate());
|
|
68
|
+
const canGoToNextDecade = canGoToYear((0, date_1.dayjsTz)(new Date(currentYear, 0)).add(5, "years").toDate());
|
|
72
69
|
const handleGoToPrevDecadeClick = (0, react_1.useCallback)(() => {
|
|
73
70
|
if (canGoToPrevDecade) {
|
|
74
71
|
goToPrevYear(9);
|
|
@@ -102,6 +99,6 @@ exports.DateRangePickerDecade = (0, react_1.memo)((props) => {
|
|
|
102
99
|
children: yearLabel,
|
|
103
100
|
isDisabled: true,
|
|
104
101
|
} }),
|
|
105
|
-
react_1.default.createElement("div", { className: "uxf-calendar__decade" }, years.map((year) => (react_1.default.createElement("button", { className: (0, cx_1.cx)("uxf-calendar__cell uxf-calendar__cell-year", !canGoToYear(year.date) && classes_1.CLASSES.IS_DISABLED, (0,
|
|
102
|
+
react_1.default.createElement("div", { className: "uxf-calendar__decade" }, years.map((year) => (react_1.default.createElement("button", { className: (0, cx_1.cx)("uxf-calendar__cell uxf-calendar__cell-year", !canGoToYear(year.date) && classes_1.CLASSES.IS_DISABLED, (0, date_1.dayjsTz)(year.date).year() === currentYear && "uxf-calendar__cell-year--current"), key: year.yearLabel, onClick: handleSelectYear(year.date), type: "button" }, year.yearLabel))))));
|
|
106
103
|
});
|
|
107
104
|
exports.DateRangePickerDecade.displayName = "UxfUiDatePickerDecade";
|
|
@@ -32,16 +32,13 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
32
32
|
return result;
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
36
|
exports.DateRangePickerMonth = void 0;
|
|
40
37
|
const translations_1 = require("@uxf/core-react/translations");
|
|
41
38
|
const date_range_picker_context_1 = require("@uxf/datepicker/contexts/date-range-picker-context");
|
|
42
39
|
const use_month_1 = require("@uxf/datepicker/hooks/use-month");
|
|
43
40
|
const use_year_1 = require("@uxf/datepicker/hooks/use-year");
|
|
44
|
-
const
|
|
41
|
+
const date_1 = require("@uxf/localize/src/date");
|
|
45
42
|
const react_1 = __importStar(require("react"));
|
|
46
43
|
const calendar_1 = require("../calendar");
|
|
47
44
|
exports.DateRangePickerMonth = (0, react_1.memo)((props) => {
|
|
@@ -50,16 +47,16 @@ exports.DateRangePickerMonth = (0, react_1.memo)((props) => {
|
|
|
50
47
|
const dateRangePickerProps = (0, react_1.useContext)(date_range_picker_context_1.DateRangePickerContext);
|
|
51
48
|
const { canGoToNextMonth, canGoToPrevMonth, firstDayOfWeek, goToNextMonthsByOneMonth, goToPrevMonthsByOneMonth } = dateRangePickerProps;
|
|
52
49
|
const { monthLabel } = (0, use_month_1.useMonth)({
|
|
53
|
-
dayLabelFormat: (date) => (0,
|
|
50
|
+
dayLabelFormat: (date) => (0, date_1.dayjsTz)(date).format("D"),
|
|
54
51
|
firstDayOfWeek,
|
|
55
52
|
month: props.month,
|
|
56
|
-
monthLabelFormat: (date) => (0,
|
|
57
|
-
weekdayLabelFormat: (date) => (0,
|
|
53
|
+
monthLabelFormat: (date) => (0, date_1.dayjsTz)(date).format("MMMM"),
|
|
54
|
+
weekdayLabelFormat: (date) => (0, date_1.dayjsTz)(date).format("dd"),
|
|
58
55
|
year: props.year,
|
|
59
56
|
});
|
|
60
57
|
const { yearLabel } = (0, use_year_1.useYear)({
|
|
61
58
|
year: props.year,
|
|
62
|
-
yearLabelFormat: (date) => (0,
|
|
59
|
+
yearLabelFormat: (date) => (0, date_1.dayjsTz)(date).format("YYYY"),
|
|
63
60
|
});
|
|
64
61
|
const handleGoToPrevMonth = (0, react_1.useCallback)(() => {
|
|
65
62
|
goToPrevMonthsByOneMonth();
|
|
@@ -32,9 +32,6 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
32
32
|
return result;
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
36
|
exports.DateRangePickerYear = void 0;
|
|
40
37
|
const translations_1 = require("@uxf/core-react/translations");
|
|
@@ -43,7 +40,7 @@ const cx_1 = require("@uxf/core/utils/cx");
|
|
|
43
40
|
const date_range_picker_context_1 = require("@uxf/datepicker/contexts/date-range-picker-context");
|
|
44
41
|
const use_month_1 = require("@uxf/datepicker/hooks/use-month");
|
|
45
42
|
const use_year_1 = require("@uxf/datepicker/hooks/use-year");
|
|
46
|
-
const
|
|
43
|
+
const date_1 = require("@uxf/localize/src/date");
|
|
47
44
|
const react_1 = __importStar(require("react"));
|
|
48
45
|
const calendar_1 = require("../calendar");
|
|
49
46
|
exports.DateRangePickerYear = (0, react_1.memo)((props) => {
|
|
@@ -54,13 +51,13 @@ exports.DateRangePickerYear = (0, react_1.memo)((props) => {
|
|
|
54
51
|
const currentYear = (_d = (_c = activeMonths.at(0)) === null || _c === void 0 ? void 0 : _c.year) !== null && _d !== void 0 ? _d : new Date().getFullYear();
|
|
55
52
|
const { months, yearLabel } = (0, use_year_1.useYear)({
|
|
56
53
|
year: currentYear,
|
|
57
|
-
yearLabelFormat: (date) => (0,
|
|
58
|
-
monthLabelFormat: (date) => (0,
|
|
54
|
+
yearLabelFormat: (date) => (0, date_1.dayjsTz)(date).format("YYYY"),
|
|
55
|
+
monthLabelFormat: (date) => (0, date_1.dayjsTz)(date).format("MMMM"),
|
|
59
56
|
});
|
|
60
57
|
const { monthLabel } = (0, use_month_1.useMonth)({
|
|
61
58
|
firstDayOfWeek,
|
|
62
59
|
month: currentMonth,
|
|
63
|
-
monthLabelFormat: (date) => (0,
|
|
60
|
+
monthLabelFormat: (date) => (0, date_1.dayjsTz)(date).format("MMMM"),
|
|
64
61
|
year: currentYear,
|
|
65
62
|
});
|
|
66
63
|
const handleGoToNextYear = (0, react_1.useCallback)(() => {
|
|
@@ -98,6 +95,6 @@ exports.DateRangePickerYear = (0, react_1.memo)((props) => {
|
|
|
98
95
|
onClick: handleYearClick,
|
|
99
96
|
title: (_k = (_j = props.customButtonTitles) === null || _j === void 0 ? void 0 : _j.selectYear) !== null && _k !== void 0 ? _k : t("uxf-ui-date-range-picker:select-year"),
|
|
100
97
|
} }),
|
|
101
|
-
react_1.default.createElement("div", { className: "uxf-calendar__year" }, months.map((month, index) => (react_1.default.createElement("button", { className: (0, cx_1.cx)("uxf-calendar__cell uxf-calendar__cell-month", !canGoToMonth(month.date) && classes_1.CLASSES.IS_DISABLED, (0,
|
|
98
|
+
react_1.default.createElement("div", { className: "uxf-calendar__year" }, months.map((month, index) => (react_1.default.createElement("button", { className: (0, cx_1.cx)("uxf-calendar__cell uxf-calendar__cell-month", !canGoToMonth(month.date) && classes_1.CLASSES.IS_DISABLED, (0, date_1.dayjsTz)(month.date).month() === currentMonth && "uxf-calendar__cell-month--current"), key: month.monthLabel + index, onClick: handleMonthClick(month.date), type: "button" }, month.monthLabel))))));
|
|
102
99
|
});
|
|
103
100
|
exports.DateRangePickerYear.displayName = "UxfUiDatePickerYear";
|
|
@@ -6,4 +6,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const react_1 = __importDefault(require("react"));
|
|
7
7
|
const snap_test_1 = require("../utils/snap-test");
|
|
8
8
|
const date_range_picker_stories_1 = require("./date-range-picker.stories");
|
|
9
|
-
(0, snap_test_1.snapTest)("render stories", react_1.default.createElement(date_range_picker_stories_1.
|
|
9
|
+
(0, snap_test_1.snapTest)("render stories", react_1.default.createElement(date_range_picker_stories_1.Basic, null));
|
|
@@ -1,2 +1,58 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
|
|
2
|
+
/** Minimal range picker with no constraints. Click start date then end date. */
|
|
3
|
+
export declare function Basic(): React.JSX.Element;
|
|
4
|
+
/** Opens with a range already selected. Shows the highlighted band immediately. */
|
|
5
|
+
export declare function PreSelected(): React.JSX.Element;
|
|
6
|
+
/**
|
|
7
|
+
* Only dates within a fixed window are selectable.
|
|
8
|
+
* Useful for short-stay booking forms with a specific availability window.
|
|
9
|
+
*/
|
|
10
|
+
export declare function MinMaxDates(): React.JSX.Element;
|
|
11
|
+
/**
|
|
12
|
+
* A cluster of dates is marked unavailable.
|
|
13
|
+
* The user cannot start or end a range on those dates.
|
|
14
|
+
*/
|
|
15
|
+
export declare function UnavailableDates(): React.JSX.Element;
|
|
16
|
+
/**
|
|
17
|
+
* `minSelectedDays` enforces a minimum stay of 3 days.
|
|
18
|
+
* The end date cannot be selected closer than 3 days after the start date.
|
|
19
|
+
*/
|
|
20
|
+
export declare function MinStayDays(): React.JSX.Element;
|
|
21
|
+
/**
|
|
22
|
+
* `exactSelectedDays` pins the stay to exactly 5 days.
|
|
23
|
+
* Selecting a start date automatically highlights the fixed-length range.
|
|
24
|
+
*/
|
|
25
|
+
export declare function ExactStayDays(): React.JSX.Element;
|
|
26
|
+
/**
|
|
27
|
+
* `numberOfMonths={2}` shows the current and next month side-by-side.
|
|
28
|
+
* Handy when users typically book multi-week stays spanning a month boundary.
|
|
29
|
+
*/
|
|
30
|
+
export declare function TwoMonthView(): React.JSX.Element;
|
|
31
|
+
/**
|
|
32
|
+
* `datesConfig` lets you style and disable arbitrary date groups independently of
|
|
33
|
+
* the global `unavailableDates` list.
|
|
34
|
+
*/
|
|
35
|
+
export declare function DatesConfigFlags(): React.JSX.Element;
|
|
36
|
+
/**
|
|
37
|
+
* `bottomContent` renders arbitrary JSX below the calendar.
|
|
38
|
+
* Typical uses: price summary, legend, or action buttons.
|
|
39
|
+
*/
|
|
40
|
+
export declare function WithBottomContent(): React.JSX.Element;
|
|
41
|
+
/**
|
|
42
|
+
* Regression story for the DST off-by-one bug.
|
|
43
|
+
*
|
|
44
|
+
* In Europe, clocks go back on the night of 2026-10-25 → 2026-10-26 (CEST → CET).
|
|
45
|
+
* Before the fix, `toDateString()` would misread a UTC-midnight Date in a UTC+ timezone
|
|
46
|
+
* and shift it one day back, making Oct 26 appear as Oct 25 in the calendar.
|
|
47
|
+
*
|
|
48
|
+
* This story opens on October 2026 with minSelectedDays=2 so you can verify that:
|
|
49
|
+
* - Oct 25 and Oct 26 are both visible as distinct, correct cells
|
|
50
|
+
* - Selecting Oct 25 as start date allows Oct 26 as the earliest valid end date
|
|
51
|
+
* - The highlighted range 2026-10-25 → 2026-10-26 renders without off-by-one shift
|
|
52
|
+
*/
|
|
53
|
+
export declare function DstBoundaryOct2026(): React.JSX.Element;
|
|
54
|
+
/**
|
|
55
|
+
* Kitchen-sink story: two months, min/max window, blocked dates, datesConfig flags,
|
|
56
|
+
* minimum 2-day stay, and a bottom content footer. Good for regression testing.
|
|
57
|
+
*/
|
|
58
|
+
export declare function AllFeatures(): React.JSX.Element;
|
|
@@ -33,31 +33,232 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.
|
|
36
|
+
exports.Basic = Basic;
|
|
37
|
+
exports.PreSelected = PreSelected;
|
|
38
|
+
exports.MinMaxDates = MinMaxDates;
|
|
39
|
+
exports.UnavailableDates = UnavailableDates;
|
|
40
|
+
exports.MinStayDays = MinStayDays;
|
|
41
|
+
exports.ExactStayDays = ExactStayDays;
|
|
42
|
+
exports.TwoMonthView = TwoMonthView;
|
|
43
|
+
exports.DatesConfigFlags = DatesConfigFlags;
|
|
44
|
+
exports.WithBottomContent = WithBottomContent;
|
|
45
|
+
exports.DstBoundaryOct2026 = DstBoundaryOct2026;
|
|
46
|
+
exports.AllFeatures = AllFeatures;
|
|
37
47
|
const noop_1 = require("@uxf/core/utils/noop");
|
|
38
|
-
const
|
|
48
|
+
const date_string_1 = require("@uxf/datepicker/utils/date-string");
|
|
39
49
|
const react_1 = __importStar(require("react"));
|
|
40
50
|
const action_1 = require("../utils/action");
|
|
41
51
|
const date_range_picker_1 = require("./date-range-picker");
|
|
42
|
-
|
|
43
|
-
const
|
|
44
|
-
const
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
react_1.default.createElement(
|
|
52
|
+
// Build all demo dates relative to today using timezone-safe arithmetic
|
|
53
|
+
const todayStr = (0, date_string_1.todayDateString)();
|
|
54
|
+
const d = (n) => (0, date_string_1.fromDateString)((0, date_string_1.addDays)(todayStr, n));
|
|
55
|
+
const s = (n) => (0, date_string_1.addDays)(todayStr, n); // DateString for use in descriptions
|
|
56
|
+
// ─── Basic usage ───────────────────────────────────────────────────────────────
|
|
57
|
+
/** Minimal range picker with no constraints. Click start date then end date. */
|
|
58
|
+
function Basic() {
|
|
59
|
+
const [value, setValue] = (0, react_1.useState)(null);
|
|
60
|
+
return (react_1.default.createElement("div", { className: "space-y-2 p-8" },
|
|
61
|
+
react_1.default.createElement("p", { className: "text-sm text-gray-500" }, "Click a start date, then an end date. No constraints applied."),
|
|
62
|
+
react_1.default.createElement(date_range_picker_1.DateRangePicker, { onChange: (0, action_1.action)("onChange", setValue), onClosePopover: noop_1.noop, selectedDates: value })));
|
|
63
|
+
}
|
|
64
|
+
// ─── Pre-selected range ────────────────────────────────────────────────────────
|
|
65
|
+
/** Opens with a range already selected. Shows the highlighted band immediately. */
|
|
66
|
+
function PreSelected() {
|
|
67
|
+
const [value, setValue] = (0, react_1.useState)({
|
|
68
|
+
from: d(0),
|
|
69
|
+
to: d(7),
|
|
70
|
+
});
|
|
71
|
+
return (react_1.default.createElement("div", { className: "space-y-2 p-8" },
|
|
72
|
+
react_1.default.createElement("p", { className: "text-sm text-gray-500" },
|
|
73
|
+
"Pre-selected range: ",
|
|
74
|
+
s(0),
|
|
75
|
+
" \u2192 ",
|
|
76
|
+
s(7),
|
|
77
|
+
"."),
|
|
78
|
+
react_1.default.createElement(date_range_picker_1.DateRangePicker, { onChange: (0, action_1.action)("onChange", setValue), onClosePopover: noop_1.noop, selectedDates: value })));
|
|
79
|
+
}
|
|
80
|
+
// ─── Min / max date constraints ────────────────────────────────────────────────
|
|
81
|
+
/**
|
|
82
|
+
* Only dates within a fixed window are selectable.
|
|
83
|
+
* Useful for short-stay booking forms with a specific availability window.
|
|
84
|
+
*/
|
|
85
|
+
function MinMaxDates() {
|
|
86
|
+
const [value, setValue] = (0, react_1.useState)(null);
|
|
87
|
+
return (react_1.default.createElement("div", { className: "space-y-2 p-8" },
|
|
88
|
+
react_1.default.createElement("p", { className: "text-sm text-gray-500" },
|
|
89
|
+
"Bookable window: ",
|
|
90
|
+
s(2),
|
|
91
|
+
" \u2192 ",
|
|
92
|
+
s(16),
|
|
93
|
+
". Dates outside are dimmed."),
|
|
94
|
+
react_1.default.createElement(date_range_picker_1.DateRangePicker, { maxDate: d(16), minDate: d(2), onChange: (0, action_1.action)("onChange", setValue), onClosePopover: noop_1.noop, selectedDates: value })));
|
|
95
|
+
}
|
|
96
|
+
// ─── Unavailable dates ─────────────────────────────────────────────────────────
|
|
97
|
+
/**
|
|
98
|
+
* A cluster of dates is marked unavailable.
|
|
99
|
+
* The user cannot start or end a range on those dates.
|
|
100
|
+
*/
|
|
101
|
+
function UnavailableDates() {
|
|
102
|
+
const [value, setValue] = (0, react_1.useState)(null);
|
|
103
|
+
const unavailableDates = [d(0), d(5), d(6), d(7), d(11), d(12)];
|
|
104
|
+
return (react_1.default.createElement("div", { className: "space-y-2 p-8" },
|
|
105
|
+
react_1.default.createElement("p", { className: "text-sm text-gray-500" },
|
|
106
|
+
"Blocked dates: ",
|
|
107
|
+
s(0),
|
|
108
|
+
", ",
|
|
109
|
+
s(5),
|
|
110
|
+
", ",
|
|
111
|
+
s(6),
|
|
112
|
+
", ",
|
|
113
|
+
s(7),
|
|
114
|
+
", ",
|
|
115
|
+
s(11),
|
|
116
|
+
", ",
|
|
117
|
+
s(12),
|
|
118
|
+
". A range cannot cross them."),
|
|
119
|
+
react_1.default.createElement(date_range_picker_1.DateRangePicker, { onChange: (0, action_1.action)("onChange", setValue), onClosePopover: noop_1.noop, selectedDates: value, unavailableDates: unavailableDates })));
|
|
120
|
+
}
|
|
121
|
+
// ─── Minimum stay length ───────────────────────────────────────────────────────
|
|
122
|
+
/**
|
|
123
|
+
* `minSelectedDays` enforces a minimum stay of 3 days.
|
|
124
|
+
* The end date cannot be selected closer than 3 days after the start date.
|
|
125
|
+
*/
|
|
126
|
+
function MinStayDays() {
|
|
127
|
+
const [value, setValue] = (0, react_1.useState)(null);
|
|
128
|
+
return (react_1.default.createElement("div", { className: "space-y-2 p-8" },
|
|
129
|
+
react_1.default.createElement("p", { className: "text-sm text-gray-500" },
|
|
130
|
+
"Minimum 3 days \u2014 if start is ",
|
|
131
|
+
s(0),
|
|
132
|
+
", earliest end is ",
|
|
133
|
+
s(2),
|
|
134
|
+
"."),
|
|
135
|
+
react_1.default.createElement(date_range_picker_1.DateRangePicker, { minSelectedDays: 3, onChange: (0, action_1.action)("onChange", setValue), onClosePopover: noop_1.noop, selectedDates: value })));
|
|
136
|
+
}
|
|
137
|
+
// ─── Exact stay length ─────────────────────────────────────────────────────────
|
|
138
|
+
/**
|
|
139
|
+
* `exactSelectedDays` pins the stay to exactly 5 days.
|
|
140
|
+
* Selecting a start date automatically highlights the fixed-length range.
|
|
141
|
+
*/
|
|
142
|
+
function ExactStayDays() {
|
|
143
|
+
const [value, setValue] = (0, react_1.useState)(null);
|
|
144
|
+
return (react_1.default.createElement("div", { className: "space-y-2 p-8" },
|
|
145
|
+
react_1.default.createElement("p", { className: "text-sm text-gray-500" },
|
|
146
|
+
"Exactly 5 days \u2014 if start is ",
|
|
147
|
+
s(0),
|
|
148
|
+
", end is locked to ",
|
|
149
|
+
s(4),
|
|
150
|
+
"."),
|
|
151
|
+
react_1.default.createElement(date_range_picker_1.DateRangePicker, { exactSelectedDays: 5, onChange: (0, action_1.action)("onChange", setValue), onClosePopover: noop_1.noop, selectedDates: value })));
|
|
152
|
+
}
|
|
153
|
+
// ─── Two-month view ────────────────────────────────────────────────────────────
|
|
154
|
+
/**
|
|
155
|
+
* `numberOfMonths={2}` shows the current and next month side-by-side.
|
|
156
|
+
* Handy when users typically book multi-week stays spanning a month boundary.
|
|
157
|
+
*/
|
|
158
|
+
function TwoMonthView() {
|
|
159
|
+
const [value, setValue] = (0, react_1.useState)(null);
|
|
160
|
+
return (react_1.default.createElement("div", { className: "space-y-2 p-8" },
|
|
161
|
+
react_1.default.createElement("p", { className: "text-sm text-gray-500" }, "Two months displayed side-by-side for easier range selection."),
|
|
162
|
+
react_1.default.createElement(date_range_picker_1.DateRangePicker, { numberOfMonths: 2, onChange: (0, action_1.action)("onChange", setValue), onClosePopover: noop_1.noop, selectedDates: value })));
|
|
163
|
+
}
|
|
164
|
+
// ─── DatesConfig — flags and disabled groups ───────────────────────────────────
|
|
165
|
+
/**
|
|
166
|
+
* `datesConfig` lets you style and disable arbitrary date groups independently of
|
|
167
|
+
* the global `unavailableDates` list.
|
|
168
|
+
*/
|
|
169
|
+
function DatesConfigFlags() {
|
|
170
|
+
const [value, setValue] = (0, react_1.useState)(null);
|
|
171
|
+
const datesConfig = [
|
|
172
|
+
{ flag: "flag-promo", dates: [d(2), d(3)] },
|
|
173
|
+
{ flag: "flag-sold-out", dates: [d(6), d(7)], isDisabled: true },
|
|
174
|
+
];
|
|
175
|
+
return (react_1.default.createElement("div", { className: "space-y-2 p-8" },
|
|
176
|
+
react_1.default.createElement("p", { className: "text-sm text-gray-500" },
|
|
177
|
+
react_1.default.createElement("code", null, "flag-promo"),
|
|
178
|
+
" (selectable): ",
|
|
179
|
+
s(2),
|
|
180
|
+
", ",
|
|
181
|
+
s(3),
|
|
182
|
+
" \u00B7 ",
|
|
183
|
+
react_1.default.createElement("code", null, "flag-sold-out"),
|
|
184
|
+
" (disabled): ",
|
|
185
|
+
s(6),
|
|
186
|
+
",",
|
|
187
|
+
" ",
|
|
188
|
+
s(7),
|
|
189
|
+
"."),
|
|
190
|
+
react_1.default.createElement(date_range_picker_1.DateRangePicker, { datesConfig: datesConfig, onChange: (0, action_1.action)("onChange", setValue), onClosePopover: noop_1.noop, selectedDates: value })));
|
|
191
|
+
}
|
|
192
|
+
// ─── Bottom content slot ───────────────────────────────────────────────────────
|
|
193
|
+
/**
|
|
194
|
+
* `bottomContent` renders arbitrary JSX below the calendar.
|
|
195
|
+
* Typical uses: price summary, legend, or action buttons.
|
|
196
|
+
*/
|
|
197
|
+
function WithBottomContent() {
|
|
198
|
+
const [value, setValue] = (0, react_1.useState)(null);
|
|
199
|
+
return (react_1.default.createElement("div", { className: "space-y-2 p-8" },
|
|
200
|
+
react_1.default.createElement("p", { className: "text-sm text-gray-500" }, "Custom footer rendered below the calendar grid."),
|
|
201
|
+
react_1.default.createElement(date_range_picker_1.DateRangePicker, { bottomContent: react_1.default.createElement("div", { className: "border-t pt-2 text-sm text-gray-600" },
|
|
202
|
+
react_1.default.createElement("p", null,
|
|
203
|
+
"Average nightly rate: ",
|
|
204
|
+
react_1.default.createElement("strong", null, "\u20AC120"))), onChange: (0, action_1.action)("onChange", setValue), onClosePopover: noop_1.noop, selectedDates: value })));
|
|
205
|
+
}
|
|
206
|
+
// ─── DST boundary — Oct 25/26 2026 ────────────────────────────────────────────
|
|
207
|
+
/**
|
|
208
|
+
* Regression story for the DST off-by-one bug.
|
|
209
|
+
*
|
|
210
|
+
* In Europe, clocks go back on the night of 2026-10-25 → 2026-10-26 (CEST → CET).
|
|
211
|
+
* Before the fix, `toDateString()` would misread a UTC-midnight Date in a UTC+ timezone
|
|
212
|
+
* and shift it one day back, making Oct 26 appear as Oct 25 in the calendar.
|
|
213
|
+
*
|
|
214
|
+
* This story opens on October 2026 with minSelectedDays=2 so you can verify that:
|
|
215
|
+
* - Oct 25 and Oct 26 are both visible as distinct, correct cells
|
|
216
|
+
* - Selecting Oct 25 as start date allows Oct 26 as the earliest valid end date
|
|
217
|
+
* - The highlighted range 2026-10-25 → 2026-10-26 renders without off-by-one shift
|
|
218
|
+
*/
|
|
219
|
+
function DstBoundaryOct2026() {
|
|
220
|
+
const [value, setValue] = (0, react_1.useState)({
|
|
221
|
+
from: (0, date_string_1.fromDateString)("2026-10-25"),
|
|
222
|
+
to: null,
|
|
223
|
+
});
|
|
224
|
+
return (react_1.default.createElement("div", { className: "space-y-2 p-8" },
|
|
225
|
+
react_1.default.createElement("p", { className: "text-sm text-gray-500" }, "DST regression: Europe clocks go back on 2026-10-25 \u2192 2026-10-26. Start is pre-set to 2026-10-25; select 2026-10-26 as end (minSelectedDays=2). Both cells must appear on the correct day without any off-by-one shift."),
|
|
226
|
+
react_1.default.createElement(date_range_picker_1.DateRangePicker, { maxDate: (0, date_string_1.fromDateString)("2026-11-05"), minDate: (0, date_string_1.fromDateString)("2026-10-20"), minSelectedDays: 2, onChange: (0, action_1.action)("onChange", setValue), onClosePopover: noop_1.noop, selectedDates: value })));
|
|
227
|
+
}
|
|
228
|
+
// ─── All features together ─────────────────────────────────────────────────────
|
|
229
|
+
/**
|
|
230
|
+
* Kitchen-sink story: two months, min/max window, blocked dates, datesConfig flags,
|
|
231
|
+
* minimum 2-day stay, and a bottom content footer. Good for regression testing.
|
|
232
|
+
*/
|
|
233
|
+
function AllFeatures() {
|
|
234
|
+
const [value, setValue] = (0, react_1.useState)(null);
|
|
235
|
+
const datesConfig = [
|
|
236
|
+
{ flag: "flag-promo", dates: [d(3), d(4)] },
|
|
237
|
+
{ flag: "flag-sold-out", dates: [d(9), d(10)], isDisabled: true },
|
|
238
|
+
];
|
|
239
|
+
return (react_1.default.createElement("div", { className: "space-y-2 p-8" },
|
|
240
|
+
react_1.default.createElement("p", { className: "text-sm text-gray-500" },
|
|
241
|
+
"2 months \u00B7 window ",
|
|
242
|
+
s(-1),
|
|
243
|
+
" \u2192 ",
|
|
244
|
+
s(30),
|
|
245
|
+
" \u00B7 blocked: ",
|
|
246
|
+
s(0),
|
|
247
|
+
", ",
|
|
248
|
+
s(15),
|
|
249
|
+
" \u00B7 ",
|
|
250
|
+
react_1.default.createElement("code", null, "flag-promo"),
|
|
251
|
+
": ",
|
|
252
|
+
s(3),
|
|
253
|
+
", ",
|
|
254
|
+
s(4),
|
|
255
|
+
" ",
|
|
256
|
+
"\u00B7 ",
|
|
257
|
+
react_1.default.createElement("code", null, "flag-sold-out"),
|
|
258
|
+
": ",
|
|
259
|
+
s(9),
|
|
260
|
+
", ",
|
|
261
|
+
s(10),
|
|
262
|
+
" \u00B7 min 2 days."),
|
|
263
|
+
react_1.default.createElement(date_range_picker_1.DateRangePicker, { bottomContent: react_1.default.createElement("div", { className: "border-t pt-2 text-xs text-gray-500" }, "Promo = discounted rate \u00B7 Sold-out = unavailable"), datesConfig: datesConfig, maxDate: d(30), minDate: d(-1), minSelectedDays: 2, numberOfMonths: 2, onChange: (0, action_1.action)("onChange", setValue), onClosePopover: noop_1.noop, selectedDates: value, unavailableDates: [d(0), d(15)] })));
|
|
63
264
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uxf/ui",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.111.0-canary.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"@headlessui/react": "1.7.19",
|
|
26
26
|
"@uxf/core": "11.110.0",
|
|
27
27
|
"@uxf/core-react": "11.110.0",
|
|
28
|
-
"@uxf/datepicker": "11.
|
|
28
|
+
"@uxf/datepicker": "11.111.0-canary.1",
|
|
29
29
|
"@uxf/localize": "11.110.0",
|
|
30
30
|
"@uxf/styles": "11.110.0",
|
|
31
31
|
"dayjs": "^1.11.19",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"@types/react-dom": "18.3.7",
|
|
42
42
|
"@uxf/core": "11.110.0",
|
|
43
43
|
"@uxf/core-react": "11.110.0",
|
|
44
|
-
"@uxf/datepicker": "11.
|
|
44
|
+
"@uxf/datepicker": "11.111.0-canary.1",
|
|
45
45
|
"@uxf/localize": "11.110.0",
|
|
46
46
|
"@uxf/styles": "11.110.0",
|
|
47
47
|
"dayjs": "^1.11.19",
|