@swan-io/shared-business 3.0.0 → 3.2.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swan-io/shared-business",
3
- "version": "3.0.0",
3
+ "version": "3.2.0",
4
4
  "engines": {
5
5
  "node": ">=18.0.0",
6
6
  "yarn": "^1.22.0"
@@ -47,12 +47,10 @@ export type DatePickerProps = {
47
47
  error?: string;
48
48
  format: DateFormat;
49
49
  firstWeekDay: keyof typeof weekDayIndex;
50
- monthNames: MonthNames;
51
- weekDayNames: WeekDayNames;
52
50
  isSelectable?: (date: DatePickerDate) => boolean;
53
51
  onChange: (date: string) => void;
54
52
  };
55
- export declare const DatePicker: ({ label, value, error, format, firstWeekDay, monthNames, weekDayNames, isSelectable, onChange, }: DatePickerProps) => import("react/jsx-runtime").JSX.Element;
53
+ export declare const DatePicker: ({ label, value, error, format, firstWeekDay, isSelectable, onChange, }: DatePickerProps) => import("react/jsx-runtime").JSX.Element;
56
54
  type DatePickerModalProps = Except<DatePickerProps, "error"> & {
57
55
  visible: boolean;
58
56
  cancelLabel: string;
@@ -60,7 +58,7 @@ type DatePickerModalProps = Except<DatePickerProps, "error"> & {
60
58
  validate?: (value: string) => ValidatorResult;
61
59
  onDissmiss: () => void;
62
60
  };
63
- export declare const DatePickerModal: ({ value, format, firstWeekDay, monthNames, weekDayNames, isSelectable, onChange, visible, label, cancelLabel, confirmLabel, validate, onDissmiss, }: DatePickerModalProps) => import("react/jsx-runtime").JSX.Element;
61
+ export declare const DatePickerModal: ({ value, format, firstWeekDay, isSelectable, onChange, visible, label, cancelLabel, confirmLabel, validate, onDissmiss, }: DatePickerModalProps) => import("react/jsx-runtime").JSX.Element;
64
62
  export type DateRangePickerProps = {
65
63
  value: {
66
64
  start: string;
@@ -71,20 +69,18 @@ export type DateRangePickerProps = {
71
69
  startLabel: string;
72
70
  endLabel: string;
73
71
  firstWeekDay: keyof typeof weekDayIndex;
74
- monthNames: MonthNames;
75
- weekDayNames: WeekDayNames;
76
72
  isSelectable?: (date: DatePickerDate) => boolean;
77
73
  onChange: (date: {
78
74
  start: string;
79
75
  end: string;
80
76
  }) => void;
81
77
  };
82
- export declare const DateRangePicker: ({ value, error, format, startLabel, endLabel, firstWeekDay, monthNames, weekDayNames, isSelectable, onChange, }: DateRangePickerProps) => import("react/jsx-runtime").JSX.Element;
78
+ export declare const DateRangePicker: ({ value, error, format, startLabel, endLabel, firstWeekDay, isSelectable, onChange, }: DateRangePickerProps) => import("react/jsx-runtime").JSX.Element;
83
79
  type DateRangePickerModalProps = DateRangePickerProps & {
84
80
  visible: boolean;
85
81
  cancelLabel: string;
86
82
  confirmLabel: string;
87
83
  onDissmiss: () => void;
88
84
  };
89
- export declare const DateRangePickerModal: ({ value, error, format, firstWeekDay, monthNames, weekDayNames, isSelectable, onChange, visible, startLabel, endLabel, cancelLabel, confirmLabel, onDissmiss, }: DateRangePickerModalProps) => import("react/jsx-runtime").JSX.Element;
85
+ export declare const DateRangePickerModal: ({ value, error, format, firstWeekDay, isSelectable, onChange, visible, startLabel, endLabel, cancelLabel, confirmLabel, onDissmiss, }: DateRangePickerModalProps) => import("react/jsx-runtime").JSX.Element;
90
86
  export {};
@@ -111,6 +111,29 @@ const MODALE_MOBILE_THRESHOLD = 600;
111
111
  const DATE_PICKER_MOBILE_THRESHOLD = 400;
112
112
  const DATE_RANGE_PICKER_THRESHOLD = 800;
113
113
  const NB_DAYS_IN_WEEK = 7;
114
+ const weekDayNames = [
115
+ t("datePicker.day.sunday"),
116
+ t("datePicker.day.monday"),
117
+ t("datePicker.day.tuesday"),
118
+ t("datePicker.day.wednesday"),
119
+ t("datePicker.day.thursday"),
120
+ t("datePicker.day.friday"),
121
+ t("datePicker.day.saturday"),
122
+ ];
123
+ const monthNames = [
124
+ t("datePicker.month.january"),
125
+ t("datePicker.month.february"),
126
+ t("datePicker.month.march"),
127
+ t("datePicker.month.april"),
128
+ t("datePicker.month.may"),
129
+ t("datePicker.month.june"),
130
+ t("datePicker.month.july"),
131
+ t("datePicker.month.august"),
132
+ t("datePicker.month.september"),
133
+ t("datePicker.month.october"),
134
+ t("datePicker.month.november"),
135
+ t("datePicker.month.december"),
136
+ ];
114
137
  const weekDayIndex = {
115
138
  sunday: 0,
116
139
  monday: 1,
@@ -395,8 +418,8 @@ const YearMonthSelect = ({ monthNames, value, arrowsPosition = "right", hideArro
395
418
  : value.year >= maxValue.year && value.month >= maxValue.month;
396
419
  return (_jsxs(Box, { direction: "row", alignItems: "center", children: [arrowsPosition === "around" && hideArrows !== true && (_jsxs(_Fragment, { children: [_jsx(LakeButton, { size: "small", mode: "tertiary", icon: "arrow-left-filled", disabled: isPreviousDisabled, onPress: setPreviousMonth, ariaLabel: t("datePicker.month.previous") }), _jsx(Fill, { minWidth: 12 })] })), _jsx(LakeSelect, { items: monthItems, value: value.month, onValueChange: selectMonth, mode: "borderless", size: "small", hideErrors: true, style: styles.monthSelect }), _jsx(LakeSelect, { items: yearItems, value: value.year, onValueChange: selectYear, mode: "borderless", size: "small", hideErrors: true, style: styles.yearSelect }), hideArrows !== true && (_jsxs(_Fragment, { children: [_jsx(Fill, { minWidth: 12 }), arrowsPosition === "right" && (_jsxs(_Fragment, { children: [_jsx(LakeButton, { size: "small", mode: "tertiary", icon: "arrow-left-filled", disabled: isPreviousDisabled, onPress: setPreviousMonth, ariaLabel: t("datePicker.month.previous") }), _jsx(Space, { width: 12 })] })), _jsx(LakeButton, { size: "small", mode: "tertiary", icon: "arrow-right-filled", disabled: isNextDisabled, onPress: setNextMonth, ariaLabel: t("datePicker.month.next") })] }))] }));
397
420
  };
398
- const MonthCalendar = ({ month, year, value, firstWeekDay, weekDayNames, isSelectable, onChange, }) => {
399
- const dayNames = useMemo(() => getWeekDayNames(weekDayNames, firstWeekDay), [weekDayNames, firstWeekDay]);
421
+ const MonthCalendar = ({ month, year, value, firstWeekDay, isSelectable, onChange, }) => {
422
+ const dayNames = useMemo(() => getWeekDayNames(weekDayNames, firstWeekDay), [firstWeekDay]);
400
423
  const weeks = useMemo(() => getMonthWeeks(month, year, firstWeekDay), [month, year, firstWeekDay]);
401
424
  return (_jsxs(View, { children: [_jsx(Box, { direction: "row", alignItems: "center", style: styles.weekRow, children: dayNames.map(dayName => (_jsx(View, { style: styles.dayName, children: _jsx(LakeText, { variant: "medium", color: colors.gray[600], children: dayName.substring(0, 1) }) }, dayName))) }), weeks.map((week, weekIndex) => (_jsx(Box, { direction: "row", alignItems: "center", style: styles.weekRow, children: week.map((date, dateIndex) => {
402
425
  const isDisabled = date.match({
@@ -434,7 +457,7 @@ const MonthCalendar = ({ month, year, value, firstWeekDay, weekDayNames, isSelec
434
457
  : colors.gray[900], children: date.match({ Some: ({ day }) => day.toString(), None: () => " " }) }), isToday && _jsx(View, { style: styles.todayIndicator })] })] }, dateIndex));
435
458
  }) }, weekIndex)))] }));
436
459
  };
437
- const DatePickerPopoverContent = ({ value, format, firstWeekDay, monthNames, weekDayNames, desktop, isSelectable, onChange, }) => {
460
+ const DatePickerPopoverContent = ({ value, format, firstWeekDay, desktop, isSelectable, onChange, }) => {
438
461
  const [monthYear, setMonthYear] = useState(() => getYearMonth(value, format).getWithDefault(getTodayYearMonth()));
439
462
  // Automatically change displayed year and month when user change the value with text input
440
463
  useEffect(() => {
@@ -447,16 +470,16 @@ const DatePickerPopoverContent = ({ value, format, firstWeekDay, monthNames, wee
447
470
  const formatted = stringifyDate(date, format);
448
471
  onChange(formatted);
449
472
  }, [format, onChange]);
450
- return (_jsxs(_Fragment, { children: [_jsx(YearMonthSelect, { monthNames: monthNames, value: monthYear, hideArrows: !desktop, onChange: setMonthYear }), _jsx(Space, { height: 24 }), _jsx(MonthCalendar, { month: monthYear.month, year: monthYear.year, value: isNotNullishOrEmpty(value) ? parseDate(value, format) : Option.None(), firstWeekDay: firstWeekDay, weekDayNames: weekDayNames, isSelectable: isSelectable, onChange: handleChange })] }));
473
+ return (_jsxs(_Fragment, { children: [_jsx(YearMonthSelect, { monthNames: monthNames, value: monthYear, hideArrows: !desktop, onChange: setMonthYear }), _jsx(Space, { height: 24 }), _jsx(MonthCalendar, { month: monthYear.month, year: monthYear.year, value: isNotNullishOrEmpty(value) ? parseDate(value, format) : Option.None(), firstWeekDay: firstWeekDay, isSelectable: isSelectable, onChange: handleChange })] }));
451
474
  };
452
- export const DatePicker = ({ label, value, error, format, firstWeekDay, monthNames, weekDayNames, isSelectable, onChange, }) => {
475
+ export const DatePicker = ({ label, value, error, format, firstWeekDay, isSelectable, onChange, }) => {
453
476
  const { desktop } = useResponsive(DATE_PICKER_MOBILE_THRESHOLD);
454
477
  const ref = useRef(null);
455
478
  const [isOpened, { open, close }] = useDisclosure(false);
456
479
  const popoverId = useId();
457
- return (_jsxs(_Fragment, { children: [_jsx(Box, { direction: "row", alignItems: "end", children: _jsx(LakeLabel, { label: label, style: styles.label, actions: _jsx(LakeButton, { mode: "secondary", icon: "calendar-ltr-regular", size: "small", onPress: open, ariaLabel: t("common.open") }), render: id => (_jsx(Rifm, { value: value ?? "", onChange: onChange, ...rifmDateProps, children: ({ value, onChange }) => (_jsx(LakeTextInput, { ref: ref, id: id, placeholder: format, value: value, error: error, onChange: onChange, ariaExpanded: isOpened })) })) }) }), _jsx(Popover, { id: popoverId, role: "dialog", onDismiss: close, referenceRef: ref, visible: isOpened, children: _jsx(View, { style: desktop ? styles.popoverDesktop : styles.popover, children: _jsx(DatePickerPopoverContent, { value: value, format: format, firstWeekDay: firstWeekDay, monthNames: monthNames, weekDayNames: weekDayNames, desktop: desktop, isSelectable: isSelectable, onChange: onChange }) }) })] }));
480
+ return (_jsxs(_Fragment, { children: [_jsx(Box, { direction: "row", alignItems: "end", children: _jsx(LakeLabel, { label: label, style: styles.label, actions: _jsx(LakeButton, { mode: "secondary", icon: "calendar-ltr-regular", size: "small", onPress: open, ariaLabel: t("common.open") }), render: id => (_jsx(Rifm, { value: value ?? "", onChange: onChange, ...rifmDateProps, children: ({ value, onChange }) => (_jsx(LakeTextInput, { ref: ref, id: id, placeholder: format, value: value, error: error, onChange: onChange, ariaExpanded: isOpened })) })) }) }), _jsx(Popover, { id: popoverId, role: "dialog", onDismiss: close, referenceRef: ref, visible: isOpened, children: _jsx(View, { style: desktop ? styles.popoverDesktop : styles.popover, children: _jsx(DatePickerPopoverContent, { value: value, format: format, firstWeekDay: firstWeekDay, desktop: desktop, isSelectable: isSelectable, onChange: onChange }) }) })] }));
458
481
  };
459
- export const DatePickerModal = ({ value, format, firstWeekDay, monthNames, weekDayNames, isSelectable, onChange, visible, label, cancelLabel, confirmLabel, validate, onDissmiss, }) => {
482
+ export const DatePickerModal = ({ value, format, firstWeekDay, isSelectable, onChange, visible, label, cancelLabel, confirmLabel, validate, onDissmiss, }) => {
460
483
  const { desktop } = useResponsive(DATE_PICKER_MOBILE_THRESHOLD);
461
484
  const { Field, submitForm, setFieldValue, resetField } = useForm({
462
485
  date: {
@@ -481,7 +504,7 @@ export const DatePickerModal = ({ value, format, firstWeekDay, monthNames, weekD
481
504
  resetField("date");
482
505
  }
483
506
  }, [visible, resetField]);
484
- return (_jsxs(DateModal, { visible: visible, maxWidth: 500, onPressClose: handleCancel, children: [_jsx(Field, { name: "date", children: ({ ref, value, error, onBlur, onChange }) => (_jsxs(_Fragment, { children: [_jsx(LakeLabel, { label: label, render: id => (_jsx(Rifm, { value: value, onChange: onChange, ...rifmDateProps, children: ({ value, onChange }) => (_jsx(LakeTextInput, { ref: ref, id: id, placeholder: format, value: value, error: error, onBlur: onBlur, onChange: onChange })) })) }), _jsx(DatePickerPopoverContent, { value: value, format: format, firstWeekDay: firstWeekDay, monthNames: monthNames, weekDayNames: weekDayNames, desktop: desktop, isSelectable: isSelectable, onChange: onChange })] })) }), _jsx(Space, { height: 24 }), _jsxs(Box, { direction: "row", alignItems: "center", children: [_jsx(LakeButton, { mode: "secondary", size: "small", onPress: handleCancel, style: styles.button, children: cancelLabel }), _jsx(Space, { width: 24 }), _jsx(LakeButton, { color: "current", size: "small", onPress: handleConfirm, style: styles.button, children: confirmLabel })] })] }));
507
+ return (_jsxs(DateModal, { visible: visible, maxWidth: 500, onPressClose: handleCancel, children: [_jsx(Field, { name: "date", children: ({ ref, value, error, onBlur, onChange }) => (_jsxs(_Fragment, { children: [_jsx(LakeLabel, { label: label, render: id => (_jsx(Rifm, { value: value, onChange: onChange, ...rifmDateProps, children: ({ value, onChange }) => (_jsx(LakeTextInput, { ref: ref, id: id, placeholder: format, value: value, error: error, onBlur: onBlur, onChange: onChange })) })) }), _jsx(DatePickerPopoverContent, { value: value, format: format, firstWeekDay: firstWeekDay, desktop: desktop, isSelectable: isSelectable, onChange: onChange })] })) }), _jsx(Space, { height: 24 }), _jsxs(Box, { direction: "row", alignItems: "center", children: [_jsx(LakeButton, { mode: "secondary", size: "small", onPress: handleCancel, style: styles.button, children: cancelLabel }), _jsx(Space, { width: 24 }), _jsx(LakeButton, { color: "current", size: "small", onPress: handleConfirm, style: styles.button, children: confirmLabel })] })] }));
485
508
  };
486
509
  const DateModal = ({ children, visible, maxWidth, withCloseButton, onPressClose, }) => {
487
510
  const { desktop } = useResponsive(MODALE_MOBILE_THRESHOLD);
@@ -490,7 +513,7 @@ const DateModal = ({ children, visible, maxWidth, withCloseButton, onPressClose,
490
513
  }
491
514
  return (_jsx(BottomPanel, { visible: visible, onPressClose: onPressClose, children: _jsx(View, { style: styles.popover, children: children }) }));
492
515
  };
493
- const DateRangePickerModalContent = ({ value, format, firstWeekDay, monthNames, weekDayNames, desktop, displayTwoCalendar, isSelectable, onChange, }) => {
516
+ const DateRangePickerModalContent = ({ value, format, firstWeekDay, desktop, displayTwoCalendar, isSelectable, onChange, }) => {
494
517
  const isFirstMount = useFirstMountState();
495
518
  const [periods, setPeriods] = useState(() => {
496
519
  const startYearMonth = getYearMonth(value.start, format).getWithDefault(getTodayYearMonth());
@@ -578,11 +601,11 @@ const DateRangePickerModalContent = ({ value, format, firstWeekDay, monthNames,
578
601
  onChange(newValue);
579
602
  };
580
603
  if (!displayTwoCalendar) {
581
- return (_jsxs(_Fragment, { children: [_jsx(YearMonthSelect, { monthNames: monthNames, value: periods.start, hideArrows: !desktop, onChange: setStartPeriod }), _jsx(Space, { height: 24 }), _jsx(MonthCalendar, { month: periods.start.month, year: periods.start.year, value: dateRange, firstWeekDay: firstWeekDay, weekDayNames: weekDayNames, isSelectable: isSelectable, onChange: handleSelectDate })] }));
604
+ return (_jsxs(_Fragment, { children: [_jsx(YearMonthSelect, { monthNames: monthNames, value: periods.start, hideArrows: !desktop, onChange: setStartPeriod }), _jsx(Space, { height: 24 }), _jsx(MonthCalendar, { month: periods.start.month, year: periods.start.year, value: dateRange, firstWeekDay: firstWeekDay, isSelectable: isSelectable, onChange: handleSelectDate })] }));
582
605
  }
583
- return (_jsx(View, { children: _jsxs(Box, { direction: "row", alignItems: "start", children: [_jsxs(View, { style: styles.rangeCalendarSide, children: [_jsx(YearMonthSelect, { monthNames: monthNames, value: periods.start, maxValue: decrementYearMonth(periods.end), arrowsPosition: "around", onChange: setStartPeriod }), _jsx(Space, { height: 24 }), _jsx(MonthCalendar, { month: periods.start.month, year: periods.start.year, value: dateRange, firstWeekDay: firstWeekDay, weekDayNames: weekDayNames, isSelectable: isSelectable, onChange: handleSelectDate })] }), _jsx(Separator, { space: 24, horizontal: true }), _jsxs(View, { style: styles.rangeCalendarSide, children: [_jsx(YearMonthSelect, { monthNames: monthNames, value: periods.end, minValue: incrementYearMonth(periods.start), arrowsPosition: "around", onChange: setEndPeriod }), _jsx(Space, { height: 24 }), _jsx(MonthCalendar, { month: periods.end.month, year: periods.end.year, value: dateRange, firstWeekDay: firstWeekDay, weekDayNames: weekDayNames, isSelectable: isSelectable, onChange: handleSelectDate })] })] }) }));
606
+ return (_jsx(View, { children: _jsxs(Box, { direction: "row", alignItems: "start", children: [_jsxs(View, { style: styles.rangeCalendarSide, children: [_jsx(YearMonthSelect, { monthNames: monthNames, value: periods.start, maxValue: decrementYearMonth(periods.end), arrowsPosition: "around", onChange: setStartPeriod }), _jsx(Space, { height: 24 }), _jsx(MonthCalendar, { month: periods.start.month, year: periods.start.year, value: dateRange, firstWeekDay: firstWeekDay, isSelectable: isSelectable, onChange: handleSelectDate })] }), _jsx(Separator, { space: 24, horizontal: true }), _jsxs(View, { style: styles.rangeCalendarSide, children: [_jsx(YearMonthSelect, { monthNames: monthNames, value: periods.end, minValue: incrementYearMonth(periods.start), arrowsPosition: "around", onChange: setEndPeriod }), _jsx(Space, { height: 24 }), _jsx(MonthCalendar, { month: periods.end.month, year: periods.end.year, value: dateRange, firstWeekDay: firstWeekDay, isSelectable: isSelectable, onChange: handleSelectDate })] })] }) }));
584
607
  };
585
- export const DateRangePicker = ({ value, error, format, startLabel, endLabel, firstWeekDay, monthNames, weekDayNames, isSelectable, onChange, }) => {
608
+ export const DateRangePicker = ({ value, error, format, startLabel, endLabel, firstWeekDay, isSelectable, onChange, }) => {
586
609
  const { desktop } = useResponsive(DATE_PICKER_MOBILE_THRESHOLD);
587
610
  const { desktop: displayTwoCalendar } = useResponsive(DATE_RANGE_PICKER_THRESHOLD);
588
611
  const ref = useRef(null);
@@ -593,9 +616,9 @@ export const DateRangePicker = ({ value, error, format, startLabel, endLabel, fi
593
616
  const handleEndChange = useCallback((end) => {
594
617
  onChange({ start: value.start, end });
595
618
  }, [value, onChange]);
596
- return (_jsxs(View, { children: [_jsxs(Box, { direction: "row", alignItems: "end", children: [_jsx(LakeLabel, { label: startLabel, style: styles.label, render: id => (_jsx(Rifm, { value: value.start, onChange: handleStartChange, ...rifmDateProps, children: ({ value, onChange }) => (_jsx(LakeTextInput, { ref: ref, id: id, placeholder: format, value: value, onChange: onChange, error: error, hideErrors: true, ariaExpanded: isOpened })) })) }), _jsx(Space, { width: 12 }), _jsx(Box, { style: styles.arrowContainer, justifyContent: "center", children: _jsx(Icon, { name: "arrow-right-filled", size: 20 }) }), _jsx(Space, { width: 12 }), _jsx(LakeLabel, { label: endLabel, style: styles.label, render: id => (_jsx(Rifm, { value: value.end, onChange: handleEndChange, ...rifmDateProps, children: ({ value, onChange }) => (_jsx(LakeTextInput, { id: id, placeholder: format, value: value, onChange: onChange, error: error, hideErrors: true, ariaExpanded: isOpened })) })) }), _jsx(Space, { width: 12 }), _jsx(LakeButton, { mode: "secondary", icon: "calendar-ltr-regular", size: "small", onPress: open, ariaLabel: t("common.open") })] }), _jsx(Space, { height: 4 }), _jsx(LakeText, { variant: "smallRegular", color: colors.negative[500], children: error ?? " " }), _jsx(DateModal, { visible: isOpened, maxWidth: 900, withCloseButton: true, onPressClose: close, children: _jsx(DateRangePickerModalContent, { value: value, format: format, firstWeekDay: firstWeekDay, monthNames: monthNames, weekDayNames: weekDayNames, desktop: desktop, displayTwoCalendar: displayTwoCalendar, isSelectable: isSelectable, onChange: onChange }) })] }));
619
+ return (_jsxs(View, { children: [_jsxs(Box, { direction: "row", alignItems: "end", children: [_jsx(LakeLabel, { label: startLabel, style: styles.label, render: id => (_jsx(Rifm, { value: value.start, onChange: handleStartChange, ...rifmDateProps, children: ({ value, onChange }) => (_jsx(LakeTextInput, { ref: ref, id: id, placeholder: format, value: value, onChange: onChange, error: error, hideErrors: true, ariaExpanded: isOpened })) })) }), _jsx(Space, { width: 12 }), _jsx(Box, { style: styles.arrowContainer, justifyContent: "center", children: _jsx(Icon, { name: "arrow-right-filled", size: 20 }) }), _jsx(Space, { width: 12 }), _jsx(LakeLabel, { label: endLabel, style: styles.label, render: id => (_jsx(Rifm, { value: value.end, onChange: handleEndChange, ...rifmDateProps, children: ({ value, onChange }) => (_jsx(LakeTextInput, { id: id, placeholder: format, value: value, onChange: onChange, error: error, hideErrors: true, ariaExpanded: isOpened })) })) }), _jsx(Space, { width: 12 }), _jsx(LakeButton, { mode: "secondary", icon: "calendar-ltr-regular", size: "small", onPress: open, ariaLabel: t("common.open") })] }), _jsx(Space, { height: 4 }), _jsx(LakeText, { variant: "smallRegular", color: colors.negative[500], children: error ?? " " }), _jsx(DateModal, { visible: isOpened, maxWidth: 900, withCloseButton: true, onPressClose: close, children: _jsx(DateRangePickerModalContent, { value: value, format: format, firstWeekDay: firstWeekDay, desktop: desktop, displayTwoCalendar: displayTwoCalendar, isSelectable: isSelectable, onChange: onChange }) })] }));
597
620
  };
598
- export const DateRangePickerModal = ({ value, error, format, firstWeekDay, monthNames, weekDayNames, isSelectable, onChange, visible, startLabel, endLabel, cancelLabel, confirmLabel, onDissmiss, }) => {
621
+ export const DateRangePickerModal = ({ value, error, format, firstWeekDay, isSelectable, onChange, visible, startLabel, endLabel, cancelLabel, confirmLabel, onDissmiss, }) => {
599
622
  const { desktop } = useResponsive(MODALE_MOBILE_THRESHOLD);
600
623
  const { desktop: displayTwoCalendar } = useResponsive(DATE_RANGE_PICKER_THRESHOLD);
601
624
  const [localeValue, setLocaleValue] = useState(value);
@@ -616,5 +639,5 @@ export const DateRangePickerModal = ({ value, error, format, firstWeekDay, month
616
639
  onChange(localeValue);
617
640
  onDissmiss();
618
641
  };
619
- return (_jsxs(DateModal, { visible: visible, maxWidth: 900, onPressClose: handleCancel, children: [_jsxs(View, { children: [_jsxs(Box, { direction: "row", alignItems: "end", children: [_jsx(LakeLabel, { label: startLabel, style: styles.label, render: id => (_jsx(Rifm, { value: localeValue.start, onChange: handleStartChange, ...rifmDateProps, children: ({ value, onChange }) => (_jsx(LakeTextInput, { id: id, placeholder: format, value: value, onChange: onChange, error: error, hideErrors: true })) })) }), _jsx(Space, { width: 12 }), _jsx(Box, { style: styles.arrowContainer, justifyContent: "center", children: _jsx(Icon, { name: "arrow-right-filled", size: 20 }) }), _jsx(Space, { width: 12 }), _jsx(LakeLabel, { label: endLabel, style: styles.label, render: id => (_jsx(Rifm, { value: localeValue.end, onChange: handleEndChange, ...rifmDateProps, children: ({ value, onChange }) => (_jsx(LakeTextInput, { id: id, placeholder: format, value: value, onChange: onChange, error: error, hideErrors: true })) })) })] }), _jsx(Space, { height: 4 }), _jsx(LakeText, { variant: "smallRegular", color: colors.negative[500], children: error ?? " " })] }), _jsx(DateRangePickerModalContent, { value: localeValue, format: format, firstWeekDay: firstWeekDay, monthNames: monthNames, weekDayNames: weekDayNames, desktop: desktop, displayTwoCalendar: displayTwoCalendar, isSelectable: isSelectable, onChange: setLocaleValue }), _jsx(Space, { height: 24 }), _jsxs(Box, { direction: "row", alignItems: "center", children: [_jsx(LakeButton, { mode: "secondary", size: "small", onPress: handleCancel, style: styles.button, children: cancelLabel }), _jsx(Space, { width: 24 }), _jsx(LakeButton, { color: "current", size: "small", onPress: handleConfirm, style: styles.button, children: confirmLabel })] })] }));
642
+ return (_jsxs(DateModal, { visible: visible, maxWidth: 900, onPressClose: handleCancel, children: [_jsxs(View, { children: [_jsxs(Box, { direction: "row", alignItems: "end", children: [_jsx(LakeLabel, { label: startLabel, style: styles.label, render: id => (_jsx(Rifm, { value: localeValue.start, onChange: handleStartChange, ...rifmDateProps, children: ({ value, onChange }) => (_jsx(LakeTextInput, { id: id, placeholder: format, value: value, onChange: onChange, error: error, hideErrors: true })) })) }), _jsx(Space, { width: 12 }), _jsx(Box, { style: styles.arrowContainer, justifyContent: "center", children: _jsx(Icon, { name: "arrow-right-filled", size: 20 }) }), _jsx(Space, { width: 12 }), _jsx(LakeLabel, { label: endLabel, style: styles.label, render: id => (_jsx(Rifm, { value: localeValue.end, onChange: handleEndChange, ...rifmDateProps, children: ({ value, onChange }) => (_jsx(LakeTextInput, { id: id, placeholder: format, value: value, onChange: onChange, error: error, hideErrors: true })) })) })] }), _jsx(Space, { height: 4 }), _jsx(LakeText, { variant: "smallRegular", color: colors.negative[500], children: error ?? " " })] }), _jsx(DateRangePickerModalContent, { value: localeValue, format: format, firstWeekDay: firstWeekDay, desktop: desktop, displayTwoCalendar: displayTwoCalendar, isSelectable: isSelectable, onChange: setLocaleValue }), _jsx(Space, { height: 24 }), _jsxs(Box, { direction: "row", alignItems: "center", children: [_jsx(LakeButton, { mode: "secondary", size: "small", onPress: handleCancel, style: styles.button, children: cancelLabel }), _jsx(Space, { width: 24 }), _jsx(LakeButton, { color: "current", size: "small", onPress: handleConfirm, style: styles.button, children: confirmLabel })] })] }));
620
643
  };
@@ -1,3 +1,4 @@
1
+ import { AsyncData } from "@swan-io/boxed";
1
2
  import { IconName } from "@swan-io/lake/src/components/Icon";
2
3
  import { DropzoneOptions } from "react-dropzone";
3
4
  export type UploadFileStatus = ({
@@ -16,9 +17,10 @@ export type UploadFileStatus = ({
16
17
  type Props = {
17
18
  icon: IconName;
18
19
  documents?: UploadFileStatus[];
19
- onRemoveFile?: (fileId: string) => void;
20
+ onRemoveDocument?: (fileId: string) => void;
21
+ onRemoveFile?: () => void;
20
22
  accept: string[];
21
- value?: File | Element;
23
+ value?: AsyncData<File>;
22
24
  disabled?: boolean;
23
25
  onDropAccepted?: DropzoneOptions["onDropAccepted"];
24
26
  onDropRejected?: DropzoneOptions["onDropRejected"];
@@ -27,5 +29,5 @@ type Props = {
27
29
  error?: string;
28
30
  maxSize?: number;
29
31
  };
30
- export declare const UploadArea: ({ icon, accept, value, documents, disabled, onRemoveFile, onDropAccepted, onDropRejected, layout, description, error, maxSize, }: Props) => import("react/jsx-runtime").JSX.Element;
32
+ export declare const UploadArea: ({ icon, accept, value, documents, disabled, onRemoveFile, onRemoveDocument, onDropAccepted, onDropRejected, layout, description, error, maxSize, }: Props) => import("react/jsx-runtime").JSX.Element;
31
33
  export {};
@@ -1,8 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { Box } from "@swan-io/lake/src/components/Box";
3
3
  import { Icon } from "@swan-io/lake/src/components/Icon";
4
+ import { LakeButton } from "@swan-io/lake/src/components/LakeButton";
4
5
  import { LakeHeading } from "@swan-io/lake/src/components/LakeHeading";
5
6
  import { LakeText } from "@swan-io/lake/src/components/LakeText";
7
+ import { LoadingView } from "@swan-io/lake/src/components/LoadingView";
6
8
  import { Space } from "@swan-io/lake/src/components/Space";
7
9
  import { commonStyles } from "@swan-io/lake/src/constants/commonStyles";
8
10
  import { backgroundColor, colors, gray75, radii, shadows, spacings, } from "@swan-io/lake/src/constants/design";
@@ -10,7 +12,7 @@ import { useBoolean } from "@swan-io/lake/src/hooks/useBoolean";
10
12
  import { getIconNameFromFilename } from "@swan-io/lake/src/utils/file";
11
13
  import { isNotNullish } from "@swan-io/lake/src/utils/nullish";
12
14
  import { FileTile } from "@swan-io/shared-business/src/components/FileTile";
13
- import { Fragment, useLayoutEffect, useRef } from "react";
15
+ import { Fragment, useMemo } from "react";
14
16
  import { useDropzone } from "react-dropzone";
15
17
  import { StyleSheet, Text, View } from "react-native";
16
18
  import { match } from "ts-pattern";
@@ -103,32 +105,23 @@ const styles = StyleSheet.create({
103
105
  borderColor: colors.negative[500],
104
106
  },
105
107
  preview: {
106
- aspectRatio: 16 / 4,
108
+ aspectRatio: 16 / 5,
107
109
  width: "50%",
110
+ backgroundPosition: "center",
111
+ backgroundSize: "contain",
112
+ backgroundRepeat: "no-repeat",
113
+ },
114
+ deleteButton: {
115
+ position: "absolute",
116
+ right: spacings[20],
117
+ top: spacings[20],
108
118
  },
109
119
  });
110
- const UploadAreaPreview = ({ value }) => {
111
- const containerRef = useRef(null);
112
- useLayoutEffect(() => {
113
- const element = containerRef.current;
114
- if (element != null) {
115
- while (element.firstChild) {
116
- element.firstChild.remove();
117
- }
118
- const previewElement = value.cloneNode(true);
119
- element.append(previewElement);
120
- previewElement.style.position = "absolute";
121
- previewElement.style.top = "0";
122
- previewElement.style.left = "0";
123
- previewElement.style.width = "100%";
124
- previewElement.style.height = "100%";
125
- previewElement.style.objectFit = "contain";
126
- previewElement.style.objectPosition = "50% 50%";
127
- }
128
- }, [value]);
129
- return _jsx(View, { ref: containerRef, style: styles.preview });
120
+ const UploadAreaPreview = ({ file }) => {
121
+ const url = useMemo(() => URL.createObjectURL(file), [file]);
122
+ return _jsx(View, { style: [styles.preview, { backgroundImage: `url("${url}")` }] });
130
123
  };
131
- export const UploadArea = ({ icon, accept, value, documents = [], disabled = false, onRemoveFile, onDropAccepted, onDropRejected, layout = "vertical", description, error, maxSize, }) => {
124
+ export const UploadArea = ({ icon, accept, value, documents = [], disabled = false, onRemoveFile, onRemoveDocument, onDropAccepted, onDropRejected, layout = "vertical", description, error, maxSize, }) => {
132
125
  const [isHovered, setIsHovered] = useBoolean(false);
133
126
  const { getRootProps, getInputProps, isDragActive, fileRejections } = useDropzone({
134
127
  accept: accept.reduce((acc, item) => ({ ...acc, [item]: [] }), {}),
@@ -137,6 +130,18 @@ export const UploadArea = ({ icon, accept, value, documents = [], disabled = fal
137
130
  disabled,
138
131
  maxSize,
139
132
  });
133
+ const browseElement = (_jsxs(_Fragment, { children: [_jsxs(View, { style: styles.icon, children: [_jsx(Icon, { name: icon, size: 48, color: disabled ? colors.gray[200] : colors.current[500], style: [
134
+ styles.decorativeIconLeft,
135
+ (isDragActive || isHovered) && styles.decorativeIconLeftHovered,
136
+ ] }), _jsx(Icon, { name: icon, size: 48, color: disabled ? colors.gray[200] : colors.current[500], style: [
137
+ styles.decorativeIconRight,
138
+ (isDragActive || isHovered) && styles.decorativeIconRightHovered,
139
+ ] }), _jsx(Icon, { name: icon, size: 48, color: disabled ? colors.gray[200] : colors.current[500] })] }), _jsx(Space, { width: layout === "horizontal" ? 48 : 16, height: layout === "horizontal" ? 48 : 16 }), _jsxs(View, { style: styles.browseBlock, children: [_jsx(LakeHeading, { level: 5, variant: "h5", align: layout === "horizontal" ? "left" : "center", color: disabled ? colors.gray[200] : undefined, children: disabled
140
+ ? t("uploadArea.noValue")
141
+ : formatNestedMessage("uploadArea.dropFile", {
142
+ browse: _jsx(Text, { style: styles.browse, children: t("uploadArea.browse") }),
143
+ }) }), isNotNullish(error) ? (_jsxs(_Fragment, { children: [_jsx(Space, { height: 4 }), _jsx(LakeText, { color: colors.negative[400], align: layout === "horizontal" ? "left" : "center", children: error })] })) : (!disabled &&
144
+ isNotNullish(description) && (_jsxs(_Fragment, { children: [_jsx(Space, { height: 4 }), _jsx(LakeText, { align: layout === "horizontal" ? "left" : "center", children: description })] })))] })] }));
140
145
  return (_jsxs(View, { style: commonStyles.fill, children: [_jsx("div", { ...getRootProps(), onMouseEnter: setIsHovered.on, onMouseLeave: setIsHovered.off, children: _jsxs(View, { "aria-errormessage": error ?? fileRejections[0]?.errors.join(", "), style: [
141
146
  styles.container,
142
147
  disabled && styles.disabled,
@@ -144,21 +149,16 @@ export const UploadArea = ({ icon, accept, value, documents = [], disabled = fal
144
149
  !disabled && isHovered && styles.hoveredContainer,
145
150
  isDragActive && styles.activeContainer,
146
151
  (error != null || fileRejections.length > 0) && styles.errorContainer,
147
- ], children: [_jsx("input", { ...getInputProps() }), isNotNullish(value) ? (value instanceof Element ? (_jsx(UploadAreaPreview, { value: value })) : (_jsxs(_Fragment, { children: [_jsx(Icon, { name: getIconNameFromFilename(value.name), size: 48, color: disabled ? colors.gray[200] : colors.current[500] }), _jsx(Space, { width: layout === "horizontal" ? 48 : 16, height: layout === "horizontal" ? 48 : 16 }), _jsxs(View, { style: styles.browseBlock, children: [_jsx(LakeHeading, { level: 5, variant: "h5", align: layout === "horizontal" ? "left" : "center", children: t("uploadArea.droppedFile") }), _jsx(Space, { height: 4 }), _jsx(LakeText, { variant: "smallRegular", color: colors.gray[200], children: value.name })] })] }))) : (_jsxs(_Fragment, { children: [_jsxs(View, { style: styles.icon, children: [_jsx(Icon, { name: icon, size: 48, color: disabled ? colors.gray[200] : colors.current[500], style: [
148
- styles.decorativeIconLeft,
149
- (isDragActive || isHovered) && styles.decorativeIconLeftHovered,
150
- ] }), _jsx(Icon, { name: icon, size: 48, color: disabled ? colors.gray[200] : colors.current[500], style: [
151
- styles.decorativeIconRight,
152
- (isDragActive || isHovered) && styles.decorativeIconRightHovered,
153
- ] }), _jsx(Icon, { name: icon, size: 48, color: disabled ? colors.gray[200] : colors.current[500] })] }), _jsx(Space, { width: layout === "horizontal" ? 48 : 16, height: layout === "horizontal" ? 48 : 16 }), _jsxs(View, { style: styles.browseBlock, children: [_jsx(LakeHeading, { level: 5, variant: "h5", align: layout === "horizontal" ? "left" : "center", color: disabled ? colors.gray[200] : undefined, children: disabled
154
- ? t("uploadArea.noValue")
155
- : formatNestedMessage("uploadArea.dropFile", {
156
- browse: _jsx(Text, { style: styles.browse, children: t("uploadArea.browse") }),
157
- }) }), isNotNullish(error) ? (_jsxs(_Fragment, { children: [_jsx(Space, { height: 4 }), _jsx(LakeText, { color: colors.negative[400], align: layout === "horizontal" ? "left" : "center", children: error })] })) : (!disabled &&
158
- isNotNullish(description) && (_jsxs(_Fragment, { children: [_jsx(Space, { height: 4 }), _jsx(LakeText, { align: layout === "horizontal" ? "left" : "center", children: description })] })))] })] }))] }) }), documents.map(({ ...document }, index) => {
152
+ ], children: [_jsx("input", { ...getInputProps() }), isNotNullish(value)
153
+ ? value.match({
154
+ NotAsked: () => browseElement,
155
+ Loading: () => _jsx(LoadingView, {}),
156
+ Done: value => value.type.startsWith("image/") ? (_jsxs(_Fragment, { children: [_jsx(UploadAreaPreview, { file: value }), onRemoveFile != null ? (_jsx(LakeButton, { mode: "tertiary", size: "small", icon: "delete-regular", color: "negative", onPress: onRemoveFile, style: styles.deleteButton, ariaLabel: t("common.remove") })) : null] })) : (_jsxs(_Fragment, { children: [_jsx(Icon, { name: getIconNameFromFilename(value.name), size: 48, color: disabled ? colors.gray[200] : colors.current[500] }), _jsx(Space, { width: layout === "horizontal" ? 48 : 16, height: layout === "horizontal" ? 48 : 16 }), _jsxs(View, { style: styles.browseBlock, children: [_jsx(LakeHeading, { level: 5, variant: "h5", align: layout === "horizontal" ? "left" : "center", children: t("uploadArea.droppedFile") }), _jsx(Space, { height: 4 }), _jsx(LakeText, { variant: "smallRegular", color: colors.gray[200], children: value.name })] }), onRemoveFile != null ? (_jsx(LakeButton, { mode: "tertiary", size: "small", icon: "delete-regular", color: "negative", style: styles.deleteButton, onPress: onRemoveFile, ariaLabel: t("common.remove") })) : null] })),
157
+ })
158
+ : browseElement] }) }), documents.map(({ ...document }, index) => {
159
159
  return (_jsxs(Fragment, { children: [_jsx(Space, { height: index === 0 ? 8 : 4 }), match(document)
160
- .with({ status: "finished" }, () => (_jsx(FileTile, { name: document.name ?? t("uploadArea.unknownFileName"), url: document.fileUrl, onRemove: onRemoveFile ? () => onRemoveFile(document.id) : undefined })))
161
- .with({ status: "failed" }, ({ error }) => (_jsx(FileTile, { name: document.name ?? t("uploadArea.unknownFileName"), url: document.fileUrl, onRemove: () => (onRemoveFile ? onRemoveFile(document.id) : undefined), variant: "refused", title: error })))
160
+ .with({ status: "finished" }, () => (_jsx(FileTile, { name: document.name ?? t("uploadArea.unknownFileName"), url: document.fileUrl, onRemove: onRemoveDocument ? () => onRemoveDocument(document.id) : undefined })))
161
+ .with({ status: "failed" }, ({ error }) => (_jsx(FileTile, { name: document.name ?? t("uploadArea.unknownFileName"), url: document.fileUrl, onRemove: () => (onRemoveDocument ? onRemoveDocument(document.id) : undefined), variant: "refused", title: error })))
162
162
  .with({ status: "uploading" }, ({ progress }) => (_jsxs(Box, { direction: "row", alignItems: "center", style: styles.item, children: [_jsx(LakeText, { numberOfLines: 1, color: colors.gray[700], children: t("uploadArea.uploading") }), _jsx(Space, { width: 20 }), _jsx(View, { role: "progressbar", style: styles.progressBar, children: _jsx(View, { style: [styles.progress, { width: `${progress}%` }] }) })] })))
163
163
  .exhaustive()] }, document.id));
164
164
  })] }));
@@ -1,5 +1,2 @@
1
- import { MonthNames, WeekDayNames } from "@swan-io/shared-business/src/components/DatePicker";
2
1
  export declare const decodeBirthDate: (value: string) => string;
3
2
  export declare const encodeBirthDate: (value: string) => string;
4
- export declare const weekDayNames: WeekDayNames;
5
- export declare const monthNames: MonthNames;
package/src/utils/date.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import dayjs from "dayjs";
2
- import { t } from "./i18n";
3
2
  export const decodeBirthDate = (value) => {
4
3
  const date = dayjs.utc(value, "YYYY-MM-DD");
5
4
  return date.isValid() ? date.format("DD/MM/YYYY") : "";
@@ -8,26 +7,3 @@ export const encodeBirthDate = (value) => {
8
7
  const date = dayjs.utc(value, "DD/MM/YYYY");
9
8
  return date.isValid() ? date.format("YYYY-MM-DD") : "";
10
9
  };
11
- export const weekDayNames = [
12
- t("datePicker.day.sunday"),
13
- t("datePicker.day.monday"),
14
- t("datePicker.day.tuesday"),
15
- t("datePicker.day.wednesday"),
16
- t("datePicker.day.thursday"),
17
- t("datePicker.day.friday"),
18
- t("datePicker.day.saturday"),
19
- ];
20
- export const monthNames = [
21
- t("datePicker.month.january"),
22
- t("datePicker.month.february"),
23
- t("datePicker.month.march"),
24
- t("datePicker.month.april"),
25
- t("datePicker.month.may"),
26
- t("datePicker.month.june"),
27
- t("datePicker.month.july"),
28
- t("datePicker.month.august"),
29
- t("datePicker.month.september"),
30
- t("datePicker.month.october"),
31
- t("datePicker.month.november"),
32
- t("datePicker.month.december"),
33
- ];