@xsolla/xui-date-picker 0.64.0-pr56.1768440195

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/web/index.mjs ADDED
@@ -0,0 +1,922 @@
1
+ // src/DatePicker.tsx
2
+ import { forwardRef as forwardRef4, useCallback as useCallback3, useEffect as useEffect2, useRef, useState as useState2 } from "react";
3
+
4
+ // ../primitives-web/src/Box.tsx
5
+ import React from "react";
6
+ import styled from "styled-components";
7
+ import { jsx } from "react/jsx-runtime";
8
+ var StyledBox = styled.div`
9
+ display: flex;
10
+ box-sizing: border-box;
11
+ background-color: ${(props) => props.backgroundColor || "transparent"};
12
+ border-color: ${(props) => props.borderColor || "transparent"};
13
+ border-width: ${(props) => typeof props.borderWidth === "number" ? `${props.borderWidth}px` : props.borderWidth || 0};
14
+
15
+ ${(props) => props.borderBottomWidth !== void 0 && `
16
+ border-bottom-width: ${typeof props.borderBottomWidth === "number" ? `${props.borderBottomWidth}px` : props.borderBottomWidth};
17
+ border-bottom-color: ${props.borderBottomColor || props.borderColor || "transparent"};
18
+ border-bottom-style: solid;
19
+ `}
20
+ ${(props) => props.borderTopWidth !== void 0 && `
21
+ border-top-width: ${typeof props.borderTopWidth === "number" ? `${props.borderTopWidth}px` : props.borderTopWidth};
22
+ border-top-color: ${props.borderTopColor || props.borderColor || "transparent"};
23
+ border-top-style: solid;
24
+ `}
25
+ ${(props) => props.borderLeftWidth !== void 0 && `
26
+ border-left-width: ${typeof props.borderLeftWidth === "number" ? `${props.borderLeftWidth}px` : props.borderLeftWidth};
27
+ border-left-color: ${props.borderLeftColor || props.borderColor || "transparent"};
28
+ border-left-style: solid;
29
+ `}
30
+ ${(props) => props.borderRightWidth !== void 0 && `
31
+ border-right-width: ${typeof props.borderRightWidth === "number" ? `${props.borderRightWidth}px` : props.borderRightWidth};
32
+ border-right-color: ${props.borderRightColor || props.borderColor || "transparent"};
33
+ border-right-style: solid;
34
+ `}
35
+
36
+ border-style: ${(props) => props.borderStyle || (props.borderWidth || props.borderBottomWidth || props.borderTopWidth || props.borderLeftWidth || props.borderRightWidth ? "solid" : "none")};
37
+ border-radius: ${(props) => typeof props.borderRadius === "number" ? `${props.borderRadius}px` : props.borderRadius || 0};
38
+ height: ${(props) => typeof props.height === "number" ? `${props.height}px` : props.height || "auto"};
39
+ width: ${(props) => typeof props.width === "number" ? `${props.width}px` : props.width || "auto"};
40
+ min-width: ${(props) => typeof props.minWidth === "number" ? `${props.minWidth}px` : props.minWidth || "auto"};
41
+ min-height: ${(props) => typeof props.minHeight === "number" ? `${props.minHeight}px` : props.minHeight || "auto"};
42
+
43
+ padding: ${(props) => typeof props.padding === "number" ? `${props.padding}px` : props.padding || 0};
44
+ ${(props) => props.paddingHorizontal && `
45
+ padding-left: ${typeof props.paddingHorizontal === "number" ? `${props.paddingHorizontal}px` : props.paddingHorizontal};
46
+ padding-right: ${typeof props.paddingHorizontal === "number" ? `${props.paddingHorizontal}px` : props.paddingHorizontal};
47
+ `}
48
+ ${(props) => props.paddingVertical && `
49
+ padding-top: ${typeof props.paddingVertical === "number" ? `${props.paddingVertical}px` : props.paddingVertical};
50
+ padding-bottom: ${typeof props.paddingVertical === "number" ? `${props.paddingVertical}px` : props.paddingVertical};
51
+ `}
52
+ ${(props) => props.paddingTop !== void 0 && `padding-top: ${typeof props.paddingTop === "number" ? `${props.paddingTop}px` : props.paddingTop};`}
53
+ ${(props) => props.paddingBottom !== void 0 && `padding-bottom: ${typeof props.paddingBottom === "number" ? `${props.paddingBottom}px` : props.paddingBottom};`}
54
+ ${(props) => props.paddingLeft !== void 0 && `padding-left: ${typeof props.paddingLeft === "number" ? `${props.paddingLeft}px` : props.paddingLeft};`}
55
+ ${(props) => props.paddingRight !== void 0 && `padding-right: ${typeof props.paddingRight === "number" ? `${props.paddingRight}px` : props.paddingRight};`}
56
+
57
+ margin: ${(props) => typeof props.margin === "number" ? `${props.margin}px` : props.margin || 0};
58
+ ${(props) => props.marginTop !== void 0 && `margin-top: ${typeof props.marginTop === "number" ? `${props.marginTop}px` : props.marginTop};`}
59
+ ${(props) => props.marginBottom !== void 0 && `margin-bottom: ${typeof props.marginBottom === "number" ? `${props.marginBottom}px` : props.marginBottom};`}
60
+ ${(props) => props.marginLeft !== void 0 && `margin-left: ${typeof props.marginLeft === "number" ? `${props.marginLeft}px` : props.marginLeft};`}
61
+ ${(props) => props.marginRight !== void 0 && `margin-right: ${typeof props.marginRight === "number" ? `${props.marginRight}px` : props.marginRight};`}
62
+
63
+ flex-direction: ${(props) => props.flexDirection || "column"};
64
+ flex-wrap: ${(props) => props.flexWrap || "nowrap"};
65
+ align-items: ${(props) => props.alignItems || "stretch"};
66
+ justify-content: ${(props) => props.justifyContent || "flex-start"};
67
+ cursor: ${(props) => props.cursor ? props.cursor : props.onClick || props.onPress ? "pointer" : "inherit"};
68
+ position: ${(props) => props.position || "static"};
69
+ top: ${(props) => typeof props.top === "number" ? `${props.top}px` : props.top};
70
+ bottom: ${(props) => typeof props.bottom === "number" ? `${props.bottom}px` : props.bottom};
71
+ left: ${(props) => typeof props.left === "number" ? `${props.left}px` : props.left};
72
+ right: ${(props) => typeof props.right === "number" ? `${props.right}px` : props.right};
73
+ flex: ${(props) => props.flex};
74
+ flex-shrink: ${(props) => props.flexShrink ?? 1};
75
+ gap: ${(props) => typeof props.gap === "number" ? `${props.gap}px` : props.gap || 0};
76
+ align-self: ${(props) => props.alignSelf || "auto"};
77
+ overflow: ${(props) => props.overflow || "visible"};
78
+ overflow-x: ${(props) => props.overflowX || "visible"};
79
+ overflow-y: ${(props) => props.overflowY || "visible"};
80
+ z-index: ${(props) => props.zIndex};
81
+ opacity: ${(props) => props.disabled ? 0.5 : 1};
82
+ pointer-events: ${(props) => props.disabled ? "none" : "auto"};
83
+
84
+ &:hover {
85
+ ${(props) => props.hoverStyle?.backgroundColor && `background-color: ${props.hoverStyle.backgroundColor};`}
86
+ ${(props) => props.hoverStyle?.borderColor && `border-color: ${props.hoverStyle.borderColor};`}
87
+ }
88
+
89
+ &:active {
90
+ ${(props) => props.pressStyle?.backgroundColor && `background-color: ${props.pressStyle.backgroundColor};`}
91
+ }
92
+ `;
93
+ var Box = React.forwardRef(
94
+ ({
95
+ children,
96
+ onPress,
97
+ onKeyDown,
98
+ onKeyUp,
99
+ role,
100
+ "aria-label": ariaLabel,
101
+ "aria-labelledby": ariaLabelledBy,
102
+ "aria-current": ariaCurrent,
103
+ "aria-disabled": ariaDisabled,
104
+ "aria-live": ariaLive,
105
+ "aria-busy": ariaBusy,
106
+ "aria-describedby": ariaDescribedBy,
107
+ "aria-expanded": ariaExpanded,
108
+ "aria-haspopup": ariaHasPopup,
109
+ "aria-pressed": ariaPressed,
110
+ "aria-controls": ariaControls,
111
+ tabIndex,
112
+ as,
113
+ src,
114
+ alt,
115
+ type,
116
+ disabled,
117
+ id,
118
+ ...props
119
+ }, ref) => {
120
+ if (as === "img" && src) {
121
+ return /* @__PURE__ */ jsx(
122
+ "img",
123
+ {
124
+ src,
125
+ alt: alt || "",
126
+ style: {
127
+ display: "block",
128
+ objectFit: "cover",
129
+ width: typeof props.width === "number" ? `${props.width}px` : props.width,
130
+ height: typeof props.height === "number" ? `${props.height}px` : props.height,
131
+ borderRadius: typeof props.borderRadius === "number" ? `${props.borderRadius}px` : props.borderRadius,
132
+ position: props.position,
133
+ top: typeof props.top === "number" ? `${props.top}px` : props.top,
134
+ left: typeof props.left === "number" ? `${props.left}px` : props.left,
135
+ right: typeof props.right === "number" ? `${props.right}px` : props.right,
136
+ bottom: typeof props.bottom === "number" ? `${props.bottom}px` : props.bottom
137
+ }
138
+ }
139
+ );
140
+ }
141
+ return /* @__PURE__ */ jsx(
142
+ StyledBox,
143
+ {
144
+ ref,
145
+ as,
146
+ id,
147
+ type: as === "button" ? type || "button" : void 0,
148
+ disabled: as === "button" ? disabled : void 0,
149
+ onClick: onPress,
150
+ onKeyDown,
151
+ onKeyUp,
152
+ role,
153
+ "aria-label": ariaLabel,
154
+ "aria-labelledby": ariaLabelledBy,
155
+ "aria-current": ariaCurrent,
156
+ "aria-disabled": ariaDisabled,
157
+ "aria-busy": ariaBusy,
158
+ "aria-describedby": ariaDescribedBy,
159
+ "aria-expanded": ariaExpanded,
160
+ "aria-haspopup": ariaHasPopup,
161
+ "aria-pressed": ariaPressed,
162
+ "aria-controls": ariaControls,
163
+ "aria-live": ariaLive,
164
+ tabIndex: tabIndex !== void 0 ? tabIndex : void 0,
165
+ ...props,
166
+ children
167
+ }
168
+ );
169
+ }
170
+ );
171
+ Box.displayName = "Box";
172
+
173
+ // ../primitives-web/src/Text.tsx
174
+ import styled2 from "styled-components";
175
+ import { jsx as jsx2 } from "react/jsx-runtime";
176
+ var StyledText = styled2.span`
177
+ color: ${(props) => props.color || "inherit"};
178
+ font-size: ${(props) => typeof props.fontSize === "number" ? `${props.fontSize}px` : props.fontSize || "inherit"};
179
+ font-weight: ${(props) => props.fontWeight || "normal"};
180
+ font-family: ${(props) => props.fontFamily || '"Pilat Wide Bold", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif !important'};
181
+ line-height: ${(props) => typeof props.lineHeight === "number" ? `${props.lineHeight}px` : props.lineHeight || "inherit"};
182
+ white-space: ${(props) => props.whiteSpace || "normal"};
183
+ text-align: ${(props) => props.textAlign || "inherit"};
184
+ text-decoration: ${(props) => props.textDecoration || "none"};
185
+ `;
186
+ var Text = ({
187
+ style,
188
+ className,
189
+ id,
190
+ role,
191
+ ...props
192
+ }) => {
193
+ return /* @__PURE__ */ jsx2(
194
+ StyledText,
195
+ {
196
+ ...props,
197
+ style,
198
+ className,
199
+ id,
200
+ role
201
+ }
202
+ );
203
+ };
204
+
205
+ // ../primitives-web/src/Spinner.tsx
206
+ import styled3, { keyframes } from "styled-components";
207
+ import { jsx as jsx3 } from "react/jsx-runtime";
208
+ var rotate = keyframes`
209
+ from {
210
+ transform: rotate(0deg);
211
+ }
212
+ to {
213
+ transform: rotate(360deg);
214
+ }
215
+ `;
216
+ var StyledSpinner = styled3.div`
217
+ width: ${(props) => typeof props.size === "number" ? `${props.size}px` : props.size || "24px"};
218
+ height: ${(props) => typeof props.size === "number" ? `${props.size}px` : props.size || "24px"};
219
+ border: ${(props) => props.strokeWidth || 2}px solid
220
+ ${(props) => props.color || "currentColor"};
221
+ border-bottom-color: transparent;
222
+ border-radius: 50%;
223
+ display: inline-block;
224
+ box-sizing: border-box;
225
+ animation: ${rotate} 1s linear infinite;
226
+ `;
227
+ var Spinner = ({
228
+ role = "status",
229
+ "aria-label": ariaLabel,
230
+ "aria-live": ariaLive = "polite",
231
+ "aria-describedby": ariaDescribedBy,
232
+ testID,
233
+ ...props
234
+ }) => {
235
+ return /* @__PURE__ */ jsx3(
236
+ StyledSpinner,
237
+ {
238
+ role,
239
+ "aria-label": ariaLabel,
240
+ "aria-live": ariaLive,
241
+ "aria-describedby": ariaDescribedBy,
242
+ "data-testid": testID,
243
+ ...props
244
+ }
245
+ );
246
+ };
247
+ Spinner.displayName = "Spinner";
248
+
249
+ // ../primitives-web/src/Icon.tsx
250
+ import styled4 from "styled-components";
251
+ import { jsx as jsx4 } from "react/jsx-runtime";
252
+ var StyledIcon = styled4.div`
253
+ display: flex;
254
+ align-items: center;
255
+ justify-content: center;
256
+ width: ${(props) => typeof props.size === "number" ? `${props.size}px` : props.size || "24px"};
257
+ height: ${(props) => typeof props.size === "number" ? `${props.size}px` : props.size || "24px"};
258
+ color: ${(props) => props.color || "currentColor"};
259
+
260
+ svg {
261
+ width: 100%;
262
+ height: 100%;
263
+ fill: none;
264
+ stroke: currentColor;
265
+ }
266
+ `;
267
+
268
+ // ../primitives-web/src/Divider.tsx
269
+ import styled5 from "styled-components";
270
+ import { jsx as jsx5 } from "react/jsx-runtime";
271
+ var StyledDivider = styled5.div`
272
+ background-color: ${(props) => props.dashStroke ? "transparent" : props.color || "rgba(255, 255, 255, 0.15)"};
273
+ width: ${(props) => props.vertical ? typeof props.width === "number" ? `${props.width}px` : props.width || "1px" : "100%"};
274
+ height: ${(props) => props.vertical ? "100%" : typeof props.height === "number" ? `${props.height}px` : props.height || "1px"};
275
+
276
+ ${(props) => props.dashStroke && `
277
+ border-style: dashed;
278
+ border-color: ${props.color || "rgba(255, 255, 255, 0.15)"};
279
+ border-width: 0;
280
+ ${props.vertical ? `
281
+ border-left-width: ${typeof props.width === "number" ? `${props.width}px` : props.width || "1px"};
282
+ height: 100%;
283
+ ` : `
284
+ border-top-width: ${typeof props.height === "number" ? `${props.height}px` : props.height || "1px"};
285
+ width: 100%;
286
+ `}
287
+ `}
288
+ `;
289
+
290
+ // ../primitives-web/src/Input.tsx
291
+ import { forwardRef } from "react";
292
+ import styled6 from "styled-components";
293
+ import { jsx as jsx6 } from "react/jsx-runtime";
294
+ var StyledInput = styled6.input`
295
+ background: transparent;
296
+ border: none;
297
+ outline: none;
298
+ width: 100%;
299
+ height: 100%;
300
+ padding: 0;
301
+ margin: 0;
302
+ color: ${(props) => props.color || "inherit"};
303
+ font-size: ${(props) => typeof props.fontSize === "number" ? `${props.fontSize}px` : props.fontSize || "inherit"};
304
+ font-family: inherit;
305
+ text-align: inherit;
306
+
307
+ &::placeholder {
308
+ color: ${(props) => props.placeholderTextColor || "rgba(255, 255, 255, 0.5)"};
309
+ }
310
+
311
+ &:disabled {
312
+ cursor: not-allowed;
313
+ }
314
+ `;
315
+ var InputPrimitive = forwardRef(
316
+ ({
317
+ value,
318
+ placeholder,
319
+ onChange,
320
+ onChangeText,
321
+ onFocus,
322
+ onBlur,
323
+ onKeyDown,
324
+ disabled,
325
+ secureTextEntry,
326
+ style,
327
+ color,
328
+ fontSize,
329
+ placeholderTextColor,
330
+ maxLength,
331
+ name,
332
+ type,
333
+ inputMode,
334
+ autoComplete,
335
+ id,
336
+ "aria-invalid": ariaInvalid,
337
+ "aria-describedby": ariaDescribedBy,
338
+ "aria-labelledby": ariaLabelledBy,
339
+ "aria-label": ariaLabel,
340
+ "aria-disabled": ariaDisabled,
341
+ "data-testid": dataTestId,
342
+ ...rest
343
+ }, ref) => {
344
+ const handleChange = (e) => {
345
+ if (onChange) {
346
+ onChange(e);
347
+ }
348
+ if (onChangeText) {
349
+ onChangeText(e.target.value);
350
+ }
351
+ };
352
+ const inputValue = value !== void 0 ? value : "";
353
+ return /* @__PURE__ */ jsx6(
354
+ StyledInput,
355
+ {
356
+ ref,
357
+ id,
358
+ value: inputValue,
359
+ name,
360
+ placeholder,
361
+ onChange: handleChange,
362
+ onFocus,
363
+ onBlur,
364
+ onKeyDown,
365
+ disabled,
366
+ type: secureTextEntry ? "password" : type || "text",
367
+ inputMode,
368
+ autoComplete,
369
+ style,
370
+ color,
371
+ fontSize,
372
+ placeholderTextColor,
373
+ maxLength,
374
+ "aria-invalid": ariaInvalid,
375
+ "aria-describedby": ariaDescribedBy,
376
+ "aria-labelledby": ariaLabelledBy,
377
+ "aria-label": ariaLabel,
378
+ "aria-disabled": ariaDisabled,
379
+ "data-testid": dataTestId,
380
+ ...rest
381
+ }
382
+ );
383
+ }
384
+ );
385
+ InputPrimitive.displayName = "InputPrimitive";
386
+
387
+ // ../primitives-web/src/TextArea.tsx
388
+ import { forwardRef as forwardRef2 } from "react";
389
+ import styled7 from "styled-components";
390
+ import { jsx as jsx7 } from "react/jsx-runtime";
391
+ var StyledTextArea = styled7.textarea`
392
+ background: transparent;
393
+ border: none;
394
+ outline: none;
395
+ width: 100%;
396
+ height: 100%;
397
+ padding: 0;
398
+ margin: 0;
399
+ color: ${(props) => props.color || "inherit"};
400
+ font-size: ${(props) => typeof props.fontSize === "number" ? `${props.fontSize}px` : props.fontSize || "inherit"};
401
+ font-family: inherit;
402
+ text-align: inherit;
403
+ resize: none;
404
+
405
+ &::placeholder {
406
+ color: ${(props) => props.placeholderTextColor || "rgba(255, 255, 255, 0.5)"};
407
+ }
408
+
409
+ &:disabled {
410
+ cursor: not-allowed;
411
+ }
412
+ `;
413
+ var TextAreaPrimitive = forwardRef2(
414
+ ({
415
+ value,
416
+ placeholder,
417
+ onChangeText,
418
+ onFocus,
419
+ onBlur,
420
+ onKeyDown,
421
+ disabled,
422
+ style,
423
+ color,
424
+ fontSize,
425
+ placeholderTextColor,
426
+ maxLength,
427
+ rows
428
+ }, ref) => {
429
+ return /* @__PURE__ */ jsx7(
430
+ StyledTextArea,
431
+ {
432
+ ref,
433
+ value,
434
+ placeholder,
435
+ onChange: (e) => onChangeText?.(e.target.value),
436
+ onFocus,
437
+ onBlur,
438
+ onKeyDown,
439
+ disabled,
440
+ style,
441
+ color,
442
+ fontSize,
443
+ placeholderTextColor,
444
+ maxLength,
445
+ rows
446
+ }
447
+ );
448
+ }
449
+ );
450
+ TextAreaPrimitive.displayName = "TextAreaPrimitive";
451
+
452
+ // src/DatePicker.tsx
453
+ import { Input } from "@xsolla/xui-input";
454
+ import { useDesignSystem as useDesignSystem2, isWeb, isNative } from "@xsolla/xui-core";
455
+ import { format as format3 } from "date-fns";
456
+
457
+ // src/Calendar.tsx
458
+ import { forwardRef as forwardRef3, useCallback as useCallback2, useEffect, useMemo as useMemo2, useState } from "react";
459
+ import { useDesignSystem } from "@xsolla/xui-core";
460
+ import {
461
+ addDays,
462
+ addMonths,
463
+ eachDayOfInterval,
464
+ endOfDay,
465
+ endOfMonth,
466
+ endOfWeek,
467
+ format as format2,
468
+ isAfter,
469
+ isBefore,
470
+ isSameDay,
471
+ isSameMonth,
472
+ isToday,
473
+ isWithinInterval,
474
+ startOfDay,
475
+ startOfMonth,
476
+ startOfWeek,
477
+ subMonths
478
+ } from "date-fns";
479
+ import * as locales2 from "date-fns/locale";
480
+
481
+ // src/CalendarHeader.tsx
482
+ import { useCallback, useMemo } from "react";
483
+ import { IconButton } from "@xsolla/xui-button";
484
+ import { Select } from "@xsolla/xui-select";
485
+
486
+ // src/utils.ts
487
+ import { format, setMonth } from "date-fns";
488
+ import * as locales from "date-fns/locale";
489
+ var defaultLocale = "enUS";
490
+ function formatDate(date, formatStr, locale = defaultLocale) {
491
+ const localeObj = locales[locale] || locales[defaultLocale];
492
+ return format(date, formatStr, {
493
+ locale: localeObj
494
+ });
495
+ }
496
+ function getMonthInLocale(month, locale = defaultLocale) {
497
+ return formatDate(setMonth(/* @__PURE__ */ new Date(), month), "LLLL", locale);
498
+ }
499
+
500
+ // src/CalendarHeader.tsx
501
+ import { jsx as jsx8, jsxs } from "react/jsx-runtime";
502
+ var ArrowLeft = () => /* @__PURE__ */ jsx8("svg", { viewBox: "0 0 24 24", width: 16, height: 16, fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx8("polyline", { points: "15 18 9 12 15 6" }) });
503
+ var ArrowRight = () => /* @__PURE__ */ jsx8("svg", { viewBox: "0 0 24 24", width: 16, height: 16, fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx8("polyline", { points: "9 18 15 12 9 6" }) });
504
+ var months = [
505
+ "january",
506
+ "february",
507
+ "march",
508
+ "april",
509
+ "may",
510
+ "june",
511
+ "july",
512
+ "august",
513
+ "september",
514
+ "october",
515
+ "november",
516
+ "december"
517
+ ];
518
+ var CalendarHeader = ({
519
+ monthDate,
520
+ decreaseMonth,
521
+ increaseMonth,
522
+ changeYear,
523
+ changeMonth,
524
+ prevMonthButtonDisabled,
525
+ nextMonthButtonDisabled,
526
+ locale,
527
+ minDate,
528
+ maxDate,
529
+ contextMenuMaxHeight = 240
530
+ }) => {
531
+ const handleChangeMonth = useCallback(
532
+ (value) => {
533
+ changeMonth(months.indexOf(value));
534
+ },
535
+ [changeMonth]
536
+ );
537
+ const handleChangeYear = useCallback(
538
+ (value) => {
539
+ changeYear(parseInt(value, 10));
540
+ },
541
+ [changeYear]
542
+ );
543
+ const monthOptions = useMemo(() => {
544
+ return months.map((month, index) => ({
545
+ label: getMonthInLocale(index, locale),
546
+ value: month
547
+ }));
548
+ }, [locale]);
549
+ const yearOptions = useMemo(() => {
550
+ const options = [];
551
+ const yearStart = minDate ? minDate.getFullYear() : 1900;
552
+ const yearEnd = maxDate ? maxDate.getFullYear() : (/* @__PURE__ */ new Date()).getFullYear() + 100;
553
+ for (let i = yearEnd; i >= yearStart; i--) {
554
+ options.push({ value: i.toString(), label: i.toString() });
555
+ }
556
+ return options;
557
+ }, [minDate, maxDate]);
558
+ return /* @__PURE__ */ jsxs(
559
+ Box,
560
+ {
561
+ width: "100%",
562
+ flexDirection: "row",
563
+ justifyContent: "space-between",
564
+ alignItems: "center",
565
+ marginBottom: 16,
566
+ gap: 8,
567
+ children: [
568
+ /* @__PURE__ */ jsx8(
569
+ IconButton,
570
+ {
571
+ size: "xs",
572
+ tone: "mono",
573
+ variant: "secondary",
574
+ onPress: decreaseMonth,
575
+ disabled: prevMonthButtonDisabled,
576
+ icon: /* @__PURE__ */ jsx8(ArrowLeft, {}),
577
+ "aria-label": "Previous month"
578
+ }
579
+ ),
580
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", flex: 1, gap: 4, children: [
581
+ /* @__PURE__ */ jsx8(Box, { flex: 1.5, children: /* @__PURE__ */ jsx8(
582
+ Select,
583
+ {
584
+ value: months[monthDate.getMonth()],
585
+ onValueChange: handleChangeMonth,
586
+ options: monthOptions,
587
+ size: "s"
588
+ }
589
+ ) }),
590
+ /* @__PURE__ */ jsx8(Box, { flex: 1, children: /* @__PURE__ */ jsx8(
591
+ Select,
592
+ {
593
+ value: monthDate.getFullYear().toString(),
594
+ onValueChange: handleChangeYear,
595
+ options: yearOptions,
596
+ size: "s"
597
+ }
598
+ ) })
599
+ ] }),
600
+ /* @__PURE__ */ jsx8(
601
+ IconButton,
602
+ {
603
+ size: "xs",
604
+ tone: "mono",
605
+ variant: "secondary",
606
+ onPress: increaseMonth,
607
+ disabled: nextMonthButtonDisabled,
608
+ icon: /* @__PURE__ */ jsx8(ArrowRight, {}),
609
+ "aria-label": "Next month"
610
+ }
611
+ )
612
+ ]
613
+ }
614
+ );
615
+ };
616
+
617
+ // src/Calendar.tsx
618
+ import { jsx as jsx9, jsxs as jsxs2 } from "react/jsx-runtime";
619
+ var Calendar = forwardRef3(
620
+ ({
621
+ locale = "enUS",
622
+ onChange,
623
+ startDate,
624
+ endDate,
625
+ selectedDate,
626
+ selectsRange = false,
627
+ contextMenuMaxHeight,
628
+ topContent,
629
+ bottomContent,
630
+ testID,
631
+ minDate,
632
+ maxDate,
633
+ firstDayOfWeek = 0,
634
+ month,
635
+ initialMonth
636
+ }, ref) => {
637
+ const { theme } = useDesignSystem();
638
+ const localeObj = locales2[locale] || locales2.enUS;
639
+ const [currentMonth, setCurrentMonth] = useState(
640
+ month || initialMonth || selectedDate || startDate || /* @__PURE__ */ new Date()
641
+ );
642
+ const [selectedStartDate, setSelectedStartDate] = useState(startDate);
643
+ const [selectedEndDate, setSelectedEndDate] = useState(endDate);
644
+ const [locSelectedDate, setLocSelectedDate] = useState(selectedDate);
645
+ const [selectingRange, setSelectingRange] = useState(null);
646
+ useEffect(() => {
647
+ setSelectedStartDate(startDate);
648
+ setSelectedEndDate(endDate);
649
+ setLocSelectedDate(selectedDate);
650
+ if (month !== void 0) {
651
+ setCurrentMonth(month);
652
+ }
653
+ }, [startDate, endDate, selectedDate, month]);
654
+ const handleChange = useCallback2(
655
+ (date) => {
656
+ const newDate = new Date(
657
+ currentMonth.getFullYear(),
658
+ currentMonth.getMonth(),
659
+ date.getDate()
660
+ );
661
+ if (!selectsRange) {
662
+ setLocSelectedDate(newDate);
663
+ onChange?.(newDate);
664
+ } else {
665
+ if (!selectedStartDate || selectedStartDate && selectedEndDate) {
666
+ setSelectedStartDate(newDate);
667
+ setSelectedEndDate(null);
668
+ setSelectingRange(newDate);
669
+ onChange?.([newDate, null]);
670
+ } else {
671
+ const start = selectedStartDate < newDate ? selectedStartDate : newDate;
672
+ const end = selectedStartDate < newDate ? newDate : selectedStartDate;
673
+ setSelectedStartDate(start);
674
+ setSelectedEndDate(end);
675
+ setSelectingRange(null);
676
+ onChange?.([start, end]);
677
+ }
678
+ }
679
+ },
680
+ [onChange, selectsRange, selectedStartDate, selectedEndDate, currentMonth]
681
+ );
682
+ const decreaseMonth = useCallback2(() => setCurrentMonth((prev) => subMonths(prev, 1)), []);
683
+ const increaseMonth = useCallback2(() => setCurrentMonth((prev) => addMonths(prev, 1)), []);
684
+ const changeMonth = useCallback2((m) => setCurrentMonth((prev) => new Date(prev.getFullYear(), m, 1)), []);
685
+ const changeYear = useCallback2((y) => setCurrentMonth((prev) => new Date(y, prev.getMonth(), 1)), []);
686
+ const monthStart = startOfMonth(currentMonth);
687
+ const monthEnd = endOfMonth(currentMonth);
688
+ const weekStartsOn = firstDayOfWeek ?? 0;
689
+ const calendarStart = startOfWeek(monthStart, { weekStartsOn });
690
+ const calendarEnd = endOfWeek(monthEnd, { weekStartsOn });
691
+ const days = eachDayOfInterval({ start: calendarStart, end: calendarEnd });
692
+ const weekDays = useMemo2(() => {
693
+ return Array.from({ length: 7 }, (_, i) => {
694
+ const day = addDays(calendarStart, i);
695
+ return format2(day, "EEEEEE", { locale: localeObj });
696
+ });
697
+ }, [calendarStart, localeObj]);
698
+ const weeks = useMemo2(() => {
699
+ const weekArray = [];
700
+ for (let i = 0; i < days.length; i += 7) {
701
+ weekArray.push(days.slice(i, i + 7));
702
+ }
703
+ return weekArray;
704
+ }, [days]);
705
+ const isDateDisabled = useCallback2(
706
+ (date) => {
707
+ if (minDate && isBefore(date, startOfDay(minDate))) return true;
708
+ if (maxDate && isAfter(date, endOfDay(maxDate))) return true;
709
+ return false;
710
+ },
711
+ [minDate, maxDate]
712
+ );
713
+ const isDateInRange = useCallback2(
714
+ (date) => {
715
+ if (!selectsRange || !selectedStartDate) return false;
716
+ const rangeEnd = selectedEndDate || selectingRange;
717
+ if (!rangeEnd) return false;
718
+ const start = selectedStartDate < rangeEnd ? selectedStartDate : rangeEnd;
719
+ const end = selectedStartDate < rangeEnd ? rangeEnd : selectedStartDate;
720
+ return isWithinInterval(date, { start: startOfDay(start), end: endOfDay(end) });
721
+ },
722
+ [selectsRange, selectedStartDate, selectedEndDate, selectingRange]
723
+ );
724
+ return /* @__PURE__ */ jsxs2(
725
+ Box,
726
+ {
727
+ ref,
728
+ testID,
729
+ backgroundColor: theme.colors.background.secondary,
730
+ borderRadius: 8,
731
+ padding: 16,
732
+ overflow: "hidden",
733
+ style: {
734
+ boxShadow: "0px 4px 16px 0px rgba(7, 7, 8, 0.1)",
735
+ width: 312
736
+ },
737
+ children: [
738
+ topContent?.({ close: () => {
739
+ } }),
740
+ /* @__PURE__ */ jsx9(
741
+ CalendarHeader,
742
+ {
743
+ monthDate: currentMonth,
744
+ decreaseMonth,
745
+ increaseMonth,
746
+ changeYear,
747
+ changeMonth,
748
+ locale,
749
+ minDate,
750
+ maxDate,
751
+ contextMenuMaxHeight
752
+ }
753
+ ),
754
+ /* @__PURE__ */ jsx9(Box, { flexDirection: "row", justifyContent: "space-between", marginBottom: 8, children: weekDays.map((day, i) => /* @__PURE__ */ jsx9(Box, { width: 40, alignItems: "center", children: /* @__PURE__ */ jsx9(Text, { fontSize: 12, fontWeight: "600", color: theme.colors.content.tertiary, children: day.toUpperCase() }) }, i)) }),
755
+ /* @__PURE__ */ jsx9(Box, { gap: 2, children: weeks.map((week, i) => /* @__PURE__ */ jsx9(Box, { flexDirection: "row", justifyContent: "space-between", children: week.map((day, j) => {
756
+ const isOutsideMonth = !isSameMonth(day, currentMonth);
757
+ const isSelected = !selectsRange && locSelectedDate && isSameDay(day, locSelectedDate) || selectsRange && selectedStartDate && selectedEndDate && isSameDay(day, selectedStartDate) && isSameDay(day, selectedEndDate);
758
+ const isRangeStart = selectsRange && selectedStartDate && isSameDay(day, selectedStartDate);
759
+ const isRangeEnd = selectsRange && selectedEndDate && isSameDay(day, selectedEndDate);
760
+ const inRange = isDateInRange(day);
761
+ const today = isToday(day);
762
+ const disabled = isDateDisabled(day);
763
+ let bgColor = "transparent";
764
+ let textColor = theme.colors.content.primary;
765
+ if (isSelected || isRangeStart || isRangeEnd) {
766
+ bgColor = theme.colors.background.brand.primary;
767
+ textColor = theme.colors.content.on.brand;
768
+ } else if (inRange) {
769
+ bgColor = theme.colors.overlay.brand;
770
+ } else if (today) {
771
+ bgColor = theme.colors.overlay.mono;
772
+ }
773
+ if (isOutsideMonth || disabled) {
774
+ textColor = theme.colors.content.tertiary;
775
+ }
776
+ return /* @__PURE__ */ jsx9(
777
+ Box,
778
+ {
779
+ width: 40,
780
+ height: 32,
781
+ alignItems: "center",
782
+ justifyContent: "center",
783
+ borderRadius: isSelected || isRangeStart || isRangeEnd ? 4 : 0,
784
+ backgroundColor: bgColor,
785
+ cursor: disabled || isOutsideMonth ? "default" : "pointer",
786
+ onPress: () => !disabled && !isOutsideMonth && handleChange(day),
787
+ hoverStyle: !disabled && !isOutsideMonth && !isSelected ? { backgroundColor: theme.colors.overlay.mono } : void 0,
788
+ children: /* @__PURE__ */ jsx9(Text, { color: textColor, fontSize: 14, fontWeight: isSelected || isRangeStart || isRangeEnd ? "600" : "400", children: format2(day, "d") })
789
+ },
790
+ j
791
+ );
792
+ }) }, i)) }),
793
+ bottomContent?.({ close: () => {
794
+ } })
795
+ ]
796
+ }
797
+ );
798
+ }
799
+ );
800
+ Calendar.displayName = "Calendar";
801
+
802
+ // src/DatePicker.tsx
803
+ import { jsx as jsx10, jsxs as jsxs3 } from "react/jsx-runtime";
804
+ var DatePicker = forwardRef4(
805
+ ({
806
+ onChange,
807
+ size = "m",
808
+ locale = "enUS",
809
+ selectsRange = false,
810
+ startDate,
811
+ endDate,
812
+ selectedDate,
813
+ placeholder,
814
+ backgroundColor,
815
+ testID,
816
+ ...rest
817
+ }, ref) => {
818
+ const { theme } = useDesignSystem2();
819
+ const [open, setOpen] = useState2(false);
820
+ const [inputValue, setInputValue] = useState2("");
821
+ const containerRef = useRef(null);
822
+ const formatDateForDisplay = (date) => {
823
+ if (!date) return "";
824
+ try {
825
+ return format3(date, "MM/dd/yyyy");
826
+ } catch {
827
+ return "";
828
+ }
829
+ };
830
+ const getDisplayValue = useCallback3(() => {
831
+ if (selectsRange) {
832
+ if (startDate && endDate) {
833
+ return `${formatDateForDisplay(startDate)} - ${formatDateForDisplay(endDate)}`;
834
+ } else if (startDate) {
835
+ return formatDateForDisplay(startDate);
836
+ }
837
+ return "";
838
+ } else {
839
+ return formatDateForDisplay(selectedDate);
840
+ }
841
+ }, [selectsRange, startDate, endDate, selectedDate]);
842
+ useEffect2(() => {
843
+ setInputValue(getDisplayValue());
844
+ }, [getDisplayValue]);
845
+ const handleInputChange = (text) => {
846
+ setInputValue(text);
847
+ };
848
+ const handleDateChange = (date) => {
849
+ if (!selectsRange) {
850
+ onChange?.(date);
851
+ setOpen(false);
852
+ } else {
853
+ const range = date;
854
+ onChange?.(range);
855
+ if (range[0] && range[1]) {
856
+ setOpen(false);
857
+ }
858
+ }
859
+ };
860
+ useEffect2(() => {
861
+ if (isNative) return;
862
+ const handleClickOutside = (event) => {
863
+ if (containerRef.current && !containerRef.current.contains(event.target)) {
864
+ setOpen(false);
865
+ }
866
+ };
867
+ document.addEventListener("mousedown", handleClickOutside);
868
+ return () => document.removeEventListener("mousedown", handleClickOutside);
869
+ }, []);
870
+ const renderCalendar = () => /* @__PURE__ */ jsx10(
871
+ Calendar,
872
+ {
873
+ locale,
874
+ startDate,
875
+ endDate,
876
+ selectedDate,
877
+ onChange: handleDateChange,
878
+ selectsRange,
879
+ ...rest
880
+ }
881
+ );
882
+ return /* @__PURE__ */ jsxs3(Box, { ref: containerRef, position: "relative", width: "100%", children: [
883
+ /* @__PURE__ */ jsx10(
884
+ Input,
885
+ {
886
+ ...rest,
887
+ size,
888
+ placeholder: placeholder || (selectsRange ? "MM/DD/YYYY - MM/DD/YYYY" : "MM/DD/YYYY"),
889
+ value: inputValue,
890
+ onChangeText: handleInputChange,
891
+ onFocus: () => setOpen(true),
892
+ backgroundColor,
893
+ testID
894
+ }
895
+ ),
896
+ open && (isWeb ? /* @__PURE__ */ jsx10(
897
+ Box,
898
+ {
899
+ position: "absolute",
900
+ top: "100%",
901
+ left: 0,
902
+ marginTop: 4,
903
+ zIndex: 1e3,
904
+ children: renderCalendar()
905
+ }
906
+ ) : (
907
+ // Native implementation could use a Modal here
908
+ // For now, we just show it below the input if needed,
909
+ // but usually a bottom sheet or centered modal is better.
910
+ /* @__PURE__ */ jsx10(Box, { marginTop: 4, children: renderCalendar() })
911
+ ))
912
+ ] });
913
+ }
914
+ );
915
+ DatePicker.displayName = "DatePicker";
916
+ export {
917
+ Calendar,
918
+ DatePicker,
919
+ formatDate,
920
+ getMonthInLocale
921
+ };
922
+ //# sourceMappingURL=index.mjs.map