@gympass/yoga 7.118.0 → 7.119.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.
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
2
  var __create = Object.create;
3
3
  var __defProp = Object.defineProperty;
4
- var __defProps = Object.defineProperties;
5
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
7
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
8
6
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
9
7
  var __getProtoOf = Object.getPrototypeOf;
@@ -21,7 +19,6 @@ var __spreadValues = (a, b) => {
21
19
  }
22
20
  return a;
23
21
  };
24
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
25
22
  var __objRest = (source, exclude) => {
26
23
  var target = {};
27
24
  for (var prop in source)
@@ -64,11 +61,13 @@ module.exports = __toCommonJS(Dialog_exports);
64
61
  var import_jsx_runtime = require("react/jsx-runtime");
65
62
  var import_react = __toESM(require("react"));
66
63
  var import_react_dom = require("react-dom");
64
+ var import_react_focus_lock = __toESM(require("react-focus-lock"));
67
65
  var import_styled_components = __toESM(require("styled-components"));
68
66
  var import_prop_types = require("prop-types");
69
67
  var import_yoga_icons = require("@gympass/yoga-icons");
70
68
  var import_hooks = require("../../hooks");
71
69
  var import__ = require("../..");
70
+ var import_utils = require("./utils");
72
71
  const StyledDialog = (0, import_styled_components.default)(import__.Card)`
73
72
  ${({
74
73
  onClose,
@@ -136,10 +135,33 @@ const CloseButton = (0, import_styled_components.default)(import__.Button.Icon)`
136
135
  `;
137
136
  const Dialog = import_react.default.forwardRef(
138
137
  (_a, forwardedRef) => {
139
- var _b = _a, { isOpen, hideCloseButton, children, dialogId, onClose, zIndex } = _b, props = __objRest(_b, ["isOpen", "hideCloseButton", "children", "dialogId", "onClose", "zIndex"]);
138
+ var _b = _a, {
139
+ isOpen,
140
+ hideCloseButton,
141
+ children,
142
+ dialogId,
143
+ onClose,
144
+ zIndex,
145
+ closeLabel,
146
+ className
147
+ } = _b, props = __objRest(_b, [
148
+ "isOpen",
149
+ "hideCloseButton",
150
+ "children",
151
+ "dialogId",
152
+ "onClose",
153
+ "zIndex",
154
+ "closeLabel",
155
+ "className"
156
+ ]);
140
157
  const dialogRef = (0, import_hooks.useCombinedRefs)(forwardedRef);
141
158
  const dialogElement = (0, import_hooks.usePortal)(dialogId != null ? dialogId : "dialog");
142
159
  const isCloseButtonVisible = onClose && !hideCloseButton;
160
+ const lockProps = __spreadValues({
161
+ role: "dialog",
162
+ "aria-modal": true,
163
+ onClose
164
+ }, props);
143
165
  const closeDialog = (0, import_react.useCallback)(
144
166
  (e) => {
145
167
  if (dialogRef.current === e.target && isOpen && onClose) {
@@ -170,18 +192,30 @@ const Dialog = import_react.default.forwardRef(
170
192
  onClose,
171
193
  ref: dialogRef,
172
194
  zIndex,
173
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(StyledDialog, __spreadProps(__spreadValues({ onClose }, props), { children: [
174
- isCloseButtonVisible && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import__.Box, { d: "flex", justifyContent: "flex-end", w: "100%", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
175
- CloseButton,
176
- {
177
- icon: import_yoga_icons.Close,
178
- inverted: true,
179
- secondary: true,
180
- onClick: onClose
181
- }
182
- ) }),
183
- children
184
- ] }))
195
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
196
+ import_react_focus_lock.default,
197
+ {
198
+ as: StyledDialog,
199
+ lockProps,
200
+ returnFocus: true,
201
+ disabled: !isOpen,
202
+ className,
203
+ onActivation: import_utils.focusOnFirstProgrammaticFocusableElement,
204
+ children: [
205
+ isCloseButtonVisible && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import__.Box, { d: "flex", justifyContent: "flex-end", w: "100%", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
206
+ CloseButton,
207
+ {
208
+ "aria-label": closeLabel,
209
+ icon: import_yoga_icons.Close,
210
+ inverted: true,
211
+ secondary: true,
212
+ onClick: onClose
213
+ }
214
+ ) }),
215
+ children
216
+ ]
217
+ }
218
+ )
185
219
  }
186
220
  ),
187
221
  dialogElement
@@ -197,6 +231,8 @@ Dialog.propTypes = {
197
231
  hideCloseButton: import_prop_types.bool,
198
232
  /** Function to close the dialog. */
199
233
  onClose: import_prop_types.func,
234
+ closeLabel: import_prop_types.string,
235
+ className: import_prop_types.string,
200
236
  zIndex: import_prop_types.number,
201
237
  children: import_prop_types.node.isRequired
202
238
  };
@@ -204,6 +240,8 @@ Dialog.defaultProps = {
204
240
  isOpen: false,
205
241
  hideCloseButton: false,
206
242
  onClose: void 0,
243
+ closeLabel: void 0,
244
+ className: void 0,
207
245
  zIndex: 3,
208
246
  dialogId: void 0
209
247
  };
@@ -66,9 +66,9 @@ describe("<Dialog />", () => {
66
66
  it("should render with close button", () => {
67
67
  const onCloseMock = jest.fn();
68
68
  (0, import_react2.render)(
69
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import__.ThemeProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import__2.default, { isOpen: true, onClose: onCloseMock, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import__2.default.Header, { children: "Title" }) }) })
69
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import__.ThemeProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import__2.default, { isOpen: true, onClose: onCloseMock, closeLabel: "Close", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import__2.default.Header, { children: "Title" }) }) })
70
70
  );
71
- const button = import_react2.screen.getByRole("button");
71
+ const button = import_react2.screen.getByRole("button", { name: "Close" });
72
72
  import_react2.fireEvent.click(button);
73
73
  expect(onCloseMock).toHaveBeenCalledTimes(1);
74
74
  });
@@ -89,4 +89,10 @@ describe("<Dialog />", () => {
89
89
  expect(import_react2.screen.getByText("Title")).toBeInTheDocument();
90
90
  expect(import_react2.screen.getByText("Second Title")).toBeInTheDocument();
91
91
  });
92
+ it("should focus on the title when dialog is opened", () => {
93
+ (0, import_react2.render)(
94
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import__.ThemeProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import__2.default, { isOpen: true, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import__2.default.Header, { children: "Add e-mail" }) }) })
95
+ );
96
+ expect(document.activeElement).toHaveTextContent("Add e-mail");
97
+ });
92
98
  });
@@ -48,6 +48,6 @@ module.exports = __toCommonJS(Header_exports);
48
48
  var import_jsx_runtime = require("react/jsx-runtime");
49
49
  var import_react = __toESM(require("react"));
50
50
  var import_Text = __toESM(require("../../Text"));
51
- const Header = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Text.default.H4, __spreadValues({ bold: true, as: "header", ta: "center", mb: "large" }, props));
51
+ const Header = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Text.default.H4, __spreadValues({ bold: true, as: "h2", ta: "center", mb: "large", tabIndex: -1 }, props));
52
52
  Header.displayName = "Dialog.Header";
53
53
  var Header_default = Header;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var utils_exports = {};
20
+ __export(utils_exports, {
21
+ focusOnFirstProgrammaticFocusableElement: () => focusOnFirstProgrammaticFocusableElement
22
+ });
23
+ module.exports = __toCommonJS(utils_exports);
24
+ function focusOnFirstProgrammaticFocusableElement(container) {
25
+ const element = container.querySelector('[tabindex="-1"]');
26
+ element == null ? void 0 : element.focus();
27
+ }
28
+ // Annotate the CommonJS export names for ESM import in node:
29
+ 0 && (module.exports = {
30
+ focusOnFirstProgrammaticFocusableElement
31
+ });
@@ -1,6 +1,4 @@
1
1
  var __defProp = Object.defineProperty;
2
- var __defProps = Object.defineProperties;
3
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
2
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
3
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
4
  var __propIsEnum = Object.prototype.propertyIsEnumerable;
@@ -16,7 +14,6 @@ var __spreadValues = (a, b) => {
16
14
  }
17
15
  return a;
18
16
  };
19
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
17
  var __objRest = (source, exclude) => {
21
18
  var target = {};
22
19
  for (var prop in source)
@@ -32,11 +29,13 @@ var __objRest = (source, exclude) => {
32
29
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
33
30
  import React, { useEffect, useCallback } from "react";
34
31
  import { createPortal } from "react-dom";
32
+ import FocusLock from "react-focus-lock";
35
33
  import styled, { css } from "styled-components";
36
34
  import { func, bool, node, number, string } from "prop-types";
37
35
  import { Close } from "@gympass/yoga-icons";
38
36
  import { usePortal, useCombinedRefs } from "../../hooks";
39
37
  import { Button, Card, Box } from "../..";
38
+ import { focusOnFirstProgrammaticFocusableElement } from "./utils";
40
39
  const StyledDialog = styled(Card)`
41
40
  ${({
42
41
  onClose,
@@ -104,10 +103,33 @@ const CloseButton = styled(Button.Icon)`
104
103
  `;
105
104
  const Dialog = React.forwardRef(
106
105
  (_a, forwardedRef) => {
107
- var _b = _a, { isOpen, hideCloseButton, children, dialogId, onClose, zIndex } = _b, props = __objRest(_b, ["isOpen", "hideCloseButton", "children", "dialogId", "onClose", "zIndex"]);
106
+ var _b = _a, {
107
+ isOpen,
108
+ hideCloseButton,
109
+ children,
110
+ dialogId,
111
+ onClose,
112
+ zIndex,
113
+ closeLabel,
114
+ className
115
+ } = _b, props = __objRest(_b, [
116
+ "isOpen",
117
+ "hideCloseButton",
118
+ "children",
119
+ "dialogId",
120
+ "onClose",
121
+ "zIndex",
122
+ "closeLabel",
123
+ "className"
124
+ ]);
108
125
  const dialogRef = useCombinedRefs(forwardedRef);
109
126
  const dialogElement = usePortal(dialogId != null ? dialogId : "dialog");
110
127
  const isCloseButtonVisible = onClose && !hideCloseButton;
128
+ const lockProps = __spreadValues({
129
+ role: "dialog",
130
+ "aria-modal": true,
131
+ onClose
132
+ }, props);
111
133
  const closeDialog = useCallback(
112
134
  (e) => {
113
135
  if (dialogRef.current === e.target && isOpen && onClose) {
@@ -138,18 +160,30 @@ const Dialog = React.forwardRef(
138
160
  onClose,
139
161
  ref: dialogRef,
140
162
  zIndex,
141
- children: /* @__PURE__ */ jsxs(StyledDialog, __spreadProps(__spreadValues({ onClose }, props), { children: [
142
- isCloseButtonVisible && /* @__PURE__ */ jsx(Box, { d: "flex", justifyContent: "flex-end", w: "100%", children: /* @__PURE__ */ jsx(
143
- CloseButton,
144
- {
145
- icon: Close,
146
- inverted: true,
147
- secondary: true,
148
- onClick: onClose
149
- }
150
- ) }),
151
- children
152
- ] }))
163
+ children: /* @__PURE__ */ jsxs(
164
+ FocusLock,
165
+ {
166
+ as: StyledDialog,
167
+ lockProps,
168
+ returnFocus: true,
169
+ disabled: !isOpen,
170
+ className,
171
+ onActivation: focusOnFirstProgrammaticFocusableElement,
172
+ children: [
173
+ isCloseButtonVisible && /* @__PURE__ */ jsx(Box, { d: "flex", justifyContent: "flex-end", w: "100%", children: /* @__PURE__ */ jsx(
174
+ CloseButton,
175
+ {
176
+ "aria-label": closeLabel,
177
+ icon: Close,
178
+ inverted: true,
179
+ secondary: true,
180
+ onClick: onClose
181
+ }
182
+ ) }),
183
+ children
184
+ ]
185
+ }
186
+ )
153
187
  }
154
188
  ),
155
189
  dialogElement
@@ -165,6 +199,8 @@ Dialog.propTypes = {
165
199
  hideCloseButton: bool,
166
200
  /** Function to close the dialog. */
167
201
  onClose: func,
202
+ closeLabel: string,
203
+ className: string,
168
204
  zIndex: number,
169
205
  children: node.isRequired
170
206
  };
@@ -172,6 +208,8 @@ Dialog.defaultProps = {
172
208
  isOpen: false,
173
209
  hideCloseButton: false,
174
210
  onClose: void 0,
211
+ closeLabel: void 0,
212
+ className: void 0,
175
213
  zIndex: 3,
176
214
  dialogId: void 0
177
215
  };
@@ -43,9 +43,9 @@ describe("<Dialog />", () => {
43
43
  it("should render with close button", () => {
44
44
  const onCloseMock = jest.fn();
45
45
  render(
46
- /* @__PURE__ */ jsx(ThemeProvider, { children: /* @__PURE__ */ jsx(Dialog, { isOpen: true, onClose: onCloseMock, children: /* @__PURE__ */ jsx(Dialog.Header, { children: "Title" }) }) })
46
+ /* @__PURE__ */ jsx(ThemeProvider, { children: /* @__PURE__ */ jsx(Dialog, { isOpen: true, onClose: onCloseMock, closeLabel: "Close", children: /* @__PURE__ */ jsx(Dialog.Header, { children: "Title" }) }) })
47
47
  );
48
- const button = screen.getByRole("button");
48
+ const button = screen.getByRole("button", { name: "Close" });
49
49
  fireEvent.click(button);
50
50
  expect(onCloseMock).toHaveBeenCalledTimes(1);
51
51
  });
@@ -66,4 +66,10 @@ describe("<Dialog />", () => {
66
66
  expect(screen.getByText("Title")).toBeInTheDocument();
67
67
  expect(screen.getByText("Second Title")).toBeInTheDocument();
68
68
  });
69
+ it("should focus on the title when dialog is opened", () => {
70
+ render(
71
+ /* @__PURE__ */ jsx(ThemeProvider, { children: /* @__PURE__ */ jsx(Dialog, { isOpen: true, children: /* @__PURE__ */ jsx(Dialog.Header, { children: "Add e-mail" }) }) })
72
+ );
73
+ expect(document.activeElement).toHaveTextContent("Add e-mail");
74
+ });
69
75
  });
@@ -17,7 +17,7 @@ var __spreadValues = (a, b) => {
17
17
  import { jsx } from "react/jsx-runtime";
18
18
  import React from "react";
19
19
  import Text from "../../Text";
20
- const Header = (props) => /* @__PURE__ */ jsx(Text.H4, __spreadValues({ bold: true, as: "header", ta: "center", mb: "large" }, props));
20
+ const Header = (props) => /* @__PURE__ */ jsx(Text.H4, __spreadValues({ bold: true, as: "h2", ta: "center", mb: "large", tabIndex: -1 }, props));
21
21
  Header.displayName = "Dialog.Header";
22
22
  var Header_default = Header;
23
23
  export {
@@ -0,0 +1,7 @@
1
+ function focusOnFirstProgrammaticFocusableElement(container) {
2
+ const element = container.querySelector('[tabindex="-1"]');
3
+ element == null ? void 0 : element.focus();
4
+ }
5
+ export {
6
+ focusOnFirstProgrammaticFocusableElement
7
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gympass/yoga",
3
- "version": "7.118.0",
3
+ "version": "7.119.0",
4
4
  "description": "Gympass component library",
5
5
  "main": "./cjs",
6
6
  "types": "./typings/index.d.ts",
@@ -41,6 +41,7 @@
41
41
  "prop-types": "^15.7.2",
42
42
  "proxy-polyfill": "^0.3.1",
43
43
  "rc-slider": "^8.7.1",
44
+ "react-focus-lock": "^2.13.2",
44
45
  "react-google-font-loader": "^1.1.0",
45
46
  "react-phone-input-2": "^2.15.1"
46
47
  },
@@ -57,7 +58,7 @@
57
58
  "react-native": "0.72.3",
58
59
  "styled-components": "^4.4.0"
59
60
  },
60
- "gitHead": "a8f23e4f87e4e60758e10a35ca6afd27c177e60c",
61
+ "gitHead": "14c7d64e2380f7edaf06dcbe5953b516ee6edea5",
61
62
  "module": "./esm",
62
63
  "private": false,
63
64
  "react-native": "./cjs/index.native.js"