Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@arch-ui/modal-utils

Package Overview
Dependencies
Maintainers
8
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@arch-ui/modal-utils - npm Package Compare versions

Comparing version 1.0.10 to 1.0.11

6

CHANGELOG.md
# @arch-ui/modal-utils
## 1.0.11
### Patch Changes
- [`a212ae6e7`](https://github.com/keystonejs/keystone/commit/a212ae6e780d36160cf6089a59601acaaadaf210) [#3131](https://github.com/keystonejs/keystone/pull/3131) Thanks [@Vultraz](https://github.com/Vultraz)! - Converted withModalHandlers to a functional component.
## 1.0.10

@@ -4,0 +10,0 @@

239

dist/modal-utils.cjs.dev.js

@@ -22,3 +22,3 @@ 'use strict';

const transitionDurationMs = 220;
const transitionDuration = "".concat(transitionDurationMs, "ms");
const transitionDuration = `${transitionDurationMs}ms`;
const transitionTimingFunction = 'cubic-bezier(0.2, 0, 0, 1)';

@@ -64,3 +64,3 @@ const TransitionProvider = (_ref) => {

const fade = transitionState => _objectSpread({}, makeTransitionBase('opacity'), {
const fade = transitionState => _objectSpread(_objectSpread({}, makeTransitionBase('opacity')), {}, {
opacity: {

@@ -80,3 +80,3 @@ entering: 1,

};
return _objectSpread({}, makeTransitionBase('opacity, transform'), {}, {
return _objectSpread(_objectSpread({}, makeTransitionBase('opacity, transform')), {
entering: {

@@ -97,5 +97,5 @@ opacity: 1

opacity: 0,
transform: "translate3d(0,".concat(from, ",0)")
transform: `translate3d(0,${from},0)`
};
return _objectSpread({}, makeTransitionBase('opacity, transform'), {}, {
return _objectSpread(_objectSpread({}, makeTransitionBase('opacity, transform')), {
entering: {

@@ -120,3 +120,3 @@ opacity: 1

const initial = fromMap[slideInFrom];
return _objectSpread({}, makeTransitionBase('transform'), {}, {
return _objectSpread(_objectSpread({}, makeTransitionBase('transform')), {
entering: {

@@ -129,6 +129,6 @@ transform: 'translate3d(0,0,0)'

exiting: {
transform: "translate3d(".concat(initial, ", 0, 0)")
transform: `translate3d(${initial}, 0, 0)`
},
exited: {
transform: "translate3d(".concat(initial, ", 0, 0)")
transform: `translate3d(${initial}, 0, 0)`
}

@@ -214,9 +214,7 @@ }[transitionState]);

function getDisplayName(C) {
return "withModalHandlers(".concat(C.displayName || C.name || 'Component', ")");
}
const getDisplayName = C => {
return `withModalHandlers(${C.displayName || C.name || 'Component'})`;
};
const NOOP = () => {};
let Target = React.memo(function Target({
const Target = React.memo(({
isOpen,

@@ -228,3 +226,3 @@ mode,

toggle
}) {
}) => {
const cloneProps = {

@@ -238,75 +236,52 @@ isActive: isOpen,

});
function withModalHandlers(WrappedComponent, {
const withModalHandlers = (WrappedComponent, {
transition
}) {
class IntermediateComponent extends React.Component {
constructor(...args) {
super(...args);
}) => {
return React.forwardRef((_ref, ref) => {
let {
defaultIsOpen = false,
mode = 'click',
onClose = () => {},
onOpen = () => {},
target
} = _ref,
props = _objectWithoutProperties(_ref, ["defaultIsOpen", "mode", "onClose", "onOpen", "target"]);
_defineProperty(this, "state", {
isOpen: this.props.defaultIsOpen,
clientX: 0,
clientY: 0
});
const [isOpen, setIsOpen] = React.useState(defaultIsOpen); // TODO: remove. Wrapped components (currently only Dropdown) use these for calculating position,
// but react-popper should be used instead
_defineProperty(this, "open", event => {
if (event.defaultPrevented) return;
if (this.props.mode === 'contextmenu') event.preventDefault();
const {
clientX,
clientY
} = event;
this.setState({
isOpen: true,
clientX,
clientY
});
document.addEventListener('mousedown', this.handleMouseDown);
document.addEventListener('keydown', this.handleKeyDown, false);
});
const [clientX, setClientX] = React.useState(0);
const [clientY, setClientY] = React.useState(0);
const contentNode = React.useRef();
const targetNode = React.useRef(); // Expose open() and close() for via ref
_defineProperty(this, "close", event => {
if (event && event.defaultPrevented) return;
this.setState({
isOpen: false,
clientX: 0,
clientY: 0
});
document.removeEventListener('mousedown', this.handleMouseDown);
document.removeEventListener('keydown', this.handleKeyDown, false);
});
React.useImperativeHandle(ref, () => ({
open,
close
}));
React.useEffect(() => {
// If the dialog was closed, don't do anything. The cleanup function already removed the handlers.
if (!isOpen) return;
_defineProperty(this, "toggle", event => {
if (this.state.isOpen) {
this.close(event);
} else {
this.open(event);
}
});
_defineProperty(this, "handleScroll", event => {
event.preventDefault();
});
_defineProperty(this, "handleMouseDown", event => {
const handleMouseDown = event => {
const {
target
} = event;
const {
isOpen
} = this.state;
if (!(target instanceof HTMLElement) && !(target instanceof SVGElement)) {
return;
} // NOTE: Why not use the <Blanket /> component to close?
// We don't want to interupt the user's flow. Taking this approach allows
}
const clickNotIn = node => !node.current.contains(target); // NOTE: Why not use the <Blanket /> component to close?
// We don't want to interrupt the user's flow. Taking this approach allows
// user to click "through" to other elements and close the popout.
if (isOpen && !this.contentNode.contains(target) && !this.targetNode.contains(target)) {
this.close(event);
if (isOpen && clickNotIn(contentNode) && clickNotIn(targetNode)) {
close(event);
}
});
};
_defineProperty(this, "handleKeyDown", event => {
const handleKeyDown = event => {
const {

@@ -317,65 +292,77 @@ key

if (key === 'Escape') {
this.close(event);
close(event);
}
});
};
_defineProperty(this, "getTarget", ref => {
this.targetNode = ref;
});
document.addEventListener('mousedown', handleMouseDown);
document.addEventListener('keydown', handleKeyDown, false);
return () => {
document.removeEventListener('mousedown', handleMouseDown);
document.removeEventListener('keydown', handleKeyDown, false);
};
}, [isOpen]);
React.useDebugValue(getDisplayName(WrappedComponent));
_defineProperty(this, "getContent", ref => {
this.contentNode = ref;
});
}
render() {
const open = event => {
if (event.defaultPrevented) return;
if (mode === 'contextmenu') event.preventDefault();
const {
mode,
onClose,
onOpen,
target
} = this.props;
const {
clientX,
clientY,
isOpen
} = this.state;
return React__default.createElement(React.Fragment, null, React__default.createElement(Target, {
targetRef: this.getTarget,
target: target,
mode: mode,
isOpen: isOpen,
toggle: this.toggle,
open: this.open
}), isOpen ? React__default.createElement(ScrollLock, null) : null, React__default.createElement(TransitionProvider, {
isOpen: isOpen,
onEntered: onOpen,
onExited: onClose
}, transitionState => React__default.createElement(WrappedComponent, _extends({
close: this.close,
open: this.open,
getModalRef: this.getContent,
targetNode: this.targetNode,
contentNode: this.contentNode,
isOpen: isOpen,
mouseCoords: {
clientX,
clientY
},
style: transition(transitionState)
}, this.props))));
}
clientY
} = event;
setIsOpen(true);
setClientX(clientX);
setClientY(clientY);
};
}
const close = event => {
if (event && event.defaultPrevented) return;
setIsOpen(false);
setClientX(0);
setClientY(0);
};
_defineProperty(IntermediateComponent, "defaultProps", {
mode: 'click',
onClose: NOOP,
onOpen: NOOP
const toggle = event => {
if (isOpen) {
close(event);
} else {
open(event);
}
};
const getTarget = ref => {
targetNode.current = ref;
};
const getContent = ref => {
contentNode.current = ref;
};
return React__default.createElement(React.Fragment, null, React__default.createElement(Target, {
targetRef: getTarget,
target: target,
mode: mode,
isOpen: isOpen,
toggle: toggle,
open: open
}), isOpen && React__default.createElement(ScrollLock, null), React__default.createElement(TransitionProvider, {
isOpen: isOpen,
onEntered: onOpen,
onExited: onClose
}, transitionState => React__default.createElement(WrappedComponent, _extends({
close: close,
open: open,
getModalRef: getContent,
targetNode: targetNode.current,
contentNode: contentNode.current,
isOpen: isOpen,
mouseCoords: {
clientX,
clientY
},
style: transition(transitionState)
}, props))));
});
};
IntermediateComponent.displayName = getDisplayName(WrappedComponent);
return IntermediateComponent;
}
function generateUEID() {

@@ -382,0 +369,0 @@ let first = Math.random() * 46656 | 0;

@@ -36,3 +36,3 @@ "use strict";

const transitionDurationMs = 220, transitionDuration = "".concat(220, "ms"), transitionTimingFunction = "cubic-bezier(0.2, 0, 0, 1)", TransitionProvider = _ref => {
const transitionDurationMs = 220, transitionDuration = "220ms", transitionTimingFunction = "cubic-bezier(0.2, 0, 0, 1)", TransitionProvider = _ref => {
let {children: children, isOpen: isOpen} = _ref, props = _objectWithoutProperties(_ref, [ "children", "isOpen" ]);

@@ -59,3 +59,3 @@ return React__default.createElement(reactTransitionGroup.TransitionGroup, {

transitionProperty: transitionProperty,
transitionDuration: transitionDuration,
transitionDuration: "220ms",
transitionTimingFunction: transitionTimingFunction

@@ -65,3 +65,3 @@ };

const fade = transitionState => _objectSpread({}, makeTransitionBase("opacity"), {
const fade = transitionState => _objectSpread(_objectSpread({}, makeTransitionBase("opacity")), {}, {
opacity: {

@@ -78,3 +78,3 @@ entering: 1,

};
return _objectSpread({}, makeTransitionBase("opacity, transform"), {}, {
return _objectSpread(_objectSpread({}, makeTransitionBase("opacity, transform")), {
entering: {

@@ -92,5 +92,5 @@ opacity: 1

opacity: 0,
transform: "translate3d(0,".concat(from, ",0)")
transform: `translate3d(0,${from},0)`
};
return _objectSpread({}, makeTransitionBase("opacity, transform"), {}, {
return _objectSpread(_objectSpread({}, makeTransitionBase("opacity, transform")), {
entering: {

@@ -110,3 +110,3 @@ opacity: 1

const initial = fromMap[slideInFrom];
return _objectSpread({}, makeTransitionBase("transform"), {}, {
return _objectSpread(_objectSpread({}, makeTransitionBase("transform")), {
entering: {

@@ -119,6 +119,6 @@ transform: "translate3d(0,0,0)"

exiting: {
transform: "translate3d(".concat(initial, ", 0, 0)")
transform: `translate3d(${initial}, 0, 0)`
},
exited: {
transform: "translate3d(".concat(initial, ", 0, 0)")
transform: `translate3d(${initial}, 0, 0)`
}

@@ -129,3 +129,3 @@ }[transitionState]);

transitionProperty: "opacity, transform",
transitionDuration: transitionDuration,
transitionDuration: "220ms",
transitionTimingFunction: transitionTimingFunction

@@ -152,3 +152,3 @@ }, {

transitionProperty: "opacity, transform",
transitionDuration: transitionDuration,
transitionDuration: "220ms",
transitionTimingFunction: "cubic-bezier(0.2, 0, 0.16, 1.6)"

@@ -186,11 +186,3 @@ }, {

}, props));
};
function getDisplayName(C) {
return "withModalHandlers(".concat(C.displayName || C.name || "Component", ")");
}
const NOOP = () => {};
let Target = React.memo((function({isOpen: isOpen, mode: mode, target: target, targetRef: targetRef, open: open, toggle: toggle}) {
}, getDisplayName = C => `withModalHandlers(${C.displayName || C.name || "Component"})`, Target = React.memo(({isOpen: isOpen, mode: mode, target: target, targetRef: targetRef, open: open, toggle: toggle}) => {
const cloneProps = {

@@ -202,80 +194,69 @@ isActive: isOpen,

target(cloneProps);
}));
}), withModalHandlers = (WrappedComponent, {transition: transition}) => React.forwardRef((_ref, ref) => {
let {defaultIsOpen: defaultIsOpen = !1, mode: mode = "click", onClose: onClose = (() => {}), onOpen: onOpen = (() => {}), target: target} = _ref, props = _objectWithoutProperties(_ref, [ "defaultIsOpen", "mode", "onClose", "onOpen", "target" ]);
const [isOpen, setIsOpen] = React.useState(defaultIsOpen), [clientX, setClientX] = React.useState(0), [clientY, setClientY] = React.useState(0), contentNode = React.useRef(), targetNode = React.useRef();
var C;
React.useImperativeHandle(ref, () => ({
open: open,
close: close
})), React.useEffect(() => {
if (!isOpen) return;
const handleMouseDown = event => {
const {target: target} = event;
if (!(target instanceof HTMLElement || target instanceof SVGElement)) return;
const clickNotIn = node => !node.current.contains(target);
isOpen && clickNotIn(contentNode) && clickNotIn(targetNode) && close(event);
}, handleKeyDown = event => {
const {key: key} = event;
"Escape" === key && close(event);
};
return document.addEventListener("mousedown", handleMouseDown), document.addEventListener("keydown", handleKeyDown, !1),
() => {
document.removeEventListener("mousedown", handleMouseDown), document.removeEventListener("keydown", handleKeyDown, !1);
};
}, [ isOpen ]), React.useDebugValue(`withModalHandlers(${(C = WrappedComponent).displayName || C.name || "Component"})`);
const open = event => {
if (event.defaultPrevented) return;
"contextmenu" === mode && event.preventDefault();
const {clientX: clientX, clientY: clientY} = event;
setIsOpen(!0), setClientX(clientX), setClientY(clientY);
}, close = event => {
event && event.defaultPrevented || (setIsOpen(!1), setClientX(0), setClientY(0));
}, getContent = ref => {
contentNode.current = ref;
};
return React__default.createElement(React.Fragment, null, React__default.createElement(Target, {
targetRef: ref => {
targetNode.current = ref;
},
target: target,
mode: mode,
isOpen: isOpen,
toggle: event => {
isOpen ? close(event) : open(event);
},
open: open
}), isOpen && React__default.createElement(ScrollLock, null), React__default.createElement(TransitionProvider, {
isOpen: isOpen,
onEntered: onOpen,
onExited: onClose
}, transitionState => React__default.createElement(WrappedComponent, _extends({
close: close,
open: open,
getModalRef: getContent,
targetNode: targetNode.current,
contentNode: contentNode.current,
isOpen: isOpen,
mouseCoords: {
clientX: clientX,
clientY: clientY
},
style: transition(transitionState)
}, props))));
});
function withModalHandlers(WrappedComponent, {transition: transition}) {
class IntermediateComponent extends React.Component {
constructor(...args) {
super(...args), _defineProperty(this, "state", {
isOpen: this.props.defaultIsOpen,
clientX: 0,
clientY: 0
}), _defineProperty(this, "open", event => {
if (event.defaultPrevented) return;
"contextmenu" === this.props.mode && event.preventDefault();
const {clientX: clientX, clientY: clientY} = event;
this.setState({
isOpen: !0,
clientX: clientX,
clientY: clientY
}), document.addEventListener("mousedown", this.handleMouseDown), document.addEventListener("keydown", this.handleKeyDown, !1);
}), _defineProperty(this, "close", event => {
event && event.defaultPrevented || (this.setState({
isOpen: !1,
clientX: 0,
clientY: 0
}), document.removeEventListener("mousedown", this.handleMouseDown), document.removeEventListener("keydown", this.handleKeyDown, !1));
}), _defineProperty(this, "toggle", event => {
this.state.isOpen ? this.close(event) : this.open(event);
}), _defineProperty(this, "handleScroll", event => {
event.preventDefault();
}), _defineProperty(this, "handleMouseDown", event => {
const {target: target} = event, {isOpen: isOpen} = this.state;
(target instanceof HTMLElement || target instanceof SVGElement) && (!isOpen || this.contentNode.contains(target) || this.targetNode.contains(target) || this.close(event));
}), _defineProperty(this, "handleKeyDown", event => {
const {key: key} = event;
"Escape" === key && this.close(event);
}), _defineProperty(this, "getTarget", ref => {
this.targetNode = ref;
}), _defineProperty(this, "getContent", ref => {
this.contentNode = ref;
});
}
render() {
const {mode: mode, onClose: onClose, onOpen: onOpen, target: target} = this.props, {clientX: clientX, clientY: clientY, isOpen: isOpen} = this.state;
return React__default.createElement(React.Fragment, null, React__default.createElement(Target, {
targetRef: this.getTarget,
target: target,
mode: mode,
isOpen: isOpen,
toggle: this.toggle,
open: this.open
}), isOpen ? React__default.createElement(ScrollLock, null) : null, React__default.createElement(TransitionProvider, {
isOpen: isOpen,
onEntered: onOpen,
onExited: onClose
}, transitionState => React__default.createElement(WrappedComponent, _extends({
close: this.close,
open: this.open,
getModalRef: this.getContent,
targetNode: this.targetNode,
contentNode: this.contentNode,
isOpen: isOpen,
mouseCoords: {
clientX: clientX,
clientY: clientY
},
style: transition(transitionState)
}, this.props))));
}
}
return _defineProperty(IntermediateComponent, "defaultProps", {
mode: "click",
onClose: NOOP,
onOpen: NOOP
}), IntermediateComponent.displayName = getDisplayName(WrappedComponent), IntermediateComponent;
}
function generateUEID() {
let first = 46656 * Math.random() | 0, second = 46656 * Math.random() | 0;
return (first = ("000" + first.toString(36)).slice(-3)) + (second = ("000" + second.toString(36)).slice(-3));
return first = ("000" + first.toString(36)).slice(-3), second = ("000" + second.toString(36)).slice(-3),
first + second;
}

@@ -282,0 +263,0 @@

import _defineProperty from '@babel/runtime/helpers/esm/defineProperty';
import _extends from '@babel/runtime/helpers/esm/extends';
import _objectWithoutProperties from '@babel/runtime/helpers/esm/objectWithoutProperties';
import React, { memo, Component, Fragment } from 'react';
import React, { memo, forwardRef, useState, useRef, useImperativeHandle, useEffect, useDebugValue, Fragment } from 'react';
import { TransitionGroup, Transition } from 'react-transition-group';

@@ -15,3 +15,3 @@ import { jsx } from '@emotion/core';

const transitionDurationMs = 220;
const transitionDuration = "".concat(transitionDurationMs, "ms");
const transitionDuration = `${transitionDurationMs}ms`;
const transitionTimingFunction = 'cubic-bezier(0.2, 0, 0, 1)';

@@ -57,3 +57,3 @@ const TransitionProvider = (_ref) => {

const fade = transitionState => _objectSpread({}, makeTransitionBase('opacity'), {
const fade = transitionState => _objectSpread(_objectSpread({}, makeTransitionBase('opacity')), {}, {
opacity: {

@@ -73,3 +73,3 @@ entering: 1,

};
return _objectSpread({}, makeTransitionBase('opacity, transform'), {}, {
return _objectSpread(_objectSpread({}, makeTransitionBase('opacity, transform')), {
entering: {

@@ -90,5 +90,5 @@ opacity: 1

opacity: 0,
transform: "translate3d(0,".concat(from, ",0)")
transform: `translate3d(0,${from},0)`
};
return _objectSpread({}, makeTransitionBase('opacity, transform'), {}, {
return _objectSpread(_objectSpread({}, makeTransitionBase('opacity, transform')), {
entering: {

@@ -113,3 +113,3 @@ opacity: 1

const initial = fromMap[slideInFrom];
return _objectSpread({}, makeTransitionBase('transform'), {}, {
return _objectSpread(_objectSpread({}, makeTransitionBase('transform')), {
entering: {

@@ -122,6 +122,6 @@ transform: 'translate3d(0,0,0)'

exiting: {
transform: "translate3d(".concat(initial, ", 0, 0)")
transform: `translate3d(${initial}, 0, 0)`
},
exited: {
transform: "translate3d(".concat(initial, ", 0, 0)")
transform: `translate3d(${initial}, 0, 0)`
}

@@ -207,9 +207,7 @@ }[transitionState]);

function getDisplayName(C) {
return "withModalHandlers(".concat(C.displayName || C.name || 'Component', ")");
}
const getDisplayName = C => {
return `withModalHandlers(${C.displayName || C.name || 'Component'})`;
};
const NOOP = () => {};
let Target = memo(function Target({
const Target = memo(({
isOpen,

@@ -221,3 +219,3 @@ mode,

toggle
}) {
}) => {
const cloneProps = {

@@ -231,75 +229,52 @@ isActive: isOpen,

});
function withModalHandlers(WrappedComponent, {
const withModalHandlers = (WrappedComponent, {
transition
}) {
class IntermediateComponent extends Component {
constructor(...args) {
super(...args);
}) => {
return forwardRef((_ref, ref) => {
let {
defaultIsOpen = false,
mode = 'click',
onClose = () => {},
onOpen = () => {},
target
} = _ref,
props = _objectWithoutProperties(_ref, ["defaultIsOpen", "mode", "onClose", "onOpen", "target"]);
_defineProperty(this, "state", {
isOpen: this.props.defaultIsOpen,
clientX: 0,
clientY: 0
});
const [isOpen, setIsOpen] = useState(defaultIsOpen); // TODO: remove. Wrapped components (currently only Dropdown) use these for calculating position,
// but react-popper should be used instead
_defineProperty(this, "open", event => {
if (event.defaultPrevented) return;
if (this.props.mode === 'contextmenu') event.preventDefault();
const {
clientX,
clientY
} = event;
this.setState({
isOpen: true,
clientX,
clientY
});
document.addEventListener('mousedown', this.handleMouseDown);
document.addEventListener('keydown', this.handleKeyDown, false);
});
const [clientX, setClientX] = useState(0);
const [clientY, setClientY] = useState(0);
const contentNode = useRef();
const targetNode = useRef(); // Expose open() and close() for via ref
_defineProperty(this, "close", event => {
if (event && event.defaultPrevented) return;
this.setState({
isOpen: false,
clientX: 0,
clientY: 0
});
document.removeEventListener('mousedown', this.handleMouseDown);
document.removeEventListener('keydown', this.handleKeyDown, false);
});
useImperativeHandle(ref, () => ({
open,
close
}));
useEffect(() => {
// If the dialog was closed, don't do anything. The cleanup function already removed the handlers.
if (!isOpen) return;
_defineProperty(this, "toggle", event => {
if (this.state.isOpen) {
this.close(event);
} else {
this.open(event);
}
});
_defineProperty(this, "handleScroll", event => {
event.preventDefault();
});
_defineProperty(this, "handleMouseDown", event => {
const handleMouseDown = event => {
const {
target
} = event;
const {
isOpen
} = this.state;
if (!(target instanceof HTMLElement) && !(target instanceof SVGElement)) {
return;
} // NOTE: Why not use the <Blanket /> component to close?
// We don't want to interupt the user's flow. Taking this approach allows
}
const clickNotIn = node => !node.current.contains(target); // NOTE: Why not use the <Blanket /> component to close?
// We don't want to interrupt the user's flow. Taking this approach allows
// user to click "through" to other elements and close the popout.
if (isOpen && !this.contentNode.contains(target) && !this.targetNode.contains(target)) {
this.close(event);
if (isOpen && clickNotIn(contentNode) && clickNotIn(targetNode)) {
close(event);
}
});
};
_defineProperty(this, "handleKeyDown", event => {
const handleKeyDown = event => {
const {

@@ -310,65 +285,77 @@ key

if (key === 'Escape') {
this.close(event);
close(event);
}
});
};
_defineProperty(this, "getTarget", ref => {
this.targetNode = ref;
});
document.addEventListener('mousedown', handleMouseDown);
document.addEventListener('keydown', handleKeyDown, false);
return () => {
document.removeEventListener('mousedown', handleMouseDown);
document.removeEventListener('keydown', handleKeyDown, false);
};
}, [isOpen]);
useDebugValue(getDisplayName(WrappedComponent));
_defineProperty(this, "getContent", ref => {
this.contentNode = ref;
});
}
render() {
const open = event => {
if (event.defaultPrevented) return;
if (mode === 'contextmenu') event.preventDefault();
const {
mode,
onClose,
onOpen,
target
} = this.props;
const {
clientX,
clientY,
isOpen
} = this.state;
return React.createElement(Fragment, null, React.createElement(Target, {
targetRef: this.getTarget,
target: target,
mode: mode,
isOpen: isOpen,
toggle: this.toggle,
open: this.open
}), isOpen ? React.createElement(ScrollLock, null) : null, React.createElement(TransitionProvider, {
isOpen: isOpen,
onEntered: onOpen,
onExited: onClose
}, transitionState => React.createElement(WrappedComponent, _extends({
close: this.close,
open: this.open,
getModalRef: this.getContent,
targetNode: this.targetNode,
contentNode: this.contentNode,
isOpen: isOpen,
mouseCoords: {
clientX,
clientY
},
style: transition(transitionState)
}, this.props))));
}
clientY
} = event;
setIsOpen(true);
setClientX(clientX);
setClientY(clientY);
};
}
const close = event => {
if (event && event.defaultPrevented) return;
setIsOpen(false);
setClientX(0);
setClientY(0);
};
_defineProperty(IntermediateComponent, "defaultProps", {
mode: 'click',
onClose: NOOP,
onOpen: NOOP
const toggle = event => {
if (isOpen) {
close(event);
} else {
open(event);
}
};
const getTarget = ref => {
targetNode.current = ref;
};
const getContent = ref => {
contentNode.current = ref;
};
return React.createElement(Fragment, null, React.createElement(Target, {
targetRef: getTarget,
target: target,
mode: mode,
isOpen: isOpen,
toggle: toggle,
open: open
}), isOpen && React.createElement(ScrollLock, null), React.createElement(TransitionProvider, {
isOpen: isOpen,
onEntered: onOpen,
onExited: onClose
}, transitionState => React.createElement(WrappedComponent, _extends({
close: close,
open: open,
getModalRef: getContent,
targetNode: targetNode.current,
contentNode: contentNode.current,
isOpen: isOpen,
mouseCoords: {
clientX,
clientY
},
style: transition(transitionState)
}, props))));
});
};
IntermediateComponent.displayName = getDisplayName(WrappedComponent);
return IntermediateComponent;
}
function generateUEID() {

@@ -375,0 +362,0 @@ let first = Math.random() * 46656 | 0;

{
"name": "@arch-ui/modal-utils",
"description": "Modal Utilities as used in @keystonejs Admin UI.",
"version": "1.0.10",
"version": "1.0.11",
"author": "Jed Watson",

@@ -6,0 +6,0 @@ "license": "MIT",

@@ -1,11 +0,19 @@

import React, { Component, Fragment, memo } from 'react';
import React, {
Fragment,
memo,
forwardRef,
useState,
useDebugValue,
useEffect,
useRef,
useImperativeHandle,
} from 'react';
import ScrollLock from 'react-scrolllock';
import { TransitionProvider } from './transitions';
function getDisplayName(C) {
const getDisplayName = C => {
return `withModalHandlers(${C.displayName || C.name || 'Component'})`;
}
const NOOP = () => {};
};
let Target = memo(function Target({ isOpen, mode, target, targetRef, open, toggle }) {
const Target = memo(({ isOpen, mode, target, targetRef, open, toggle }) => {
const cloneProps = { isActive: isOpen, ref: targetRef };

@@ -17,99 +25,126 @@ if (mode === 'click') cloneProps.onClick = toggle;

export default function withModalHandlers(WrappedComponent, { transition }) {
class IntermediateComponent extends Component {
state = { isOpen: this.props.defaultIsOpen, clientX: 0, clientY: 0 };
static defaultProps = {
mode: 'click',
onClose: NOOP,
onOpen: NOOP,
};
const withModalHandlers = (WrappedComponent, { transition }) => {
return forwardRef(
(
{
defaultIsOpen = false,
mode = 'click',
onClose = () => {},
onOpen = () => {},
target,
...props
},
ref
) => {
const [isOpen, setIsOpen] = useState(defaultIsOpen);
open = event => {
if (event.defaultPrevented) return;
if (this.props.mode === 'contextmenu') event.preventDefault();
// TODO: remove. Wrapped components (currently only Dropdown) use these for calculating position,
// but react-popper should be used instead
const [clientX, setClientX] = useState(0);
const [clientY, setClientY] = useState(0);
const { clientX, clientY } = event;
const contentNode = useRef();
const targetNode = useRef();
this.setState({ isOpen: true, clientX, clientY });
// Expose open() and close() for via ref
useImperativeHandle(ref, () => ({ open, close }));
document.addEventListener('mousedown', this.handleMouseDown);
document.addEventListener('keydown', this.handleKeyDown, false);
};
close = event => {
if (event && event.defaultPrevented) return;
useEffect(() => {
// If the dialog was closed, don't do anything. The cleanup function already removed the handlers.
if (!isOpen) return;
this.setState({ isOpen: false, clientX: 0, clientY: 0 });
const handleMouseDown = event => {
const { target } = event;
document.removeEventListener('mousedown', this.handleMouseDown);
document.removeEventListener('keydown', this.handleKeyDown, false);
};
if (!(target instanceof HTMLElement) && !(target instanceof SVGElement)) {
return;
}
toggle = event => {
if (this.state.isOpen) {
this.close(event);
} else {
this.open(event);
}
};
const clickNotIn = node => !node.current.contains(target);
handleScroll = event => {
event.preventDefault();
};
handleMouseDown = event => {
const { target } = event;
const { isOpen } = this.state;
// NOTE: Why not use the <Blanket /> component to close?
// We don't want to interrupt the user's flow. Taking this approach allows
// user to click "through" to other elements and close the popout.
if (isOpen && clickNotIn(contentNode) && clickNotIn(targetNode)) {
close(event);
}
};
if (!(target instanceof HTMLElement) && !(target instanceof SVGElement)) {
return;
}
const handleKeyDown = event => {
const { key } = event;
// NOTE: Why not use the <Blanket /> component to close?
// We don't want to interupt the user's flow. Taking this approach allows
// user to click "through" to other elements and close the popout.
if (isOpen && !this.contentNode.contains(target) && !this.targetNode.contains(target)) {
this.close(event);
}
};
handleKeyDown = event => {
const { key } = event;
if (key === 'Escape') {
close(event);
}
};
if (key === 'Escape') {
this.close(event);
}
};
document.addEventListener('mousedown', handleMouseDown);
document.addEventListener('keydown', handleKeyDown, false);
getTarget = ref => {
this.targetNode = ref;
};
getContent = ref => {
this.contentNode = ref;
};
return () => {
document.removeEventListener('mousedown', handleMouseDown);
document.removeEventListener('keydown', handleKeyDown, false);
};
}, [isOpen]);
render() {
const { mode, onClose, onOpen, target } = this.props;
const { clientX, clientY, isOpen } = this.state;
useDebugValue(getDisplayName(WrappedComponent));
const open = event => {
if (event.defaultPrevented) return;
if (mode === 'contextmenu') event.preventDefault();
const { clientX, clientY } = event;
setIsOpen(true);
setClientX(clientX);
setClientY(clientY);
};
const close = event => {
if (event && event.defaultPrevented) return;
setIsOpen(false);
setClientX(0);
setClientY(0);
};
const toggle = event => {
if (isOpen) {
close(event);
} else {
open(event);
}
};
const getTarget = ref => {
targetNode.current = ref;
};
const getContent = ref => {
contentNode.current = ref;
};
return (
<Fragment>
<Target
targetRef={this.getTarget}
targetRef={getTarget}
target={target}
mode={mode}
isOpen={isOpen}
toggle={this.toggle}
open={this.open}
toggle={toggle}
open={open}
/>
{isOpen ? <ScrollLock /> : null}
{isOpen && <ScrollLock />}
<TransitionProvider isOpen={isOpen} onEntered={onOpen} onExited={onClose}>
{transitionState => (
<WrappedComponent
close={this.close}
open={this.open}
getModalRef={this.getContent}
targetNode={this.targetNode}
contentNode={this.contentNode}
close={close}
open={open}
getModalRef={getContent}
targetNode={targetNode.current}
contentNode={contentNode.current}
isOpen={isOpen}
mouseCoords={{ clientX, clientY }}
style={transition(transitionState)}
{...this.props}
{...props}
/>

@@ -121,5 +156,5 @@ )}

}
}
IntermediateComponent.displayName = getDisplayName(WrappedComponent);
return IntermediateComponent;
}
);
};
export default withModalHandlers;
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