[
  {
    "path": ".babelrc",
    "content": "{\n  \"presets\": [\"@babel/env\", \"@babel/react\"],\n  \"plugins\": [\n    [\"@babel/plugin-transform-runtime\"],\n    [\"babel-plugin-styled-components\", {\n      \"displayName\": true,\n      \"ssr\": false\n    }]\n  ]\n}\n"
  },
  {
    "path": ".circleci/config.yml",
    "content": "version: 2.1\n\n# Orbs are reusable packages of CircleCI configuration that you may share across projects, enabling you to create encapsulated, parameterized commands, jobs, and executors that can be used across multiple projects.\n# See: https://circleci.com/docs/2.0/orb-intro/\norbs:\n  node: circleci/node@5.0.2\n  codecov: codecov/codecov@3.2.3\n\n# Invoke jobs via workflows\n# See: https://circleci.com/docs/2.0/configuration-reference/#workflows\nworkflows:\n  test:\n    jobs:\n      - node/test:\n          # This is the node version to use for the `cimg/node` tag\n          # Relevant tags can be found on the CircleCI Developer Hub\n          # https://circleci.com/developer/images/image/cimg/node\n          version: \"16.17\"\n          pkg-manager: yarn\n          post-steps:\n            - codecov/upload\n"
  },
  {
    "path": ".codesandbox/ci.json",
    "content": "{\n  \"sandboxes\": [\"m9jlky57y\"]\n}\n"
  },
  {
    "path": ".eslintignore",
    "content": "build/\nnode_modules/\ncoverage/\n"
  },
  {
    "path": ".eslintrc",
    "content": "{\n  \"extends\": \"prettier\",\n  \"parser\": \"babel-eslint\",\n  \"plugins\": [\"prettier\", \"react\"]\n}\n"
  },
  {
    "path": ".gitignore",
    "content": "# dependencies\n/node_modules\n\n# misc\n.DS_Store\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n/coverage\n"
  },
  {
    "path": ".hound.yml",
    "content": "eslint:\n  enabled: true\n  config_file: .eslintrc\n  ignore_file: .eslintignore\n"
  },
  {
    "path": ".npmignore",
    "content": "coverage/\n"
  },
  {
    "path": ".nvmrc",
    "content": "v18.7.0\n"
  },
  {
    "path": ".prettierrc",
    "content": "{\n  \"printWidth\": 80,\n  \"tabWidth\": 2,\n  \"useTabs\": false,\n  \"semi\": true,\n  \"singleQuote\": false,\n  \"trailingComma\": \"none\",\n  \"bracketSpacing\": true,\n  \"jsxBracketSameLine\": false,\n  \"fluid\": false\n}\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright (c) 2022 Alexander Richey\n\nThis is free and unencumbered software released into the public domain.\n\nAnyone is free to copy, modify, publish, use, compile, sell, or\ndistribute this software, either in source code form or as a compiled\nbinary, for any purpose, commercial or non-commercial, and by any\nmeans.\n\nIn jurisdictions that recognize copyright laws, the author or authors\nof this software dedicate any and all copyright interest in the\nsoftware to the public domain. We make this dedication for the benefit\nof the public at large and to the detriment of our heirs and\nsuccessors. We intend this dedication to be an overt act of\nrelinquishment in perpetuity of all present and future rights to this\nsoftware under copyright law.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR\nOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\nFor more information, please refer to <http://unlicense.org>\n"
  },
  {
    "path": "README.md",
    "content": "# Styled React Modal\n\n[![style: styled-components](https://img.shields.io/badge/style-%F0%9F%92%85%20styled--components-orange.svg?colorB=daa357&colorA=db748e)](https://github.com/styled-components/styled-components) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)\n [![npm version](https://img.shields.io/npm/v/styled-react-modal.svg)](https://www.npmjs.com/package/styled-react-modal) [![npm downloads](https://img.shields.io/npm/dm/styled-react-modal.svg)](https://www.npmjs.com/package/styled-react-modal) [![CircleCI](https://dl.circleci.com/status-badge/img/gh/AlexanderRichey/styled-react-modal/tree/main.svg?style=shield)](https://dl.circleci.com/status-badge/redirect/gh/AlexanderRichey/styled-react-modal/tree/main) [![codecov](https://codecov.io/gh/AlexanderRichey/styled-react-modal/branch/main/graph/badge.svg)](https://codecov.io/gh/AlexanderRichey/styled-react-modal)\n\n> For support for **react <16.9**, please use **styled-react-modal@1.2.4**.\n\n> For support for **create-react-app <5.0.0**, please import from `styled-react-modal/build/umd`.\n\nStyled React Modal is built with styled-components. It uses the latest React 17.x features and exposes a familiar, easy to use API. It supports `beforeOpen()`, `afterOpen()`, and other lifecycle hooks so that animations can be handled easily. Unlike several other modal implementations in React, it does not pollute the DOM with excessive nodes.\n\n[**Demo on CodeSandbox**](https://codesandbox.io/s/m9jlky57y)\n\n## Install\n\n```\nnpm i -s styled-react-modal  # or use yarn\n```\n\n## Usage\n\nAdd the `<ModalProvider>` component near the top of your application's tree.\n\n```js\nimport React from 'react'\nimport { ModalProvider } from 'styled-react-modal'\n...\n\nexport default function App() {\n  return (\n    <ThemeProvider theme={theme}>\n      <ModalProvider>\n        <FancyModalButton />\n      </ModalProvider>\n    </ThemeProvider>\n  )\n}\n```\n\nUse the `<Modal>` component.\n\n> For instructions on how the make your modal accessible according to the [WAI-ARIA spec](https://www.w3.org/TR/wai-aria-practices/#dialog_modal), see [this CodeSandbox](https://codesandbox.io/s/styled-react-modal-a11y-9uco3?file=/src/index.js).\n\n```js\nimport Modal from 'styled-react-modal'\n...\n\nconst StyledModal = Modal.styled`\n  width: 20rem;\n  height: 20rem;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  background-color: ${props => props.theme.colors.white};\n`\n\nfunction FancyModalButton() {\n  const [isOpen, setIsOpen] = useState(false)\n\n  function toggleModal(e) {\n    setIsOpen(!isOpen)\n  }\n\n  return (\n    <div>\n      <button onClick={toggleModal}>Click me</button>\n      <StyledModal\n        isOpen={isOpen}\n        onBackgroundClick={toggleModal}\n        onEscapeKeydown={toggleModal}>\n        <span>I am a modal!</span>\n        <button onClick={toggleModal}>Close me</button>\n      </StyledModal>\n    </div>\n  )\n}\n```\n\n## API\n\n#### Top-Level Exports\n- `<ModalProvider>`\n- `Modal` \\(Default\\)\n  - `Modal.styled(styles)`\n  - `<Modal>`\n- `<BaseModalBackground>`\n\n<hr>\n\n### `<ModalProvider>`\n\nSets the root portal where `<Modal>`s will be rendered.\n\n**Props**\n\n- [`backgroundComponent`] \\(Component\\): A styled component to be used as the default modal background. If not provided, library defaults will be used.\n\n*Example:*\n\n```js\nimport { ModalProvider } from 'styled-react-modal'\n\nconst SpecialModalBackground = styled.div`\n  display: flex;\n  position: fixed;\n  top: 0;\n  left: 0;\n  width: 100vw;\n  height: 100vh;\n  z-index: 30;\n  opacity: ${props => props.opacity};\n  background-color: green;\n`\n\nexport default function App() {\n  return (\n    <ThemeProvider theme={theme}>\n      <ModalProvider backgroundComponent={SpecialModalBackground}>\n        <FancyModalButton />\n      </ModalProvider>\n    </ThemeProvider>\n  )\n}\n```\n\n### `Modal.styled(styles)`\n\nFactory method that accepts a tagged template literal and returns a `<Modal>` component with styles included.\n\n**Arguments**\n\n - `styles` \\(Tagged Template Literal\\): styled-components compatible css styles.\n\n*Example:*\n\n```js\nconst StyledModal = Modal.styled`\n  width: 20rem;\n  height: 20rem;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  background-color: ${props => props.theme.colors.white};\n`\n```\n\n### `<Modal>`\n\nRenders its children in a modal when open, nothing when not open.\n\n**Props**\n\n- `isOpen` \\(Boolean\\): A boolean that indicates whether the modal is to be open or closed.\n- [`onBackgroundClick`] \\(Function\\): A function that is called when the modal background is clicked.\n- [`onEscapeKeydown`] \\(Function\\): A function that is called when the escape key is pressed while the modal is open.\n- [`backgroundProps`] \\(Object\\): A props object that is spread over the `backgroundComponent` when included.\n- [`allowScroll`] \\(Boolean\\): When true, scrolling in the document body is not disabled when the modal is open.\n- [`beforeOpen`] \\(Function\\): A function that is called before the modal opens. If this function returns a promise, then the modal is opened after the promise is resolved.\n- [`afterOpen`] \\(Function\\): A function that is called after the modal opens.\n- [`beforeClose`] \\(Function\\): A function that is called before the modal closes. If this function returns a promise, then the modal is closed after the promise is resolved.\n- [`afterClose`] \\(Function\\): A function that is called after the modal closes.\n\n\n*Example:*\n\n```js\nimport Modal from 'styled-react-modal'\n\nfunction FancyModalButton() {\n  const [isOpen, setIsOpen] = useState(false)\n\n  function toggleModal(e) {\n    setIsOpen(!isOpen)\n  }\n\n  return (\n    <div>\n      <button onClick={toggleModal}>Click me</button>\n      <Modal\n        isOpen={isOpen}\n        onBackgroundClick={toggleModal}\n        onEscapeKeydown={toggleModal}>\n        <span>I am a modal!</span>\n        <button onClick={toggleModal}>Close me</button>\n      </Modal>\n    </div>\n  )\n}\n```\n\n### `<BaseModalBackground>`\n\nA convenience base component for making default background styles with `<ModalProvider>`.\n\n*Example:*\n\n```js\nconst SpecialModalBackground = styled(BaseModalBackground)`\n  background-color: green;\n`\n```\n"
  },
  {
    "path": "build/mjs/index.mjs",
    "content": "import e from\"styled-components\";import n,{useRef as r,useState as t,useEffect as o}from\"react\";import a from\"react-dom\";var c=e.div.withConfig({displayName:\"baseStyles__BaseModalBackground\"})([\"display:flex;position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:30;background-color:rgba(0,0,0,0.5);align-items:center;justify-content:center;\"]);function l(e,n){(null==n||n>e.length)&&(n=e.length);for(var r=0,t=new Array(n);r<n;r++)t[r]=e[r];return t}function i(e,n){return function(e){if(Array.isArray(e))return e}(e)||function(e,n){var r=null==e?null:\"undefined\"!=typeof Symbol&&e[Symbol.iterator]||e[\"@@iterator\"];if(null!=r){var t,o,a=[],c=!0,l=!1;try{for(r=r.call(e);!(c=(t=r.next()).done)&&(a.push(t.value),!n||a.length!==n);c=!0);}catch(e){l=!0,o=e}finally{try{c||null==r.return||r.return()}finally{if(l)throw o}}return a}}(e,n)||function(e,n){if(e){if(\"string\"==typeof e)return l(e,n);var r=Object.prototype.toString.call(e).slice(8,-1);return\"Object\"===r&&e.constructor&&(r=e.constructor.name),\"Map\"===r||\"Set\"===r?Array.from(e):\"Arguments\"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?l(e,n):void 0}}(e,n)||function(){throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\")}()}function u(){}function f(){}f.resetWarningCache=u;var p,s,d=function(){function e(e,n,r,t,o,a){if(\"SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED\"!==a){var c=new Error(\"Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types\");throw c.name=\"Invariant Violation\",c}}function n(){return e}e.isRequired=e;var r={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:n,element:e,elementType:e,instanceOf:n,node:e,objectOf:n,oneOf:n,oneOfType:n,shape:n,exact:n,checkPropTypes:f,resetWarningCache:u};return r.PropTypes=r,r},y=(p=function(e){e.exports=d()},p(s={exports:{}},s.exports),s.exports),m=y,b=n.createContext({}),v=b.Provider,g=b.Consumer;function h(e){var a=e.backgroundComponent,l=e.children,u=r(null),f=i(t(null),2),p=f[0],s=f[1],d=i(t(c),2),y=d[0],m=d[1];return o((function(){a&&m(a)}),[m,a]),o((function(){s(u.current)}),[s,u]),n.createElement(v,{value:{modalNode:p,BackgroundComponent:y}},l,n.createElement(\"div\",{ref:u}))}function O(){return O=Object.assign?Object.assign.bind():function(e){for(var n=1;n<arguments.length;n++){var r=arguments[n];for(var t in r)Object.prototype.hasOwnProperty.call(r,t)&&(e[t]=r[t])}return e},O.apply(this,arguments)}function w(e,n){if(null==e)return{};var r,t,o=function(e,n){if(null==e)return{};var r,t,o={},a=Object.keys(e);for(t=0;t<a.length;t++)r=a[t],n.indexOf(r)>=0||(o[r]=e[r]);return o}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(t=0;t<a.length;t++)r=a[t],n.indexOf(r)>=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}h.propTypes={backgroundComponent:m.oneOfType([m.element,m.object])};var C=[\"WrapperComponent\",\"children\",\"onBackgroundClick\",\"onEscapeKeydown\",\"allowScroll\",\"beforeOpen\",\"afterOpen\",\"beforeClose\",\"afterClose\",\"backgroundProps\",\"isOpen\"];function k(e){for(var n=arguments.length,r=new Array(n>1?n-1:0),t=1;t<n;t++)r[t-1]=arguments[t];e&&e.apply(void 0,r)}function E(e){var c,l=e.WrapperComponent,u=e.children,f=e.onBackgroundClick,p=e.onEscapeKeydown,s=e.allowScroll,d=e.beforeOpen,y=e.afterOpen,m=e.beforeClose,b=e.afterClose,v=e.backgroundProps,h=void 0===v?{}:v,E=e.isOpen,j=w(e,C),S=r(null),T=r(null),_=r(!1),P=i(t(!1),2),x=P[0],A=P[1];function B(e){S.current===e.target&&f&&f(e)}return o((function(){function e(e){A(e),k(e?y:b)}function n(n){if(n){var r=n();\"function\"==typeof(null==r?void 0:r.then)?(_.current=!0,r.then((function(){e(E),_.current=!1}))):e(E)}else e(E)}x===E||_.current||n(E?d:m)}),[_,x,E,d,m,b,y]),o((function(){function e(e){\"Escape\"===e.key&&p&&p(e)}return x&&document.addEventListener(\"keydown\",e),function(){document.removeEventListener(\"keydown\",e)}}),[x,p]),o((function(){return x&&!s&&(T.current=document.body.style.overflow,document.body.style.overflow=\"hidden\"),function(){s||(document.body.style.overflow=T.current||\"\")}}),[x,s]),c=l?n.createElement(l,j,u):u,n.createElement(g,null,(function(e){var r=e.modalNode,t=e.BackgroundComponent;return r&&t&&x?a.createPortal(n.createElement(t,O({},h,{onClick:B,ref:S}),c),r):null}))}E.styled=function(){for(var r=arguments.length,t=new Array(r),o=0;o<r;o++)t[o]=arguments[o];var a=t?e.div.withConfig({displayName:\"Modal__wrap\"}).apply(void 0,t):e.div.withConfig({displayName:\"Modal__wrap\"})();return function(e){return n.createElement(E,O({WrapperComponent:a},e))}},E.propTypes={WrapperComponent:m.oneOfType([m.element,m.object]),onBackgroundClick:m.func,onEscapeKeydown:m.func,allowScroll:m.bool,beforeOpen:m.func,afterOpen:m.func,beforeClose:m.func,afterClose:m.func,backgroundProps:m.object,isOpen:m.bool};export{c as BaseModalBackground,h as ModalProvider,E as default};\n"
  },
  {
    "path": "build/umd/index.js",
    "content": "!function(e,n){\"object\"==typeof exports&&\"undefined\"!=typeof module?n(exports,require(\"styled-components\"),require(\"react\"),require(\"react-dom\")):\"function\"==typeof define&&define.amd?define([\"exports\",\"styled-components\",\"react\",\"react-dom\"],n):n((e=\"undefined\"!=typeof globalThis?globalThis:e||self)[\"styled-react-modal\"]={},e.styled,e.React,e.ReactDOM)}(this,(function(e,n,t,r){\"use strict\";function o(e){return e&&\"object\"==typeof e&&\"default\"in e?e:{default:e}}var a=o(n),u=o(t),l=o(r),c=a.default.div.withConfig({displayName:\"baseStyles__BaseModalBackground\"})([\"display:flex;position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:30;background-color:rgba(0,0,0,0.5);align-items:center;justify-content:center;\"]);function f(e,n){(null==n||n>e.length)&&(n=e.length);for(var t=0,r=new Array(n);t<n;t++)r[t]=e[t];return r}function i(e,n){return function(e){if(Array.isArray(e))return e}(e)||function(e,n){var t=null==e?null:\"undefined\"!=typeof Symbol&&e[Symbol.iterator]||e[\"@@iterator\"];if(null!=t){var r,o,a=[],u=!0,l=!1;try{for(t=t.call(e);!(u=(r=t.next()).done)&&(a.push(r.value),!n||a.length!==n);u=!0);}catch(e){l=!0,o=e}finally{try{u||null==t.return||t.return()}finally{if(l)throw o}}return a}}(e,n)||function(e,n){if(e){if(\"string\"==typeof e)return f(e,n);var t=Object.prototype.toString.call(e).slice(8,-1);return\"Object\"===t&&e.constructor&&(t=e.constructor.name),\"Map\"===t||\"Set\"===t?Array.from(e):\"Arguments\"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?f(e,n):void 0}}(e,n)||function(){throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\")}()}function p(){}function d(){}d.resetWarningCache=p;var s=function(){function e(e,n,t,r,o,a){if(\"SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED\"!==a){var u=new Error(\"Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types\");throw u.name=\"Invariant Violation\",u}}function n(){return e}e.isRequired=e;var t={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:n,element:e,elementType:e,instanceOf:n,node:e,objectOf:n,oneOf:n,oneOfType:n,shape:n,exact:n,checkPropTypes:d,resetWarningCache:p};return t.PropTypes=t,t},y=function(e,n){return e(n={exports:{}},n.exports),n.exports}((function(e){e.exports=s()})),m=u.default.createContext({}),b=m.Provider,v=m.Consumer;function g(e){var n=e.backgroundComponent,r=e.children,o=t.useRef(null),a=i(t.useState(null),2),l=a[0],f=a[1],p=i(t.useState(c),2),d=p[0],s=p[1];return t.useEffect((function(){n&&s(n)}),[s,n]),t.useEffect((function(){f(o.current)}),[f,o]),u.default.createElement(b,{value:{modalNode:l,BackgroundComponent:d}},r,u.default.createElement(\"div\",{ref:o}))}function h(){return h=Object.assign?Object.assign.bind():function(e){for(var n=1;n<arguments.length;n++){var t=arguments[n];for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r])}return e},h.apply(this,arguments)}function O(e,n){if(null==e)return{};var t,r,o=function(e,n){if(null==e)return{};var t,r,o={},a=Object.keys(e);for(r=0;r<a.length;r++)t=a[r],n.indexOf(t)>=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)t=a[r],n.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}g.propTypes={backgroundComponent:y.oneOfType([y.element,y.object])};var w=[\"WrapperComponent\",\"children\",\"onBackgroundClick\",\"onEscapeKeydown\",\"allowScroll\",\"beforeOpen\",\"afterOpen\",\"beforeClose\",\"afterClose\",\"backgroundProps\",\"isOpen\"];function C(e){for(var n=arguments.length,t=new Array(n>1?n-1:0),r=1;r<n;r++)t[r-1]=arguments[r];e&&e.apply(void 0,t)}function k(e){var n,r=e.WrapperComponent,o=e.children,a=e.onBackgroundClick,c=e.onEscapeKeydown,f=e.allowScroll,p=e.beforeOpen,d=e.afterOpen,s=e.beforeClose,y=e.afterClose,m=e.backgroundProps,b=void 0===m?{}:m,g=e.isOpen,k=O(e,w),E=t.useRef(null),j=t.useRef(null),S=t.useRef(!1),T=i(t.useState(!1),2),_=T[0],P=T[1];function x(e){E.current===e.target&&a&&a(e)}return t.useEffect((function(){function e(e){P(e),C(e?d:y)}function n(n){if(n){var t=n();\"function\"==typeof(null==t?void 0:t.then)?(S.current=!0,t.then((function(){e(g),S.current=!1}))):e(g)}else e(g)}_===g||S.current||n(g?p:s)}),[S,_,g,p,s,y,d]),t.useEffect((function(){function e(e){\"Escape\"===e.key&&c&&c(e)}return _&&document.addEventListener(\"keydown\",e),function(){document.removeEventListener(\"keydown\",e)}}),[_,c]),t.useEffect((function(){return _&&!f&&(j.current=document.body.style.overflow,document.body.style.overflow=\"hidden\"),function(){f||(document.body.style.overflow=j.current||\"\")}}),[_,f]),n=r?u.default.createElement(r,k,o):o,u.default.createElement(v,null,(function(e){var t=e.modalNode,r=e.BackgroundComponent;return t&&r&&_?l.default.createPortal(u.default.createElement(r,h({},b,{onClick:x,ref:E}),n),t):null}))}k.styled=function(){for(var e=arguments.length,n=new Array(e),t=0;t<e;t++)n[t]=arguments[t];var r=n?a.default.div.withConfig({displayName:\"Modal__wrap\"}).apply(void 0,n):a.default.div.withConfig({displayName:\"Modal__wrap\"})();return function(e){return u.default.createElement(k,h({WrapperComponent:r},e))}},k.propTypes={WrapperComponent:y.oneOfType([y.element,y.object]),onBackgroundClick:y.func,onEscapeKeydown:y.func,allowScroll:y.bool,beforeOpen:y.func,afterOpen:y.func,beforeClose:y.func,afterClose:y.func,backgroundProps:y.object,isOpen:y.bool},e.BaseModalBackground=c,e.ModalProvider=g,e.default=k,Object.defineProperty(e,\"__esModule\",{value:!0})}));\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"styled-react-modal\",\n  \"version\": \"3.1.2\",\n  \"description\": \"A React modal built with styled-components.\",\n  \"main\": \"build/umd/index.js\",\n  \"module\": \"build/mjs/index.mjs\",\n  \"scripts\": {\n    \"test\": \"jest --coverage --verbose\",\n    \"lint\": \"prettier src/ tests/\",\n    \"prepublish\": \"yarn run build\",\n    \"build\": \"rollup -c rollup.config.js\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/AlexanderRichey/styled-react-modal.git\"\n  },\n  \"keywords\": [\n    \"react-modal\",\n    \"styled-components\",\n    \"modal\",\n    \"react\"\n  ],\n  \"tags\": [\n    \"react\",\n    \"modal\",\n    \"styled-components\"\n  ],\n  \"author\": \"Alexander Richey <alexander.richey@gmail.com>\",\n  \"license\": \"Unlicense\",\n  \"bugs\": {\n    \"url\": \"https://github.com/AlexanderRichey/styled-react-modal/issues\"\n  },\n  \"homepage\": \"https://github.com/AlexanderRichey/styled-react-modal#readme\",\n  \"peerDependencies\": {\n    \"react\": \">=18 <19\",\n    \"react-dom\": \">=18 <19\",\n    \"styled-components\": \"^6.1.1\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.19.1\",\n    \"@babel/plugin-transform-runtime\": \"^7.19.1\",\n    \"@babel/preset-env\": \"^7.19.1\",\n    \"@babel/preset-react\": \"^7.18.6\",\n    \"@rollup/plugin-babel\": \"^5.3.1\",\n    \"@rollup/plugin-node-resolve\": \"^14.1.0\",\n    \"@rollup/plugin-replace\": \"^4.0.0\",\n    \"@testing-library/dom\": \"^8.18.1\",\n    \"@testing-library/jest-dom\": \"^5.16.5\",\n    \"@testing-library/react\": \"^13.4.0\",\n    \"babel-eslint\": \"^10.1.0\",\n    \"babel-jest\": \"^29.0.3\",\n    \"babel-plugin-styled-components\": \"^2.0.7\",\n    \"babel-plugin-transform-object-rest-spread\": \"^6.26.0\",\n    \"eslint\": \"^8.23.1\",\n    \"eslint-config-prettier\": \"^8.5.0\",\n    \"eslint-plugin-prettier\": \"^4.2.1\",\n    \"eslint-plugin-react\": \"^7.31.8\",\n    \"jest\": \"^29.0.3\",\n    \"jest-environment-jsdom\": \"^29.0.3\",\n    \"prettier\": \"^2.7.1\",\n    \"react\": \"^18.2.0\",\n    \"react-dom\": \"^18.2.0\",\n    \"react-is\": \"^18.2.0\",\n    \"react-test-renderer\": \"^18.2.0\",\n    \"rollup\": \"^2.79.0\",\n    \"rollup-plugin-commonjs\": \"^10.1.0\",\n    \"rollup-plugin-terser\": \"^7.0.2\",\n    \"styled-components\": \"^6.1.1\"\n  },\n  \"resolutions\": {\n    \"eslint-utils\": \"^2.0.0\",\n    \"mixin-deep\": \"^2.0.1\",\n    \"set-value\": \"^3.0.2\",\n    \"minimist\": \"^0.2.1\",\n    \"acorn\": \"^6.4.1\",\n    \"kind-of\": \"^6.0.3\",\n    \"serialize-javascript\": \"^3.1.0\",\n    \"ssri\": \"^8.0.1\",\n    \"node-notifier\": \"^8.0.1\",\n    \"terser\": \"5.14.2\",\n    \"ajv\": \"6.12.6\"\n  },\n  \"jest\": {\n    \"coverageDirectory\": \"./coverage/\",\n    \"collectCoverage\": true,\n    \"testEnvironment\": \"jsdom\"\n  },\n  \"dependencies\": {\n    \"prop-types\": \"^15.8.1\"\n  },\n  \"packageManager\": \"yarn@1.22.19+sha1.4ba7fc5c6e704fce2066ecbfb0b0d8976fe62447\"\n}\n"
  },
  {
    "path": "rollup.config.js",
    "content": "import resolve from \"@rollup/plugin-node-resolve\";\nimport replace from \"@rollup/plugin-replace\";\nimport { terser } from \"rollup-plugin-terser\";\nimport babel from \"@rollup/plugin-babel\";\nimport commonjs from \"rollup-plugin-commonjs\";\n\nexport default {\n  input: \"src/index.jsx\",\n  output: [\n    {\n      name: \"styled-react-modal\",\n      file: \"build/umd/index.js\",\n      format: \"umd\",\n      exports: \"named\",\n      globals: {\n        react: \"React\",\n        \"react-dom\": \"ReactDOM\",\n        \"styled-components\": \"styled\"\n      }\n    },\n    {\n      name: \"styled-react-modal\",\n      exports: \"named\",\n      file: \"build/mjs/index.mjs\",\n      format: \"es\"\n    }\n  ],\n  plugins: [\n    resolve({\n      extensions: [\".jsx\", \".js\"],\n      moduleDirectories: [\"node_modules\"]\n    }),\n    replace({\n      \"process.env.NODE_ENV\": JSON.stringify(\"production\"),\n      preventAssignment: true\n    }),\n    commonjs({\n      include: /node_modules/\n    }),\n    babel({\n      babelHelpers: \"runtime\",\n      extensions: [\".jsx\", \".js\"],\n      exclude: /(node_modules|build)/\n    }),\n    terser()\n  ],\n  external: [\"react\", \"react-dom\", \"styled-components\"]\n};\n"
  },
  {
    "path": "src/Modal.jsx",
    "content": "import React, { useState, useRef, useEffect } from \"react\";\nimport ReactDOM from \"react-dom\";\nimport styled from \"styled-components\";\nimport PropTypes from \"prop-types\";\nimport { Consumer } from \"./context\";\n\nfunction callIfDefined(fun, ...args) {\n  fun && fun(...args);\n}\n\nfunction Modal({\n  WrapperComponent,\n  children,\n  onBackgroundClick,\n  onEscapeKeydown,\n  allowScroll,\n  beforeOpen,\n  afterOpen,\n  beforeClose,\n  afterClose,\n  backgroundProps = {},\n  isOpen: isOpenProp,\n  ...rest\n}) {\n  const node = useRef(null);\n  const prevBodyOverflowStyle = useRef(null);\n  const isTransitioning = useRef(false);\n\n  const [isOpen, setIsOpen] = useState(false);\n\n  // Handle opening and closing\n  useEffect(() => {\n    function handleIsOpenChange(value) {\n      setIsOpen(value);\n      value ? callIfDefined(afterOpen) : callIfDefined(afterClose);\n    }\n\n    function handleChange(callback) {\n      if (callback) {\n        const maybePromise = callback();\n        if (typeof maybePromise?.then === \"function\") {\n          isTransitioning.current = true;\n\n          maybePromise.then(() => {\n            handleIsOpenChange(isOpenProp);\n\n            isTransitioning.current = false;\n          });\n        } else {\n          handleIsOpenChange(isOpenProp);\n        }\n      } else {\n        handleIsOpenChange(isOpenProp);\n      }\n    }\n\n    if (isOpen !== isOpenProp && !isTransitioning.current) {\n      if (isOpenProp) {\n        handleChange(beforeOpen);\n      } else {\n        handleChange(beforeClose);\n      }\n    }\n  }, [\n    isTransitioning,\n    isOpen,\n    isOpenProp,\n    beforeOpen,\n    beforeClose,\n    afterClose,\n    afterOpen\n  ]);\n\n  // Handle Escape keydown\n  useEffect(() => {\n    function handleKeydown(e) {\n      if (e.key === \"Escape\") {\n        onEscapeKeydown && onEscapeKeydown(e);\n      }\n    }\n\n    if (isOpen) {\n      document.addEventListener(\"keydown\", handleKeydown);\n    }\n\n    return () => {\n      document.removeEventListener(\"keydown\", handleKeydown);\n    };\n  }, [isOpen, onEscapeKeydown]);\n\n  // Handle changing document.body styles based on isOpen state\n  useEffect(() => {\n    if (isOpen && !allowScroll) {\n      prevBodyOverflowStyle.current = document.body.style.overflow;\n      document.body.style.overflow = \"hidden\";\n    }\n\n    return () => {\n      if (!allowScroll) {\n        document.body.style.overflow = prevBodyOverflowStyle.current || \"\";\n      }\n    };\n  }, [isOpen, allowScroll]);\n\n  function handleBackgroundClick(e) {\n    if (node.current === e.target) {\n      onBackgroundClick && onBackgroundClick(e);\n    }\n  }\n\n  let content;\n  if (WrapperComponent) {\n    content = <WrapperComponent {...rest}>{children}</WrapperComponent>;\n  } else {\n    content = children;\n  }\n\n  return (\n    <Consumer>\n      {({ modalNode, BackgroundComponent }) => {\n        if (modalNode && BackgroundComponent && isOpen) {\n          return ReactDOM.createPortal(\n            <BackgroundComponent\n              {...backgroundProps}\n              onClick={handleBackgroundClick}\n              ref={node}\n            >\n              {content}\n            </BackgroundComponent>,\n            modalNode\n          );\n        } else {\n          return null;\n        }\n      }}\n    </Consumer>\n  );\n}\n\nModal.styled = function (...args) {\n  const wrap = args ? styled.div(...args) : styled.div();\n\n  return function (props) {\n    return <Modal WrapperComponent={wrap} {...props} />;\n  };\n};\n\nModal.propTypes = {\n  WrapperComponent: PropTypes.oneOfType([PropTypes.element, PropTypes.object]),\n  onBackgroundClick: PropTypes.func,\n  onEscapeKeydown: PropTypes.func,\n  allowScroll: PropTypes.bool,\n  beforeOpen: PropTypes.func,\n  afterOpen: PropTypes.func,\n  beforeClose: PropTypes.func,\n  afterClose: PropTypes.func,\n  backgroundProps: PropTypes.object,\n  isOpen: PropTypes.bool\n};\n\nexport default Modal;\n"
  },
  {
    "path": "src/ModalProvider.jsx",
    "content": "import React, { useState, useEffect, useRef } from \"react\";\nimport PropTypes from \"prop-types\";\nimport { BaseModalBackground } from \"./baseStyles\";\nimport { Provider } from \"./context\";\n\nfunction ModalProvider({\n  backgroundComponent: propsBackgroundComponent,\n  children\n}) {\n  const modalNode = useRef(null);\n  const [stateModalNode, setStateModalNode] = useState(null);\n  const [BackgroundComponent, setBackgroundComponent] = useState(\n    BaseModalBackground\n  );\n\n  useEffect(() => {\n    if (propsBackgroundComponent) {\n      setBackgroundComponent(propsBackgroundComponent);\n    }\n  }, [setBackgroundComponent, propsBackgroundComponent]);\n\n  useEffect(() => {\n    setStateModalNode(modalNode.current);\n  }, [setStateModalNode, modalNode]);\n\n  return (\n    <Provider\n      value={{\n        modalNode: stateModalNode,\n        BackgroundComponent: BackgroundComponent\n      }}\n    >\n      {children}\n      <div ref={modalNode} />\n    </Provider>\n  );\n}\n\nModalProvider.propTypes = {\n  backgroundComponent: PropTypes.oneOfType([\n    PropTypes.element,\n    PropTypes.object\n  ])\n};\n\nexport default ModalProvider;\n"
  },
  {
    "path": "src/baseStyles.jsx",
    "content": "import styled from 'styled-components'\n\nexport const BaseModalBackground = styled.div`\n  display: flex;\n  position: fixed;\n  top: 0;\n  left: 0;\n  width: 100vw;\n  height: 100vh;\n  z-index: 30;\n  background-color: rgba(0, 0, 0, 0.5);\n  align-items: center;\n  justify-content: center;\n`\n"
  },
  {
    "path": "src/context.jsx",
    "content": "import React from 'react'\n\nexport const { Provider, Consumer } = React.createContext({})\n"
  },
  {
    "path": "src/index.jsx",
    "content": "import { BaseModalBackground } from \"./baseStyles\";\nimport ModalProvider from \"./ModalProvider\";\nimport Modal from \"./Modal\";\n\nexport { Modal as default, ModalProvider, BaseModalBackground };\n"
  },
  {
    "path": "tests/Modal.test.jsx",
    "content": "import \"@testing-library/jest-dom/extend-expect\";\n\nimport React, { useState } from \"react\";\nimport { act } from \"react-dom/test-utils\";\nimport styled from \"styled-components\";\nimport { render, fireEvent, waitFor } from \"@testing-library/react\";\nimport Modal, { ModalProvider } from \"../src\";\n\nfunction StatefulModal(props) {\n  const { isOpen: propsIsOpen, ...rest } = props;\n  const [isOpen, setIsOpen] = useState(propsIsOpen);\n  return (\n    <div>\n      <button data-testid=\"button\" onClick={() => setIsOpen(!isOpen)}>\n        Click me\n      </button>\n      <Modal isOpen={isOpen} {...rest}>\n        <span data-testid=\"content\">Hello world</span>\n      </Modal>\n    </div>\n  );\n}\n\nfunction renderWithProvider(modalProps = {}, providerProps = {}) {\n  const finalModalProps = {\n    isOpen: false,\n    onBackgroundClick: jest.fn(),\n    onEscapeKeyDown: jest.fn(),\n    ...modalProps\n  };\n\n  return render(\n    <ModalProvider data-testid=\"provider\" {...providerProps}>\n      <StatefulModal {...finalModalProps} />\n    </ModalProvider>\n  );\n}\n\ndescribe(\"<Modal />\", () => {\n  it(\"renders nothing when not open\", () => {\n    const { queryByText } = renderWithProvider();\n    expect(queryByText(\"Hello world\")).toBeNull();\n  });\n\n  it(\"renders children when open\", () => {\n    const { getByText } = renderWithProvider({ isOpen: true });\n    expect(getByText(\"Hello world\")).toBeTruthy();\n  });\n\n  it(\"calls onBackgroundClick when the background is clicked\", () => {\n    const spy = jest.fn();\n    const { getByTestId } = renderWithProvider({\n      onBackgroundClick: spy,\n      isOpen: true,\n      backgroundProps: { \"data-testid\": \"background\" }\n    });\n    fireEvent.click(getByTestId(\"background\"));\n    expect(spy.mock.calls.length).toBe(1);\n  });\n\n  it(\"calls onEscapeKeydown when the escape key is pressed\", () => {\n    const spy = jest.fn();\n    renderWithProvider({\n      isOpen: true,\n      onEscapeKeydown: spy\n    });\n    fireEvent.keyDown(document, { key: \"Escape\" });\n    expect(spy.mock.calls.length).toBe(1);\n  });\n\n  it(\"calls beforeOpen() before it opens\", () => {\n    const spy = jest.fn();\n    const sleeper = jest.fn();\n    const { getByTestId } = renderWithProvider({\n      beforeOpen: spy,\n      beforeClose: sleeper\n    });\n    fireEvent.click(getByTestId(\"button\"));\n    expect(spy.mock.calls.length).toBe(1);\n    expect(sleeper).not.toHaveBeenCalled();\n  });\n\n  it(\"calls beforeOpen() before it opens and waits to call afterOpen() if it returns a promise\", async () => {\n    const spy = jest.fn(\n      () => new Promise((resolve) => setTimeout(act(resolve), 100))\n    );\n    const afterOpenSpy = jest.fn();\n    const sleeper = jest.fn();\n    const { getByTestId } = renderWithProvider({\n      beforeOpen: spy,\n      afterOpen: afterOpenSpy,\n      beforeClose: sleeper\n    });\n    fireEvent.click(getByTestId(\"button\"));\n    expect(spy.mock.calls.length).toBe(1);\n    await waitFor(() => expect(afterOpenSpy.mock.calls.length).toBe(1));\n    expect(sleeper).not.toHaveBeenCalled();\n  });\n\n  it(\"calls afterOpen() after it opens\", () => {\n    const spy = jest.fn();\n    const sleeper = jest.fn();\n    const { getByTestId } = renderWithProvider({\n      afterOpen: spy,\n      afterClose: sleeper\n    });\n    fireEvent.click(getByTestId(\"button\"));\n    expect(spy.mock.calls.length).toBe(1);\n    expect(sleeper).not.toHaveBeenCalled();\n  });\n\n  it(\"calls beforeClose() before it closes\", () => {\n    const spy = jest.fn();\n    const sleeper = jest.fn();\n    const { getByTestId } = renderWithProvider({\n      isOpen: true,\n      beforeClose: spy,\n      beforeOpen: sleeper\n    });\n    fireEvent.click(getByTestId(\"button\"));\n    expect(spy.mock.calls.length).toBe(1);\n    expect(sleeper.mock.calls.length).toBe(1);\n  });\n\n  it(\"calls beforeClose() before it closes and waits to call afterClose() if it returns a promise\", async () => {\n    const spy = jest.fn(\n      () => new Promise((resolve) => setTimeout(act(resolve), 100))\n    );\n    const afterCloseSpy = jest.fn();\n    const sleeper = jest.fn();\n    const { getByTestId } = renderWithProvider({\n      isOpen: true,\n      beforeClose: spy,\n      afterClose: afterCloseSpy,\n      beforeOpen: sleeper\n    });\n    fireEvent.click(getByTestId(\"button\"));\n    expect(spy.mock.calls.length).toBe(1);\n    await waitFor(() => expect(afterCloseSpy.mock.calls.length).toBe(1));\n    expect(sleeper.mock.calls.length).toBe(1);\n  });\n\n  it(\"calls afterClose() after it closes\", () => {\n    const spy = jest.fn();\n    const sleeper = jest.fn();\n    const { getByTestId } = renderWithProvider({\n      isOpen: true,\n      afterClose: spy,\n      afterOpen: sleeper\n    });\n    fireEvent.click(getByTestId(\"button\"));\n    expect(spy.mock.calls.length).toBe(1);\n    expect(sleeper.mock.calls.length).toBe(1);\n  });\n\n  it(\"passes background props to background\", () => {\n    const Background = styled.div`\n      background: ${(props) => props.color || \"green\"};\n    `;\n\n    const { getByTestId } = renderWithProvider(\n      {\n        isOpen: true,\n        backgroundProps: { color: \"blue\", \"data-testid\": \"background\" }\n      },\n      {\n        backgroundComponent: Background\n      }\n    );\n\n    expect(getByTestId(\"background\")).toHaveStyle(`background: blue`);\n  });\n});\n\ndescribe(\"Modal.styled()\", () => {\n  it(\"returns to a <Modal /> instance\", () => {\n    const StyledModal = Modal.styled`\n      background-color: green;\n    `;\n\n    const { getByTestId } = render(\n      <ModalProvider>\n        <StyledModal isOpen={true} data-testid=\"modal\" />\n      </ModalProvider>\n    );\n\n    expect(getByTestId(\"modal\")).toHaveStyle(`background-color: green`);\n  });\n});\n"
  }
]