Socket
Socket
Sign inDemoInstall

@reach/dialog

Package Overview
Dependencies
Maintainers
3
Versions
67
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@reach/dialog - npm Package Compare versions

Comparing version 0.4.0-beta.0 to 0.4.0

index.d.ts

288

es/index.js

@@ -6,3 +6,2 @@ function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }

import React from "react";
import Component from "@reach/component-component";
import Portal from "@reach/portal";

@@ -12,7 +11,148 @@ import { checkStyles, wrapEvent, assignRef } from "@reach/utils";

import { RemoveScroll } from "react-remove-scroll";
import { func, bool } from "prop-types";
import { string, func, bool } from "prop-types";
var createAriaHider = function createAriaHider(dialogNode) {
var noop = function noop() {}; ////////////////////////////////////////////////////////////////////////////////
export var DialogOverlay = React.forwardRef(function DialogOverlay(_ref, forwardedRef) {
var _ref$isOpen = _ref.isOpen,
isOpen = _ref$isOpen === void 0 ? true : _ref$isOpen,
props = _objectWithoutPropertiesLoose(_ref, ["isOpen"]);
var ownRef = React.useRef(null);
var ref = forwardedRef || ownRef;
React.useEffect(function () {
checkStyles("dialog");
}, []);
return isOpen ? React.createElement(Portal, {
"data-reach-dialog-wrapper": true
}, React.createElement(DialogInner, _extends({
ref: ref
}, props))) : null;
});
if (process.env.NODE_ENV !== "production") {
DialogOverlay.propTypes = {
initialFocusRef: function initialFocusRef() {}
};
DialogOverlay.displayName = "DialogOverlay";
} ////////////////////////////////////////////////////////////////////////////////
var DialogInner = React.forwardRef(function DialogInner(_ref2, forwardedRef) {
var initialFocusRef = _ref2.initialFocusRef,
onClick = _ref2.onClick,
_ref2$onDismiss = _ref2.onDismiss,
onDismiss = _ref2$onDismiss === void 0 ? noop : _ref2$onDismiss,
onMouseDown = _ref2.onMouseDown,
onKeyDown = _ref2.onKeyDown,
props = _objectWithoutPropertiesLoose(_ref2, ["initialFocusRef", "onClick", "onDismiss", "onMouseDown", "onKeyDown"]);
var mouseDownTarget = React.useRef(null);
var overlayNode = React.useRef(null);
var ref = useForkedRef(overlayNode, forwardedRef);
React.useEffect(function () {
return createAriaHider(forwardedRef.current);
}, [forwardedRef]);
return React.createElement(FocusLock, {
autoFocus: true,
returnFocus: true,
onActivation: function onActivation() {
if (initialFocusRef && initialFocusRef.current) {
initialFocusRef.current.focus();
}
}
}, React.createElement(RemoveScroll, null, React.createElement("div", _extends({
"data-reach-dialog-overlay": true,
onClick: wrapEvent(onClick, function (event) {
if (mouseDownTarget.current === event.target) {
event.stopPropagation();
onDismiss(event);
}
}),
onMouseDown: wrapEvent(onMouseDown, function (event) {
mouseDownTarget.current = event.target;
}),
onKeyDown: wrapEvent(onKeyDown, function (event) {
if (event.key === "Escape") {
event.stopPropagation();
onDismiss(event);
}
}),
ref: ref
}, props))));
});
if (process.env.NODE_ENV !== "production") {
DialogOverlay.displayName = "DialogOverlay";
} ////////////////////////////////////////////////////////////////////////////////
export var DialogContent = React.forwardRef(function DialogContent(_ref3, forwardedRef) {
var onClick = _ref3.onClick,
onKeyDown = _ref3.onKeyDown,
props = _objectWithoutPropertiesLoose(_ref3, ["onClick", "onKeyDown"]);
return React.createElement("div", _extends({
role: "dialog",
"aria-modal": "true",
"data-reach-dialog-content": true,
tabIndex: "-1",
onClick: wrapEvent(onClick, function (event) {
event.stopPropagation();
}),
ref: forwardedRef
}, props));
});
if (process.env.NODE_ENV !== "production") {
DialogContent.propTypes = {
"aria-label": ariaLabelType,
"aria-labelledby": ariaLabelType
};
DialogContent.displayName = "DialogContent";
} ////////////////////////////////////////////////////////////////////////////////
export var Dialog = React.forwardRef(function Dialog(_ref4, forwardedRef) {
var isOpen = _ref4.isOpen,
_ref4$onDismiss = _ref4.onDismiss,
onDismiss = _ref4$onDismiss === void 0 ? noop : _ref4$onDismiss,
initialFocusRef = _ref4.initialFocusRef,
props = _objectWithoutPropertiesLoose(_ref4, ["isOpen", "onDismiss", "initialFocusRef"]);
var ownRef = React.useRef(null);
var ref = forwardedRef || ownRef;
return React.createElement(DialogOverlay, {
isOpen: isOpen,
onDismiss: onDismiss,
initialFocusRef: initialFocusRef
}, React.createElement(DialogContent, _extends({
ref: ref
}, props)));
});
if (process.env.NODE_ENV !== "production") {
Dialog.propTypes = {
isOpen: bool,
onDismiss: func,
"aria-label": ariaLabelType,
"aria-labelledby": ariaLabelType
};
Dialog.displayName = "Dialog";
} ////////////////////////////////////////////////////////////////////////////////
function createAriaHider(dialogNode) {
var originalValues = [];
var rootNodes = [];
if (!dialogNode) {
if (process.env.NODE_ENV !== "production") {
console.warn("A ref has not yet been attached to a dialog node when attempting to call `createAriaHider`.");
}
return noop;
}
Array.prototype.forEach.call(document.querySelectorAll("body > *"), function (node) {

@@ -47,121 +187,41 @@ var portalNode = dialogNode.parentNode.parentNode.parentNode;

};
};
} // TODO: Remove and import from @reach/utils once it's been added to the package
var k = function k() {};
var checkDialogStyles = function checkDialogStyles() {
return checkStyles("dialog");
};
function useForkedRef() {
for (var _len = arguments.length, refs = new Array(_len), _key = 0; _key < _len; _key++) {
refs[_key] = arguments[_key];
}
var portalDidMount = function portalDidMount(refs) {
refs.disposeAriaHider = createAriaHider(refs.overlayNode);
};
return React.useMemo(function () {
if (refs.every(function (ref) {
return ref == null;
})) {
return null;
}
var contentWillUnmount = function contentWillUnmount(_ref) {
var refs = _ref.refs;
refs.disposeAriaHider();
}; // eslint-disable-next-line no-unused-vars
return function (node) {
refs.forEach(function (ref) {
assignRef(ref, node);
});
}; // eslint-disable-next-line react-hooks/exhaustive-deps
}, refs);
}
function ariaLabelType(props, name, compName) {
var details = "\nSee https://www.w3.org/TR/wai-aria/#aria-label for details.";
var FocusContext = React.createContext();
var DialogOverlay = React.forwardRef(function (_ref2, forwardedRef) {
var _ref2$isOpen = _ref2.isOpen,
isOpen = _ref2$isOpen === void 0 ? true : _ref2$isOpen,
_ref2$onDismiss = _ref2.onDismiss,
onDismiss = _ref2$onDismiss === void 0 ? k : _ref2$onDismiss,
onMouseDown = _ref2.onMouseDown,
initialFocusRef = _ref2.initialFocusRef,
onClick = _ref2.onClick,
onKeyDown = _ref2.onKeyDown,
props = _objectWithoutPropertiesLoose(_ref2, ["isOpen", "onDismiss", "onMouseDown", "initialFocusRef", "onClick", "onKeyDown"]);
if (!props["aria-label"] && !props["aria-labelledby"]) {
return new Error("A <" + compName + "> must have either an `aria-label` or `aria-labelledby` prop.\n " + details);
}
return React.createElement(Component, {
didMount: checkDialogStyles
}, isOpen ? React.createElement(Portal, {
"data-reach-dialog-wrapper": true
}, React.createElement(Component, {
refs: {
overlayNode: null,
mouseDownTarget: null
},
didMount: function didMount(_ref3) {
var refs = _ref3.refs;
portalDidMount(refs);
},
willUnmount: contentWillUnmount
}, function (_ref4) {
var refs = _ref4.refs;
return React.createElement(FocusLock, {
returnFocus: true,
onActivation: function onActivation() {
if (initialFocusRef) {
initialFocusRef.current.focus();
}
}
}, React.createElement(RemoveScroll, null, React.createElement("div", _extends({
"data-reach-dialog-overlay": true,
onClick: wrapEvent(onClick, function (event) {
if (refs.mouseDownTarget === event.target) {
event.stopPropagation();
onDismiss(event);
}
}),
onMouseDown: wrapEvent(onMouseDown, function (event) {
refs.mouseDownTarget = event.target;
}),
onKeyDown: wrapEvent(onKeyDown, function (event) {
if (event.key === "Escape") {
event.stopPropagation();
onDismiss(event);
}
}),
ref: function ref(node) {
refs.overlayNode = node;
assignRef(forwardedRef, node);
}
}, props))));
})) : null);
});
DialogOverlay.propTypes = {
initialFocusRef: function initialFocusRef() {}
};
if (props["aria-label"] && props["aria-labelledby"]) {
return new Error("You provided both `aria-label` and `aria-labelledby` props to a <" + compName + ">. If the a label for this component is visible on the screen, that label's component should be given a unique ID prop, and that ID should be passed as the `aria-labelledby` prop into <" + compName + ">. If the label cannot be determined programmatically from the content of the element, an alternative label should be provided as the `aria-label` prop, which will be used as an `aria-label` on the HTML tag." + details);
}
var stopPropagation = function stopPropagation(event) {
return event.stopPropagation();
};
for (var _len2 = arguments.length, rest = new Array(_len2 > 3 ? _len2 - 3 : 0), _key2 = 3; _key2 < _len2; _key2++) {
rest[_key2 - 3] = arguments[_key2];
}
var DialogContent = React.forwardRef(function (_ref5, forwardedRef) {
var onClick = _ref5.onClick,
onKeyDown = _ref5.onKeyDown,
props = _objectWithoutPropertiesLoose(_ref5, ["onClick", "onKeyDown"]);
return React.createElement("div", _extends({
"aria-modal": "true",
"data-reach-dialog-content": true,
tabIndex: "-1",
onClick: wrapEvent(onClick, stopPropagation),
ref: function ref(node) {
assignRef(forwardedRef, node);
}
}, props));
});
var Dialog = function Dialog(_ref6) {
var isOpen = _ref6.isOpen,
_ref6$onDismiss = _ref6.onDismiss,
onDismiss = _ref6$onDismiss === void 0 ? k : _ref6$onDismiss,
initialFocusRef = _ref6.initialFocusRef,
props = _objectWithoutPropertiesLoose(_ref6, ["isOpen", "onDismiss", "initialFocusRef"]);
return React.createElement(DialogOverlay, {
isOpen: isOpen,
onDismiss: onDismiss,
initialFocusRef: initialFocusRef
}, React.createElement(DialogContent, props));
};
Dialog.propTypes = {
isOpen: bool,
onDismiss: func
};
export { DialogOverlay, DialogContent, Dialog };
return string.apply(void 0, [name, props, compName].concat(rest));
}

@@ -8,4 +8,2 @@ "use strict";

var _componentComponent = _interopRequireDefault(require("@reach/component-component"));
var _portal = _interopRequireDefault(require("@reach/portal"));

@@ -27,5 +25,160 @@

var createAriaHider = function createAriaHider(dialogNode) {
var noop = function noop() {}; ////////////////////////////////////////////////////////////////////////////////
var DialogOverlay = _react["default"].forwardRef(function DialogOverlay(_ref, forwardedRef) {
var _ref$isOpen = _ref.isOpen,
isOpen = _ref$isOpen === void 0 ? true : _ref$isOpen,
props = _objectWithoutPropertiesLoose(_ref, ["isOpen"]);
var ownRef = _react["default"].useRef(null);
var ref = forwardedRef || ownRef;
_react["default"].useEffect(function () {
(0, _utils.checkStyles)("dialog");
}, []);
return isOpen ? _react["default"].createElement(_portal["default"], {
"data-reach-dialog-wrapper": true
}, _react["default"].createElement(DialogInner, _extends({
ref: ref
}, props))) : null;
});
exports.DialogOverlay = DialogOverlay;
if (process.env.NODE_ENV !== "production") {
DialogOverlay.propTypes = {
initialFocusRef: function initialFocusRef() {}
};
DialogOverlay.displayName = "DialogOverlay";
} ////////////////////////////////////////////////////////////////////////////////
var DialogInner = _react["default"].forwardRef(function DialogInner(_ref2, forwardedRef) {
var initialFocusRef = _ref2.initialFocusRef,
onClick = _ref2.onClick,
_ref2$onDismiss = _ref2.onDismiss,
onDismiss = _ref2$onDismiss === void 0 ? noop : _ref2$onDismiss,
onMouseDown = _ref2.onMouseDown,
onKeyDown = _ref2.onKeyDown,
props = _objectWithoutPropertiesLoose(_ref2, ["initialFocusRef", "onClick", "onDismiss", "onMouseDown", "onKeyDown"]);
var mouseDownTarget = _react["default"].useRef(null);
var overlayNode = _react["default"].useRef(null);
var ref = useForkedRef(overlayNode, forwardedRef);
_react["default"].useEffect(function () {
return createAriaHider(forwardedRef.current);
}, [forwardedRef]);
return _react["default"].createElement(_reactFocusLock["default"], {
autoFocus: true,
returnFocus: true,
onActivation: function onActivation() {
if (initialFocusRef && initialFocusRef.current) {
initialFocusRef.current.focus();
}
}
}, _react["default"].createElement(_reactRemoveScroll.RemoveScroll, null, _react["default"].createElement("div", _extends({
"data-reach-dialog-overlay": true,
onClick: (0, _utils.wrapEvent)(onClick, function (event) {
if (mouseDownTarget.current === event.target) {
event.stopPropagation();
onDismiss(event);
}
}),
onMouseDown: (0, _utils.wrapEvent)(onMouseDown, function (event) {
mouseDownTarget.current = event.target;
}),
onKeyDown: (0, _utils.wrapEvent)(onKeyDown, function (event) {
if (event.key === "Escape") {
event.stopPropagation();
onDismiss(event);
}
}),
ref: ref
}, props))));
});
if (process.env.NODE_ENV !== "production") {
DialogOverlay.displayName = "DialogOverlay";
} ////////////////////////////////////////////////////////////////////////////////
var DialogContent = _react["default"].forwardRef(function DialogContent(_ref3, forwardedRef) {
var onClick = _ref3.onClick,
onKeyDown = _ref3.onKeyDown,
props = _objectWithoutPropertiesLoose(_ref3, ["onClick", "onKeyDown"]);
return _react["default"].createElement("div", _extends({
role: "dialog",
"aria-modal": "true",
"data-reach-dialog-content": true,
tabIndex: "-1",
onClick: (0, _utils.wrapEvent)(onClick, function (event) {
event.stopPropagation();
}),
ref: forwardedRef
}, props));
});
exports.DialogContent = DialogContent;
if (process.env.NODE_ENV !== "production") {
DialogContent.propTypes = {
"aria-label": ariaLabelType,
"aria-labelledby": ariaLabelType
};
DialogContent.displayName = "DialogContent";
} ////////////////////////////////////////////////////////////////////////////////
var Dialog = _react["default"].forwardRef(function Dialog(_ref4, forwardedRef) {
var isOpen = _ref4.isOpen,
_ref4$onDismiss = _ref4.onDismiss,
onDismiss = _ref4$onDismiss === void 0 ? noop : _ref4$onDismiss,
initialFocusRef = _ref4.initialFocusRef,
props = _objectWithoutPropertiesLoose(_ref4, ["isOpen", "onDismiss", "initialFocusRef"]);
var ownRef = _react["default"].useRef(null);
var ref = forwardedRef || ownRef;
return _react["default"].createElement(DialogOverlay, {
isOpen: isOpen,
onDismiss: onDismiss,
initialFocusRef: initialFocusRef
}, _react["default"].createElement(DialogContent, _extends({
ref: ref
}, props)));
});
exports.Dialog = Dialog;
if (process.env.NODE_ENV !== "production") {
Dialog.propTypes = {
isOpen: _propTypes.bool,
onDismiss: _propTypes.func,
"aria-label": ariaLabelType,
"aria-labelledby": ariaLabelType
};
Dialog.displayName = "Dialog";
} ////////////////////////////////////////////////////////////////////////////////
function createAriaHider(dialogNode) {
var originalValues = [];
var rootNodes = [];
if (!dialogNode) {
if (process.env.NODE_ENV !== "production") {
console.warn("A ref has not yet been attached to a dialog node when attempting to call `createAriaHider`.");
}
return noop;
}
Array.prototype.forEach.call(document.querySelectorAll("body > *"), function (node) {

@@ -60,126 +213,41 @@ var portalNode = dialogNode.parentNode.parentNode.parentNode;

};
};
} // TODO: Remove and import from @reach/utils once it's been added to the package
var k = function k() {};
var checkDialogStyles = function checkDialogStyles() {
return (0, _utils.checkStyles)("dialog");
};
function useForkedRef() {
for (var _len = arguments.length, refs = new Array(_len), _key = 0; _key < _len; _key++) {
refs[_key] = arguments[_key];
}
var portalDidMount = function portalDidMount(refs) {
refs.disposeAriaHider = createAriaHider(refs.overlayNode);
};
return _react["default"].useMemo(function () {
if (refs.every(function (ref) {
return ref == null;
})) {
return null;
}
var contentWillUnmount = function contentWillUnmount(_ref) {
var refs = _ref.refs;
refs.disposeAriaHider();
}; // eslint-disable-next-line no-unused-vars
return function (node) {
refs.forEach(function (ref) {
(0, _utils.assignRef)(ref, node);
});
}; // eslint-disable-next-line react-hooks/exhaustive-deps
}, refs);
}
function ariaLabelType(props, name, compName) {
var details = "\nSee https://www.w3.org/TR/wai-aria/#aria-label for details.";
var FocusContext = _react["default"].createContext();
if (!props["aria-label"] && !props["aria-labelledby"]) {
return new Error("A <" + compName + "> must have either an `aria-label` or `aria-labelledby` prop.\n " + details);
}
var DialogOverlay = _react["default"].forwardRef(function (_ref2, forwardedRef) {
var _ref2$isOpen = _ref2.isOpen,
isOpen = _ref2$isOpen === void 0 ? true : _ref2$isOpen,
_ref2$onDismiss = _ref2.onDismiss,
onDismiss = _ref2$onDismiss === void 0 ? k : _ref2$onDismiss,
onMouseDown = _ref2.onMouseDown,
initialFocusRef = _ref2.initialFocusRef,
onClick = _ref2.onClick,
onKeyDown = _ref2.onKeyDown,
props = _objectWithoutPropertiesLoose(_ref2, ["isOpen", "onDismiss", "onMouseDown", "initialFocusRef", "onClick", "onKeyDown"]);
if (props["aria-label"] && props["aria-labelledby"]) {
return new Error("You provided both `aria-label` and `aria-labelledby` props to a <" + compName + ">. If the a label for this component is visible on the screen, that label's component should be given a unique ID prop, and that ID should be passed as the `aria-labelledby` prop into <" + compName + ">. If the label cannot be determined programmatically from the content of the element, an alternative label should be provided as the `aria-label` prop, which will be used as an `aria-label` on the HTML tag." + details);
}
return _react["default"].createElement(_componentComponent["default"], {
didMount: checkDialogStyles
}, isOpen ? _react["default"].createElement(_portal["default"], {
"data-reach-dialog-wrapper": true
}, _react["default"].createElement(_componentComponent["default"], {
refs: {
overlayNode: null,
mouseDownTarget: null
},
didMount: function didMount(_ref3) {
var refs = _ref3.refs;
portalDidMount(refs);
},
willUnmount: contentWillUnmount
}, function (_ref4) {
var refs = _ref4.refs;
return _react["default"].createElement(_reactFocusLock["default"], {
returnFocus: true,
onActivation: function onActivation() {
if (initialFocusRef) {
initialFocusRef.current.focus();
}
}
}, _react["default"].createElement(_reactRemoveScroll.RemoveScroll, null, _react["default"].createElement("div", _extends({
"data-reach-dialog-overlay": true,
onClick: (0, _utils.wrapEvent)(onClick, function (event) {
if (refs.mouseDownTarget === event.target) {
event.stopPropagation();
onDismiss(event);
}
}),
onMouseDown: (0, _utils.wrapEvent)(onMouseDown, function (event) {
refs.mouseDownTarget = event.target;
}),
onKeyDown: (0, _utils.wrapEvent)(onKeyDown, function (event) {
if (event.key === "Escape") {
event.stopPropagation();
onDismiss(event);
}
}),
ref: function ref(node) {
refs.overlayNode = node;
(0, _utils.assignRef)(forwardedRef, node);
}
}, props))));
})) : null);
});
for (var _len2 = arguments.length, rest = new Array(_len2 > 3 ? _len2 - 3 : 0), _key2 = 3; _key2 < _len2; _key2++) {
rest[_key2 - 3] = arguments[_key2];
}
exports.DialogOverlay = DialogOverlay;
DialogOverlay.propTypes = {
initialFocusRef: function initialFocusRef() {}
};
var stopPropagation = function stopPropagation(event) {
return event.stopPropagation();
};
var DialogContent = _react["default"].forwardRef(function (_ref5, forwardedRef) {
var onClick = _ref5.onClick,
onKeyDown = _ref5.onKeyDown,
props = _objectWithoutPropertiesLoose(_ref5, ["onClick", "onKeyDown"]);
return _react["default"].createElement("div", _extends({
"aria-modal": "true",
"data-reach-dialog-content": true,
tabIndex: "-1",
onClick: (0, _utils.wrapEvent)(onClick, stopPropagation),
ref: function ref(node) {
(0, _utils.assignRef)(forwardedRef, node);
}
}, props));
});
exports.DialogContent = DialogContent;
var Dialog = function Dialog(_ref6) {
var isOpen = _ref6.isOpen,
_ref6$onDismiss = _ref6.onDismiss,
onDismiss = _ref6$onDismiss === void 0 ? k : _ref6$onDismiss,
initialFocusRef = _ref6.initialFocusRef,
props = _objectWithoutPropertiesLoose(_ref6, ["isOpen", "onDismiss", "initialFocusRef"]);
return _react["default"].createElement(DialogOverlay, {
isOpen: isOpen,
onDismiss: onDismiss,
initialFocusRef: initialFocusRef
}, _react["default"].createElement(DialogContent, props));
};
exports.Dialog = Dialog;
Dialog.propTypes = {
isOpen: _propTypes.bool,
onDismiss: _propTypes.func
};
return _propTypes.string.apply(void 0, [name, props, compName].concat(rest));
}
{
"name": "@reach/dialog",
"version": "0.4.0-beta.0",
"version": "0.4.0",
"description": "Accessible React Modal Dialog.",
"author": "Ryan Florence <@ryanflorence>",
"author": "React Training <hello@reacttraining.com>",
"license": "MIT",

@@ -10,12 +10,10 @@ "main": "index.js",

"scripts": {
"build": "node ../../shared/build-package",
"lint": "eslint . --max-warnings=0"
"build": "node ../../shared/build-package"
},
"dependencies": {
"@reach/component-component": "^0.4.0-beta.0",
"@reach/portal": "^0.4.0-beta.0",
"@reach/utils": "^0.4.0-beta.0",
"@reach/portal": "^0.4.0",
"@reach/utils": "^0.4.0",
"prop-types": "^15.7.2",
"react-focus-lock": "^2.1.0",
"react-remove-scroll": "^2.0.4"
"react-focus-lock": "^2.2.0",
"react-remove-scroll": "^2.1.1"
},

@@ -27,5 +25,6 @@ "peerDependencies": {

"devDependencies": {
"@reach/menu-button": "^0.4.0-beta.0",
"react": "^16.8.0",
"react-test-renderer": "^16.8.0"
"@reach/menu-button": "^0.4.0",
"react": "^16.10.2",
"react-spring": "^8.0.27",
"react-test-renderer": "^16.10.2"
},

@@ -37,4 +36,6 @@ "files": [

"index.js",
"index.d.ts",
"styles.css"
]
],
"gitHead": "0f3d2c7e530cd80e1d1bd338182ac89a3ba23999"
}
import React from "react";
import Component from "@reach/component-component";
import Portal from "@reach/portal";

@@ -7,8 +6,159 @@ import { checkStyles, wrapEvent, assignRef } from "@reach/utils";

import { RemoveScroll } from "react-remove-scroll";
import { func, bool } from "prop-types";
import { string, func, bool } from "prop-types";
let createAriaHider = dialogNode => {
const noop = () => {};
////////////////////////////////////////////////////////////////////////////////
export const DialogOverlay = React.forwardRef(function DialogOverlay(
{ isOpen = true, ...props },
forwardedRef
) {
const ownRef = React.useRef(null);
const ref = forwardedRef || ownRef;
React.useEffect(() => {
checkStyles("dialog");
}, []);
return isOpen ? (
<Portal data-reach-dialog-wrapper>
<DialogInner ref={ref} {...props} />
</Portal>
) : null;
});
if (__DEV__) {
DialogOverlay.propTypes = {
initialFocusRef: () => {}
};
DialogOverlay.displayName = "DialogOverlay";
}
////////////////////////////////////////////////////////////////////////////////
const DialogInner = React.forwardRef(function DialogInner(
{
initialFocusRef,
onClick,
onDismiss = noop,
onMouseDown,
onKeyDown,
...props
},
forwardedRef
) {
const mouseDownTarget = React.useRef(null);
const overlayNode = React.useRef(null);
const ref = useForkedRef(overlayNode, forwardedRef);
React.useEffect(() => createAriaHider(forwardedRef.current), [forwardedRef]);
return (
<FocusLock
autoFocus
returnFocus
onActivation={() => {
if (initialFocusRef && initialFocusRef.current) {
initialFocusRef.current.focus();
}
}}
>
<RemoveScroll>
<div
data-reach-dialog-overlay
onClick={wrapEvent(onClick, event => {
if (mouseDownTarget.current === event.target) {
event.stopPropagation();
onDismiss(event);
}
})}
onMouseDown={wrapEvent(onMouseDown, event => {
mouseDownTarget.current = event.target;
})}
onKeyDown={wrapEvent(onKeyDown, event => {
if (event.key === "Escape") {
event.stopPropagation();
onDismiss(event);
}
})}
ref={ref}
{...props}
/>
</RemoveScroll>
</FocusLock>
);
});
if (__DEV__) {
DialogOverlay.displayName = "DialogOverlay";
}
////////////////////////////////////////////////////////////////////////////////
export const DialogContent = React.forwardRef(function DialogContent(
{ onClick, onKeyDown, ...props },
forwardedRef
) {
return (
<div
role="dialog"
aria-modal="true"
data-reach-dialog-content
tabIndex="-1"
onClick={wrapEvent(onClick, event => {
event.stopPropagation();
})}
ref={forwardedRef}
{...props}
/>
);
});
if (__DEV__) {
DialogContent.propTypes = {
"aria-label": ariaLabelType,
"aria-labelledby": ariaLabelType
};
DialogContent.displayName = "DialogContent";
}
////////////////////////////////////////////////////////////////////////////////
export const Dialog = React.forwardRef(function Dialog(
{ isOpen, onDismiss = noop, initialFocusRef, ...props },
forwardedRef
) {
const ownRef = React.useRef(null);
const ref = forwardedRef || ownRef;
return (
<DialogOverlay
isOpen={isOpen}
onDismiss={onDismiss}
initialFocusRef={initialFocusRef}
>
<DialogContent ref={ref} {...props} />
</DialogOverlay>
);
});
if (__DEV__) {
Dialog.propTypes = {
isOpen: bool,
onDismiss: func,
"aria-label": ariaLabelType,
"aria-labelledby": ariaLabelType
};
Dialog.displayName = "Dialog";
}
////////////////////////////////////////////////////////////////////////////////
function createAriaHider(dialogNode) {
let originalValues = [];
let rootNodes = [];
if (!dialogNode) {
if (__DEV__) {
console.warn(
"A ref has not yet been attached to a dialog node when attempting to call `createAriaHider`."
);
}
return noop;
}
Array.prototype.forEach.call(document.querySelectorAll("body > *"), node => {

@@ -39,123 +189,39 @@ const portalNode = dialogNode.parentNode.parentNode.parentNode;

};
};
}
let k = () => {};
// TODO: Remove and import from @reach/utils once it's been added to the package
function useForkedRef(...refs) {
return React.useMemo(() => {
if (refs.every(ref => ref == null)) {
return null;
}
return node => {
refs.forEach(ref => {
assignRef(ref, node);
});
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, refs);
}
let checkDialogStyles = () => checkStyles("dialog");
let portalDidMount = refs => {
refs.disposeAriaHider = createAriaHider(refs.overlayNode);
};
let contentWillUnmount = ({ refs }) => {
refs.disposeAriaHider();
};
// eslint-disable-next-line no-unused-vars
let FocusContext = React.createContext();
let DialogOverlay = React.forwardRef(
(
{
isOpen = true,
onDismiss = k,
onMouseDown,
initialFocusRef,
onClick,
onKeyDown,
...props
},
forwardedRef
) => {
return (
<Component didMount={checkDialogStyles}>
{isOpen ? (
<Portal data-reach-dialog-wrapper>
<Component
refs={{ overlayNode: null, mouseDownTarget: null }}
didMount={({ refs }) => {
portalDidMount(refs);
}}
willUnmount={contentWillUnmount}
>
{({ refs }) => (
<FocusLock
returnFocus
onActivation={() => {
if (initialFocusRef) {
initialFocusRef.current.focus();
}
}}
>
<RemoveScroll>
<div
data-reach-dialog-overlay
onClick={wrapEvent(onClick, event => {
if (refs.mouseDownTarget === event.target) {
event.stopPropagation();
onDismiss(event);
}
})}
onMouseDown={wrapEvent(onMouseDown, event => {
refs.mouseDownTarget = event.target;
})}
onKeyDown={wrapEvent(onKeyDown, event => {
if (event.key === "Escape") {
event.stopPropagation();
onDismiss(event);
}
})}
ref={node => {
refs.overlayNode = node;
assignRef(forwardedRef, node);
}}
{...props}
/>
</RemoveScroll>
</FocusLock>
)}
</Component>
</Portal>
) : null}
</Component>
function ariaLabelType(props, name, compName, ...rest) {
const details =
"\nSee https://www.w3.org/TR/wai-aria/#aria-label for details.";
if (!props["aria-label"] && !props["aria-labelledby"]) {
return new Error(
`A <${compName}> must have either an \`aria-label\` or \`aria-labelledby\` prop.
${details}`
);
}
);
DialogOverlay.propTypes = {
initialFocusRef: () => {}
};
let stopPropagation = event => event.stopPropagation();
let DialogContent = React.forwardRef(
({ onClick, onKeyDown, ...props }, forwardedRef) => (
<div
aria-modal="true"
data-reach-dialog-content
tabIndex="-1"
onClick={wrapEvent(onClick, stopPropagation)}
ref={node => {
assignRef(forwardedRef, node);
}}
{...props}
/>
)
);
let Dialog = ({ isOpen, onDismiss = k, initialFocusRef, ...props }) => (
<DialogOverlay
isOpen={isOpen}
onDismiss={onDismiss}
initialFocusRef={initialFocusRef}
>
<DialogContent {...props} />
</DialogOverlay>
);
Dialog.propTypes = {
isOpen: bool,
onDismiss: func
};
export { DialogOverlay, DialogContent, Dialog };
if (props["aria-label"] && props["aria-labelledby"]) {
return new Error(
"You provided both `aria-label` and `aria-labelledby` props to a <" +
compName +
">. If the a label for this component is visible on the screen, that label's component should be given a unique ID prop, and that ID should be passed as the `aria-labelledby` prop into <" +
compName +
">. If the label cannot be determined programmatically from the content of the element, an alternative label should be provided as the `aria-label` prop, which will be used as an `aria-label` on the HTML tag." +
details
);
}
return string(name, props, compName, ...rest);
}

@@ -9,3 +9,3 @@ import React from "react";

<div lang="gr">
<Dialog isOpen={false}>
<Dialog isOpen={false} aria-label="cool dialog">
<div lang="en" />

@@ -12,0 +12,0 @@ </Dialog>

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc