@artemy-tech/datepicker 0.6.1 → 0.7.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/dist/index.cjs CHANGED
@@ -117,34 +117,137 @@ function Spinner() {
117
117
 
118
118
  // src/utils/date-mask.ts
119
119
  var import_date_fns = require("date-fns");
120
- var DATE_FORMAT = "dd.MM.yyyy";
121
- function resolveTimeFormat(showTime) {
122
- if (!showTime) return null;
123
- if (showTime === true) return "HH:mm:ss";
124
- return showTime.format;
120
+
121
+ // src/utils/format-schema.ts
122
+ var DATE_TOKENS = ["yyyy", "dd", "MM"];
123
+ var TIME_TOKENS = ["HH", "mm", "ss"];
124
+ var ALL_TOKENS = [...DATE_TOKENS, ...TIME_TOKENS];
125
+ var TOKEN_LENGTH = {
126
+ yyyy: 4,
127
+ dd: 2,
128
+ MM: 2,
129
+ HH: 2,
130
+ mm: 2,
131
+ ss: 2
132
+ };
133
+ var RU_TOKEN_PLACEHOLDER = {
134
+ yyyy: "\u0433\u0433\u0433\u0433",
135
+ dd: "\u0434\u0434",
136
+ MM: "\u043C\u043C",
137
+ HH: "\u0447\u0447",
138
+ mm: "\u043C\u043C",
139
+ ss: "\u0441\u0441"
140
+ };
141
+ var EN_TOKEN_PLACEHOLDER = {
142
+ yyyy: "yyyy",
143
+ dd: "dd",
144
+ MM: "mm",
145
+ HH: "hh",
146
+ mm: "mm",
147
+ ss: "ss"
148
+ };
149
+ function tokenize(format4, allowTime) {
150
+ const parts = [];
151
+ let i = 0;
152
+ while (i < format4.length) {
153
+ let matched = null;
154
+ for (const token of ALL_TOKENS) {
155
+ if (format4.startsWith(token, i)) {
156
+ matched = token;
157
+ break;
158
+ }
159
+ }
160
+ if (matched) {
161
+ if (!allowTime && TIME_TOKENS.includes(matched)) {
162
+ throw new Error(
163
+ `dateFormat must not contain time tokens (got "${matched}"). Use the "showTime" prop instead.`
164
+ );
165
+ }
166
+ parts.push({ kind: "token", token: matched });
167
+ i += matched.length;
168
+ continue;
169
+ }
170
+ parts.push({ kind: "sep", char: format4[i] });
171
+ i++;
172
+ }
173
+ return parts;
174
+ }
175
+ function validateDateParts(parts) {
176
+ var _a, _b;
177
+ const counts = {};
178
+ for (const p of parts) {
179
+ if (p.kind === "token") counts[p.token] = ((_a = counts[p.token]) != null ? _a : 0) + 1;
180
+ }
181
+ for (const token of DATE_TOKENS) {
182
+ if (counts[token] !== 1) {
183
+ throw new Error(
184
+ `dateFormat must contain "${token}" exactly once. Supported tokens: dd, MM, yyyy. Got: ${(_b = counts[token]) != null ? _b : 0}`
185
+ );
186
+ }
187
+ }
125
188
  }
126
- function buildDateFormat(timeFormat) {
127
- return timeFormat ? `${DATE_FORMAT} ${timeFormat}` : DATE_FORMAT;
189
+ function buildSchemaFromParts(parts, isRu) {
190
+ const placeholderMap = isRu ? RU_TOKEN_PLACEHOLDER : EN_TOKEN_PLACEHOLDER;
191
+ const separators = [];
192
+ let digitCount = 0;
193
+ let format4 = "";
194
+ let placeholder = "";
195
+ let pendingSep = "";
196
+ for (const part of parts) {
197
+ if (part.kind === "sep") {
198
+ pendingSep += part.char;
199
+ format4 += part.char;
200
+ placeholder += part.char;
201
+ continue;
202
+ }
203
+ if (pendingSep) {
204
+ separators.push({ afterDigit: digitCount, chars: pendingSep });
205
+ pendingSep = "";
206
+ }
207
+ digitCount += TOKEN_LENGTH[part.token];
208
+ format4 += part.token;
209
+ placeholder += placeholderMap[part.token];
210
+ }
211
+ return { format: format4, digitCount, separators, placeholder };
128
212
  }
129
- function buildMaxDigits(timeFormat) {
130
- if (!timeFormat) return 8;
131
- return timeFormat === "HH:mm" ? 12 : 14;
213
+ function isRuLocale(locale) {
214
+ if (!locale) return true;
215
+ return locale.code === "ru";
132
216
  }
133
- function buildPlaceholder(timeFormat) {
134
- if (!timeFormat) return "\u0434\u0434.\u043C\u043C.\u0433\u0433\u0433\u0433";
135
- return timeFormat === "HH:mm" ? "\u0434\u0434.\u043C\u043C.\u0433\u0433\u0433\u0433 \u0447\u0447:\u043C\u043C" : "\u0434\u0434.\u043C\u043C.\u0433\u0433\u0433\u0433 \u0447\u0447:\u043C\u043C:\u0441\u0441";
217
+ function buildFormatSchema(dateFormat, timeFormat, locale) {
218
+ const dateParts = tokenize(dateFormat, false);
219
+ validateDateParts(dateParts);
220
+ const parts = [...dateParts];
221
+ if (timeFormat) {
222
+ parts.push({ kind: "sep", char: " " });
223
+ parts.push(...tokenize(timeFormat, true));
224
+ }
225
+ return buildSchemaFromParts(parts, isRuLocale(locale));
136
226
  }
137
- function applyMask(digits, maxDigits) {
138
- const d = digits.slice(0, maxDigits);
227
+ function applySchemaMask(digits, schema) {
228
+ const d = digits.slice(0, schema.digitCount);
139
229
  let result = "";
230
+ let sepIdx = 0;
140
231
  for (let i = 0; i < d.length; i++) {
141
- if (i === 2 || i === 4) result += ".";
142
- else if (i === 8) result += " ";
143
- else if (i === 10 || i === 12) result += ":";
232
+ while (sepIdx < schema.separators.length && schema.separators[sepIdx].afterDigit === i) {
233
+ result += schema.separators[sepIdx].chars;
234
+ sepIdx++;
235
+ }
144
236
  result += d[i];
145
237
  }
146
238
  return result;
147
239
  }
240
+
241
+ // src/utils/date-mask.ts
242
+ var DEFAULT_DATE_FORMAT = "dd.MM.yyyy";
243
+ function resolveTimeFormat(showTime) {
244
+ if (!showTime) return null;
245
+ if (showTime === true) return "HH:mm:ss";
246
+ return showTime.format;
247
+ }
248
+ function applyMask(digits, schema) {
249
+ return applySchemaMask(digits, schema);
250
+ }
148
251
  function getCursorPos(masked, digitCount) {
149
252
  if (digitCount === 0) return 0;
150
253
  let count = 0;
@@ -159,11 +262,11 @@ function getCursorPos(masked, digitCount) {
159
262
  function toDateOnly(date) {
160
263
  return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 12, 0, 0);
161
264
  }
162
- function parseDateTime(masked, dateFormat, maxDigits) {
163
- if (masked.replace(/\D/g, "").length !== maxDigits) return void 0;
164
- const date = (0, import_date_fns.parse)(masked, dateFormat, /* @__PURE__ */ new Date());
165
- if (!(0, import_date_fns.isValid)(date) || (0, import_date_fns.format)(date, dateFormat) !== masked) return void 0;
166
- return maxDigits === 8 ? toDateOnly(date) : date;
265
+ function parseDateTime(masked, schema) {
266
+ if (masked.replace(/\D/g, "").length !== schema.digitCount) return void 0;
267
+ const date = (0, import_date_fns.parse)(masked, schema.format, /* @__PURE__ */ new Date());
268
+ if (!(0, import_date_fns.isValid)(date) || (0, import_date_fns.format)(date, schema.format) !== masked) return void 0;
269
+ return schema.digitCount === 8 ? toDateOnly(date) : date;
167
270
  }
168
271
 
169
272
  // src/components/DatePicker/DatePicker.tsx
@@ -186,12 +289,18 @@ function DatePicker({
186
289
  iconPosition = "end",
187
290
  className,
188
291
  renderInput,
189
- customTrigger
292
+ customTrigger,
293
+ locale = import_locale.ru,
294
+ dateFormat: dateFormatProp = DEFAULT_DATE_FORMAT
190
295
  }) {
191
296
  const timeFormat = resolveTimeFormat(showTime);
192
- const dateFormat = buildDateFormat(timeFormat);
193
- const maxDigits = buildMaxDigits(timeFormat);
194
- const defaultPlaceholder = placeholder != null ? placeholder : buildPlaceholder(timeFormat);
297
+ const schema = (0, import_react3.useMemo)(
298
+ () => buildFormatSchema(dateFormatProp, timeFormat, locale),
299
+ [dateFormatProp, timeFormat, locale]
300
+ );
301
+ const dateFormat = schema.format;
302
+ const maxDigits = schema.digitCount;
303
+ const defaultPlaceholder = placeholder != null ? placeholder : schema.placeholder;
195
304
  const showSeconds = timeFormat === "HH:mm:ss";
196
305
  const fromDay = fromDate ? (0, import_date_fns2.startOfDay)(fromDate) : void 0;
197
306
  const toDay = toDate ? (0, import_date_fns2.startOfDay)(toDate) : void 0;
@@ -255,7 +364,7 @@ function DatePicker({
255
364
  if (!isControlled) setInternalDate(void 0);
256
365
  onChange == null ? void 0 : onChange(void 0);
257
366
  } else if (digits.length === maxDigits) {
258
- const date = parseDateTime(masked, dateFormat, maxDigits);
367
+ const date = parseDateTime(masked, schema);
259
368
  lastEmittedRef.current = date;
260
369
  if (date) lastValidRef.current = masked;
261
370
  setInputInvalid(!date);
@@ -279,7 +388,7 @@ function DatePicker({
279
388
  const cursorPos = (_a = input.selectionStart) != null ? _a : 0;
280
389
  const raw = input.value;
281
390
  const digits = raw.replace(/\D/g, "").slice(0, maxDigits);
282
- const masked = applyMask(digits, maxDigits);
391
+ const masked = applyMask(digits, schema);
283
392
  const digitsBeforeCursor = raw.slice(0, cursorPos).replace(/\D/g, "").length;
284
393
  const newCursorPos = getCursorPos(masked, digitsBeforeCursor);
285
394
  setInputValue(masked);
@@ -297,10 +406,14 @@ function DatePicker({
297
406
  e.preventDefault();
298
407
  return;
299
408
  }
300
- if (e.key === "Backspace" && pos > 0 && /[.: ]/.test(input.value[pos - 1])) {
409
+ const separatorChars = /* @__PURE__ */ new Set();
410
+ schema.separators.forEach((s) => {
411
+ for (const ch of s.chars) separatorChars.add(ch);
412
+ });
413
+ if (e.key === "Backspace" && pos > 0 && separatorChars.has(input.value[pos - 1])) {
301
414
  e.preventDefault();
302
415
  const val = input.value;
303
- const masked = applyMask((val.slice(0, pos - 2) + val.slice(pos)).replace(/\D/g, ""), maxDigits);
416
+ const masked = applyMask((val.slice(0, pos - 2) + val.slice(pos)).replace(/\D/g, ""), schema);
304
417
  setInputValue(masked);
305
418
  commit(masked);
306
419
  requestAnimationFrame(() => input.setSelectionRange(pos - 2, pos - 2));
@@ -308,7 +421,7 @@ function DatePicker({
308
421
  }
309
422
  function handlePaste(e) {
310
423
  e.preventDefault();
311
- const masked = applyMask(e.clipboardData.getData("text").replace(/\D/g, ""), maxDigits);
424
+ const masked = applyMask(e.clipboardData.getData("text").replace(/\D/g, ""), schema);
312
425
  setInputValue(masked);
313
426
  commit(masked);
314
427
  requestAnimationFrame(() => {
@@ -422,7 +535,7 @@ function DatePicker({
422
535
  endMonth: toDay,
423
536
  disabled: disabledDays.length ? disabledDays : void 0,
424
537
  navLayout: "around",
425
- locale: import_locale.ru
538
+ locale
426
539
  }
427
540
  ) }),
428
541
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "datepicker__time-separator" }),
@@ -456,7 +569,7 @@ function DatePicker({
456
569
  endMonth: toDay,
457
570
  disabled: disabledDays.length ? disabledDays : void 0,
458
571
  navLayout: "around",
459
- locale: import_locale.ru
572
+ locale
460
573
  }
461
574
  )
462
575
  }
@@ -473,22 +586,16 @@ var import_locale2 = require("date-fns/locale");
473
586
 
474
587
  // src/utils/range-mask.ts
475
588
  var import_date_fns3 = require("date-fns");
476
- var DATE_FORMAT2 = "dd.MM.yyyy";
477
- function applyDateMask(digits) {
478
- const d = digits.slice(0, 8);
479
- let result = "";
480
- for (let i = 0; i < d.length; i++) {
481
- if (i === 2 || i === 4) result += ".";
482
- result += d[i];
483
- }
484
- return result;
589
+ function applyDateMask(digits, schema) {
590
+ return applySchemaMask(digits, schema);
485
591
  }
486
- function applyRangeMask(digits) {
487
- const all = digits.slice(0, 16);
488
- const fromMasked = applyDateMask(all.slice(0, 8));
489
- const toDigits = all.slice(8);
592
+ function applyRangeMask(digits, schema) {
593
+ const total = schema.digitCount * 2;
594
+ const all = digits.slice(0, total);
595
+ const fromMasked = applyDateMask(all.slice(0, schema.digitCount), schema);
596
+ const toDigits = all.slice(schema.digitCount);
490
597
  if (toDigits.length === 0) return fromMasked;
491
- return `${fromMasked} \u2014 ${applyDateMask(toDigits)}`;
598
+ return `${fromMasked} \u2014 ${applyDateMask(toDigits, schema)}`;
492
599
  }
493
600
  function getRangeCursorPos(masked, digitCount) {
494
601
  if (digitCount === 0) return 0;
@@ -504,17 +611,17 @@ function getRangeCursorPos(masked, digitCount) {
504
611
  function toDateOnly2(date) {
505
612
  return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 12, 0, 0);
506
613
  }
507
- function parseDate(masked) {
508
- if (masked.replace(/\D/g, "").length !== 8) return void 0;
509
- const date = (0, import_date_fns3.parse)(masked, DATE_FORMAT2, /* @__PURE__ */ new Date());
510
- if (!(0, import_date_fns3.isValid)(date) || (0, import_date_fns3.format)(date, DATE_FORMAT2) !== masked) return void 0;
614
+ function parseDate(masked, schema) {
615
+ if (masked.replace(/\D/g, "").length !== schema.digitCount) return void 0;
616
+ const date = (0, import_date_fns3.parse)(masked, schema.format, /* @__PURE__ */ new Date());
617
+ if (!(0, import_date_fns3.isValid)(date) || (0, import_date_fns3.format)(date, schema.format) !== masked) return void 0;
511
618
  return toDateOnly2(date);
512
619
  }
513
- function formatRange(from, to) {
620
+ function formatRange(from, to, schema) {
514
621
  if (!from) return "";
515
- const fromStr = (0, import_date_fns3.format)(from, DATE_FORMAT2);
622
+ const fromStr = (0, import_date_fns3.format)(from, schema.format);
516
623
  if (!to) return fromStr;
517
- return `${fromStr} \u2014 ${(0, import_date_fns3.format)(to, DATE_FORMAT2)}`;
624
+ return `${fromStr} \u2014 ${(0, import_date_fns3.format)(to, schema.format)}`;
518
625
  }
519
626
  function resolveShowSeconds(showTime) {
520
627
  if (!showTime) return false;
@@ -539,8 +646,16 @@ function DateRangePicker({
539
646
  showTime,
540
647
  icon,
541
648
  iconPosition = "end",
542
- className
649
+ className,
650
+ locale = import_locale2.ru,
651
+ dateFormat: dateFormatProp = DEFAULT_DATE_FORMAT
543
652
  }) {
653
+ const schema = (0, import_react4.useMemo)(
654
+ () => buildFormatSchema(dateFormatProp, null, locale),
655
+ [dateFormatProp, locale]
656
+ );
657
+ const maxDigits = schema.digitCount;
658
+ const totalDigits = maxDigits * 2;
544
659
  const resolvedIcon = loading ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Spinner, {}) : icon === false ? null : icon != null ? icon : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CalendarIcon, {});
545
660
  const isControlled = value !== void 0;
546
661
  const showSeconds = resolveShowSeconds(showTime);
@@ -558,7 +673,7 @@ function DateRangePicker({
558
673
  );
559
674
  const [inputValue, setInputValue] = (0, import_react4.useState)(() => {
560
675
  const initial = value != null ? value : defaultValue;
561
- return formatRange(initial == null ? void 0 : initial.from, initial == null ? void 0 : initial.to);
676
+ return formatRange(initial == null ? void 0 : initial.from, initial == null ? void 0 : initial.to, schema);
562
677
  });
563
678
  const [inputInvalid, setInputInvalid] = (0, import_react4.useState)(false);
564
679
  const [open, setOpen] = (0, import_react4.useState)(false);
@@ -602,7 +717,7 @@ function DateRangePicker({
602
717
  const lastToTime = (_f = (_e = lastEmittedToRef.current) == null ? void 0 : _e.getTime()) != null ? _f : null;
603
718
  if (fromTime === lastFromTime && toTime === lastToTime) return;
604
719
  if (!wasControlledRef.current && value === void 0) return;
605
- setInputValue(formatRange(newFrom, newTo));
720
+ setInputValue(formatRange(newFrom, newTo, schema));
606
721
  setInputInvalid(false);
607
722
  if (!isControlled) {
608
723
  setInternalFrom(newFrom);
@@ -630,7 +745,7 @@ function DateRangePicker({
630
745
  setInternalFrom(from);
631
746
  setInternalTo(void 0);
632
747
  }
633
- setInputValue(formatRange(from, void 0));
748
+ setInputValue(formatRange(from, void 0, schema));
634
749
  setInputInvalid(false);
635
750
  lastEmittedFromRef.current = from;
636
751
  lastEmittedToRef.current = void 0;
@@ -653,7 +768,7 @@ function DateRangePicker({
653
768
  setInternalFrom(from);
654
769
  setInternalTo(to);
655
770
  }
656
- setInputValue(formatRange(from, to));
771
+ setInputValue(formatRange(from, to, schema));
657
772
  setInputInvalid(false);
658
773
  lastEmittedFromRef.current = from;
659
774
  lastEmittedToRef.current = to;
@@ -698,18 +813,18 @@ function DateRangePicker({
698
813
  const input = e.target;
699
814
  const cursorPos = (_a = input.selectionStart) != null ? _a : 0;
700
815
  const raw = input.value;
701
- const digits = raw.replace(/\D/g, "").slice(0, 16);
702
- const masked = applyRangeMask(digits);
816
+ const digits = raw.replace(/\D/g, "").slice(0, totalDigits);
817
+ const masked = applyRangeMask(digits, schema);
703
818
  const digitsBeforeCursor = raw.slice(0, cursorPos).replace(/\D/g, "").length;
704
819
  setInputValue(masked);
705
820
  setAnchorDate(void 0);
706
821
  setHoveredDate(void 0);
707
- const fromDigits = digits.slice(0, 8);
708
- const toDigits = digits.slice(8);
709
- const parsedFrom = fromDigits.length === 8 ? parseDate(applyDateMask(fromDigits)) : void 0;
710
- const parsedTo = toDigits.length === 8 ? parseDate(applyDateMask(toDigits)) : void 0;
711
- const fromComplete = fromDigits.length === 8;
712
- const toComplete = toDigits.length === 8;
822
+ const fromDigits = digits.slice(0, maxDigits);
823
+ const toDigits = digits.slice(maxDigits);
824
+ const parsedFrom = fromDigits.length === maxDigits ? parseDate(applyDateMask(fromDigits, schema), schema) : void 0;
825
+ const parsedTo = toDigits.length === maxDigits ? parseDate(applyDateMask(toDigits, schema), schema) : void 0;
826
+ const fromComplete = fromDigits.length === maxDigits;
827
+ const toComplete = toDigits.length === maxDigits;
713
828
  setInputInvalid(fromComplete && !parsedFrom || toComplete && !parsedTo);
714
829
  if (!isControlled) {
715
830
  setInternalFrom(parsedFrom);
@@ -738,13 +853,18 @@ function DateRangePicker({
738
853
  e.preventDefault();
739
854
  return;
740
855
  }
741
- if (e.key === "Backspace" && pos > 0 && /[\s—]/.test(input.value[pos - 1])) {
856
+ const separatorChars = /* @__PURE__ */ new Set([" ", "\u2014"]);
857
+ schema.separators.forEach((s) => {
858
+ for (const ch of s.chars) separatorChars.add(ch);
859
+ });
860
+ if (e.key === "Backspace" && pos > 0 && separatorChars.has(input.value[pos - 1])) {
742
861
  e.preventDefault();
743
862
  const val = input.value;
744
863
  const charsToSkip = (_c = (_b = val.slice(0, pos).match(/[\s—]+$/)) == null ? void 0 : _b[0].length) != null ? _c : 1;
745
864
  const newPos = pos - charsToSkip;
746
865
  const masked = applyRangeMask(
747
- (val.slice(0, newPos - 1) + val.slice(newPos)).replace(/\D/g, "")
866
+ (val.slice(0, newPos - 1) + val.slice(newPos)).replace(/\D/g, ""),
867
+ schema
748
868
  );
749
869
  setInputValue(masked);
750
870
  requestAnimationFrame(
@@ -755,15 +875,18 @@ function DateRangePicker({
755
875
  function handlePaste(e) {
756
876
  e.preventDefault();
757
877
  const text = e.clipboardData.getData("text");
758
- const digits = text.replace(/\D/g, "").slice(0, 16);
759
- const masked = applyRangeMask(digits);
878
+ const digits = text.replace(/\D/g, "").slice(0, totalDigits);
879
+ const masked = applyRangeMask(digits, schema);
760
880
  setInputValue(masked);
761
881
  setAnchorDate(void 0);
762
882
  setHoveredDate(void 0);
763
- const parsedFrom = digits.length >= 8 ? parseDate(applyDateMask(digits.slice(0, 8))) : void 0;
764
- const parsedTo = digits.length >= 16 ? parseDate(applyDateMask(digits.slice(8, 16))) : void 0;
883
+ const parsedFrom = digits.length >= maxDigits ? parseDate(applyDateMask(digits.slice(0, maxDigits), schema), schema) : void 0;
884
+ const parsedTo = digits.length >= totalDigits ? parseDate(
885
+ applyDateMask(digits.slice(maxDigits, totalDigits), schema),
886
+ schema
887
+ ) : void 0;
765
888
  setInputInvalid(
766
- digits.length >= 8 && !parsedFrom || digits.length >= 16 && !parsedTo
889
+ digits.length >= maxDigits && !parsedFrom || digits.length >= totalDigits && !parsedTo
767
890
  );
768
891
  if (!isControlled) {
769
892
  setInternalFrom(parsedFrom);
@@ -781,7 +904,7 @@ function DateRangePicker({
781
904
  }
782
905
  );
783
906
  }
784
- const placeholder = label && !focused && !filled ? void 0 : "\u0434\u0434.\u043C\u043C.\u0433\u0433\u0433\u0433 \u2014 \u0434\u0434.\u043C\u043C.\u0433\u0433\u0433\u0433";
907
+ const placeholder = label && !focused && !filled ? void 0 : `${schema.placeholder} \u2014 ${schema.placeholder}`;
785
908
  const interactive = !disabled && !loading;
786
909
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
787
910
  "div",
@@ -867,7 +990,7 @@ function DateRangePicker({
867
990
  endMonth: toDay,
868
991
  disabled: disabledDays.length ? disabledDays : void 0,
869
992
  numberOfMonths: 2,
870
- locale: import_locale2.ru
993
+ locale
871
994
  }
872
995
  ) }) }),
873
996
  /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "datepicker__time-row", children: [
@@ -919,7 +1042,7 @@ function DateRangePicker({
919
1042
  startMonth: fromConstraint,
920
1043
  endMonth: toConstraint,
921
1044
  numberOfMonths: 2,
922
- locale: import_locale2.ru
1045
+ locale
923
1046
  }
924
1047
  )
925
1048
  }