@navikt/ds-react 1.4.2 → 1.4.4

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.
Files changed (38) hide show
  1. package/_docs.json +120 -0
  2. package/cjs/date/hooks/useDatepicker.js +36 -11
  3. package/cjs/date/hooks/useMonthPicker.js +34 -10
  4. package/cjs/date/hooks/useRangeDatepicker.js +181 -65
  5. package/cjs/date/utils/format-date.js +3 -3
  6. package/cjs/date/utils/parse-date.js +14 -8
  7. package/esm/date/hooks/index.d.ts +3 -0
  8. package/esm/date/hooks/index.js.map +1 -1
  9. package/esm/date/hooks/useDatepicker.d.ts +18 -0
  10. package/esm/date/hooks/useDatepicker.js +36 -11
  11. package/esm/date/hooks/useDatepicker.js.map +1 -1
  12. package/esm/date/hooks/useMonthPicker.d.ts +17 -0
  13. package/esm/date/hooks/useMonthPicker.js +34 -10
  14. package/esm/date/hooks/useMonthPicker.js.map +1 -1
  15. package/esm/date/hooks/useRangeDatepicker.d.ts +12 -2
  16. package/esm/date/hooks/useRangeDatepicker.js +181 -65
  17. package/esm/date/hooks/useRangeDatepicker.js.map +1 -1
  18. package/esm/date/index.d.ts +1 -1
  19. package/esm/date/index.js.map +1 -1
  20. package/esm/date/utils/format-date.d.ts +1 -1
  21. package/esm/date/utils/format-date.js +3 -3
  22. package/esm/date/utils/format-date.js.map +1 -1
  23. package/esm/date/utils/parse-date.d.ts +1 -1
  24. package/esm/date/utils/parse-date.js +14 -8
  25. package/esm/date/utils/parse-date.js.map +1 -1
  26. package/package.json +3 -3
  27. package/src/date/datepicker/datepicker.stories.tsx +30 -5
  28. package/src/date/hooks/index.ts +3 -0
  29. package/src/date/hooks/useDatepicker.tsx +73 -10
  30. package/src/date/hooks/useMonthPicker.tsx +68 -10
  31. package/src/date/hooks/useRangeDatepicker.test.tsx +59 -0
  32. package/src/date/hooks/useRangeDatepicker.tsx +285 -92
  33. package/src/date/index.ts +3 -0
  34. package/src/date/monthpicker/monthpicker.stories.tsx +20 -0
  35. package/src/date/utils/__tests__/format-dates.test.ts +4 -4
  36. package/src/date/utils/__tests__/parse-dates.test.ts +0 -40
  37. package/src/date/utils/format-date.ts +5 -3
  38. package/src/date/utils/parse-date.ts +18 -9
package/_docs.json CHANGED
@@ -8736,6 +8736,46 @@
8736
8736
  "name": "((val?: Date) => void)"
8737
8737
  }
8738
8738
  },
8739
+ "inputFormat": {
8740
+ "defaultValue": {
8741
+ "value": "\"dd.MM.yyyy\""
8742
+ },
8743
+ "description": "Input-format",
8744
+ "name": "inputFormat",
8745
+ "parent": {
8746
+ "fileName": "src/date/hooks/useDatepicker.tsx",
8747
+ "name": "UseDatepickerOptions"
8748
+ },
8749
+ "declarations": [
8750
+ {
8751
+ "fileName": "src/date/hooks/useDatepicker.tsx",
8752
+ "name": "UseDatepickerOptions"
8753
+ }
8754
+ ],
8755
+ "required": false,
8756
+ "type": {
8757
+ "name": "string"
8758
+ }
8759
+ },
8760
+ "onValidate": {
8761
+ "defaultValue": null,
8762
+ "description": "validation-callback",
8763
+ "name": "onValidate",
8764
+ "parent": {
8765
+ "fileName": "src/date/hooks/useDatepicker.tsx",
8766
+ "name": "UseDatepickerOptions"
8767
+ },
8768
+ "declarations": [
8769
+ {
8770
+ "fileName": "src/date/hooks/useDatepicker.tsx",
8771
+ "name": "UseDatepickerOptions"
8772
+ }
8773
+ ],
8774
+ "required": false,
8775
+ "type": {
8776
+ "name": "((val: DateValidationT) => void)"
8777
+ }
8778
+ },
8739
8779
  "locale": {
8740
8780
  "defaultValue": {
8741
8781
  "value": "\"nb\" (norsk bokmål)"
@@ -8879,6 +8919,46 @@
8879
8919
  "name": "((date?: Date) => void)"
8880
8920
  }
8881
8921
  },
8922
+ "inputFormat": {
8923
+ "defaultValue": {
8924
+ "value": "\"MMMM yyyy\""
8925
+ },
8926
+ "description": "Input-format",
8927
+ "name": "inputFormat",
8928
+ "parent": {
8929
+ "fileName": "src/date/hooks/useMonthPicker.tsx",
8930
+ "name": "UseMonthPickerOptions"
8931
+ },
8932
+ "declarations": [
8933
+ {
8934
+ "fileName": "src/date/hooks/useMonthPicker.tsx",
8935
+ "name": "UseMonthPickerOptions"
8936
+ }
8937
+ ],
8938
+ "required": false,
8939
+ "type": {
8940
+ "name": "string"
8941
+ }
8942
+ },
8943
+ "onValidate": {
8944
+ "defaultValue": null,
8945
+ "description": "validation-callback",
8946
+ "name": "onValidate",
8947
+ "parent": {
8948
+ "fileName": "src/date/hooks/useMonthPicker.tsx",
8949
+ "name": "UseMonthPickerOptions"
8950
+ },
8951
+ "declarations": [
8952
+ {
8953
+ "fileName": "src/date/hooks/useMonthPicker.tsx",
8954
+ "name": "UseMonthPickerOptions"
8955
+ }
8956
+ ],
8957
+ "required": false,
8958
+ "type": {
8959
+ "name": "((val: MonthValidationT) => void)"
8960
+ }
8961
+ },
8882
8962
  "locale": {
8883
8963
  "defaultValue": {
8884
8964
  "value": "\"nb\" (norsk bokmål)"
@@ -9020,6 +9100,25 @@
9020
9100
  "name": "((val?: DateRange) => void)"
9021
9101
  }
9022
9102
  },
9103
+ "onValidate": {
9104
+ "defaultValue": null,
9105
+ "description": "validation-callback",
9106
+ "name": "onValidate",
9107
+ "parent": {
9108
+ "fileName": "src/date/hooks/useRangeDatepicker.tsx",
9109
+ "name": "UseRangeDatepickerOptions"
9110
+ },
9111
+ "declarations": [
9112
+ {
9113
+ "fileName": "src/date/hooks/useRangeDatepicker.tsx",
9114
+ "name": "UseRangeDatepickerOptions"
9115
+ }
9116
+ ],
9117
+ "required": false,
9118
+ "type": {
9119
+ "name": "((val: RangeValidationT) => void)"
9120
+ }
9121
+ },
9023
9122
  "locale": {
9024
9123
  "defaultValue": {
9025
9124
  "value": "\"nb\" (norsk bokmål)"
@@ -9137,6 +9236,27 @@
9137
9236
  "type": {
9138
9237
  "name": "boolean"
9139
9238
  }
9239
+ },
9240
+ "inputFormat": {
9241
+ "defaultValue": {
9242
+ "value": "\"dd.MM.yyyy\""
9243
+ },
9244
+ "description": "Input-format",
9245
+ "name": "inputFormat",
9246
+ "parent": {
9247
+ "fileName": "react/src/date/hooks/useDatepicker.tsx",
9248
+ "name": "UseDatepickerOptions"
9249
+ },
9250
+ "declarations": [
9251
+ {
9252
+ "fileName": "react/src/date/hooks/useDatepicker.tsx",
9253
+ "name": "UseDatepickerOptions"
9254
+ }
9255
+ ],
9256
+ "required": false,
9257
+ "type": {
9258
+ "name": "string"
9259
+ }
9140
9260
  }
9141
9261
  }
9142
9262
  },
@@ -9,8 +9,9 @@ const isWeekend_1 = __importDefault(require("date-fns/isWeekend"));
9
9
  const react_1 = require("react");
10
10
  const react_day_picker_1 = require("react-day-picker");
11
11
  const utils_1 = require("../utils");
12
+ const getValidationMessage = (val = {}) => (Object.assign({ isDisabled: false, isWeekend: false, isEmpty: false, isInvalid: false, isBefore: false, isAfter: false, isValidDate: true }, val));
12
13
  const useDatepicker = (opt = {}) => {
13
- const { locale: _locale = "nb", required, defaultSelected: _defaultSelected, today = new Date(), fromDate, toDate, disabled, disableWeekends, onDateChange, } = opt;
14
+ const { locale: _locale = "nb", required, defaultSelected: _defaultSelected, today = new Date(), fromDate, toDate, disabled, disableWeekends, onDateChange, inputFormat, onValidate, } = opt;
14
15
  const locale = (0, utils_1.getLocaleFromString)(_locale);
15
16
  const inputRef = (0, react_1.useRef)(null);
16
17
  const daypickerRef = (0, react_1.useRef)(null);
@@ -20,13 +21,17 @@ const useDatepicker = (opt = {}) => {
20
21
  const [selectedDay, setSelectedDay] = (0, react_1.useState)(defaultSelected);
21
22
  const [open, setOpen] = (0, react_1.useState)(false);
22
23
  const defaultInputValue = defaultSelected
23
- ? (0, utils_1.formatDateForInput)(defaultSelected, locale, "date")
24
+ ? (0, utils_1.formatDateForInput)(defaultSelected, locale, "date", inputFormat)
24
25
  : "";
25
26
  const [inputValue, setInputValue] = (0, react_1.useState)(defaultInputValue);
26
27
  const updateDate = (date) => {
27
28
  onDateChange === null || onDateChange === void 0 ? void 0 : onDateChange(date);
28
29
  setSelectedDay(date);
29
30
  };
31
+ const updateValidation = (val = {}) => {
32
+ const msg = getValidationMessage(val);
33
+ onValidate === null || onValidate === void 0 ? void 0 : onValidate(msg);
34
+ };
30
35
  const handleFocusIn = (0, react_1.useCallback)((e) => {
31
36
  var _a, _b;
32
37
  if (!(e === null || e === void 0 ? void 0 : e.target) || !((_a = e === null || e === void 0 ? void 0 : e.target) === null || _a === void 0 ? void 0 : _a.nodeType)) {
@@ -58,19 +63,20 @@ const useDatepicker = (opt = {}) => {
58
63
  const setSelected = (date) => {
59
64
  updateDate(date);
60
65
  setMonth(date !== null && date !== void 0 ? date : today);
61
- setInputValue(date ? (0, utils_1.formatDateForInput)(date, locale, "date") : "");
66
+ setInputValue(date ? (0, utils_1.formatDateForInput)(date, locale, "date", inputFormat) : "");
62
67
  };
63
68
  const handleFocus = (e) => {
64
69
  !open && setOpen(true);
65
70
  let day = (0, utils_1.parseDate)(e.target.value, today, locale, "date");
66
71
  if ((0, utils_1.isValidDate)(day)) {
67
72
  setMonth(day);
68
- setInputValue((0, utils_1.formatDateForInput)(day, locale, "date"));
73
+ setInputValue((0, utils_1.formatDateForInput)(day, locale, "date", inputFormat));
69
74
  }
70
75
  };
71
76
  const handleBlur = (e) => {
72
77
  let day = (0, utils_1.parseDate)(e.target.value, today, locale, "date");
73
- (0, utils_1.isValidDate)(day) && setInputValue((0, utils_1.formatDateForInput)(day, locale, "date"));
78
+ (0, utils_1.isValidDate)(day) &&
79
+ setInputValue((0, utils_1.formatDateForInput)(day, locale, "date", inputFormat));
74
80
  };
75
81
  /* Only allow de-selecting if not required */
76
82
  const handleDayClick = (day, { selected }) => {
@@ -81,11 +87,13 @@ const useDatepicker = (opt = {}) => {
81
87
  if (!required && selected) {
82
88
  updateDate(undefined);
83
89
  setInputValue("");
90
+ updateValidation({ isValidDate: false, isEmpty: true });
84
91
  return;
85
92
  }
86
93
  updateDate(day);
94
+ updateValidation();
87
95
  setMonth(day);
88
- setInputValue(day ? (0, utils_1.formatDateForInput)(day, locale, "date") : "");
96
+ setInputValue(day ? (0, utils_1.formatDateForInput)(day, locale, "date", inputFormat) : "");
89
97
  };
90
98
  // When changing the input field, save its value in state and check if the
91
99
  // string is a valid date. If it is a valid day, set it as selected and update
@@ -93,19 +101,34 @@ const useDatepicker = (opt = {}) => {
93
101
  const handleChange = (e) => {
94
102
  setInputValue(e.target.value);
95
103
  const day = (0, utils_1.parseDate)(e.target.value, today, locale, "date");
104
+ const isBefore = fromDate && day && (0, differenceInCalendarDays_1.default)(fromDate, day) > 0;
105
+ const isAfter = toDate && day && (0, differenceInCalendarDays_1.default)(day, toDate) > 0;
96
106
  if (!(0, utils_1.isValidDate)(day) ||
97
- (disabled &&
98
- ((disableWeekends && (0, isWeekend_1.default)(day)) || (0, react_day_picker_1.isMatch)(day, disabled)))) {
107
+ (disableWeekends && (0, isWeekend_1.default)(day)) ||
108
+ (disabled && (0, react_day_picker_1.isMatch)(day, disabled))) {
99
109
  updateDate(undefined);
110
+ updateValidation({
111
+ isInvalid: (0, utils_1.isValidDate)(day),
112
+ isWeekend: disableWeekends && (0, isWeekend_1.default)(day),
113
+ isDisabled: disabled && (0, react_day_picker_1.isMatch)(day, disabled),
114
+ isValidDate: false,
115
+ isEmpty: !e.target.value,
116
+ isBefore: isBefore !== null && isBefore !== void 0 ? isBefore : false,
117
+ isAfter: isAfter !== null && isAfter !== void 0 ? isAfter : false,
118
+ });
100
119
  return;
101
120
  }
102
- const isBefore = fromDate && (0, differenceInCalendarDays_1.default)(fromDate, day) > 0;
103
- const isAfter = toDate && (0, differenceInCalendarDays_1.default)(day, toDate) > 0;
104
121
  if (isBefore || isAfter) {
105
122
  updateDate(undefined);
123
+ updateValidation({
124
+ isValidDate: false,
125
+ isBefore: isBefore !== null && isBefore !== void 0 ? isBefore : false,
126
+ isAfter: isAfter !== null && isAfter !== void 0 ? isAfter : false,
127
+ });
106
128
  return;
107
129
  }
108
130
  updateDate(day);
131
+ updateValidation();
109
132
  setMonth(day);
110
133
  };
111
134
  const handleClose = (0, react_1.useCallback)(() => {
@@ -123,13 +146,15 @@ const useDatepicker = (opt = {}) => {
123
146
  month,
124
147
  onMonthChange: (month) => setMonth(month),
125
148
  onDayClick: handleDayClick,
126
- selected: selectedDay,
149
+ selected: selectedDay !== null && selectedDay !== void 0 ? selectedDay : new Date("Invalid date"),
127
150
  locale: _locale,
128
151
  fromDate,
129
152
  toDate,
130
153
  today,
131
154
  open,
132
155
  onOpenToggle: () => setOpen((x) => !x),
156
+ disabled,
157
+ disableWeekends,
133
158
  ref: daypickerRef,
134
159
  };
135
160
  const inputProps = {
@@ -3,8 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useMonthpicker = void 0;
4
4
  const react_1 = require("react");
5
5
  const utils_1 = require("../utils");
6
+ const getValidationMessage = (val = {}) => (Object.assign({ isDisabled: false, isEmpty: false, isInvalid: false, isBefore: false, isAfter: false, isValidMonth: true }, val));
6
7
  const useMonthpicker = (opt = {}) => {
7
- const { locale: _locale = "nb", defaultSelected: _defaultSelected, fromDate, toDate, disabled, required, onMonthChange, } = opt;
8
+ const { locale: _locale = "nb", defaultSelected: _defaultSelected, fromDate, toDate, disabled, required, onMonthChange, inputFormat, onValidate, } = opt;
8
9
  const [defaultSelected, setDefaultSelected] = (0, react_1.useState)(_defaultSelected);
9
10
  const today = new Date();
10
11
  const locale = (0, utils_1.getLocaleFromString)(_locale);
@@ -15,13 +16,17 @@ const useMonthpicker = (opt = {}) => {
15
16
  const [selectedMonth, setSelectedMonth] = (0, react_1.useState)(defaultSelected);
16
17
  const [open, setOpen] = (0, react_1.useState)(false);
17
18
  const defaultInputValue = defaultSelected
18
- ? (0, utils_1.formatDateForInput)(defaultSelected, locale, "month")
19
+ ? (0, utils_1.formatDateForInput)(defaultSelected, locale, "month", inputFormat)
19
20
  : "";
20
21
  const [inputValue, setInputValue] = (0, react_1.useState)(defaultInputValue);
21
22
  const updateMonth = (date) => {
22
23
  onMonthChange === null || onMonthChange === void 0 ? void 0 : onMonthChange(date);
23
24
  setSelectedMonth(date);
24
25
  };
26
+ const updateValidation = (val = {}) => {
27
+ const msg = getValidationMessage(val);
28
+ onValidate === null || onValidate === void 0 ? void 0 : onValidate(msg);
29
+ };
25
30
  const handleFocusIn = (0, react_1.useCallback)((e) => {
26
31
  var _a, _b;
27
32
  if (!(e === null || e === void 0 ? void 0 : e.target) || !((_a = e === null || e === void 0 ? void 0 : e.target) === null || _a === void 0 ? void 0 : _a.nodeType)) {
@@ -53,19 +58,20 @@ const useMonthpicker = (opt = {}) => {
53
58
  const setSelected = (date) => {
54
59
  updateMonth(date);
55
60
  setYear(date !== null && date !== void 0 ? date : today);
56
- setInputValue(date ? (0, utils_1.formatDateForInput)(date, locale, "month") : "");
61
+ setInputValue(date ? (0, utils_1.formatDateForInput)(date, locale, "month", inputFormat) : "");
57
62
  };
58
63
  const handleFocus = (e) => {
59
64
  !open && setOpen(true);
60
65
  let day = (0, utils_1.parseDate)(e.target.value, today, locale, "month");
61
66
  if ((0, utils_1.isValidDate)(day)) {
62
67
  setYear(day);
63
- setInputValue((0, utils_1.formatDateForInput)(day, locale, "month"));
68
+ setInputValue((0, utils_1.formatDateForInput)(day, locale, "month", inputFormat));
64
69
  }
65
70
  };
66
71
  const handleBlur = (e) => {
67
72
  let day = (0, utils_1.parseDate)(e.target.value, today, locale, "month");
68
- (0, utils_1.isValidDate)(day) && setInputValue((0, utils_1.formatDateForInput)(day, locale, "month"));
73
+ (0, utils_1.isValidDate)(day) &&
74
+ setInputValue((0, utils_1.formatDateForInput)(day, locale, "month", inputFormat));
69
75
  };
70
76
  /* Only allow de-selecting if not required */
71
77
  const handleMonthClick = (month) => {
@@ -75,11 +81,13 @@ const useMonthpicker = (opt = {}) => {
75
81
  }
76
82
  if (!required && !month) {
77
83
  updateMonth(undefined);
84
+ updateValidation({ isValidMonth: false, isEmpty: true });
78
85
  setInputValue("");
79
86
  return;
80
87
  }
81
88
  updateMonth(month);
82
- setInputValue(month ? (0, utils_1.formatDateForInput)(month, locale, "month") : "");
89
+ updateValidation();
90
+ setInputValue(month ? (0, utils_1.formatDateForInput)(month, locale, "month", inputFormat) : "");
83
91
  };
84
92
  // When changing the input field, save its value in state and check if the
85
93
  // string is a valid date. If it is a valid day, set it as selected and update
@@ -87,25 +95,41 @@ const useMonthpicker = (opt = {}) => {
87
95
  const handleChange = (e) => {
88
96
  setInputValue(e.target.value);
89
97
  const month = (0, utils_1.parseDate)(e.target.value, today, locale, "month");
90
- if (!(0, utils_1.isValidDate)(month) || (disabled && (0, utils_1.isMatch)(month, disabled))) {
91
- updateMonth(undefined);
92
- return;
93
- }
94
98
  const isBefore = fromDate &&
99
+ month &&
95
100
  (fromDate.getFullYear() > month.getFullYear() ||
96
101
  (fromDate.getFullYear() === month.getFullYear() &&
97
102
  fromDate.getMonth() > month.getMonth()));
98
103
  const isAfter = toDate &&
104
+ month &&
99
105
  (toDate.getFullYear() < month.getFullYear() ||
100
106
  (toDate.getFullYear() === month.getFullYear() &&
101
107
  toDate.getMonth() < month.getMonth()));
108
+ if (!(0, utils_1.isValidDate)(month) || (disabled && (0, utils_1.isMatch)(month, disabled))) {
109
+ updateMonth(undefined);
110
+ updateValidation({
111
+ isInvalid: (0, utils_1.isValidDate)(month),
112
+ isDisabled: disabled && (0, utils_1.isMatch)(month, disabled),
113
+ isValidMonth: false,
114
+ isEmpty: !e.target.value,
115
+ isBefore: isBefore !== null && isBefore !== void 0 ? isBefore : false,
116
+ isAfter: isAfter !== null && isAfter !== void 0 ? isAfter : false,
117
+ });
118
+ return;
119
+ }
102
120
  if (isAfter ||
103
121
  isBefore ||
104
122
  (fromDate && toDate && !(0, utils_1.isMatch)(month, [{ from: fromDate, to: toDate }]))) {
105
123
  updateMonth(undefined);
124
+ updateValidation({
125
+ isValidMonth: false,
126
+ isBefore: isBefore !== null && isBefore !== void 0 ? isBefore : false,
127
+ isAfter: isAfter !== null && isAfter !== void 0 ? isAfter : false,
128
+ });
106
129
  return;
107
130
  }
108
131
  updateMonth(month);
132
+ updateValidation();
109
133
  setYear(month);
110
134
  };
111
135
  const handleClose = (0, react_1.useCallback)(() => {