├── .editorconfig
├── .eslintrc
├── .gitignore
├── .npmignore
├── .prettierrc
├── .travis.yml
├── LICENSE
├── README.md
├── _webpack.demo.config.js
├── demo
├── demo.jsx
├── demo2.jsx
├── demo3.jsx
├── demoPopup.html
├── exampleContainer.jsx
├── examples.js
├── index.html
└── test.css
├── lib
└── react-popout.tsx
├── package.json
├── test
└── react-popout.spec.jsx
└── tsconfig.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 |
3 | # A special property that should be specified at the top of the file outside of
4 | # any sections. Set to true to stop .editor config file search on current file
5 | root = true
6 |
7 | [*]
8 | # Indentation style
9 | # Possible values - tab, space
10 | indent_style = space
11 |
12 | # Indentation size in single-spaced characters
13 | # Possible values - an integer, tab
14 | indent_size = 4
15 |
16 | # Line ending file format
17 | # Possible values - lf, crlf, cr
18 | end_of_line = lf
19 |
20 | # File character encoding
21 | # Possible values - latin1, utf-8, utf-16be, utf-16le
22 | charset = utf-8
23 |
24 | # Denotes whether to trim whitespace at the end of lines
25 | # Possible values - true, false
26 | trim_trailing_whitespace = true
27 |
28 | # Denotes whether file should end with a newline
29 | # Possible values - true, false
30 | insert_final_newline = true
31 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env":{
3 | "browser":true,
4 | "es6":true,
5 | "mocha":true
6 | },
7 | "ecmaFeatures":{
8 | "modules":true,
9 | "jsx":true
10 | },
11 | "plugins": [
12 | "react"
13 | ],
14 | "parser": "babel-eslint",
15 | "rules": {
16 | "semi": 1,
17 | "global-strict": 0,
18 | "quotes": [2, "single"],
19 | "key-spacing": 0,
20 | "no-trailing-spaces": 0,
21 | "eol-last": 0,
22 | "no-underscore-dangle": 0,
23 | "no-console": 0
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # Runtime data
6 | pids
7 | *.pid
8 | *.seed
9 |
10 | # Directory for instrumented libs generated by jscoverage/JSCover
11 | lib-cov
12 |
13 | # Coverage directory used by tools like istanbul
14 | coverage
15 |
16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
17 | .grunt
18 |
19 | # node-waf configuration
20 | .lock-wscript
21 |
22 | # Compiled binary addons (http://nodejs.org/api/addons.html)
23 | build/Release
24 |
25 | # Dependency directory
26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
27 | node_modules
28 | *.orig
29 |
30 | demo/demo.js
31 | dist/react-popout.min.js
32 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | # Dependency directory
2 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
3 | node_modules
4 | *.orig
5 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 140,
3 | "tabWidth": 4,
4 | "singleQuote": true
5 | }
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "stable"
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Jake Ginnivan
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-popout
2 | React popout is a React component wrapping `window.open` allowing you to host content in a browser popup window.
3 |
4 | > npm install react-popout --save
5 |
6 | ## Demo
7 | To see it in action just go to [http://jake.ginnivan.net/react-popout](http://jake.ginnivan.net/react-popout)
8 |
9 | ## Usage
10 | Import with `es6`
11 | ```
12 | import Popout from 'react-popout'
13 | ```
14 | The usage is really simple. When the component is mounted the popup is open, and when it is unmounted the popup is closed.
15 |
16 | ``` js
17 |
18 |
Popped out content!
19 |
20 | ```
21 |
22 | To close the window programatically give the window a ref and use the `closeWindow` function.
23 |
24 | ## props
25 | ### title [required]
26 | Title for popup window.
27 |
28 | ### url [optional]
29 | URL of the page to load intially. Often needed for css. `about:blank` will be used if not specified.
30 |
31 | ### onClosing [optional]
32 | Called when popout window is closed, either by user or by calling close.
33 |
34 | ### options [optional]
35 | Object representing window options. See [the docs](https://developer.mozilla.org/en-US/docs/Web/API/Window/open#Position_and_size_features) for reference.
36 |
37 | Example:
38 | ``
39 |
40 | By default 500px wide, 400px high and centered over the window hosting the react component.
41 |
42 | You can also specify a function with signature `(options, window) => { }` to perform calculations.
43 | For example top is calculated with `(o, w) => ((w.innerHeight - o.height) / 2) + w.screenY`
44 |
45 | ### window [optional]
46 | Instead of using the `window` global, a window object can be passed in. It needs the following functions on it:
47 |
48 | `window.open(, , );` and return an object which looks like this:
49 |
50 | ```
51 | {
52 | onbeforeunload: () => { },
53 | onload: () => { },
54 | close: () => { },
55 | document: {
56 | title: string,
57 | body: {
58 | appendChild: (ele) => { }
59 | }
60 | }
61 | }
62 | ```
63 | This can be used if you need to intercept the calls and do something else.
64 |
65 | ### containerId [optional]
66 |
67 | Assigns an Id to the container that will be injected in the popup window `document.body`, defaults to `popout-content-container`, useful for cascading styles.
68 |
69 | Example:
70 | ```
71 | // input
72 |
73 |
74 |
75 |
76 | // output in new window:
77 |
17 | );
18 | }
19 | }
20 |
21 | const container = document.createElement('div');
22 | document.body.appendChild(container);
23 | const root = createRoot(container);
24 | root.render();
25 |
--------------------------------------------------------------------------------
/demo/examples.js:
--------------------------------------------------------------------------------
1 | !function(e){function t(o){if(n[o])return n[o].exports;var r=n[o]={exports:{},id:o,loaded:!1};return e[o].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){e.exports=n(1)},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{"default":e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function a(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}var i=function(){function e(e,t){for(var n=0;n-1&&-1===navigator.userAgent.indexOf("Edge")||navigator.userAgent.indexOf("Firefox")>-1)&&console.debug("Download the React DevTools for a better development experience: https://fb.me/react-devtools");var y=document.documentMode&&document.documentMode<8;"production"!==t.env.NODE_ENV?h(!y,'Internet Explorer is running in compatibility mode; please add the following tag to your HTML to prevent this from happening: '):void 0;for(var E=[Array.isArray,Array.prototype.every,Array.prototype.forEach,Array.prototype.indexOf,Array.prototype.map,Date.now,Function.prototype.bind,Object.keys,String.prototype.split,String.prototype.trim,Object.create,Object.freeze],N=0;N1)for(var n=1;n"+p+""},receiveComponent:function(e,t){if(e!==this._currentElement){this._currentElement=e;var n=""+e;if(n!==this._stringText){this._stringText=n;var r=i.getNode(this._rootNodeID);o.updateTextContent(r,n)}}},unmountComponent:function(){a.unmountIDFromEnvironment(this._rootNodeID)}}),e.exports=p}).call(t,n(5))},function(e,t,n){(function(t){"use strict";function o(e,t,n){var o=n>=e.childNodes.length?null:e.childNodes.item(n);e.insertBefore(t,o)}var r=n(9),a=n(17),i=n(19),u=n(20),s=n(21),l=n(14),c={dangerouslyReplaceNodeWithMarkup:r.dangerouslyReplaceNodeWithMarkup,updateTextContent:s,processUpdates:function(e,n){for(var i,c=null,p=null,d=0;d when using tables, nesting tags like