@gympass/yoga 7.129.2 → 7.130.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.
@@ -98,7 +98,8 @@ function ActionRequirement(props) {
98
98
  checkable,
99
99
  illustration,
100
100
  list,
101
- titleAsTextDisplay = false
101
+ titleAsTextDisplay = false,
102
+ ariaLevelTitle = 1
102
103
  } = props;
103
104
  let primaryButton;
104
105
  let secondaryButton;
@@ -114,7 +115,7 @@ function ActionRequirement(props) {
114
115
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(StyledActionRequirement, __spreadProps(__spreadValues({}, props), { children: [
115
116
  illustration && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BoxIllustration, { "aria-hidden": true, children: illustration }),
116
117
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Content, { children: [
117
- titleAsTextDisplay ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Text.default.Display2, { as: "h1", children: title }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ActionRequirementStyles.Title, { children: title }),
118
+ titleAsTextDisplay ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Text.default.Display2, { as: "h1", "aria-level": ariaLevelTitle, children: title }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ActionRequirementStyles.Title, { "aria-level": ariaLevelTitle, children: title }),
118
119
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Text.default.Body1, { mt: "small", color: "deep", children: description }),
119
120
  list && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Box.default, { mt: "large", children: list }),
120
121
  checkable && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Box.default, { mt: "xxlarge", children: checkable }),
@@ -132,6 +133,7 @@ ActionRequirement.propTypes = {
132
133
  checkable: (0, import_prop_types.oneOfType)([(0, import_prop_types.arrayOf)(import_prop_types.node), import_prop_types.node]),
133
134
  illustration: (0, import_prop_types.oneOfType)([(0, import_prop_types.arrayOf)(import_prop_types.node), import_prop_types.node]),
134
135
  list: (0, import_prop_types.oneOfType)([(0, import_prop_types.arrayOf)(import_prop_types.node), import_prop_types.node]),
135
- titleAsTextDisplay: import_prop_types.bool
136
+ titleAsTextDisplay: import_prop_types.bool,
137
+ ariaLevelTitle: import_prop_types.number
136
138
  };
137
139
  var ActionRequirement_default = ActionRequirement;
@@ -76,4 +76,18 @@ describe("<ActionRequirement />", () => {
76
76
  );
77
77
  expect(container).toMatchSnapshot();
78
78
  });
79
+ it("should match snapshot with aria-level 2", () => {
80
+ const { container } = (0, import_react2.render)(
81
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import__.ThemeProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
82
+ import_ActionRequirement.default,
83
+ {
84
+ title: "title",
85
+ description: "description",
86
+ titleAsTextDisplay: true,
87
+ ariaLevelTitle: 2
88
+ }
89
+ ) })
90
+ );
91
+ expect(container).toMatchSnapshot();
92
+ });
79
93
  });
@@ -77,6 +77,9 @@ const Month = (0, import_styled_components.default)(import__.Text.Body2)`
77
77
  }) => `
78
78
  color: ${v3theme ? colors.primary : colors.text.primary};
79
79
  align-self: center;
80
+ &:first-letter {
81
+ text-transform: capitalize;
82
+ };
80
83
  `}
81
84
  `;
82
85
  const getDayFieldColor = (selected, disabled, colors, aux) => {
@@ -191,7 +194,8 @@ function Calendar({
191
194
  disablePastDates = false,
192
195
  disableFutureDates = false,
193
196
  disablePastFrom,
194
- disableFutureFrom
197
+ disableFutureFrom,
198
+ locale
195
199
  }) {
196
200
  const [month, setMonth] = (0, import_react.useState)((/* @__PURE__ */ new Date()).getUTCMonth());
197
201
  const [year, setYear] = (0, import_react.useState)((/* @__PURE__ */ new Date()).getUTCFullYear());
@@ -318,6 +322,16 @@ function Calendar({
318
322
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Row, { children: getLastWeek() })
319
323
  ] });
320
324
  };
325
+ const getLocale = () => {
326
+ return Intl.DateTimeFormat.supportedLocalesOf(locale).length > 0 ? locale : "en-US";
327
+ };
328
+ const weekDays = Array.from(
329
+ { length: 7 },
330
+ (__, i) => new Intl.DateTimeFormat(getLocale(), {
331
+ weekday: "short",
332
+ timeZone: "UTC"
333
+ }).format(new Date(Date.UTC(2024, 0, 7 + i)))
334
+ );
321
335
  const prior = () => {
322
336
  let local = month - 1;
323
337
  if (local < 0) {
@@ -356,7 +370,7 @@ function Calendar({
356
370
  "data-testid": "previous-month-arrow"
357
371
  }
358
372
  ),
359
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Month, { bold: true, children: new Intl.DateTimeFormat("en-US", {
373
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Month, { bold: true, children: new Intl.DateTimeFormat(getLocale(), {
360
374
  month: "long",
361
375
  year: "numeric"
362
376
  }).format(new Date(year, month, 1, 0, 0, 0)) }),
@@ -375,15 +389,7 @@ function Calendar({
375
389
  ]
376
390
  }
377
391
  ),
378
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DaysWrapper, { children: [
379
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Day, { children: "S" }),
380
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Day, { children: "M" }),
381
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Day, { children: "T" }),
382
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Day, { children: "W" }),
383
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Day, { children: "T" }),
384
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Day, { children: "F" }),
385
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Day, { children: "S" })
386
- ] }),
392
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DaysWrapper, { children: weekDays.map((weekDay) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Day, { children: weekDay.toLocaleUpperCase().charAt(0) }, `${weekDay}`)) }),
387
393
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import__.Box, { children: getDays() })
388
394
  ] });
389
395
  }
@@ -396,6 +402,7 @@ Calendar.propTypes = {
396
402
  disablePastDates: import_prop_types.bool,
397
403
  disableFutureDates: import_prop_types.bool,
398
404
  disablePastFrom: (0, import_prop_types.instanceOf)(Date),
399
- disableFutureFrom: (0, import_prop_types.instanceOf)(Date)
405
+ disableFutureFrom: (0, import_prop_types.instanceOf)(Date),
406
+ locale: import_prop_types.string
400
407
  };
401
408
  var Calendar_default = Calendar;
@@ -66,7 +66,6 @@ var import_react = __toESM(require("react"));
66
66
  var import_yoga_icons = require("@gympass/yoga-icons");
67
67
  var import_styled_components = __toESM(require("styled-components"));
68
68
  var import_prop_types = require("prop-types");
69
- var import_date_fns = require("date-fns");
70
69
  var import__ = require("../..");
71
70
  var import_Theme = require("../../Theme");
72
71
  var import_Calendar = __toESM(require("./Calendar"));
@@ -230,7 +229,8 @@ function Datepicker(_c) {
230
229
  disableFutureFrom,
231
230
  error,
232
231
  onOpen,
233
- displayEndDateOnly = false
232
+ displayEndDateOnly = false,
233
+ locale
234
234
  } = _d, props = __objRest(_d, [
235
235
  "fullWidth",
236
236
  "type",
@@ -247,7 +247,8 @@ function Datepicker(_c) {
247
247
  "disableFutureFrom",
248
248
  "error",
249
249
  "onOpen",
250
- "displayEndDateOnly"
250
+ "displayEndDateOnly",
251
+ "locale"
251
252
  ]);
252
253
  const [open, setOpen] = (0, import_react.useState)();
253
254
  const [startDateLocal, setStartDateLocal] = (0, import_react.useState)(startDate);
@@ -318,12 +319,21 @@ function Datepicker(_c) {
318
319
  if (!start && !end || displayEndDateOnly && !end) {
319
320
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InputPlaceholder, { disabled, children: placeholder != null ? placeholder : `Select Date` });
320
321
  }
321
- const dateFormat = "MMM d, yyyy";
322
+ const formattedDate = (date) => {
323
+ let month = new Intl.DateTimeFormat(locale, {
324
+ month: "short",
325
+ timeZone: "UTC"
326
+ }).format(date);
327
+ month = month.charAt(0).toUpperCase() + month.slice(1, 3);
328
+ const day = date.getUTCDate();
329
+ const year = date.getUTCFullYear();
330
+ return `${month} ${day}, ${year}`;
331
+ };
322
332
  if (displayEndDateOnly)
323
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Input, { disabled, children: end && (0, import_date_fns.format)(toUTC(end), dateFormat) });
333
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Input, { disabled, children: end && formattedDate(end) });
324
334
  return start && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Input, { disabled, children: [
325
- (0, import_date_fns.format)(toUTC(start), dateFormat),
326
- end && ` - ${(0, import_date_fns.format)(toUTC(end), dateFormat)}`
335
+ formattedDate(start),
336
+ end && ` - ${formattedDate(end)}`
327
337
  ] });
328
338
  };
329
339
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrapper, __spreadProps(__spreadValues({ fullWidth, tabIndex: "0" }, props), { children: [
@@ -366,7 +376,8 @@ function Datepicker(_c) {
366
376
  disablePastDates,
367
377
  disableFutureDates,
368
378
  disablePastFrom,
369
- disableFutureFrom
379
+ disableFutureFrom,
380
+ locale
370
381
  }
371
382
  ) })
372
383
  ] }));
@@ -387,7 +398,8 @@ Datepicker.propTypes = {
387
398
  disableFutureFrom: (0, import_prop_types.instanceOf)(Date),
388
399
  error: import_prop_types.string,
389
400
  onOpen: import_prop_types.func,
390
- displayEndDateOnly: import_prop_types.bool
401
+ displayEndDateOnly: import_prop_types.bool,
402
+ locale: import_prop_types.string
391
403
  };
392
404
  var Datepicker_default = Datepicker;
393
405
  // Annotate the CommonJS export names for ESM import in node:
@@ -29,6 +29,10 @@ var import__ = require("../..");
29
29
  var import_Datepicker = require("./Datepicker");
30
30
  describe("<Datepicker />", () => {
31
31
  const testDate = new Date(2022, 7, 3, 14, 0, 0);
32
+ let originalDateTimeFormat;
33
+ beforeAll(() => {
34
+ originalDateTimeFormat = Intl.DateTimeFormat;
35
+ });
32
36
  describe("Snapshots", () => {
33
37
  it("should match snapshot when v3Theme is settled", () => {
34
38
  const { container } = (0, import_react2.render)(
@@ -249,4 +253,67 @@ describe("<Datepicker />", () => {
249
253
  expect(import_react2.screen.getByText("This is an error")).toBeVisible();
250
254
  });
251
255
  });
256
+ describe("Internationalization", () => {
257
+ let originalNavigator;
258
+ beforeEach(() => {
259
+ originalNavigator = global.navigator;
260
+ });
261
+ afterEach(() => {
262
+ global.Intl.DateTimeFormat = originalDateTimeFormat;
263
+ Object.defineProperty(global, "navigator", {
264
+ value: originalNavigator,
265
+ writable: true
266
+ });
267
+ });
268
+ it("should display calendar in English when locale is not supported", () => {
269
+ (0, import_react2.render)(
270
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import__.ThemeProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import__.Datepicker, { type: "single", locale: "xx-XX" }) })
271
+ );
272
+ import_react2.fireEvent.click(import_react2.screen.getByRole("button"));
273
+ const currentDate = /* @__PURE__ */ new Date();
274
+ const currentMonth = new Intl.DateTimeFormat("en-US", {
275
+ month: "long"
276
+ }).format(currentDate);
277
+ expect(
278
+ import_react2.screen.getByText(new RegExp(currentMonth, "i"))
279
+ ).toBeInTheDocument();
280
+ });
281
+ it("should display calendar in Portuguese when browser locale is pt-BR", () => {
282
+ (0, import_react2.render)(
283
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import__.ThemeProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import__.Datepicker, { type: "single", locale: "pt-BR" }) })
284
+ );
285
+ import_react2.fireEvent.click(import_react2.screen.getByRole("button"));
286
+ const currentDate = /* @__PURE__ */ new Date();
287
+ const months = [
288
+ "janeiro",
289
+ "fevereiro",
290
+ "mar\xE7o",
291
+ "abril",
292
+ "maio",
293
+ "junho",
294
+ "julho",
295
+ "agosto",
296
+ "setembro",
297
+ "outubro",
298
+ "novembro",
299
+ "dezembro"
300
+ ];
301
+ const currentMonth = months[currentDate.getMonth()];
302
+ expect(
303
+ import_react2.screen.getByText(new RegExp(currentMonth, "i"))
304
+ ).toBeInTheDocument();
305
+ });
306
+ it("should display only the first letter of each weekday in uppercase", () => {
307
+ (0, import_react2.render)(
308
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import__.ThemeProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import__.Datepicker, { type: "single" }) })
309
+ );
310
+ import_react2.fireEvent.click(import_react2.screen.getByRole("button"));
311
+ const weekdayLetters = ["S", "M", "T", "W", "T", "F", "S"];
312
+ weekdayLetters.forEach((letter) => {
313
+ expect(import_react2.screen.getAllByText(letter).length).toBeGreaterThan(0);
314
+ });
315
+ expect(import_react2.screen.queryByText("sun")).not.toBeInTheDocument();
316
+ expect(import_react2.screen.queryByText("mon")).not.toBeInTheDocument();
317
+ });
318
+ });
252
319
  });
@@ -19,7 +19,7 @@ var __spreadValues = (a, b) => {
19
19
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
20
  import { jsx, jsxs } from "react/jsx-runtime";
21
21
  import React from "react";
22
- import { arrayOf, bool, node, oneOfType, string } from "prop-types";
22
+ import { arrayOf, bool, node, oneOfType, string, number } from "prop-types";
23
23
  import styled from "styled-components";
24
24
  import { media } from "@gympass/yoga-helpers";
25
25
  import {
@@ -72,7 +72,8 @@ function ActionRequirement(props) {
72
72
  checkable,
73
73
  illustration,
74
74
  list,
75
- titleAsTextDisplay = false
75
+ titleAsTextDisplay = false,
76
+ ariaLevelTitle = 1
76
77
  } = props;
77
78
  let primaryButton;
78
79
  let secondaryButton;
@@ -88,7 +89,7 @@ function ActionRequirement(props) {
88
89
  return /* @__PURE__ */ jsxs(StyledActionRequirement, __spreadProps(__spreadValues({}, props), { children: [
89
90
  illustration && /* @__PURE__ */ jsx(BoxIllustration, { "aria-hidden": true, children: illustration }),
90
91
  /* @__PURE__ */ jsxs(Content, { children: [
91
- titleAsTextDisplay ? /* @__PURE__ */ jsx(Text.Display2, { as: "h1", children: title }) : /* @__PURE__ */ jsx(Title, { children: title }),
92
+ titleAsTextDisplay ? /* @__PURE__ */ jsx(Text.Display2, { as: "h1", "aria-level": ariaLevelTitle, children: title }) : /* @__PURE__ */ jsx(Title, { "aria-level": ariaLevelTitle, children: title }),
92
93
  /* @__PURE__ */ jsx(Text.Body1, { mt: "small", color: "deep", children: description }),
93
94
  list && /* @__PURE__ */ jsx(Box, { mt: "large", children: list }),
94
95
  checkable && /* @__PURE__ */ jsx(Box, { mt: "xxlarge", children: checkable }),
@@ -106,7 +107,8 @@ ActionRequirement.propTypes = {
106
107
  checkable: oneOfType([arrayOf(node), node]),
107
108
  illustration: oneOfType([arrayOf(node), node]),
108
109
  list: oneOfType([arrayOf(node), node]),
109
- titleAsTextDisplay: bool
110
+ titleAsTextDisplay: bool,
111
+ ariaLevelTitle: number
110
112
  };
111
113
  var ActionRequirement_default = ActionRequirement;
112
114
  export {
@@ -53,4 +53,18 @@ describe("<ActionRequirement />", () => {
53
53
  );
54
54
  expect(container).toMatchSnapshot();
55
55
  });
56
+ it("should match snapshot with aria-level 2", () => {
57
+ const { container } = render(
58
+ /* @__PURE__ */ jsx(ThemeProvider, { children: /* @__PURE__ */ jsx(
59
+ ActionRequirement,
60
+ {
61
+ title: "title",
62
+ description: "description",
63
+ titleAsTextDisplay: true,
64
+ ariaLevelTitle: 2
65
+ }
66
+ ) })
67
+ );
68
+ expect(container).toMatchSnapshot();
69
+ });
56
70
  });
@@ -2,7 +2,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import React, { useEffect, useState } from "react";
3
3
  import styled from "styled-components";
4
4
  import { ChevronLeft, ChevronRight } from "@gympass/yoga-icons";
5
- import { oneOf, func, instanceOf, bool } from "prop-types";
5
+ import { oneOf, func, instanceOf, bool, string } from "prop-types";
6
6
  import _ from "lodash";
7
7
  import { Icon, Text, Box } from "../..";
8
8
  const CalendarWrapper = styled.div`
@@ -44,6 +44,9 @@ const Month = styled(Text.Body2)`
44
44
  }) => `
45
45
  color: ${v3theme ? colors.primary : colors.text.primary};
46
46
  align-self: center;
47
+ &:first-letter {
48
+ text-transform: capitalize;
49
+ };
47
50
  `}
48
51
  `;
49
52
  const getDayFieldColor = (selected, disabled, colors, aux) => {
@@ -158,7 +161,8 @@ function Calendar({
158
161
  disablePastDates = false,
159
162
  disableFutureDates = false,
160
163
  disablePastFrom,
161
- disableFutureFrom
164
+ disableFutureFrom,
165
+ locale
162
166
  }) {
163
167
  const [month, setMonth] = useState((/* @__PURE__ */ new Date()).getUTCMonth());
164
168
  const [year, setYear] = useState((/* @__PURE__ */ new Date()).getUTCFullYear());
@@ -285,6 +289,16 @@ function Calendar({
285
289
  /* @__PURE__ */ jsx(Row, { children: getLastWeek() })
286
290
  ] });
287
291
  };
292
+ const getLocale = () => {
293
+ return Intl.DateTimeFormat.supportedLocalesOf(locale).length > 0 ? locale : "en-US";
294
+ };
295
+ const weekDays = Array.from(
296
+ { length: 7 },
297
+ (__, i) => new Intl.DateTimeFormat(getLocale(), {
298
+ weekday: "short",
299
+ timeZone: "UTC"
300
+ }).format(new Date(Date.UTC(2024, 0, 7 + i)))
301
+ );
288
302
  const prior = () => {
289
303
  let local = month - 1;
290
304
  if (local < 0) {
@@ -323,7 +337,7 @@ function Calendar({
323
337
  "data-testid": "previous-month-arrow"
324
338
  }
325
339
  ),
326
- /* @__PURE__ */ jsx(Month, { bold: true, children: new Intl.DateTimeFormat("en-US", {
340
+ /* @__PURE__ */ jsx(Month, { bold: true, children: new Intl.DateTimeFormat(getLocale(), {
327
341
  month: "long",
328
342
  year: "numeric"
329
343
  }).format(new Date(year, month, 1, 0, 0, 0)) }),
@@ -342,15 +356,7 @@ function Calendar({
342
356
  ]
343
357
  }
344
358
  ),
345
- /* @__PURE__ */ jsxs(DaysWrapper, { children: [
346
- /* @__PURE__ */ jsx(Day, { children: "S" }),
347
- /* @__PURE__ */ jsx(Day, { children: "M" }),
348
- /* @__PURE__ */ jsx(Day, { children: "T" }),
349
- /* @__PURE__ */ jsx(Day, { children: "W" }),
350
- /* @__PURE__ */ jsx(Day, { children: "T" }),
351
- /* @__PURE__ */ jsx(Day, { children: "F" }),
352
- /* @__PURE__ */ jsx(Day, { children: "S" })
353
- ] }),
359
+ /* @__PURE__ */ jsx(DaysWrapper, { children: weekDays.map((weekDay) => /* @__PURE__ */ jsx(Day, { children: weekDay.toLocaleUpperCase().charAt(0) }, `${weekDay}`)) }),
354
360
  /* @__PURE__ */ jsx(Box, { children: getDays() })
355
361
  ] });
356
362
  }
@@ -363,7 +369,8 @@ Calendar.propTypes = {
363
369
  disablePastDates: bool,
364
370
  disableFutureDates: bool,
365
371
  disablePastFrom: instanceOf(Date),
366
- disableFutureFrom: instanceOf(Date)
372
+ disableFutureFrom: instanceOf(Date),
373
+ locale: string
367
374
  };
368
375
  var Calendar_default = Calendar;
369
376
  export {
@@ -34,7 +34,6 @@ import React, { useEffect, useRef, useState, useCallback } from "react";
34
34
  import { Booking, BookingFilled } from "@gympass/yoga-icons";
35
35
  import styled, { css } from "styled-components";
36
36
  import { bool, oneOf, func, instanceOf, string } from "prop-types";
37
- import { format } from "date-fns";
38
37
  import { Text } from "../..";
39
38
  import { theme } from "../../Theme";
40
39
  import Calendar from "./Calendar";
@@ -198,7 +197,8 @@ function Datepicker(_c) {
198
197
  disableFutureFrom,
199
198
  error,
200
199
  onOpen,
201
- displayEndDateOnly = false
200
+ displayEndDateOnly = false,
201
+ locale
202
202
  } = _d, props = __objRest(_d, [
203
203
  "fullWidth",
204
204
  "type",
@@ -215,7 +215,8 @@ function Datepicker(_c) {
215
215
  "disableFutureFrom",
216
216
  "error",
217
217
  "onOpen",
218
- "displayEndDateOnly"
218
+ "displayEndDateOnly",
219
+ "locale"
219
220
  ]);
220
221
  const [open, setOpen] = useState();
221
222
  const [startDateLocal, setStartDateLocal] = useState(startDate);
@@ -286,12 +287,21 @@ function Datepicker(_c) {
286
287
  if (!start && !end || displayEndDateOnly && !end) {
287
288
  return /* @__PURE__ */ jsx(InputPlaceholder, { disabled, children: placeholder != null ? placeholder : `Select Date` });
288
289
  }
289
- const dateFormat = "MMM d, yyyy";
290
+ const formattedDate = (date) => {
291
+ let month = new Intl.DateTimeFormat(locale, {
292
+ month: "short",
293
+ timeZone: "UTC"
294
+ }).format(date);
295
+ month = month.charAt(0).toUpperCase() + month.slice(1, 3);
296
+ const day = date.getUTCDate();
297
+ const year = date.getUTCFullYear();
298
+ return `${month} ${day}, ${year}`;
299
+ };
290
300
  if (displayEndDateOnly)
291
- return /* @__PURE__ */ jsx(Input, { disabled, children: end && format(toUTC(end), dateFormat) });
301
+ return /* @__PURE__ */ jsx(Input, { disabled, children: end && formattedDate(end) });
292
302
  return start && /* @__PURE__ */ jsxs(Input, { disabled, children: [
293
- format(toUTC(start), dateFormat),
294
- end && ` - ${format(toUTC(end), dateFormat)}`
303
+ formattedDate(start),
304
+ end && ` - ${formattedDate(end)}`
295
305
  ] });
296
306
  };
297
307
  return /* @__PURE__ */ jsxs(Wrapper, __spreadProps(__spreadValues({ fullWidth, tabIndex: "0" }, props), { children: [
@@ -334,7 +344,8 @@ function Datepicker(_c) {
334
344
  disablePastDates,
335
345
  disableFutureDates,
336
346
  disablePastFrom,
337
- disableFutureFrom
347
+ disableFutureFrom,
348
+ locale
338
349
  }
339
350
  ) })
340
351
  ] }));
@@ -355,7 +366,8 @@ Datepicker.propTypes = {
355
366
  disableFutureFrom: instanceOf(Date),
356
367
  error: string,
357
368
  onOpen: func,
358
- displayEndDateOnly: bool
369
+ displayEndDateOnly: bool,
370
+ locale: string
359
371
  };
360
372
  var Datepicker_default = Datepicker;
361
373
  export {
@@ -6,6 +6,10 @@ import { ThemeProvider, Datepicker, v3theme } from "../..";
6
6
  import { toUTC } from "./Datepicker";
7
7
  describe("<Datepicker />", () => {
8
8
  const testDate = new Date(2022, 7, 3, 14, 0, 0);
9
+ let originalDateTimeFormat;
10
+ beforeAll(() => {
11
+ originalDateTimeFormat = Intl.DateTimeFormat;
12
+ });
9
13
  describe("Snapshots", () => {
10
14
  it("should match snapshot when v3Theme is settled", () => {
11
15
  const { container } = render(
@@ -226,4 +230,67 @@ describe("<Datepicker />", () => {
226
230
  expect(screen.getByText("This is an error")).toBeVisible();
227
231
  });
228
232
  });
233
+ describe("Internationalization", () => {
234
+ let originalNavigator;
235
+ beforeEach(() => {
236
+ originalNavigator = global.navigator;
237
+ });
238
+ afterEach(() => {
239
+ global.Intl.DateTimeFormat = originalDateTimeFormat;
240
+ Object.defineProperty(global, "navigator", {
241
+ value: originalNavigator,
242
+ writable: true
243
+ });
244
+ });
245
+ it("should display calendar in English when locale is not supported", () => {
246
+ render(
247
+ /* @__PURE__ */ jsx(ThemeProvider, { children: /* @__PURE__ */ jsx(Datepicker, { type: "single", locale: "xx-XX" }) })
248
+ );
249
+ fireEvent.click(screen.getByRole("button"));
250
+ const currentDate = /* @__PURE__ */ new Date();
251
+ const currentMonth = new Intl.DateTimeFormat("en-US", {
252
+ month: "long"
253
+ }).format(currentDate);
254
+ expect(
255
+ screen.getByText(new RegExp(currentMonth, "i"))
256
+ ).toBeInTheDocument();
257
+ });
258
+ it("should display calendar in Portuguese when browser locale is pt-BR", () => {
259
+ render(
260
+ /* @__PURE__ */ jsx(ThemeProvider, { children: /* @__PURE__ */ jsx(Datepicker, { type: "single", locale: "pt-BR" }) })
261
+ );
262
+ fireEvent.click(screen.getByRole("button"));
263
+ const currentDate = /* @__PURE__ */ new Date();
264
+ const months = [
265
+ "janeiro",
266
+ "fevereiro",
267
+ "mar\xE7o",
268
+ "abril",
269
+ "maio",
270
+ "junho",
271
+ "julho",
272
+ "agosto",
273
+ "setembro",
274
+ "outubro",
275
+ "novembro",
276
+ "dezembro"
277
+ ];
278
+ const currentMonth = months[currentDate.getMonth()];
279
+ expect(
280
+ screen.getByText(new RegExp(currentMonth, "i"))
281
+ ).toBeInTheDocument();
282
+ });
283
+ it("should display only the first letter of each weekday in uppercase", () => {
284
+ render(
285
+ /* @__PURE__ */ jsx(ThemeProvider, { children: /* @__PURE__ */ jsx(Datepicker, { type: "single" }) })
286
+ );
287
+ fireEvent.click(screen.getByRole("button"));
288
+ const weekdayLetters = ["S", "M", "T", "W", "T", "F", "S"];
289
+ weekdayLetters.forEach((letter) => {
290
+ expect(screen.getAllByText(letter).length).toBeGreaterThan(0);
291
+ });
292
+ expect(screen.queryByText("sun")).not.toBeInTheDocument();
293
+ expect(screen.queryByText("mon")).not.toBeInTheDocument();
294
+ });
295
+ });
229
296
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gympass/yoga",
3
- "version": "7.129.2",
3
+ "version": "7.130.0",
4
4
  "description": "Gympass component library",
5
5
  "main": "./cjs",
6
6
  "types": "./typings/index.d.ts",
@@ -45,7 +45,7 @@
45
45
  "react-phone-input-2": "^2.15.1"
46
46
  },
47
47
  "devDependencies": {
48
- "@gympass/yoga-icons": "^1.28.0",
48
+ "@gympass/yoga-icons": "^1.29.0",
49
49
  "@react-native-community/eslint-config": "^3.0.1",
50
50
  "@types/styled-components": "^5.1.34",
51
51
  "babel-plugin-inline-react-svg": "^1.1.1",
@@ -59,7 +59,7 @@
59
59
  "react-native": "0.72.3",
60
60
  "styled-components": "^4.4.0"
61
61
  },
62
- "gitHead": "80d9a26eac0590d41b55997aff7d267fb259e499",
62
+ "gitHead": "181e38376e72162bd97ae292a93c94caadf5cef2",
63
63
  "module": "./esm",
64
64
  "private": false,
65
65
  "react-native": "./cjs/index.native.js"
@@ -342,7 +342,7 @@ declare namespace Feedback {
342
342
  }
343
343
  }
344
344
 
345
- declare function Datepicker({ fullWidth, type, placeholder, startDate, endDate, onSelectSingle, disabled, onSelectRange, customOnSelectRange, disablePastDates, disableFutureDates, disablePastFrom, disableFutureFrom, error, onOpen, displayEndDateOnly, ...props }: {
345
+ declare function Datepicker({ fullWidth, type, placeholder, startDate, endDate, onSelectSingle, disabled, onSelectRange, customOnSelectRange, disablePastDates, disableFutureDates, disablePastFrom, disableFutureFrom, error, onOpen, displayEndDateOnly, locale, ...props }: {
346
346
  [x: string]: any;
347
347
  fullWidth?: boolean | undefined;
348
348
  type: any;
@@ -360,6 +360,7 @@ declare function Datepicker({ fullWidth, type, placeholder, startDate, endDate,
360
360
  error: any;
361
361
  onOpen: any;
362
362
  displayEndDateOnly?: boolean | undefined;
363
+ locale: any;
363
364
  }): JSX.Element;
364
365
  declare namespace Datepicker {
365
366
  namespace propTypes {
@@ -379,6 +380,7 @@ declare namespace Datepicker {
379
380
  export { string as error };
380
381
  export { func as onOpen };
381
382
  export { bool as displayEndDateOnly };
383
+ export { string as locale };
382
384
  }
383
385
  }
384
386
 
@@ -408,6 +410,7 @@ declare namespace ActionRequirement {
408
410
  export const illustration: prop_types.Requireable<string | number | boolean | prop_types.ReactElementLike | prop_types.ReactNodeArray>;
409
411
  export const list: prop_types.Requireable<string | number | boolean | prop_types.ReactElementLike | prop_types.ReactNodeArray>;
410
412
  export { bool as titleAsTextDisplay };
413
+ export { number as ariaLevelTitle };
411
414
  }
412
415
  }
413
416