@simplybusiness/mobius-datepicker 9.0.1 → 9.0.2

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.
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/components/DatePicker/DatePickerModal.tsx", "../../src/hooks/useFocusTrap/useFocusTrap.tsx", "../../src/components/DatePicker/utils/dateObjToString.ts", "../../src/components/DatePicker/constants.ts", "../../src/components/DatePicker/utils/weekdayAsOneLetter.ts", "../../src/components/DatePicker/utils/getStartWeekday.ts", "../../src/components/DatePicker/utils/timezoneOffset.ts", "../../src/components/DatePicker/CustomComponents/CaptionLabel.tsx", "../../src/components/DatePicker/CustomComponents/ChevronComponent.tsx"],
4
+ "sourcesContent": ["\"use client\";\n\nimport { VisuallyHidden, useOnClickOutside } from \"@simplybusiness/mobius\";\nimport classNames from \"classnames/dedupe\";\nimport { parseISO } from \"date-fns\";\nimport { useId, useRef } from \"react\";\nimport type { Matcher } from \"react-day-picker\";\nimport { DayPicker } from \"react-day-picker\";\nimport FocusTrap from \"../../hooks/useFocusTrap/useFocusTrap\";\nimport { dateObjToString, weekdayAsOneLetter } from \"./utils\";\nimport { getStartWeekday } from \"./utils/getStartWeekday\";\nimport { toLocal } from \"./utils/timezoneOffset\";\nimport { ChevronComponent, CaptionLabel } from \"./CustomComponents\";\n\nexport type DatePickerModalProps = {\n date?: string; // yyyy-mm-dd\n isOpen: boolean;\n top: number;\n onSelected: (date?: string) => void;\n min?: string;\n max?: string;\n};\n\nconst startWeekday = getStartWeekday(\n // eslint-disable-next-line ssr-friendly/no-dom-globals-in-module-scope\n typeof navigator !== \"undefined\" ? navigator?.language : undefined,\n);\n\nconst DatePickerModal = ({\n date,\n isOpen,\n onSelected,\n top,\n min,\n max,\n}: DatePickerModalProps) => {\n const modalRef = useRef<HTMLDivElement>(null);\n const initialDate = date ? toLocal(date) : undefined;\n const minDate = min ? toLocal(min) : undefined;\n const maxDate = max ? toLocal(max) : undefined;\n const hiddenId = `screen-reader-title-${useId()}`;\n\n const handleSelected = (selectedDate?: string) => {\n onSelected(selectedDate);\n };\n\n const handleDayPickerSelect = (selectedDate: Date | undefined) => {\n if (!selectedDate) return;\n\n handleSelected(dateObjToString(selectedDate));\n };\n\n useOnClickOutside(modalRef, () => {\n if (modalRef.current && isOpen) {\n handleSelected();\n }\n });\n\n const modalClasses = classNames(\"mobius-date-picker__modal\", {\n \"--is-open\": isOpen,\n });\n\n return (\n <FocusTrap>\n <div\n ref={modalRef}\n className={modalClasses}\n style={{ top }}\n aria-describedby={hiddenId}\n data-testid=\"modal-container\"\n >\n <VisuallyHidden>\n <div id={hiddenId}>Please select a date from the calendar</div>\n </VisuallyHidden>\n <DayPicker\n autoFocus\n mode=\"single\"\n {...(minDate && { startMonth: minDate })}\n {...(maxDate && { endMonth: maxDate })}\n disabled={\n {\n ...(min && { before: parseISO(min) }),\n ...(max && { after: parseISO(max) }),\n } as Matcher\n }\n selected={initialDate}\n defaultMonth={initialDate}\n onSelect={handleDayPickerSelect}\n pagedNavigation\n showOutsideDays\n weekStartsOn={startWeekday}\n formatters={{ formatWeekdayName: weekdayAsOneLetter }}\n components={{\n Chevron: ChevronComponent,\n CaptionLabel,\n }}\n classNames={{\n root: \"mobius-date-picker__root\",\n months: \"mobius-date-picker__months\",\n month: \"mobius-date-picker__month\",\n nav: \"mobius-date-picker__nav\",\n button_previous: \"mobius-date-picker__nav-button --previous\",\n button_next: \"mobius-date-picker__nav-button --next\",\n month_caption: \"mobius-date-picker__caption\",\n caption_label: \"mobius-date-picker__caption-label\",\n month_grid: \"mobius-date-picker__month-grid\",\n weekdays: \"mobius-date-picker__weekdays\",\n weekday: \"mobius-date-picker__weekday\",\n weeks: \"mobius-date-picker__weeks\",\n week: \"mobius-date-picker__week\",\n day: \"mobius-date-picker__day\",\n day_button: \"mobius-date-picker__day-button\",\n selected: \"--is-selected\",\n disabled: \"--is-disabled\",\n outside: \"--is-outside\",\n hidden: \"--is-hidden\",\n today: \"--is-today\",\n focused: \"--is-focused\",\n }}\n />\n </div>\n </FocusTrap>\n );\n};\n\nexport default DatePickerModal;\n", "import type { ReactNode } from \"react\";\nimport { useEffect, useRef } from \"react\";\n\nconst useFocusTrap = () => {\n const containerRef = useRef<HTMLDivElement | null>(null);\n\n useEffect(() => {\n if (containerRef.current) {\n const element = containerRef.current;\n const focusableElements =\n containerRef.current.querySelectorAll<HTMLElement>(\n '[tabindex=\"0\"], .mobius-date-picker__nav-button',\n );\n\n const firstElement = focusableElements[0];\n const lastElement = focusableElements[focusableElements.length - 1];\n\n const handleTabKeyPress = (event: KeyboardEvent) => {\n if (event.key === \"Tab\") {\n if (event.shiftKey && document.activeElement === firstElement) {\n event.preventDefault();\n lastElement.focus();\n } else if (\n !event.shiftKey &&\n document.activeElement &&\n document.activeElement.className.indexOf(\n \"mobius-date-picker__day-button\",\n ) > -1\n ) {\n event.preventDefault();\n firstElement.focus();\n }\n }\n };\n\n element.addEventListener(\"keydown\", handleTabKeyPress);\n return () => {\n element.removeEventListener(\"keydown\", handleTabKeyPress);\n };\n }\n return () => {};\n }, []);\n\n return containerRef;\n};\n\nexport type FocusTrapProps = {\n children: ReactNode;\n};\n\nexport default function FocusTrap({ children }: FocusTrapProps) {\n const focusRef = useFocusTrap();\n\n return (\n <div className=\"trap\" ref={focusRef}>\n {children}\n </div>\n );\n}\n", "export const dateObjToString = (date: Date) => {\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, \"0\");\n const day = String(date.getDate()).padStart(2, \"0\");\n\n // Extract the date part from the Date object\n return `${year}-${month}-${day}`;\n};\n", "export const SUNDAY_AS_NUMBER = 0;\nexport const MONDAY_AS_NUMBER = 1;\nexport const DEFAULT_LOCALE = \"en-GB\";\n", "import { DEFAULT_LOCALE } from \"../constants\";\n\nexport const weekdayAsOneLetter = (date: Date) => {\n const locale = navigator.language || DEFAULT_LOCALE;\n const oneLetter = date.toLocaleString(locale, {\n weekday: \"narrow\",\n });\n\n return oneLetter;\n};\n", "import {\n DEFAULT_LOCALE,\n MONDAY_AS_NUMBER,\n SUNDAY_AS_NUMBER,\n} from \"../constants\";\n\ntype WeekStart = 0 | 1 | 2 | 3 | 4 | 5 | 6 | undefined;\n\n// Calculates start of week for calendar in UK and US locales\n// Add more to the switch statement as needed\nexport const getStartWeekday = (locale?: string): WeekStart => {\n switch (locale || DEFAULT_LOCALE) {\n case \"en-US\":\n return SUNDAY_AS_NUMBER;\n\n default:\n return MONDAY_AS_NUMBER;\n }\n};\n", "/**\n * Converts a local date-time to UTC\n * @param localDate - Date object in local timezone\n * @returns Date object in UTC\n */\nexport function toUTC(localDate: Date): Date {\n return new Date(localDate.getTime() - localDate.getTimezoneOffset() * 60000);\n}\n\nexport function toLocal(utcDateString: string): Date {\n const utcDate = new Date(utcDateString);\n if (Number.isNaN(utcDate.getTime())) {\n throw new Error(\"Invalid date string\");\n }\n // Convert UTC date to local date\n // by adding the timezone offset in milliseconds\n return new Date(utcDate.getTime() + utcDate.getTimezoneOffset() * 60000);\n}\n", "import { type HTMLAttributes } from \"react\";\n\n/**\n *\n * This component is used to render the caption label for the date picker.\n * We are overriding the standard span with an h2 for accessibility reasons.\n */\nexport const CaptionLabel = (props: HTMLAttributes<HTMLSpanElement>) => {\n return <h2 {...props} />;\n};\n", "import { chevronLeft, chevronRight } from \"@simplybusiness/icons\";\nimport { Icon } from \"@simplybusiness/mobius\";\n\ntype ChevronComponentProps = {\n orientation?: \"up\" | \"down\" | \"left\" | \"right\";\n};\n\nexport const ChevronComponent = ({ orientation }: ChevronComponentProps) => {\n if (orientation === \"left\") {\n return <Icon icon={chevronLeft} />;\n }\n return <Icon icon={chevronRight} />;\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["useRef", "jsx", "jsx", "jsx", "useRef"]
7
+ }
package/dist/esm/index.js CHANGED
@@ -1,360 +1,19 @@
1
- var __defProp = Object.defineProperty;
2
- var __getOwnPropNames = Object.getOwnPropertyNames;
3
- var __esm = (fn, res) => function __init() {
4
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
5
- };
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
-
11
- // src/components/DatePicker/utils/dateObjToString.ts
12
- var dateObjToString;
13
- var init_dateObjToString = __esm({
14
- "src/components/DatePicker/utils/dateObjToString.ts"() {
15
- "use strict";
16
- dateObjToString = (date) => {
17
- const year = date.getFullYear();
18
- const month = String(date.getMonth() + 1).padStart(2, "0");
19
- const day = String(date.getDate()).padStart(2, "0");
20
- return `${year}-${month}-${day}`;
21
- };
22
- }
23
- });
24
-
25
- // src/components/DatePicker/utils/formatErrorMessageText.ts
26
- import { isAfter, isBefore } from "date-fns";
27
- var DEFAULT_INVALID_DATE_MESSAGE, DEFAULT_BEFORE_MIN, DEFAULT_AFTER_MAX, formatErrorMessageText;
28
- var init_formatErrorMessageText = __esm({
29
- "src/components/DatePicker/utils/formatErrorMessageText.ts"() {
30
- "use strict";
31
- DEFAULT_INVALID_DATE_MESSAGE = "Please enter a valid date";
32
- DEFAULT_BEFORE_MIN = "The date you selected is before the earliest allowed date";
33
- DEFAULT_AFTER_MAX = "The date you selected is after the latest allowed date";
34
- formatErrorMessageText = (actual, min, max) => {
35
- const actualDate = new Date(actual);
36
- const minDate = min && new Date(min);
37
- const maxDate = max && new Date(max);
38
- if (minDate && isBefore(actualDate, minDate)) {
39
- return DEFAULT_BEFORE_MIN;
40
- }
41
- if (maxDate && isAfter(actualDate, maxDate)) {
42
- return DEFAULT_AFTER_MAX;
43
- }
44
- return DEFAULT_INVALID_DATE_MESSAGE;
45
- };
46
- }
47
- });
48
-
49
- // src/components/DatePicker/utils/validateDateFormat.ts
50
- import { isMatch } from "date-fns";
51
- var DATE_FORMAT, validateDateFormat;
52
- var init_validateDateFormat = __esm({
53
- "src/components/DatePicker/utils/validateDateFormat.ts"() {
54
- "use strict";
55
- DATE_FORMAT = "yyyy-MM-dd";
56
- validateDateFormat = (date) => {
57
- if (date === "") {
58
- return "";
59
- }
60
- if (isMatch(date, DATE_FORMAT)) {
61
- return date;
62
- }
63
- throw Error(
64
- `DatePicker defaultValue '${date}' is invalid. The expected format is '${DATE_FORMAT}' `
65
- );
66
- };
67
- }
68
- });
69
-
70
- // src/components/DatePicker/constants.ts
71
- var SUNDAY_AS_NUMBER, MONDAY_AS_NUMBER, DEFAULT_LOCALE;
72
- var init_constants = __esm({
73
- "src/components/DatePicker/constants.ts"() {
74
- "use strict";
75
- SUNDAY_AS_NUMBER = 0;
76
- MONDAY_AS_NUMBER = 1;
77
- DEFAULT_LOCALE = "en-GB";
78
- }
79
- });
80
-
81
- // src/components/DatePicker/utils/weekdayAsOneLetter.ts
82
- var weekdayAsOneLetter;
83
- var init_weekdayAsOneLetter = __esm({
84
- "src/components/DatePicker/utils/weekdayAsOneLetter.ts"() {
85
- "use strict";
86
- init_constants();
87
- weekdayAsOneLetter = (date) => {
88
- const locale = navigator.language || DEFAULT_LOCALE;
89
- const oneLetter = date.toLocaleString(locale, {
90
- weekday: "narrow"
91
- });
92
- return oneLetter;
93
- };
94
- }
95
- });
96
-
97
- // src/components/DatePicker/utils/index.ts
98
- var init_utils = __esm({
99
- "src/components/DatePicker/utils/index.ts"() {
100
- "use strict";
101
- init_dateObjToString();
102
- init_formatErrorMessageText();
103
- init_validateDateFormat();
104
- init_weekdayAsOneLetter();
105
- }
106
- });
107
-
108
- // src/hooks/useFocusTrap/useFocusTrap.tsx
109
- import { useEffect, useRef } from "react";
110
- import { jsx } from "react/jsx-runtime";
111
- function FocusTrap({ children }) {
112
- const focusRef = useFocusTrap();
113
- return /* @__PURE__ */ jsx("div", { className: "trap", ref: focusRef, children });
114
- }
115
- var useFocusTrap;
116
- var init_useFocusTrap = __esm({
117
- "src/hooks/useFocusTrap/useFocusTrap.tsx"() {
118
- "use strict";
119
- useFocusTrap = () => {
120
- const containerRef = useRef(null);
121
- useEffect(() => {
122
- if (containerRef.current) {
123
- const element = containerRef.current;
124
- const focusableElements = containerRef.current.querySelectorAll(
125
- '[tabindex="0"], .mobius-date-picker__nav-button'
126
- );
127
- const firstElement = focusableElements[0];
128
- const lastElement = focusableElements[focusableElements.length - 1];
129
- const handleTabKeyPress = (event) => {
130
- if (event.key === "Tab") {
131
- if (event.shiftKey && document.activeElement === firstElement) {
132
- event.preventDefault();
133
- lastElement.focus();
134
- } else if (!event.shiftKey && document.activeElement && document.activeElement.className.indexOf(
135
- "mobius-date-picker__day-button"
136
- ) > -1) {
137
- event.preventDefault();
138
- firstElement.focus();
139
- }
140
- }
141
- };
142
- element.addEventListener("keydown", handleTabKeyPress);
143
- return () => {
144
- element.removeEventListener("keydown", handleTabKeyPress);
145
- };
146
- }
147
- return () => {
148
- };
149
- }, []);
150
- return containerRef;
151
- };
152
- }
153
- });
154
-
155
- // src/components/DatePicker/utils/getStartWeekday.ts
156
- var getStartWeekday;
157
- var init_getStartWeekday = __esm({
158
- "src/components/DatePicker/utils/getStartWeekday.ts"() {
159
- "use strict";
160
- init_constants();
161
- getStartWeekday = (locale) => {
162
- switch (locale || DEFAULT_LOCALE) {
163
- case "en-US":
164
- return SUNDAY_AS_NUMBER;
165
- default:
166
- return MONDAY_AS_NUMBER;
167
- }
168
- };
169
- }
170
- });
171
-
172
- // src/components/DatePicker/utils/timezoneOffset.ts
173
- function toLocal(utcDateString) {
174
- const utcDate = new Date(utcDateString);
175
- if (Number.isNaN(utcDate.getTime())) {
176
- throw new Error("Invalid date string");
177
- }
178
- return new Date(utcDate.getTime() + utcDate.getTimezoneOffset() * 6e4);
179
- }
180
- var init_timezoneOffset = __esm({
181
- "src/components/DatePicker/utils/timezoneOffset.ts"() {
182
- "use strict";
183
- }
184
- });
185
-
186
- // src/components/DatePicker/CustomComponents/CaptionLabel.tsx
187
- import { jsx as jsx2 } from "react/jsx-runtime";
188
- var CaptionLabel;
189
- var init_CaptionLabel = __esm({
190
- "src/components/DatePicker/CustomComponents/CaptionLabel.tsx"() {
191
- "use strict";
192
- CaptionLabel = (props) => {
193
- return /* @__PURE__ */ jsx2("h2", { ...props });
194
- };
195
- }
196
- });
197
-
198
- // src/components/DatePicker/CustomComponents/ChevronComponent.tsx
199
- import { chevronLeft, chevronRight } from "@simplybusiness/icons";
200
- import { Icon } from "@simplybusiness/mobius";
201
- import { jsx as jsx3 } from "react/jsx-runtime";
202
- var ChevronComponent;
203
- var init_ChevronComponent = __esm({
204
- "src/components/DatePicker/CustomComponents/ChevronComponent.tsx"() {
205
- "use strict";
206
- ChevronComponent = ({ orientation }) => {
207
- if (orientation === "left") {
208
- return /* @__PURE__ */ jsx3(Icon, { icon: chevronLeft });
209
- }
210
- return /* @__PURE__ */ jsx3(Icon, { icon: chevronRight });
211
- };
212
- }
213
- });
214
-
215
- // src/components/DatePicker/CustomComponents/index.tsx
216
- var init_CustomComponents = __esm({
217
- "src/components/DatePicker/CustomComponents/index.tsx"() {
218
- "use strict";
219
- init_CaptionLabel();
220
- init_ChevronComponent();
221
- }
222
- });
223
-
224
- // src/components/DatePicker/DatePickerModal.tsx
225
- var DatePickerModal_exports = {};
226
- __export(DatePickerModal_exports, {
227
- default: () => DatePickerModal_default
228
- });
229
- import { VisuallyHidden, useOnClickOutside } from "@simplybusiness/mobius";
230
- import classNames from "classnames/dedupe";
231
- import { parseISO } from "date-fns";
232
- import { useId, useRef as useRef2 } from "react";
233
- import { DayPicker } from "react-day-picker";
234
- import { jsx as jsx4, jsxs } from "react/jsx-runtime";
235
- var startWeekday, DatePickerModal, DatePickerModal_default;
236
- var init_DatePickerModal = __esm({
237
- "src/components/DatePicker/DatePickerModal.tsx"() {
238
- "use strict";
239
- "use client";
240
- init_useFocusTrap();
241
- init_utils();
242
- init_getStartWeekday();
243
- init_timezoneOffset();
244
- init_CustomComponents();
245
- startWeekday = getStartWeekday(
246
- // eslint-disable-next-line ssr-friendly/no-dom-globals-in-module-scope
247
- typeof navigator !== "undefined" ? navigator?.language : void 0
248
- );
249
- DatePickerModal = ({
250
- date,
251
- isOpen,
252
- onSelected,
253
- top,
254
- min,
255
- max
256
- }) => {
257
- const modalRef = useRef2(null);
258
- const initialDate = date ? toLocal(date) : void 0;
259
- const minDate = min ? toLocal(min) : void 0;
260
- const maxDate = max ? toLocal(max) : void 0;
261
- const hiddenId = `screen-reader-title-${useId()}`;
262
- const handleSelected = (selectedDate) => {
263
- onSelected(selectedDate);
264
- };
265
- const handleDayPickerSelect = (selectedDate) => {
266
- if (!selectedDate) return;
267
- handleSelected(dateObjToString(selectedDate));
268
- };
269
- useOnClickOutside(modalRef, () => {
270
- if (modalRef.current && isOpen) {
271
- handleSelected();
272
- }
273
- });
274
- const modalClasses = classNames("mobius-date-picker__modal", {
275
- "--is-open": isOpen
276
- });
277
- return /* @__PURE__ */ jsx4(FocusTrap, { children: /* @__PURE__ */ jsxs(
278
- "div",
279
- {
280
- ref: modalRef,
281
- className: modalClasses,
282
- style: { top },
283
- "aria-describedby": hiddenId,
284
- "data-testid": "modal-container",
285
- children: [
286
- /* @__PURE__ */ jsx4(VisuallyHidden, { children: /* @__PURE__ */ jsx4("div", { id: hiddenId, children: "Please select a date from the calendar" }) }),
287
- /* @__PURE__ */ jsx4(
288
- DayPicker,
289
- {
290
- autoFocus: true,
291
- mode: "single",
292
- ...minDate && { startMonth: minDate },
293
- ...maxDate && { endMonth: maxDate },
294
- disabled: {
295
- ...min && { before: parseISO(min) },
296
- ...max && { after: parseISO(max) }
297
- },
298
- selected: initialDate,
299
- defaultMonth: initialDate,
300
- onSelect: handleDayPickerSelect,
301
- pagedNavigation: true,
302
- showOutsideDays: true,
303
- weekStartsOn: startWeekday,
304
- formatters: { formatWeekdayName: weekdayAsOneLetter },
305
- components: {
306
- Chevron: ChevronComponent,
307
- CaptionLabel
308
- },
309
- classNames: {
310
- root: "mobius-date-picker__root",
311
- months: "mobius-date-picker__months",
312
- month: "mobius-date-picker__month",
313
- nav: "mobius-date-picker__nav",
314
- button_previous: "mobius-date-picker__nav-button --previous",
315
- button_next: "mobius-date-picker__nav-button --next",
316
- month_caption: "mobius-date-picker__caption",
317
- caption_label: "mobius-date-picker__caption-label",
318
- month_grid: "mobius-date-picker__month-grid",
319
- weekdays: "mobius-date-picker__weekdays",
320
- weekday: "mobius-date-picker__weekday",
321
- weeks: "mobius-date-picker__weeks",
322
- week: "mobius-date-picker__week",
323
- day: "mobius-date-picker__day",
324
- day_button: "mobius-date-picker__day-button",
325
- selected: "--is-selected",
326
- disabled: "--is-disabled",
327
- outside: "--is-outside",
328
- hidden: "--is-hidden",
329
- today: "--is-today",
330
- focused: "--is-focused"
331
- }
332
- }
333
- )
334
- ]
335
- }
336
- ) });
337
- };
338
- DatePickerModal_default = DatePickerModal;
339
- }
340
- });
341
-
342
1
  // src/components/DatePicker/DatePicker.tsx
343
2
  import { calendarDay } from "@simplybusiness/icons";
344
3
  import {
345
4
  Button,
346
- Icon as Icon2,
5
+ Icon,
347
6
  TextField,
348
- VisuallyHidden as VisuallyHidden2,
7
+ VisuallyHidden,
349
8
  useValidationClasses
350
9
  } from "@simplybusiness/mobius";
351
- import classNames2 from "classnames/dedupe";
10
+ import classNames from "classnames/dedupe";
352
11
  import {
353
12
  Suspense,
354
13
  lazy,
355
14
  useCallback,
356
- useEffect as useEffect2,
357
- useRef as useRef3,
15
+ useEffect,
16
+ useRef,
358
17
  useState
359
18
  } from "react";
360
19
 
@@ -366,10 +25,42 @@ var isTouchDevice = () => {
366
25
  return void 0;
367
26
  };
368
27
 
28
+ // src/components/DatePicker/utils/formatErrorMessageText.ts
29
+ import { isAfter, isBefore } from "date-fns";
30
+ var DEFAULT_INVALID_DATE_MESSAGE = "Please enter a valid date";
31
+ var DEFAULT_BEFORE_MIN = "The date you selected is before the earliest allowed date";
32
+ var DEFAULT_AFTER_MAX = "The date you selected is after the latest allowed date";
33
+ var formatErrorMessageText = (actual, min, max) => {
34
+ const actualDate = new Date(actual);
35
+ const minDate = min && new Date(min);
36
+ const maxDate = max && new Date(max);
37
+ if (minDate && isBefore(actualDate, minDate)) {
38
+ return DEFAULT_BEFORE_MIN;
39
+ }
40
+ if (maxDate && isAfter(actualDate, maxDate)) {
41
+ return DEFAULT_AFTER_MAX;
42
+ }
43
+ return DEFAULT_INVALID_DATE_MESSAGE;
44
+ };
45
+
46
+ // src/components/DatePicker/utils/validateDateFormat.ts
47
+ import { isMatch } from "date-fns";
48
+ var DATE_FORMAT = "yyyy-MM-dd";
49
+ var validateDateFormat = (date) => {
50
+ if (date === "") {
51
+ return "";
52
+ }
53
+ if (isMatch(date, DATE_FORMAT)) {
54
+ return date;
55
+ }
56
+ throw Error(
57
+ `DatePicker defaultValue '${date}' is invalid. The expected format is '${DATE_FORMAT}' `
58
+ );
59
+ };
60
+
369
61
  // src/components/DatePicker/DatePicker.tsx
370
- init_utils();
371
- import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
372
- var DatePickerModal2 = lazy(() => Promise.resolve().then(() => (init_DatePickerModal(), DatePickerModal_exports)));
62
+ import { jsx, jsxs } from "react/jsx-runtime";
63
+ var DatePickerModal = lazy(() => import("./DatePickerModal-WRMRIQDP.js"));
373
64
  var getValidationState = (isInvalid) => {
374
65
  if (isInvalid) {
375
66
  return true;
@@ -388,9 +79,9 @@ var DatePicker = (props) => {
388
79
  errorMessage = "",
389
80
  ...otherProps
390
81
  } = props;
391
- const containerRef = useRef3(null);
82
+ const containerRef = useRef(null);
392
83
  const [top, setTop] = useState(0);
393
- const inputRef = useRef3(null);
84
+ const inputRef = useRef(null);
394
85
  const [isOpen, setIsOpen] = useState(false);
395
86
  const [textFieldVal, setTextFieldVal] = useState(
396
87
  validateDateFormat(defaultValue)
@@ -400,7 +91,7 @@ var DatePicker = (props) => {
400
91
  const errorMessageText = isInvalidProp ? formatErrorMessageText(textFieldVal, props.min, props.max) : errorMessage;
401
92
  const touchDevice = isTouchDevice();
402
93
  const validationClasses = useValidationClasses({ isInvalid: isInvalidProp });
403
- const containerClasses = classNames2(
94
+ const containerClasses = classNames(
404
95
  "mobius-date-picker__container",
405
96
  {
406
97
  "--is-disabled": isDisabled,
@@ -408,7 +99,7 @@ var DatePicker = (props) => {
408
99
  },
409
100
  validationClasses
410
101
  );
411
- const popoverToggleClasses = classNames2(
102
+ const popoverToggleClasses = classNames(
412
103
  "mobius-date-picker__field-button",
413
104
  validationClasses
414
105
  );
@@ -419,7 +110,7 @@ var DatePicker = (props) => {
419
110
  setIsValid(false);
420
111
  }
421
112
  }, [isOpen]);
422
- useEffect2(() => {
113
+ useEffect(() => {
423
114
  if (!inputRef.current) return;
424
115
  const validatedValue = validateDateFormat(defaultValue);
425
116
  setTextFieldVal(validatedValue);
@@ -459,7 +150,7 @@ var DatePicker = (props) => {
459
150
  event.preventDefault();
460
151
  togglePopoverVisibility();
461
152
  };
462
- useEffect2(() => {
153
+ useEffect(() => {
463
154
  if (isOpen) {
464
155
  setTop(containerRef.current?.getBoundingClientRect().height || 0);
465
156
  setIsValid(true);
@@ -468,7 +159,7 @@ var DatePicker = (props) => {
468
159
  validate();
469
160
  }, [isOpen, validate]);
470
161
  if (touchDevice) {
471
- return /* @__PURE__ */ jsx5("div", { className: containerClasses, children: /* @__PURE__ */ jsx5(
162
+ return /* @__PURE__ */ jsx("div", { className: containerClasses, children: /* @__PURE__ */ jsx(
472
163
  TextField,
473
164
  {
474
165
  ref: inputRef,
@@ -484,8 +175,8 @@ var DatePicker = (props) => {
484
175
  }
485
176
  ) });
486
177
  }
487
- return /* @__PURE__ */ jsxs2("div", { className: containerClasses, ref: containerRef, children: [
488
- /* @__PURE__ */ jsx5(
178
+ return /* @__PURE__ */ jsxs("div", { className: containerClasses, ref: containerRef, children: [
179
+ /* @__PURE__ */ jsx(
489
180
  TextField,
490
181
  {
491
182
  ref: inputRef,
@@ -499,7 +190,7 @@ var DatePicker = (props) => {
499
190
  isInvalid: isInvalidProp,
500
191
  ...otherProps,
501
192
  errorMessage: errorMessage || errorMessageText,
502
- suffixOutside: /* @__PURE__ */ jsxs2(
193
+ suffixOutside: /* @__PURE__ */ jsxs(
503
194
  Button,
504
195
  {
505
196
  className: popoverToggleClasses,
@@ -507,15 +198,15 @@ var DatePicker = (props) => {
507
198
  isDisabled,
508
199
  size: "sm",
509
200
  children: [
510
- /* @__PURE__ */ jsx5(Icon2, { size: "sm", icon: calendarDay }),
511
- /* @__PURE__ */ jsx5(VisuallyHidden2, { children: "Pick date" })
201
+ /* @__PURE__ */ jsx(Icon, { size: "sm", icon: calendarDay }),
202
+ /* @__PURE__ */ jsx(VisuallyHidden, { children: "Pick date" })
512
203
  ]
513
204
  }
514
205
  )
515
206
  }
516
207
  ),
517
- isOpen && /* @__PURE__ */ jsx5(Suspense, { children: /* @__PURE__ */ jsx5(
518
- DatePickerModal2,
208
+ isOpen && /* @__PURE__ */ jsx(Suspense, { children: /* @__PURE__ */ jsx(
209
+ DatePickerModal,
519
210
  {
520
211
  date: textFieldVal,
521
212
  isOpen,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../src/components/DatePicker/utils/dateObjToString.ts", "../../src/components/DatePicker/utils/formatErrorMessageText.ts", "../../src/components/DatePicker/utils/validateDateFormat.ts", "../../src/components/DatePicker/constants.ts", "../../src/components/DatePicker/utils/weekdayAsOneLetter.ts", "../../src/components/DatePicker/utils/index.ts", "../../src/hooks/useFocusTrap/useFocusTrap.tsx", "../../src/components/DatePicker/utils/getStartWeekday.ts", "../../src/components/DatePicker/utils/timezoneOffset.ts", "../../src/components/DatePicker/CustomComponents/CaptionLabel.tsx", "../../src/components/DatePicker/CustomComponents/ChevronComponent.tsx", "../../src/components/DatePicker/CustomComponents/index.tsx", "../../src/components/DatePicker/DatePickerModal.tsx", "../../src/components/DatePicker/DatePicker.tsx", "../../src/utils/isTouchDevice.ts"],
4
- "sourcesContent": ["export const dateObjToString = (date: Date) => {\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, \"0\");\n const day = String(date.getDate()).padStart(2, \"0\");\n\n // Extract the date part from the Date object\n return `${year}-${month}-${day}`;\n};\n", "import { isAfter, isBefore } from \"date-fns\";\n\nexport const DEFAULT_INVALID_DATE_MESSAGE = \"Please enter a valid date\";\nexport const DEFAULT_BEFORE_MIN =\n \"The date you selected is before the earliest allowed date\";\nexport const DEFAULT_AFTER_MAX =\n \"The date you selected is after the latest allowed date\";\n\nexport const formatErrorMessageText = (\n actual: string,\n min?: string,\n max?: string,\n) => {\n const actualDate = new Date(actual);\n const minDate = min && new Date(min);\n const maxDate = max && new Date(max);\n\n if (minDate && isBefore(actualDate, minDate)) {\n return DEFAULT_BEFORE_MIN;\n }\n\n if (maxDate && isAfter(actualDate, maxDate)) {\n return DEFAULT_AFTER_MAX;\n }\n\n return DEFAULT_INVALID_DATE_MESSAGE;\n};\n", "import { isMatch } from \"date-fns\";\n\n// eg 2023-12-31\nexport const DATE_FORMAT = \"yyyy-MM-dd\";\n\nexport const validateDateFormat = (date: string) => {\n if (date === \"\") {\n return \"\";\n }\n\n if (isMatch(date, DATE_FORMAT)) {\n return date;\n }\n\n throw Error(\n `DatePicker defaultValue '${date}' is invalid. The expected format is '${DATE_FORMAT}' `,\n );\n};\n", "export const SUNDAY_AS_NUMBER = 0;\nexport const MONDAY_AS_NUMBER = 1;\nexport const DEFAULT_LOCALE = \"en-GB\";\n", "import { DEFAULT_LOCALE } from \"../constants\";\n\nexport const weekdayAsOneLetter = (date: Date) => {\n const locale = navigator.language || DEFAULT_LOCALE;\n const oneLetter = date.toLocaleString(locale, {\n weekday: \"narrow\",\n });\n\n return oneLetter;\n};\n", "export * from \"./dateObjToString\";\nexport * from \"./formatErrorMessageText\";\nexport * from \"./validateDateFormat\";\nexport * from \"./weekdayAsOneLetter\";\n", "import type { ReactNode } from \"react\";\nimport { useEffect, useRef } from \"react\";\n\nconst useFocusTrap = () => {\n const containerRef = useRef<HTMLDivElement | null>(null);\n\n useEffect(() => {\n if (containerRef.current) {\n const element = containerRef.current;\n const focusableElements =\n containerRef.current.querySelectorAll<HTMLElement>(\n '[tabindex=\"0\"], .mobius-date-picker__nav-button',\n );\n\n const firstElement = focusableElements[0];\n const lastElement = focusableElements[focusableElements.length - 1];\n\n const handleTabKeyPress = (event: KeyboardEvent) => {\n if (event.key === \"Tab\") {\n if (event.shiftKey && document.activeElement === firstElement) {\n event.preventDefault();\n lastElement.focus();\n } else if (\n !event.shiftKey &&\n document.activeElement &&\n document.activeElement.className.indexOf(\n \"mobius-date-picker__day-button\",\n ) > -1\n ) {\n event.preventDefault();\n firstElement.focus();\n }\n }\n };\n\n element.addEventListener(\"keydown\", handleTabKeyPress);\n return () => {\n element.removeEventListener(\"keydown\", handleTabKeyPress);\n };\n }\n return () => {};\n }, []);\n\n return containerRef;\n};\n\nexport type FocusTrapProps = {\n children: ReactNode;\n};\n\nexport default function FocusTrap({ children }: FocusTrapProps) {\n const focusRef = useFocusTrap();\n\n return (\n <div className=\"trap\" ref={focusRef}>\n {children}\n </div>\n );\n}\n", "import {\n DEFAULT_LOCALE,\n MONDAY_AS_NUMBER,\n SUNDAY_AS_NUMBER,\n} from \"../constants\";\n\ntype WeekStart = 0 | 1 | 2 | 3 | 4 | 5 | 6 | undefined;\n\n// Calculates start of week for calendar in UK and US locales\n// Add more to the switch statement as needed\nexport const getStartWeekday = (locale?: string): WeekStart => {\n switch (locale || DEFAULT_LOCALE) {\n case \"en-US\":\n return SUNDAY_AS_NUMBER;\n\n default:\n return MONDAY_AS_NUMBER;\n }\n};\n", "/**\n * Converts a local date-time to UTC\n * @param localDate - Date object in local timezone\n * @returns Date object in UTC\n */\nexport function toUTC(localDate: Date): Date {\n return new Date(localDate.getTime() - localDate.getTimezoneOffset() * 60000);\n}\n\nexport function toLocal(utcDateString: string): Date {\n const utcDate = new Date(utcDateString);\n if (Number.isNaN(utcDate.getTime())) {\n throw new Error(\"Invalid date string\");\n }\n // Convert UTC date to local date\n // by adding the timezone offset in milliseconds\n return new Date(utcDate.getTime() + utcDate.getTimezoneOffset() * 60000);\n}\n", "import { type HTMLAttributes } from \"react\";\n\n/**\n *\n * This component is used to render the caption label for the date picker.\n * We are overriding the standard span with an h2 for accessibility reasons.\n */\nexport const CaptionLabel = (props: HTMLAttributes<HTMLSpanElement>) => {\n return <h2 {...props} />;\n};\n", "import { chevronLeft, chevronRight } from \"@simplybusiness/icons\";\nimport { Icon } from \"@simplybusiness/mobius\";\n\ntype ChevronComponentProps = {\n orientation?: \"up\" | \"down\" | \"left\" | \"right\";\n};\n\nexport const ChevronComponent = ({ orientation }: ChevronComponentProps) => {\n if (orientation === \"left\") {\n return <Icon icon={chevronLeft} />;\n }\n return <Icon icon={chevronRight} />;\n};\n", "export * from \"./CaptionLabel\";\nexport * from \"./ChevronComponent\";\n", "\"use client\";\n\nimport { VisuallyHidden, useOnClickOutside } from \"@simplybusiness/mobius\";\nimport classNames from \"classnames/dedupe\";\nimport { parseISO } from \"date-fns\";\nimport { useId, useRef } from \"react\";\nimport type { Matcher } from \"react-day-picker\";\nimport { DayPicker } from \"react-day-picker\";\nimport FocusTrap from \"../../hooks/useFocusTrap/useFocusTrap\";\nimport { dateObjToString, weekdayAsOneLetter } from \"./utils\";\nimport { getStartWeekday } from \"./utils/getStartWeekday\";\nimport { toLocal } from \"./utils/timezoneOffset\";\nimport { ChevronComponent, CaptionLabel } from \"./CustomComponents\";\n\nexport type DatePickerModalProps = {\n date?: string; // yyyy-mm-dd\n isOpen: boolean;\n top: number;\n onSelected: (date?: string) => void;\n min?: string;\n max?: string;\n};\n\nconst startWeekday = getStartWeekday(\n // eslint-disable-next-line ssr-friendly/no-dom-globals-in-module-scope\n typeof navigator !== \"undefined\" ? navigator?.language : undefined,\n);\n\nconst DatePickerModal = ({\n date,\n isOpen,\n onSelected,\n top,\n min,\n max,\n}: DatePickerModalProps) => {\n const modalRef = useRef<HTMLDivElement>(null);\n const initialDate = date ? toLocal(date) : undefined;\n const minDate = min ? toLocal(min) : undefined;\n const maxDate = max ? toLocal(max) : undefined;\n const hiddenId = `screen-reader-title-${useId()}`;\n\n const handleSelected = (selectedDate?: string) => {\n onSelected(selectedDate);\n };\n\n const handleDayPickerSelect = (selectedDate: Date | undefined) => {\n if (!selectedDate) return;\n\n handleSelected(dateObjToString(selectedDate));\n };\n\n useOnClickOutside(modalRef, () => {\n if (modalRef.current && isOpen) {\n handleSelected();\n }\n });\n\n const modalClasses = classNames(\"mobius-date-picker__modal\", {\n \"--is-open\": isOpen,\n });\n\n return (\n <FocusTrap>\n <div\n ref={modalRef}\n className={modalClasses}\n style={{ top }}\n aria-describedby={hiddenId}\n data-testid=\"modal-container\"\n >\n <VisuallyHidden>\n <div id={hiddenId}>Please select a date from the calendar</div>\n </VisuallyHidden>\n <DayPicker\n autoFocus\n mode=\"single\"\n {...(minDate && { startMonth: minDate })}\n {...(maxDate && { endMonth: maxDate })}\n disabled={\n {\n ...(min && { before: parseISO(min) }),\n ...(max && { after: parseISO(max) }),\n } as Matcher\n }\n selected={initialDate}\n defaultMonth={initialDate}\n onSelect={handleDayPickerSelect}\n pagedNavigation\n showOutsideDays\n weekStartsOn={startWeekday}\n formatters={{ formatWeekdayName: weekdayAsOneLetter }}\n components={{\n Chevron: ChevronComponent,\n CaptionLabel,\n }}\n classNames={{\n root: \"mobius-date-picker__root\",\n months: \"mobius-date-picker__months\",\n month: \"mobius-date-picker__month\",\n nav: \"mobius-date-picker__nav\",\n button_previous: \"mobius-date-picker__nav-button --previous\",\n button_next: \"mobius-date-picker__nav-button --next\",\n month_caption: \"mobius-date-picker__caption\",\n caption_label: \"mobius-date-picker__caption-label\",\n month_grid: \"mobius-date-picker__month-grid\",\n weekdays: \"mobius-date-picker__weekdays\",\n weekday: \"mobius-date-picker__weekday\",\n weeks: \"mobius-date-picker__weeks\",\n week: \"mobius-date-picker__week\",\n day: \"mobius-date-picker__day\",\n day_button: \"mobius-date-picker__day-button\",\n selected: \"--is-selected\",\n disabled: \"--is-disabled\",\n outside: \"--is-outside\",\n hidden: \"--is-hidden\",\n today: \"--is-today\",\n focused: \"--is-focused\",\n }}\n />\n </div>\n </FocusTrap>\n );\n};\n\nexport default DatePickerModal;\n", "\"use client\";\n\nimport { calendarDay } from \"@simplybusiness/icons\";\nimport type {\n TextFieldElementType,\n TextFieldProps,\n Validation,\n} from \"@simplybusiness/mobius\";\nimport {\n Button,\n Icon,\n TextField,\n VisuallyHidden,\n useValidationClasses,\n} from \"@simplybusiness/mobius\";\nimport classNames from \"classnames/dedupe\";\nimport type { ChangeEvent, FocusEvent } from \"react\";\nimport {\n Suspense,\n lazy,\n useCallback,\n useEffect,\n useRef,\n useState,\n type MouseEvent,\n} from \"react\";\nimport { isTouchDevice } from \"../../utils/isTouchDevice\";\nimport { formatErrorMessageText, validateDateFormat } from \"./utils\";\n\nconst DatePickerModal = lazy(() => import(\"./DatePickerModal\"));\n\nconst getValidationState = (isInvalid: boolean | undefined) => {\n if (isInvalid) {\n return true;\n }\n\n if (isInvalid === false) {\n return false;\n }\n\n return undefined;\n};\n\nexport interface DatePickerProps\n extends\n Validation,\n Omit<TextFieldProps, \"defaultValue\" | \"onChange\" | \"onBlur\" | \"onFocus\"> {\n onChange?: (date: string | undefined) => void;\n defaultValue?: string;\n min?: string;\n max?: string;\n id?: string;\n}\n\nexport const DatePicker = (props: DatePickerProps) => {\n const {\n onChange,\n defaultValue = \"\",\n isDisabled,\n isInvalid,\n errorMessage = \"\",\n ...otherProps\n } = props;\n const containerRef = useRef<HTMLDivElement | null>(null);\n const [top, setTop] = useState<number>(0);\n const inputRef = useRef<TextFieldElementType | null>(null);\n const [isOpen, setIsOpen] = useState<boolean>(false);\n const [textFieldVal, setTextFieldVal] = useState<string>(\n validateDateFormat(defaultValue),\n );\n const [isValid, setIsValid] = useState<boolean | undefined>(undefined);\n const isInvalidProp = getValidationState(isValid === false || isInvalid);\n const errorMessageText = isInvalidProp\n ? formatErrorMessageText(textFieldVal, props.min, props.max)\n : errorMessage;\n const touchDevice = isTouchDevice();\n\n const validationClasses = useValidationClasses({ isInvalid: isInvalidProp });\n\n const containerClasses = classNames(\n \"mobius-date-picker__container\",\n {\n \"--is-disabled\": isDisabled,\n \"--is-touch-device\": touchDevice,\n },\n validationClasses,\n );\n\n const popoverToggleClasses = classNames(\n \"mobius-date-picker__field-button\",\n validationClasses,\n );\n\n const validate = useCallback(() => {\n if (isOpen) return;\n\n // If 'min' or 'max' values are provided, checkValidity() will\n // validate the date and return a boolean\n const isValidInput = inputRef.current?.checkValidity();\n\n if (!isValidInput) {\n setIsValid(false);\n }\n }, [isOpen]);\n\n useEffect(() => {\n if (!inputRef.current) return;\n const validatedValue = validateDateFormat(defaultValue);\n setTextFieldVal(validatedValue);\n inputRef.current.value = validatedValue;\n setIsValid(true);\n validate();\n }, [defaultValue, validate]);\n\n const togglePopoverVisibility = () => {\n setIsValid(true);\n setIsOpen(!isOpen);\n };\n\n const handleTextFieldChange = (event: ChangeEvent<TextFieldElementType>) => {\n setTextFieldVal(event.target.value);\n // onChange only triggers on a valid date\n // so this clears the error\n setIsValid(true);\n };\n\n const onDateSelected = (selectedDate: string | undefined) => {\n // Handle null callback from useOnClickOutside\n if (selectedDate) {\n setTextFieldVal(selectedDate);\n setIsValid(true);\n // Add other callback events here\n onChange?.(selectedDate);\n }\n // Focus the input\n inputRef.current?.focus();\n setIsOpen(false);\n };\n\n // User has interacted with the component and navigated away\n const handleBlur = (event: FocusEvent) => {\n const target = event.target as TextFieldElementType;\n // If the blur is caused by focusing on the DayPicker modal, do nothing\n // The modal is rendered after the input in the DOM,\n // so check if the relatedTarget is inside the modal\n if (\n isOpen &&\n event.relatedTarget &&\n containerRef.current?.contains(event.relatedTarget as HTMLElement)\n ) {\n return;\n }\n validate();\n\n // User hasn't entered a date, or entered an invalid date\n if (!textFieldVal) {\n setIsValid(false);\n }\n\n onChange?.(target.value);\n };\n\n const handleClick = (event: MouseEvent<TextFieldElementType>) => {\n event.preventDefault();\n togglePopoverVisibility();\n };\n\n useEffect(() => {\n if (isOpen) {\n setTop(containerRef.current?.getBoundingClientRect().height || 0);\n // Disable validation when day picker is open\n setIsValid(true);\n return;\n }\n\n validate();\n }, [isOpen, validate]);\n\n if (touchDevice) {\n return (\n <div className={containerClasses}>\n <TextField\n ref={inputRef}\n type=\"date\"\n className=\"mobius-date-picker\"\n onBlur={handleBlur}\n onChange={handleTextFieldChange}\n value={textFieldVal}\n isDisabled={isDisabled}\n isInvalid={isInvalidProp}\n {...otherProps}\n errorMessage={errorMessage || errorMessageText}\n />\n </div>\n );\n }\n\n return (\n <div className={containerClasses} ref={containerRef}>\n <TextField\n ref={inputRef}\n type=\"date\"\n className=\"mobius-date-picker\"\n onBlur={handleBlur}\n onChange={handleTextFieldChange}\n // @ts-expect-error onClick is not in TextField's props but is passed through via otherProps spread\n onClick={handleClick}\n value={textFieldVal}\n isDisabled={isDisabled}\n isInvalid={isInvalidProp}\n {...otherProps}\n errorMessage={errorMessage || errorMessageText}\n suffixOutside={\n <Button\n className={popoverToggleClasses}\n onClick={togglePopoverVisibility}\n isDisabled={isDisabled}\n size=\"sm\"\n >\n <Icon size=\"sm\" icon={calendarDay} />\n <VisuallyHidden>Pick date</VisuallyHidden>\n </Button>\n }\n />\n {isOpen && (\n <Suspense>\n <DatePickerModal\n date={textFieldVal}\n isOpen={isOpen}\n top={top}\n onSelected={onDateSelected}\n min={props.min}\n max={props.max}\n />\n </Suspense>\n )}\n </div>\n );\n};\n", "export const isTouchDevice = (): boolean | undefined => {\n if (typeof window !== \"undefined\") {\n return window.matchMedia(\"(hover: none), (pointer: coarse)\").matches;\n }\n\n return undefined;\n};\n"],
5
- "mappings": "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",
6
- "names": ["jsx", "jsx", "useRef", "jsx", "Icon", "VisuallyHidden", "classNames", "useEffect", "useRef", "jsx", "jsxs", "DatePickerModal", "useRef", "classNames", "useEffect", "Icon", "VisuallyHidden"]
3
+ "sources": ["../../src/components/DatePicker/DatePicker.tsx", "../../src/utils/isTouchDevice.ts", "../../src/components/DatePicker/utils/formatErrorMessageText.ts", "../../src/components/DatePicker/utils/validateDateFormat.ts"],
4
+ "sourcesContent": ["\"use client\";\n\nimport { calendarDay } from \"@simplybusiness/icons\";\nimport type {\n TextFieldElementType,\n TextFieldProps,\n Validation,\n} from \"@simplybusiness/mobius\";\nimport {\n Button,\n Icon,\n TextField,\n VisuallyHidden,\n useValidationClasses,\n} from \"@simplybusiness/mobius\";\nimport classNames from \"classnames/dedupe\";\nimport type { ChangeEvent, FocusEvent } from \"react\";\nimport {\n Suspense,\n lazy,\n useCallback,\n useEffect,\n useRef,\n useState,\n type MouseEvent,\n} from \"react\";\nimport { isTouchDevice } from \"../../utils/isTouchDevice\";\nimport { formatErrorMessageText, validateDateFormat } from \"./utils\";\n\nconst DatePickerModal = lazy(() => import(\"./DatePickerModal\"));\n\nconst getValidationState = (isInvalid: boolean | undefined) => {\n if (isInvalid) {\n return true;\n }\n\n if (isInvalid === false) {\n return false;\n }\n\n return undefined;\n};\n\nexport interface DatePickerProps\n extends\n Validation,\n Omit<TextFieldProps, \"defaultValue\" | \"onChange\" | \"onBlur\" | \"onFocus\"> {\n onChange?: (date: string | undefined) => void;\n defaultValue?: string;\n min?: string;\n max?: string;\n id?: string;\n}\n\nexport const DatePicker = (props: DatePickerProps) => {\n const {\n onChange,\n defaultValue = \"\",\n isDisabled,\n isInvalid,\n errorMessage = \"\",\n ...otherProps\n } = props;\n const containerRef = useRef<HTMLDivElement | null>(null);\n const [top, setTop] = useState<number>(0);\n const inputRef = useRef<TextFieldElementType | null>(null);\n const [isOpen, setIsOpen] = useState<boolean>(false);\n const [textFieldVal, setTextFieldVal] = useState<string>(\n validateDateFormat(defaultValue),\n );\n const [isValid, setIsValid] = useState<boolean | undefined>(undefined);\n const isInvalidProp = getValidationState(isValid === false || isInvalid);\n const errorMessageText = isInvalidProp\n ? formatErrorMessageText(textFieldVal, props.min, props.max)\n : errorMessage;\n const touchDevice = isTouchDevice();\n\n const validationClasses = useValidationClasses({ isInvalid: isInvalidProp });\n\n const containerClasses = classNames(\n \"mobius-date-picker__container\",\n {\n \"--is-disabled\": isDisabled,\n \"--is-touch-device\": touchDevice,\n },\n validationClasses,\n );\n\n const popoverToggleClasses = classNames(\n \"mobius-date-picker__field-button\",\n validationClasses,\n );\n\n const validate = useCallback(() => {\n if (isOpen) return;\n\n // If 'min' or 'max' values are provided, checkValidity() will\n // validate the date and return a boolean\n const isValidInput = inputRef.current?.checkValidity();\n\n if (!isValidInput) {\n setIsValid(false);\n }\n }, [isOpen]);\n\n useEffect(() => {\n if (!inputRef.current) return;\n const validatedValue = validateDateFormat(defaultValue);\n setTextFieldVal(validatedValue);\n inputRef.current.value = validatedValue;\n setIsValid(true);\n validate();\n }, [defaultValue, validate]);\n\n const togglePopoverVisibility = () => {\n setIsValid(true);\n setIsOpen(!isOpen);\n };\n\n const handleTextFieldChange = (event: ChangeEvent<TextFieldElementType>) => {\n setTextFieldVal(event.target.value);\n // onChange only triggers on a valid date\n // so this clears the error\n setIsValid(true);\n };\n\n const onDateSelected = (selectedDate: string | undefined) => {\n // Handle null callback from useOnClickOutside\n if (selectedDate) {\n setTextFieldVal(selectedDate);\n setIsValid(true);\n // Add other callback events here\n onChange?.(selectedDate);\n }\n // Focus the input\n inputRef.current?.focus();\n setIsOpen(false);\n };\n\n // User has interacted with the component and navigated away\n const handleBlur = (event: FocusEvent) => {\n const target = event.target as TextFieldElementType;\n // If the blur is caused by focusing on the DayPicker modal, do nothing\n // The modal is rendered after the input in the DOM,\n // so check if the relatedTarget is inside the modal\n if (\n isOpen &&\n event.relatedTarget &&\n containerRef.current?.contains(event.relatedTarget as HTMLElement)\n ) {\n return;\n }\n validate();\n\n // User hasn't entered a date, or entered an invalid date\n if (!textFieldVal) {\n setIsValid(false);\n }\n\n onChange?.(target.value);\n };\n\n const handleClick = (event: MouseEvent<TextFieldElementType>) => {\n event.preventDefault();\n togglePopoverVisibility();\n };\n\n useEffect(() => {\n if (isOpen) {\n setTop(containerRef.current?.getBoundingClientRect().height || 0);\n // Disable validation when day picker is open\n setIsValid(true);\n return;\n }\n\n validate();\n }, [isOpen, validate]);\n\n if (touchDevice) {\n return (\n <div className={containerClasses}>\n <TextField\n ref={inputRef}\n type=\"date\"\n className=\"mobius-date-picker\"\n onBlur={handleBlur}\n onChange={handleTextFieldChange}\n value={textFieldVal}\n isDisabled={isDisabled}\n isInvalid={isInvalidProp}\n {...otherProps}\n errorMessage={errorMessage || errorMessageText}\n />\n </div>\n );\n }\n\n return (\n <div className={containerClasses} ref={containerRef}>\n <TextField\n ref={inputRef}\n type=\"date\"\n className=\"mobius-date-picker\"\n onBlur={handleBlur}\n onChange={handleTextFieldChange}\n // @ts-expect-error onClick is not in TextField's props but is passed through via otherProps spread\n onClick={handleClick}\n value={textFieldVal}\n isDisabled={isDisabled}\n isInvalid={isInvalidProp}\n {...otherProps}\n errorMessage={errorMessage || errorMessageText}\n suffixOutside={\n <Button\n className={popoverToggleClasses}\n onClick={togglePopoverVisibility}\n isDisabled={isDisabled}\n size=\"sm\"\n >\n <Icon size=\"sm\" icon={calendarDay} />\n <VisuallyHidden>Pick date</VisuallyHidden>\n </Button>\n }\n />\n {isOpen && (\n <Suspense>\n <DatePickerModal\n date={textFieldVal}\n isOpen={isOpen}\n top={top}\n onSelected={onDateSelected}\n min={props.min}\n max={props.max}\n />\n </Suspense>\n )}\n </div>\n );\n};\n", "export const isTouchDevice = (): boolean | undefined => {\n if (typeof window !== \"undefined\") {\n return window.matchMedia(\"(hover: none), (pointer: coarse)\").matches;\n }\n\n return undefined;\n};\n", "import { isAfter, isBefore } from \"date-fns\";\n\nexport const DEFAULT_INVALID_DATE_MESSAGE = \"Please enter a valid date\";\nexport const DEFAULT_BEFORE_MIN =\n \"The date you selected is before the earliest allowed date\";\nexport const DEFAULT_AFTER_MAX =\n \"The date you selected is after the latest allowed date\";\n\nexport const formatErrorMessageText = (\n actual: string,\n min?: string,\n max?: string,\n) => {\n const actualDate = new Date(actual);\n const minDate = min && new Date(min);\n const maxDate = max && new Date(max);\n\n if (minDate && isBefore(actualDate, minDate)) {\n return DEFAULT_BEFORE_MIN;\n }\n\n if (maxDate && isAfter(actualDate, maxDate)) {\n return DEFAULT_AFTER_MAX;\n }\n\n return DEFAULT_INVALID_DATE_MESSAGE;\n};\n", "import { isMatch } from \"date-fns\";\n\n// eg 2023-12-31\nexport const DATE_FORMAT = \"yyyy-MM-dd\";\n\nexport const validateDateFormat = (date: string) => {\n if (date === \"\") {\n return \"\";\n }\n\n if (isMatch(date, DATE_FORMAT)) {\n return date;\n }\n\n throw Error(\n `DatePicker defaultValue '${date}' is invalid. The expected format is '${DATE_FORMAT}' `,\n );\n};\n"],
5
+ "mappings": "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",
6
+ "names": []
7
7
  }