@xsolla/xui-date-picker 0.117.0 → 0.118.0

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/native/index.mjs CHANGED
@@ -1,5 +1,14 @@
1
+ // src/index.tsx
2
+ import {
3
+ Calendar as Calendar2,
4
+ DualCalendar,
5
+ CalendarHeader,
6
+ CalendarGrid,
7
+ CalendarChips
8
+ } from "@xsolla/xui-calendar";
9
+
1
10
  // src/DatePicker.tsx
2
- import { forwardRef as forwardRef2, useCallback as useCallback3, useEffect as useEffect2, useRef, useState as useState2 } from "react";
11
+ import { forwardRef, useCallback, useEffect, useRef, useState } from "react";
3
12
 
4
13
  // ../primitives-native/src/Box.tsx
5
14
  import {
@@ -171,489 +180,13 @@ var Box = ({
171
180
  );
172
181
  };
173
182
 
174
- // ../primitives-native/src/Text.tsx
175
- import {
176
- Text as RNText,
177
- StyleSheet
178
- } from "react-native";
179
- import { jsx as jsx2 } from "react/jsx-runtime";
180
- var roleMap = {
181
- alert: "alert",
182
- heading: "header",
183
- button: "button",
184
- link: "link",
185
- text: "text"
186
- };
187
- var parseNumericValue = (value) => {
188
- if (value === void 0) return void 0;
189
- if (typeof value === "number") return value;
190
- const parsed = parseFloat(value);
191
- return isNaN(parsed) ? void 0 : parsed;
192
- };
193
- var Text = ({
194
- children,
195
- color,
196
- fontSize,
197
- fontWeight,
198
- fontFamily,
199
- textAlign,
200
- lineHeight,
201
- numberOfLines,
202
- id,
203
- role,
204
- style: styleProp,
205
- ...props
206
- }) => {
207
- let resolvedFontFamily = fontFamily ? fontFamily.split(",")[0].replace(/['"]/g, "").trim() : void 0;
208
- if (resolvedFontFamily === "Pilat Wide" || resolvedFontFamily === "Pilat Wide Bold" || resolvedFontFamily === "Aktiv Grotesk") {
209
- resolvedFontFamily = void 0;
210
- }
211
- const incomingStyle = StyleSheet.flatten(styleProp);
212
- const baseStyle = {
213
- color,
214
- fontSize: typeof fontSize === "number" ? fontSize : void 0,
215
- fontWeight,
216
- fontFamily: resolvedFontFamily,
217
- textDecorationLine: props.textDecoration,
218
- textAlign: textAlign ?? incomingStyle?.textAlign,
219
- lineHeight: parseNumericValue(lineHeight ?? incomingStyle?.lineHeight),
220
- marginTop: parseNumericValue(
221
- incomingStyle?.marginTop
222
- ),
223
- marginBottom: parseNumericValue(
224
- incomingStyle?.marginBottom
225
- )
226
- };
227
- const accessibilityRole = role ? roleMap[role] : void 0;
228
- return /* @__PURE__ */ jsx2(
229
- RNText,
230
- {
231
- style: baseStyle,
232
- numberOfLines,
233
- testID: id,
234
- accessibilityRole,
235
- children
236
- }
237
- );
238
- };
239
-
240
183
  // src/DatePicker.tsx
241
184
  import { Input } from "@xsolla/xui-input";
242
185
  import { isWeb, isNative } from "@xsolla/xui-core";
243
- import { format as format3 } from "date-fns";
244
-
245
- // src/Calendar.tsx
246
- import { forwardRef, useCallback as useCallback2, useEffect, useMemo as useMemo2, useState } from "react";
247
- import { useDesignSystem } from "@xsolla/xui-core";
248
- import {
249
- addDays,
250
- addMonths,
251
- eachDayOfInterval,
252
- endOfDay,
253
- endOfMonth,
254
- endOfWeek,
255
- format as format2,
256
- isAfter,
257
- isBefore,
258
- isSameDay,
259
- isSameMonth,
260
- isToday,
261
- isWithinInterval,
262
- startOfDay,
263
- startOfMonth,
264
- startOfWeek,
265
- subMonths
266
- } from "date-fns";
267
- import * as locales2 from "date-fns/locale";
268
-
269
- // src/CalendarHeader.tsx
270
- import { useCallback, useMemo } from "react";
271
- import { IconButton } from "@xsolla/xui-button";
272
- import { Select } from "@xsolla/xui-select";
273
-
274
- // src/utils.ts
275
- import { format, setMonth } from "date-fns";
276
- import * as locales from "date-fns/locale";
277
- var defaultLocale = "enUS";
278
- function formatDate(date, formatStr, locale = defaultLocale) {
279
- const localeObj = locales[locale] || locales[defaultLocale];
280
- return format(date, formatStr, {
281
- locale: localeObj
282
- });
283
- }
284
- function getMonthInLocale(month, locale = defaultLocale) {
285
- return formatDate(setMonth(/* @__PURE__ */ new Date(), month), "LLLL", locale);
286
- }
287
-
288
- // src/CalendarHeader.tsx
289
- import { jsx as jsx3, jsxs } from "react/jsx-runtime";
290
- var ArrowLeft = () => /* @__PURE__ */ jsx3(
291
- "svg",
292
- {
293
- viewBox: "0 0 24 24",
294
- width: 16,
295
- height: 16,
296
- fill: "none",
297
- stroke: "currentColor",
298
- strokeWidth: "2",
299
- strokeLinecap: "round",
300
- strokeLinejoin: "round",
301
- children: /* @__PURE__ */ jsx3("polyline", { points: "15 18 9 12 15 6" })
302
- }
303
- );
304
- var ArrowRight = () => /* @__PURE__ */ jsx3(
305
- "svg",
306
- {
307
- viewBox: "0 0 24 24",
308
- width: 16,
309
- height: 16,
310
- fill: "none",
311
- stroke: "currentColor",
312
- strokeWidth: "2",
313
- strokeLinecap: "round",
314
- strokeLinejoin: "round",
315
- children: /* @__PURE__ */ jsx3("polyline", { points: "9 18 15 12 9 6" })
316
- }
317
- );
318
- var months = [
319
- "january",
320
- "february",
321
- "march",
322
- "april",
323
- "may",
324
- "june",
325
- "july",
326
- "august",
327
- "september",
328
- "october",
329
- "november",
330
- "december"
331
- ];
332
- var CalendarHeader = ({
333
- monthDate,
334
- decreaseMonth,
335
- increaseMonth,
336
- changeYear,
337
- changeMonth,
338
- prevMonthButtonDisabled,
339
- nextMonthButtonDisabled,
340
- locale,
341
- minDate,
342
- maxDate
343
- }) => {
344
- const handleChangeMonth = useCallback(
345
- (value) => {
346
- changeMonth(months.indexOf(value));
347
- },
348
- [changeMonth]
349
- );
350
- const handleChangeYear = useCallback(
351
- (value) => {
352
- changeYear(parseInt(value, 10));
353
- },
354
- [changeYear]
355
- );
356
- const monthOptions = useMemo(() => {
357
- return months.map((month, index) => ({
358
- label: getMonthInLocale(index, locale),
359
- value: month
360
- }));
361
- }, [locale]);
362
- const yearOptions = useMemo(() => {
363
- const options = [];
364
- const yearStart = minDate ? minDate.getFullYear() : 1900;
365
- const yearEnd = maxDate ? maxDate.getFullYear() : (/* @__PURE__ */ new Date()).getFullYear() + 100;
366
- for (let i = yearEnd; i >= yearStart; i--) {
367
- options.push({ value: i.toString(), label: i.toString() });
368
- }
369
- return options;
370
- }, [minDate, maxDate]);
371
- return /* @__PURE__ */ jsxs(
372
- Box,
373
- {
374
- width: "100%",
375
- flexDirection: "row",
376
- justifyContent: "space-between",
377
- alignItems: "center",
378
- marginBottom: 16,
379
- gap: 8,
380
- children: [
381
- /* @__PURE__ */ jsx3(
382
- IconButton,
383
- {
384
- size: "xs",
385
- tone: "mono",
386
- variant: "secondary",
387
- onPress: decreaseMonth,
388
- disabled: prevMonthButtonDisabled,
389
- icon: /* @__PURE__ */ jsx3(ArrowLeft, {}),
390
- "aria-label": "Previous month"
391
- }
392
- ),
393
- /* @__PURE__ */ jsxs(Box, { flexDirection: "row", flex: 1, gap: 4, children: [
394
- /* @__PURE__ */ jsx3(Box, { flex: 1.5, children: /* @__PURE__ */ jsx3(
395
- Select,
396
- {
397
- value: months[monthDate.getMonth()],
398
- onValueChange: handleChangeMonth,
399
- options: monthOptions,
400
- size: "sm"
401
- }
402
- ) }),
403
- /* @__PURE__ */ jsx3(Box, { flex: 1, children: /* @__PURE__ */ jsx3(
404
- Select,
405
- {
406
- value: monthDate.getFullYear().toString(),
407
- onValueChange: handleChangeYear,
408
- options: yearOptions,
409
- size: "sm"
410
- }
411
- ) })
412
- ] }),
413
- /* @__PURE__ */ jsx3(
414
- IconButton,
415
- {
416
- size: "xs",
417
- tone: "mono",
418
- variant: "secondary",
419
- onPress: increaseMonth,
420
- disabled: nextMonthButtonDisabled,
421
- icon: /* @__PURE__ */ jsx3(ArrowRight, {}),
422
- "aria-label": "Next month"
423
- }
424
- )
425
- ]
426
- }
427
- );
428
- };
429
-
430
- // src/Calendar.tsx
431
- import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
432
- var Calendar = forwardRef(
433
- ({
434
- locale = "enUS",
435
- onChange,
436
- startDate,
437
- endDate,
438
- selectedDate,
439
- selectsRange = false,
440
- contextMenuMaxHeight,
441
- topContent,
442
- bottomContent,
443
- testID,
444
- minDate,
445
- maxDate,
446
- firstDayOfWeek = 0,
447
- month,
448
- initialMonth
449
- }, ref) => {
450
- const { theme } = useDesignSystem();
451
- const localeObj = locales2[locale] || locales2.enUS;
452
- const [currentMonth, setCurrentMonth] = useState(
453
- month || initialMonth || selectedDate || startDate || /* @__PURE__ */ new Date()
454
- );
455
- const [selectedStartDate, setSelectedStartDate] = useState(startDate);
456
- const [selectedEndDate, setSelectedEndDate] = useState(endDate);
457
- const [locSelectedDate, setLocSelectedDate] = useState(selectedDate);
458
- const [selectingRange, setSelectingRange] = useState(null);
459
- useEffect(() => {
460
- setSelectedStartDate(startDate);
461
- setSelectedEndDate(endDate);
462
- setLocSelectedDate(selectedDate);
463
- if (month !== void 0) {
464
- setCurrentMonth(month);
465
- }
466
- }, [startDate, endDate, selectedDate, month]);
467
- const handleChange = useCallback2(
468
- (date) => {
469
- const newDate = new Date(
470
- currentMonth.getFullYear(),
471
- currentMonth.getMonth(),
472
- date.getDate()
473
- );
474
- if (!selectsRange) {
475
- setLocSelectedDate(newDate);
476
- onChange?.(newDate);
477
- } else {
478
- if (!selectedStartDate || selectedStartDate && selectedEndDate) {
479
- setSelectedStartDate(newDate);
480
- setSelectedEndDate(null);
481
- setSelectingRange(newDate);
482
- onChange?.([newDate, null]);
483
- } else {
484
- const start = selectedStartDate < newDate ? selectedStartDate : newDate;
485
- const end = selectedStartDate < newDate ? newDate : selectedStartDate;
486
- setSelectedStartDate(start);
487
- setSelectedEndDate(end);
488
- setSelectingRange(null);
489
- onChange?.([start, end]);
490
- }
491
- }
492
- },
493
- [onChange, selectsRange, selectedStartDate, selectedEndDate, currentMonth]
494
- );
495
- const decreaseMonth = useCallback2(
496
- () => setCurrentMonth((prev) => subMonths(prev, 1)),
497
- []
498
- );
499
- const increaseMonth = useCallback2(
500
- () => setCurrentMonth((prev) => addMonths(prev, 1)),
501
- []
502
- );
503
- const changeMonth = useCallback2(
504
- (m) => setCurrentMonth((prev) => new Date(prev.getFullYear(), m, 1)),
505
- []
506
- );
507
- const changeYear = useCallback2(
508
- (y) => setCurrentMonth((prev) => new Date(y, prev.getMonth(), 1)),
509
- []
510
- );
511
- const monthStart = startOfMonth(currentMonth);
512
- const monthEnd = endOfMonth(currentMonth);
513
- const weekStartsOn = firstDayOfWeek ?? 0;
514
- const calendarStart = startOfWeek(monthStart, { weekStartsOn });
515
- const calendarEnd = endOfWeek(monthEnd, { weekStartsOn });
516
- const days = eachDayOfInterval({ start: calendarStart, end: calendarEnd });
517
- const weekDays = useMemo2(() => {
518
- return Array.from({ length: 7 }, (_, i) => {
519
- const day = addDays(calendarStart, i);
520
- return format2(day, "EEEEEE", { locale: localeObj });
521
- });
522
- }, [calendarStart, localeObj]);
523
- const weeks = useMemo2(() => {
524
- const weekArray = [];
525
- for (let i = 0; i < days.length; i += 7) {
526
- weekArray.push(days.slice(i, i + 7));
527
- }
528
- return weekArray;
529
- }, [days]);
530
- const isDateDisabled = useCallback2(
531
- (date) => {
532
- if (minDate && isBefore(date, startOfDay(minDate))) return true;
533
- if (maxDate && isAfter(date, endOfDay(maxDate))) return true;
534
- return false;
535
- },
536
- [minDate, maxDate]
537
- );
538
- const isDateInRange = useCallback2(
539
- (date) => {
540
- if (!selectsRange || !selectedStartDate) return false;
541
- const rangeEnd = selectedEndDate || selectingRange;
542
- if (!rangeEnd) return false;
543
- const start = selectedStartDate < rangeEnd ? selectedStartDate : rangeEnd;
544
- const end = selectedStartDate < rangeEnd ? rangeEnd : selectedStartDate;
545
- return isWithinInterval(date, {
546
- start: startOfDay(start),
547
- end: endOfDay(end)
548
- });
549
- },
550
- [selectsRange, selectedStartDate, selectedEndDate, selectingRange]
551
- );
552
- return /* @__PURE__ */ jsxs2(
553
- Box,
554
- {
555
- ref,
556
- testID,
557
- backgroundColor: theme.colors.background.secondary,
558
- borderRadius: 8,
559
- padding: 16,
560
- overflow: "hidden",
561
- style: {
562
- boxShadow: "0px 4px 16px 0px rgba(7, 7, 8, 0.1)",
563
- width: 312
564
- },
565
- children: [
566
- topContent?.({ close: () => {
567
- } }),
568
- /* @__PURE__ */ jsx4(
569
- CalendarHeader,
570
- {
571
- monthDate: currentMonth,
572
- decreaseMonth,
573
- increaseMonth,
574
- changeYear,
575
- changeMonth,
576
- locale,
577
- minDate,
578
- maxDate,
579
- contextMenuMaxHeight
580
- }
581
- ),
582
- /* @__PURE__ */ jsx4(
583
- Box,
584
- {
585
- flexDirection: "row",
586
- justifyContent: "space-between",
587
- marginBottom: 8,
588
- children: weekDays.map((day, i) => /* @__PURE__ */ jsx4(Box, { width: 40, alignItems: "center", children: /* @__PURE__ */ jsx4(
589
- Text,
590
- {
591
- fontSize: 12,
592
- fontWeight: "600",
593
- color: theme.colors.content.tertiary,
594
- children: day.toUpperCase()
595
- }
596
- ) }, i))
597
- }
598
- ),
599
- /* @__PURE__ */ jsx4(Box, { gap: 2, children: weeks.map((week, i) => /* @__PURE__ */ jsx4(Box, { flexDirection: "row", justifyContent: "space-between", children: week.map((day, j) => {
600
- const isOutsideMonth = !isSameMonth(day, currentMonth);
601
- const isSelected = !selectsRange && locSelectedDate && isSameDay(day, locSelectedDate) || selectsRange && selectedStartDate && selectedEndDate && isSameDay(day, selectedStartDate) && isSameDay(day, selectedEndDate);
602
- const isRangeStart = selectsRange && selectedStartDate && isSameDay(day, selectedStartDate);
603
- const isRangeEnd = selectsRange && selectedEndDate && isSameDay(day, selectedEndDate);
604
- const inRange = isDateInRange(day);
605
- const today = isToday(day);
606
- const disabled = isDateDisabled(day);
607
- let bgColor = "transparent";
608
- let textColor = theme.colors.content.primary;
609
- if (isSelected || isRangeStart || isRangeEnd) {
610
- bgColor = theme.colors.background.brand.primary;
611
- textColor = theme.colors.content.on.brand;
612
- } else if (inRange) {
613
- bgColor = theme.colors.overlay.brand;
614
- } else if (today) {
615
- bgColor = theme.colors.overlay.mono;
616
- }
617
- if (isOutsideMonth || disabled) {
618
- textColor = theme.colors.content.tertiary;
619
- }
620
- return /* @__PURE__ */ jsx4(
621
- Box,
622
- {
623
- width: 40,
624
- height: 32,
625
- alignItems: "center",
626
- justifyContent: "center",
627
- borderRadius: isSelected || isRangeStart || isRangeEnd ? 4 : 0,
628
- backgroundColor: bgColor,
629
- cursor: disabled || isOutsideMonth ? "default" : "pointer",
630
- onPress: () => !disabled && !isOutsideMonth && handleChange(day),
631
- hoverStyle: !disabled && !isOutsideMonth && !isSelected ? { backgroundColor: theme.colors.overlay.mono } : void 0,
632
- children: /* @__PURE__ */ jsx4(
633
- Text,
634
- {
635
- color: textColor,
636
- fontSize: 14,
637
- fontWeight: isSelected || isRangeStart || isRangeEnd ? "600" : "400",
638
- children: format2(day, "d")
639
- }
640
- )
641
- },
642
- j
643
- );
644
- }) }, i)) }),
645
- bottomContent?.({ close: () => {
646
- } })
647
- ]
648
- }
649
- );
650
- }
651
- );
652
- Calendar.displayName = "Calendar";
653
-
654
- // src/DatePicker.tsx
655
- import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
656
- var DatePicker = forwardRef2(
186
+ import { format } from "date-fns";
187
+ import { Calendar } from "@xsolla/xui-calendar";
188
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
189
+ var DatePicker = forwardRef(
657
190
  ({
658
191
  onChange,
659
192
  size = "md",
@@ -667,18 +200,18 @@ var DatePicker = forwardRef2(
667
200
  testID,
668
201
  ...rest
669
202
  }) => {
670
- const [open, setOpen] = useState2(false);
671
- const [inputValue, setInputValue] = useState2("");
203
+ const [open, setOpen] = useState(false);
204
+ const [inputValue, setInputValue] = useState("");
672
205
  const containerRef = useRef(null);
673
206
  const formatDateForDisplay = (date) => {
674
207
  if (!date) return "";
675
208
  try {
676
- return format3(date, "MM/dd/yyyy");
209
+ return format(date, "MM/dd/yyyy");
677
210
  } catch {
678
211
  return "";
679
212
  }
680
213
  };
681
- const getDisplayValue = useCallback3(() => {
214
+ const getDisplayValue = useCallback(() => {
682
215
  if (selectsRange) {
683
216
  if (startDate && endDate) {
684
217
  return `${formatDateForDisplay(startDate)} - ${formatDateForDisplay(endDate)}`;
@@ -690,7 +223,7 @@ var DatePicker = forwardRef2(
690
223
  return formatDateForDisplay(selectedDate);
691
224
  }
692
225
  }, [selectsRange, startDate, endDate, selectedDate]);
693
- useEffect2(() => {
226
+ useEffect(() => {
694
227
  setInputValue(getDisplayValue());
695
228
  }, [getDisplayValue]);
696
229
  const handleInputChange = (text) => {
@@ -708,7 +241,7 @@ var DatePicker = forwardRef2(
708
241
  }
709
242
  }
710
243
  };
711
- useEffect2(() => {
244
+ useEffect(() => {
712
245
  if (isNative) return;
713
246
  const handleClickOutside = (event) => {
714
247
  if (containerRef.current && !containerRef.current.contains(event.target)) {
@@ -718,7 +251,7 @@ var DatePicker = forwardRef2(
718
251
  document.addEventListener("mousedown", handleClickOutside);
719
252
  return () => document.removeEventListener("mousedown", handleClickOutside);
720
253
  }, []);
721
- const renderCalendar = () => /* @__PURE__ */ jsx5(
254
+ const renderCalendar = () => /* @__PURE__ */ jsx2(
722
255
  Calendar,
723
256
  {
724
257
  locale,
@@ -730,8 +263,8 @@ var DatePicker = forwardRef2(
730
263
  ...rest
731
264
  }
732
265
  );
733
- return /* @__PURE__ */ jsxs3(Box, { ref: containerRef, position: "relative", width: "100%", children: [
734
- /* @__PURE__ */ jsx5(
266
+ return /* @__PURE__ */ jsxs(Box, { ref: containerRef, position: "relative", width: "100%", children: [
267
+ /* @__PURE__ */ jsx2(
735
268
  Input,
736
269
  {
737
270
  ...rest,
@@ -744,7 +277,7 @@ var DatePicker = forwardRef2(
744
277
  testID
745
278
  }
746
279
  ),
747
- open && (isWeb ? /* @__PURE__ */ jsx5(
280
+ open && (isWeb ? /* @__PURE__ */ jsx2(
748
281
  Box,
749
282
  {
750
283
  position: "absolute",
@@ -758,16 +291,30 @@ var DatePicker = forwardRef2(
758
291
  // Native implementation could use a Modal here
759
292
  // For now, we just show it below the input if needed,
760
293
  // but usually a bottom sheet or centered modal is better.
761
- /* @__PURE__ */ jsx5(Box, { marginTop: 4, children: renderCalendar() })
294
+ /* @__PURE__ */ jsx2(Box, { marginTop: 4, children: renderCalendar() })
762
295
  ))
763
296
  ] });
764
297
  }
765
298
  );
766
299
  DatePicker.displayName = "DatePicker";
300
+
301
+ // src/utils.ts
302
+ import { format as format2 } from "date-fns";
303
+ import * as locales from "date-fns/locale";
304
+ var defaultLocale = "enUS";
305
+ function formatDate(date, formatStr, locale = defaultLocale) {
306
+ const localeObj = locales[locale] || locales[defaultLocale];
307
+ return format2(date, formatStr, {
308
+ locale: localeObj
309
+ });
310
+ }
767
311
  export {
768
- Calendar,
312
+ Calendar2 as Calendar,
313
+ CalendarChips,
314
+ CalendarGrid,
315
+ CalendarHeader,
769
316
  DatePicker,
770
- formatDate,
771
- getMonthInLocale
317
+ DualCalendar,
318
+ formatDate
772
319
  };
773
320
  //# sourceMappingURL=index.mjs.map