├── .eslintrc ├── .gitignore ├── .npmignore ├── .storybook ├── main.js └── manager.js ├── LICENSE ├── README.md ├── babel.config.js ├── docs ├── favicon.ico ├── iframe.html ├── index.html ├── main.27952d3a6b14f5ecc993.bundle.js ├── main.4d4dbb2cceb1c5ede223.bundle.js ├── main.4d4dbb2cceb1c5ede223.bundle.js.map ├── runtime~main.4d4dbb2cceb1c5ede223.bundle.js ├── runtime~main.4d4dbb2cceb1c5ede223.bundle.js.map ├── runtime~main.a70cae47b0d915ec6f24.bundle.js ├── sb_dll │ ├── storybook_ui-manifest.json │ ├── storybook_ui_dll.LICENCE │ └── storybook_ui_dll.js ├── vendors~main.4d4dbb2cceb1c5ede223.bundle.js ├── vendors~main.4d4dbb2cceb1c5ede223.bundle.js.LICENSE.txt ├── vendors~main.4d4dbb2cceb1c5ede223.bundle.js.map └── vendors~main.f0b534b6167fcffad00e.bundle.js ├── index.js ├── package-lock.json ├── package.json ├── scripts └── mocha_runner.js ├── src ├── __tests__ │ ├── Cell.js │ ├── Row.js │ ├── Table.js │ ├── config.js │ └── index.js └── index.js ├── stories ├── Basic │ └── index.js ├── Borders │ └── index.js ├── Button │ ├── index.css │ └── index.js ├── ChangingContent │ └── index.js ├── CustomZ │ └── index.js ├── MultipleChangingStickies │ └── index.js ├── NoBorders │ └── index.js ├── NoColumn │ └── index.js ├── NoHeader │ └── index.js ├── Playground │ └── index.js ├── ResizingCells │ ├── index.css │ └── index.js ├── StickyAllSides │ └── index.js ├── demo.css └── index.stories.js └── yarn.lock /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "env": { 4 | "browser": true, 5 | "node": true, 6 | "es6": true 7 | }, 8 | "parserOptions": { 9 | "ecmaVersion": 6, 10 | "sourceType": "module", 11 | "ecmaFeatures": { 12 | "jsx": true 13 | } 14 | }, 15 | "rules": { 16 | "no-bitwise": 2, 17 | "no-else-return": 2, 18 | "no-eq-null": 2, 19 | "no-extra-parens": 0, 20 | "no-floating-decimal": 2, 21 | "no-lonely-if": 2, 22 | "no-multiple-empty-lines": [2, {"max": 3}], 23 | "no-self-compare": 2, 24 | "no-underscore-dangle": 0, 25 | "no-use-before-define": 0, 26 | "no-unused-expressions": 0, 27 | "no-void": 2, 28 | "brace-style": [2, "1tbs"], 29 | "camelcase": [1, {"properties": "never"}], 30 | "consistent-return": 0, 31 | "comma-style": [2, "last"], 32 | "complexity": [1, 12], 33 | "func-names": 0, 34 | "guard-for-in": 2, 35 | "indent": [2, 2], 36 | "max-len": [0, 120, 4], 37 | "new-cap": [2, {"newIsCap": true, "capIsNew": false}], 38 | "quotes": [2, "single"], 39 | "keyword-spacing": [2, {"before": true, "after": true}], 40 | "space-before-blocks": [2, "always"], 41 | "array-bracket-spacing": [2, "never"], 42 | "space-in-parens": [2, "never"], 43 | "strict": [0], 44 | "valid-jsdoc": 2, 45 | "wrap-iife": [2, "any"], 46 | "yoda": [1, "never"] 47 | }, 48 | "plugins": [ 49 | "react" 50 | ], 51 | "globals": { 52 | 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *~ 3 | *.iml 4 | .*.haste_cache.* 5 | .DS_Store 6 | .idea 7 | npm-debug.log 8 | node_modules 9 | dist 10 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *~ 3 | *.iml 4 | .*.haste_cache.* 5 | .DS_Store 6 | .idea 7 | .babelrc 8 | .eslintrc 9 | npm-debug.log 10 | lib 11 | docs 12 | stories 13 | .storybook 14 | src 15 | babel.config.js 16 | scripts 17 | dist/__tests__ 18 | -------------------------------------------------------------------------------- /.storybook/main.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | stories: ['../stories/**/*.stories.js'], 3 | addons: ['@storybook/addon-knobs'] 4 | }; -------------------------------------------------------------------------------- /.storybook/manager.js: -------------------------------------------------------------------------------- 1 | import { addons } from '@storybook/addons'; 2 | import { create } from '@storybook/theming/create'; 3 | import { version } from '../package.json'; 4 | 5 | addons.setConfig({ 6 | panelPosition: 'bottom', 7 | theme: create({ 8 | base: 'light', 9 | brandTitle: `react-sticky-table@${version}` 10 | }) 11 | }); -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Max Hudson. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React Sticky Table 2 | 3 | Responsive and dynamically-sized fixed headers, footers, and columns for tables. 4 | 5 | SEEKING EXAMPLE LINKS - please comment in [this issue](https://github.com/henrybuilt/react-sticky-table/issues/94) with your applications using react-sticky-table 6 | 7 | [Demo](https://henrybuilt.github.io/react-sticky-table/) 8 | 9 | ## Features 10 | 11 | - 0 dependencies, no css import necessary, no js, highly performant. 12 | - 0, 1, or AS MANY sticky headers, left columns, right columns, footers as you want. 13 | - Responsive table dimensions (wrap it in any size container and it will fill that container) 14 | - Dynamic row height & column width (no need to specify fixed width/height in pixels) 15 | - Table rows/columns resize as content resizes 16 | - Custom cells (just make sure your custom cell has `display: table-cell` and the css selector `.sticky-table-cell`) 17 | - Multiple tables per page 18 | - Scrollbars that are smooth and visible at all times 19 | - Native scrolling 20 | 21 | ### Top todos 22 | 23 | - Use VirtualDom implementation 24 | - Support IE <= 11 25 | 26 | ## Getting Started 27 | 28 | ``` 29 | npm install react-sticky-table --save 30 | ``` 31 | 32 | ## Example 33 | ```javascript 34 | import React, {Component} from 'react'; 35 | import {StickyTable, Row, Cell} from 'react-sticky-table'; 36 | 37 | export default class BasicExample extends Component { 38 | render() { 39 | return ( 40 |
41 |
42 | 43 | 44 | Header 1 45 | Header 2 46 | 47 | 48 | Cell 1 49 | Cell 2 50 | 51 | 52 |
53 |
54 | ); 55 | } 56 | } 57 | ``` 58 | 59 | ## Props 60 | 61 | - sticky count 62 | - `stickyHeaderCount`: `int` - default: `1` 63 | - `leftStickyColumnCount`: `int` - default: `1` 64 | - `rightStickyColumnCount`: `int` - default: `0` 65 | - `stickyFooterCount`: `int` - default: `0` 66 | - z-index 67 | - `headerZ`: `int` - default: `2` (sticky corners are the greater of their two sides + 1) 68 | - `leftColumnZ`: `int` - default: `2` 69 | - `rightColumnZ`: `int` - default: `2` 70 | - `footerZ`: `int` - default: `2` 71 | - border 72 | - `borderWidth`: default: `'2px'` 73 | - `borderColor`: default: `'#e5e5e5'` 74 | - `wrapperRef`: default: `undefined`, value: `React ref` - a reference you can use for the wrapper element that has scroll events on it 75 | 76 | Disable sticky header: 77 | 78 | ```javascript 79 | 80 | ``` 81 | 82 | Disable sticky column: 83 | 84 | ```javascript 85 | 86 | ``` 87 | 88 | Disable borders: 89 | 90 | ```javascript 91 | 92 | ``` 93 | 94 | ## License 95 | 96 | (The MIT License) 97 | 98 | Copyright (c) 2017 Henrybuilt. 99 | 100 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 101 | 102 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 103 | 104 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 105 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@babel/preset-react', 4 | [ 5 | '@babel/preset-env', 6 | { 7 | corejs: 3, 8 | modules: 'commonjs', 9 | // TODO - figure it out how to make it work on test 10 | // modules: false, 11 | useBuiltIns: false 12 | } 13 | ] 14 | ], 15 | plugins: ['@babel/plugin-proposal-class-properties'], 16 | env: { 17 | test: { 18 | presets: [ 19 | [ 20 | '@babel/preset-env', 21 | { 22 | corejs: 3, 23 | useBuiltIns: 'usage', 24 | } 25 | ], 26 | '@babel/preset-react' 27 | ], 28 | plugins: ['@babel/plugin-proposal-class-properties'] 29 | } 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henrybuilt/react-sticky-table/ecb63f943380a65c92c88b40523ccf4a7732dc2b/docs/favicon.ico -------------------------------------------------------------------------------- /docs/iframe.html: -------------------------------------------------------------------------------- 1 | Storybook

No Preview

Sorry, but you either have no stories or none are selected somehow.

  • Please check the Storybook config.
  • Try reloading the page.

If the problem persists, check the browser console, or the terminal you've run Storybook from.

-------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | Storybook
-------------------------------------------------------------------------------- /docs/main.27952d3a6b14f5ecc993.bundle.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[0],{1245:function(t,n,e){e(334),e(584),e(1357),t.exports=e(1246)},1357:function(t,n,e){"use strict";e.r(n);var o=e(90),a=e(0),c=e(437);o.addons.setConfig({panelPosition:"bottom",theme:Object(a.create)({base:"light",brandTitle:"react-sticky-table@".concat(c.a)})})},437:function(t){t.exports=JSON.parse('{"a":"5.1.4"}')},64:function(t,n){}},[[1245,1,2]]]); -------------------------------------------------------------------------------- /docs/main.4d4dbb2cceb1c5ede223.bundle.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[0],{2:function(module,__webpack_exports__,__webpack_require__){"use strict";__webpack_require__.d(__webpack_exports__,"c",(function(){return StickyTable})),__webpack_require__.d(__webpack_exports__,"b",(function(){return Row})),__webpack_require__.d(__webpack_exports__,"a",(function(){return Cell}));__webpack_require__(8),__webpack_require__(14),__webpack_require__(15),__webpack_require__(30),__webpack_require__(41),__webpack_require__(67),__webpack_require__(97),__webpack_require__(47),__webpack_require__(9),__webpack_require__(162),__webpack_require__(154),__webpack_require__(10),__webpack_require__(118),__webpack_require__(69),__webpack_require__(42),__webpack_require__(25),__webpack_require__(265),__webpack_require__(18),__webpack_require__(266),__webpack_require__(24),__webpack_require__(48),__webpack_require__(26),__webpack_require__(6),__webpack_require__(31),__webpack_require__(20),__webpack_require__(16),__webpack_require__(17),__webpack_require__(96);var react__WEBPACK_IMPORTED_MODULE_28__=__webpack_require__(0),react__WEBPACK_IMPORTED_MODULE_28___default=__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_28__),styled_components__WEBPACK_IMPORTED_MODULE_29__=__webpack_require__(72);function _typeof(obj){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(obj){return typeof obj}:function(obj){return obj&&"function"==typeof Symbol&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj})(obj)}function _extends(){return(_extends=Object.assign||function(target){for(var source,i=1;iarr.length)&&(len=arr.length);for(var i=0,arr2=Array(len);ir;r++){cells=[];for(var c=0;20>c;c++)cells.push(react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(_src__WEBPACK_IMPORTED_MODULE_15__.a,{key:c},(0==r?"Header ":"Cell ")+c));rows.push(react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(_src__WEBPACK_IMPORTED_MODULE_15__.b,{key:r},cells))}return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement("div",null,react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement("div",{style:{width:"100%",height:"200px"}},react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(_src__WEBPACK_IMPORTED_MODULE_15__.c,null,rows)))}}]),Basic}(react__WEBPACK_IMPORTED_MODULE_14__.Component);Basic.displayName="Basic",Basic.__docgenInfo={description:"",methods:[],displayName:"Basic"},"undefined"!=typeof STORYBOOK_REACT_CLASSES&&(STORYBOOK_REACT_CLASSES["stories/Basic/index.js"]={name:"Basic",docgenInfo:Basic.__docgenInfo,path:"stories/Basic/index.js"})},285:function(module,__webpack_exports__,__webpack_require__){"use strict";__webpack_require__.d(__webpack_exports__,"a",(function(){return StickyAllSides}));__webpack_require__(8),__webpack_require__(14),__webpack_require__(15),__webpack_require__(9),__webpack_require__(10),__webpack_require__(25),__webpack_require__(18),__webpack_require__(24),__webpack_require__(26),__webpack_require__(6),__webpack_require__(31),__webpack_require__(20),__webpack_require__(16),__webpack_require__(17);var react__WEBPACK_IMPORTED_MODULE_14__=__webpack_require__(0),react__WEBPACK_IMPORTED_MODULE_14___default=__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_14__),_src__WEBPACK_IMPORTED_MODULE_15__=__webpack_require__(2);function _typeof(obj){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(obj){return typeof obj}:function(obj){return obj&&"function"==typeof Symbol&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj})(obj)}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor))throw new TypeError("Cannot call a class as a function")}function _defineProperties(target,props){for(var descriptor,i=0;ir;r++){cells=[];for(var title,c=0;20>c;c++)title="Cell ",0==r&&(title="Header "),49==r&&(title="Footer "),cells.push(react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(_src__WEBPACK_IMPORTED_MODULE_15__.a,{key:c},title+c));rows.push(react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(_src__WEBPACK_IMPORTED_MODULE_15__.b,{key:r},cells))}return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement("div",null,react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement("div",{style:{width:"100%",height:"200px"}},react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(_src__WEBPACK_IMPORTED_MODULE_15__.c,{leftStickyColumnCount:1,rightStickyColumnCount:1,stickyHeaderCount:1,stickyFooterCount:1},rows)))}}]),StickyAllSides}(react__WEBPACK_IMPORTED_MODULE_14__.Component);StickyAllSides.displayName="StickyAllSides",StickyAllSides.__docgenInfo={description:"",methods:[],displayName:"StickyAllSides"},"undefined"!=typeof STORYBOOK_REACT_CLASSES&&(STORYBOOK_REACT_CLASSES["stories/StickyAllSides/index.js"]={name:"StickyAllSides",docgenInfo:StickyAllSides.__docgenInfo,path:"stories/StickyAllSides/index.js"})},286:function(module,__webpack_exports__,__webpack_require__){"use strict";__webpack_require__.d(__webpack_exports__,"a",(function(){return Borders}));__webpack_require__(8),__webpack_require__(14),__webpack_require__(15),__webpack_require__(9),__webpack_require__(10),__webpack_require__(25),__webpack_require__(18),__webpack_require__(24),__webpack_require__(26),__webpack_require__(6),__webpack_require__(31),__webpack_require__(20),__webpack_require__(16),__webpack_require__(17);var react__WEBPACK_IMPORTED_MODULE_14__=__webpack_require__(0),react__WEBPACK_IMPORTED_MODULE_14___default=__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_14__),_src__WEBPACK_IMPORTED_MODULE_15__=__webpack_require__(2);function _typeof(obj){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(obj){return typeof obj}:function(obj){return obj&&"function"==typeof Symbol&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj})(obj)}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor))throw new TypeError("Cannot call a class as a function")}function _defineProperties(target,props){for(var descriptor,i=0;ir;r++){cells=[];for(var c=0;20>c;c++)cells.push(react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(_src__WEBPACK_IMPORTED_MODULE_15__.a,{key:c},(0==r?"Header ":"Cell ")+c));rows.push(react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(_src__WEBPACK_IMPORTED_MODULE_15__.b,{key:r},cells))}return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement("div",null,react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement("div",{style:{width:"100%",height:"200px"}},react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(_src__WEBPACK_IMPORTED_MODULE_15__.c,{borderWidth:"1px",borderColor:"blue"},rows)))}}]),Borders}(react__WEBPACK_IMPORTED_MODULE_14__.Component);Borders.displayName="Borders",Borders.__docgenInfo={description:"",methods:[],displayName:"Borders"},"undefined"!=typeof STORYBOOK_REACT_CLASSES&&(STORYBOOK_REACT_CLASSES["stories/Borders/index.js"]={name:"Borders",docgenInfo:Borders.__docgenInfo,path:"stories/Borders/index.js"})},287:function(module,__webpack_exports__,__webpack_require__){"use strict";__webpack_require__.d(__webpack_exports__,"a",(function(){return NoBorders}));__webpack_require__(8),__webpack_require__(14),__webpack_require__(15),__webpack_require__(9),__webpack_require__(10),__webpack_require__(25),__webpack_require__(18),__webpack_require__(24),__webpack_require__(26),__webpack_require__(6),__webpack_require__(31),__webpack_require__(20),__webpack_require__(16),__webpack_require__(17);var react__WEBPACK_IMPORTED_MODULE_14__=__webpack_require__(0),react__WEBPACK_IMPORTED_MODULE_14___default=__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_14__),_src__WEBPACK_IMPORTED_MODULE_15__=__webpack_require__(2);function _typeof(obj){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(obj){return typeof obj}:function(obj){return obj&&"function"==typeof Symbol&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj})(obj)}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor))throw new TypeError("Cannot call a class as a function")}function _defineProperties(target,props){for(var descriptor,i=0;ir;r++){cells=[];for(var c=0;20>c;c++)cells.push(react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(_src__WEBPACK_IMPORTED_MODULE_15__.a,{key:c},(0==r?"Header ":"Cell ")+c));rows.push(react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(_src__WEBPACK_IMPORTED_MODULE_15__.b,{key:r},cells))}return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement("div",null,react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement("div",{style:{width:"100%",height:"200px"}},react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(_src__WEBPACK_IMPORTED_MODULE_15__.c,{borderWidth:0},rows)))}}]),NoBorders}(react__WEBPACK_IMPORTED_MODULE_14__.Component);NoBorders.displayName="NoBorders",NoBorders.__docgenInfo={description:"",methods:[],displayName:"NoBorders"},"undefined"!=typeof STORYBOOK_REACT_CLASSES&&(STORYBOOK_REACT_CLASSES["stories/NoBorders/index.js"]={name:"NoBorders",docgenInfo:NoBorders.__docgenInfo,path:"stories/NoBorders/index.js"})},288:function(module,__webpack_exports__,__webpack_require__){"use strict";__webpack_require__.d(__webpack_exports__,"a",(function(){return NoHeader}));__webpack_require__(8),__webpack_require__(14),__webpack_require__(15),__webpack_require__(9),__webpack_require__(10),__webpack_require__(25),__webpack_require__(18),__webpack_require__(24),__webpack_require__(26),__webpack_require__(6),__webpack_require__(31),__webpack_require__(20),__webpack_require__(16),__webpack_require__(17);var react__WEBPACK_IMPORTED_MODULE_14__=__webpack_require__(0),react__WEBPACK_IMPORTED_MODULE_14___default=__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_14__),_src__WEBPACK_IMPORTED_MODULE_15__=__webpack_require__(2);function _typeof(obj){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(obj){return typeof obj}:function(obj){return obj&&"function"==typeof Symbol&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj})(obj)}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor))throw new TypeError("Cannot call a class as a function")}function _defineProperties(target,props){for(var descriptor,i=0;ir;r++){cells=[];for(var c=0;20>c;c++)cells.push(react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(_src__WEBPACK_IMPORTED_MODULE_15__.a,{key:c},(1>r?"Header ":"Cell ")+c));rows.push(react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(_src__WEBPACK_IMPORTED_MODULE_15__.b,{key:r},cells))}return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement("div",null,react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement("div",{style:{width:"100%",height:"200px"}},react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(_src__WEBPACK_IMPORTED_MODULE_15__.c,{stickyColumnCount:0,stickyHeaderCount:1},rows)))}}]),NoHeader}(react__WEBPACK_IMPORTED_MODULE_14__.Component);NoHeader.displayName="NoHeader",NoHeader.__docgenInfo={description:"",methods:[],displayName:"NoHeader"},"undefined"!=typeof STORYBOOK_REACT_CLASSES&&(STORYBOOK_REACT_CLASSES["stories/NoColumn/index.js"]={name:"NoHeader",docgenInfo:NoHeader.__docgenInfo,path:"stories/NoColumn/index.js"})},289:function(module,__webpack_exports__,__webpack_require__){"use strict";__webpack_require__.d(__webpack_exports__,"a",(function(){return NoHeader}));__webpack_require__(8),__webpack_require__(14),__webpack_require__(15),__webpack_require__(9),__webpack_require__(10),__webpack_require__(25),__webpack_require__(18),__webpack_require__(24),__webpack_require__(26),__webpack_require__(6),__webpack_require__(31),__webpack_require__(20),__webpack_require__(16),__webpack_require__(17);var react__WEBPACK_IMPORTED_MODULE_14__=__webpack_require__(0),react__WEBPACK_IMPORTED_MODULE_14___default=__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_14__),_src__WEBPACK_IMPORTED_MODULE_15__=__webpack_require__(2);function _typeof(obj){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(obj){return typeof obj}:function(obj){return obj&&"function"==typeof Symbol&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj})(obj)}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor))throw new TypeError("Cannot call a class as a function")}function _defineProperties(target,props){for(var descriptor,i=0;ir;r++){cells=[];for(var c=0;20>c;c++)cells.push(react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(_src__WEBPACK_IMPORTED_MODULE_15__.a,{key:c},(0==r?"Header ":"Cell ")+c));rows.push(react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(_src__WEBPACK_IMPORTED_MODULE_15__.b,{key:r},cells))}return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement("div",null,react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement("div",{style:{width:"100%",height:"200px"}},react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(_src__WEBPACK_IMPORTED_MODULE_15__.c,{stickyHeaderCount:0,stickyColumnCount:1},rows)))}}]),NoHeader}(react__WEBPACK_IMPORTED_MODULE_14__.Component);NoHeader.displayName="NoHeader",NoHeader.__docgenInfo={description:"",methods:[],displayName:"NoHeader"},"undefined"!=typeof STORYBOOK_REACT_CLASSES&&(STORYBOOK_REACT_CLASSES["stories/NoHeader/index.js"]={name:"NoHeader",docgenInfo:NoHeader.__docgenInfo,path:"stories/NoHeader/index.js"})},290:function(module,__webpack_exports__,__webpack_require__){"use strict";__webpack_require__.d(__webpack_exports__,"a",(function(){return ResizingCells}));__webpack_require__(8),__webpack_require__(14),__webpack_require__(15),__webpack_require__(9),__webpack_require__(10),__webpack_require__(25),__webpack_require__(18),__webpack_require__(24),__webpack_require__(26),__webpack_require__(6),__webpack_require__(31),__webpack_require__(20),__webpack_require__(16),__webpack_require__(17);var react__WEBPACK_IMPORTED_MODULE_14__=__webpack_require__(0),react__WEBPACK_IMPORTED_MODULE_14___default=__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_14__),_src__WEBPACK_IMPORTED_MODULE_15__=__webpack_require__(2);__webpack_require__(636);function _typeof(obj){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(obj){return typeof obj}:function(obj){return obj&&"function"==typeof Symbol&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj})(obj)}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor))throw new TypeError("Cannot call a class as a function")}function _defineProperties(target,props){for(var descriptor,i=0;i"+Math.floor(1e9*Math.random())}},{key:"render",value:function render(){for(var cells,rows=[],r=0;50>r;r++){cells=[];for(var c=0;20>c;c++)cells.push(react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(_src__WEBPACK_IMPORTED_MODULE_15__.a,{key:c,onClick:this.onCellClick},"Click Me!"));rows.push(react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(_src__WEBPACK_IMPORTED_MODULE_15__.b,{key:r},cells))}return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement("div",{className:"resizing-cells"},react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement("div",{style:{width:"100%",height:"200px"}},react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(_src__WEBPACK_IMPORTED_MODULE_15__.c,null,rows)))}}]),ResizingCells}(react__WEBPACK_IMPORTED_MODULE_14__.Component);ResizingCells.displayName="ResizingCells",ResizingCells.__docgenInfo={description:"",methods:[{name:"onCellClick",docblock:null,modifiers:[],params:[{name:"event",type:null}],returns:null}],displayName:"ResizingCells"},"undefined"!=typeof STORYBOOK_REACT_CLASSES&&(STORYBOOK_REACT_CLASSES["stories/ResizingCells/index.js"]={name:"ResizingCells",docgenInfo:ResizingCells.__docgenInfo,path:"stories/ResizingCells/index.js"})},291:function(module,__webpack_exports__,__webpack_require__){"use strict";__webpack_require__.d(__webpack_exports__,"a",(function(){return CustomZ}));__webpack_require__(8),__webpack_require__(14),__webpack_require__(15),__webpack_require__(9),__webpack_require__(10),__webpack_require__(25),__webpack_require__(18),__webpack_require__(24),__webpack_require__(26),__webpack_require__(6),__webpack_require__(31),__webpack_require__(20),__webpack_require__(16),__webpack_require__(17);var react__WEBPACK_IMPORTED_MODULE_14__=__webpack_require__(0),react__WEBPACK_IMPORTED_MODULE_14___default=__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_14__),_src__WEBPACK_IMPORTED_MODULE_15__=__webpack_require__(2);function _typeof(obj){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(obj){return typeof obj}:function(obj){return obj&&"function"==typeof Symbol&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj})(obj)}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor))throw new TypeError("Cannot call a class as a function")}function _defineProperties(target,props){for(var descriptor,i=0;ir;r++){cells=[];for(var c=0;20>c;c++)cells.push(react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(_src__WEBPACK_IMPORTED_MODULE_15__.a,{key:c},(0==r?"Header ":"Cell ")+c));rows.push(react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(_src__WEBPACK_IMPORTED_MODULE_15__.b,{key:r},cells))}return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement("div",null,react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement("div",{style:{width:"100%",height:"200px"}},react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(_src__WEBPACK_IMPORTED_MODULE_15__.c,{headerZ:4,columnZ:5},rows)))}}]),CustomZ}(react__WEBPACK_IMPORTED_MODULE_14__.Component);CustomZ.displayName="CustomZ",CustomZ.__docgenInfo={description:"",methods:[],displayName:"CustomZ"},"undefined"!=typeof STORYBOOK_REACT_CLASSES&&(STORYBOOK_REACT_CLASSES["stories/CustomZ/index.js"]={name:"CustomZ",docgenInfo:CustomZ.__docgenInfo,path:"stories/CustomZ/index.js"})},292:function(module,__webpack_exports__,__webpack_require__){"use strict";__webpack_require__.d(__webpack_exports__,"a",(function(){return MultipleResizingStickies}));__webpack_require__(8),__webpack_require__(14),__webpack_require__(15),__webpack_require__(9),__webpack_require__(10),__webpack_require__(25),__webpack_require__(18),__webpack_require__(24),__webpack_require__(26),__webpack_require__(6),__webpack_require__(31),__webpack_require__(20),__webpack_require__(16),__webpack_require__(17);var react__WEBPACK_IMPORTED_MODULE_14__=__webpack_require__(0),react__WEBPACK_IMPORTED_MODULE_14___default=__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_14__),_src__WEBPACK_IMPORTED_MODULE_15__=__webpack_require__(2);function _typeof(obj){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(obj){return typeof obj}:function(obj){return obj&&"function"==typeof Symbol&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj})(obj)}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor))throw new TypeError("Cannot call a class as a function")}function _defineProperties(target,props){for(var descriptor,i=0;i"+Math.floor(1e9*Math.random())}},{key:"render",value:function render(){for(var cells,rows=[],r=0;50>r;r++){cells=[];for(var c=0;20>c;c++)cells.push(react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(_src__WEBPACK_IMPORTED_MODULE_15__.a,{key:c,onClick:this.onCellClick},"Click Me!"));rows.push(react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(_src__WEBPACK_IMPORTED_MODULE_15__.b,{key:r},cells))}return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement("div",{className:"resizing-cells"},react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement("div",{style:{width:"100%",height:"400px"}},react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(_src__WEBPACK_IMPORTED_MODULE_15__.c,{leftStickyColumnCount:3,rightStickyColumnCount:3,stickyHeaderCount:3,stickyFooterCount:3},rows)))}}]),MultipleResizingStickies}(react__WEBPACK_IMPORTED_MODULE_14__.Component);MultipleResizingStickies.displayName="MultipleResizingStickies",MultipleResizingStickies.__docgenInfo={description:"",methods:[{name:"onCellClick",docblock:null,modifiers:[],params:[{name:"event",type:null}],returns:null}],displayName:"MultipleResizingStickies"},"undefined"!=typeof STORYBOOK_REACT_CLASSES&&(STORYBOOK_REACT_CLASSES["stories/MultipleChangingStickies/index.js"]={name:"MultipleResizingStickies",docgenInfo:MultipleResizingStickies.__docgenInfo,path:"stories/MultipleChangingStickies/index.js"})},293:function(module,__webpack_exports__,__webpack_require__){"use strict";__webpack_require__.d(__webpack_exports__,"a",(function(){return Playground}));__webpack_require__(8),__webpack_require__(14),__webpack_require__(15),__webpack_require__(30),__webpack_require__(9),__webpack_require__(10),__webpack_require__(25),__webpack_require__(18),__webpack_require__(24),__webpack_require__(26),__webpack_require__(6),__webpack_require__(31),__webpack_require__(20),__webpack_require__(16),__webpack_require__(17);var react__WEBPACK_IMPORTED_MODULE_15__=__webpack_require__(0),react__WEBPACK_IMPORTED_MODULE_15___default=__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_15__),_src__WEBPACK_IMPORTED_MODULE_16__=__webpack_require__(2);function _typeof(obj){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(obj){return typeof obj}:function(obj){return obj&&"function"==typeof Symbol&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj})(obj)}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor))throw new TypeError("Cannot call a class as a function")}function _defineProperties(target,props){for(var descriptor,i=0;ir;r++){cells=[];for(var c=0;20>c;c++)cells.push(react__WEBPACK_IMPORTED_MODULE_15___default.a.createElement(_src__WEBPACK_IMPORTED_MODULE_16__.a,{key:c},0==r?"Header ".concat(c):"Cell (".concat(r,", ").concat(c,")")));rows.push(react__WEBPACK_IMPORTED_MODULE_15___default.a.createElement(_src__WEBPACK_IMPORTED_MODULE_16__.b,{key:r},cells))}var _this$props=this.props,stickyHeaderCount=_this$props.stickyHeaderCount,leftStickyColumnCount=_this$props.leftStickyColumnCount,rightStickyColumnCount=_this$props.rightStickyColumnCount,stickyFooterCount=_this$props.stickyFooterCount,height=_this$props.height,width=_this$props.width;return react__WEBPACK_IMPORTED_MODULE_15___default.a.createElement("div",null,react__WEBPACK_IMPORTED_MODULE_15___default.a.createElement("div",{style:{width:width,height:height}},react__WEBPACK_IMPORTED_MODULE_15___default.a.createElement(_src__WEBPACK_IMPORTED_MODULE_16__.c,{stickyHeaderCount:stickyHeaderCount,leftStickyColumnCount:leftStickyColumnCount,rightStickyColumnCount:rightStickyColumnCount,stickyFooterCount:stickyFooterCount},rows)))}}]),Playground}(react__WEBPACK_IMPORTED_MODULE_15__.Component);Playground.displayName="Playground",Playground.__docgenInfo={description:"",methods:[],displayName:"Playground"},"undefined"!=typeof STORYBOOK_REACT_CLASSES&&(STORYBOOK_REACT_CLASSES["stories/Playground/index.js"]={name:"Playground",docgenInfo:Playground.__docgenInfo,path:"stories/Playground/index.js"})},294:function(module,__webpack_exports__,__webpack_require__){"use strict";__webpack_require__.d(__webpack_exports__,"a",(function(){return ChangingContent_ChangingContent}));__webpack_require__(8),__webpack_require__(14),__webpack_require__(15),__webpack_require__(9),__webpack_require__(10),__webpack_require__(118),__webpack_require__(25),__webpack_require__(18),__webpack_require__(24),__webpack_require__(26),__webpack_require__(6),__webpack_require__(31),__webpack_require__(20),__webpack_require__(16),__webpack_require__(17);var react=__webpack_require__(0),react_default=__webpack_require__.n(react),src=__webpack_require__(2);__webpack_require__(42),__webpack_require__(634);function _typeof(obj){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(obj){return typeof obj}:function(obj){return obj&&"function"==typeof Symbol&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj})(obj)}function _extends(){return(_extends=Object.assign||function(target){for(var source,i=1;ir;r++){cells=[];for(var c=0;20>c;c++)cells.push(react_default.a.createElement(src.a,{key:c},(0==r?"Header ":"Cell ")+c));rows.push(react_default.a.createElement(src.b,{key:r},cells))}return _this.state={rows:rows},_this}return function ChangingContent_createClass(Constructor,protoProps,staticProps){return protoProps&&ChangingContent_defineProperties(Constructor.prototype,protoProps),staticProps&&ChangingContent_defineProperties(Constructor,staticProps),Constructor}(ChangingContent,[{key:"changeContent",value:function changeContent(){for(var cells,rows=[],r=0;50>r;r++){cells=[];for(var c=0;20>c;c++)cells.push(react_default.a.createElement(src.a,{key:c},(0==r?"New Header ":"Cell ")+c));rows.push(react_default.a.createElement(src.b,{key:r},cells))}this.setState({rows:rows})}},{key:"render",value:function render(){return react_default.a.createElement("div",null,react_default.a.createElement(Button_Button,{onClick:this.changeContent.bind(this)},"Change content"),_ref,_ref2,react_default.a.createElement("div",{style:{width:"100%",height:"200px"}},react_default.a.createElement(src.c,{stickyColumnCount:0},this.state.rows)))}}]),ChangingContent}(react.Component);ChangingContent_ChangingContent.displayName="ChangingContent",ChangingContent_ChangingContent.__docgenInfo={description:"",methods:[{name:"changeContent",docblock:null,modifiers:[],params:[],returns:null}],displayName:"ChangingContent"},"undefined"!=typeof STORYBOOK_REACT_CLASSES&&(STORYBOOK_REACT_CLASSES["stories/ChangingContent/index.js"]={name:"ChangingContent",docgenInfo:ChangingContent_ChangingContent.__docgenInfo,path:"stories/ChangingContent/index.js"})},295:function(module,exports,__webpack_require__){__webpack_require__(296),__webpack_require__(441),__webpack_require__(442),module.exports=__webpack_require__(599)},360:function(module,exports){},599:function(module,__webpack_exports__,__webpack_require__){"use strict";__webpack_require__.r(__webpack_exports__),function(module){var _storybook_react__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(98);module._StorybookPreserveDecorators=!0,Object(_storybook_react__WEBPACK_IMPORTED_MODULE_0__.configure)([__webpack_require__(628)],module)}.call(this,__webpack_require__(276)(module))},628:function(module,exports,__webpack_require__){var map={"./index.stories.js":629};function webpackContext(req){var id=webpackContextResolve(req);return __webpack_require__(id)}function webpackContextResolve(req){if(!__webpack_require__.o(map,req)){var e=new Error("Cannot find module '"+req+"'");throw e.code="MODULE_NOT_FOUND",e}return map[req]}webpackContext.keys=function webpackContextKeys(){return Object.keys(map)},webpackContext.resolve=webpackContextResolve,module.exports=webpackContext,webpackContext.id=628},629:function(module,__webpack_exports__,__webpack_require__){"use strict";__webpack_require__.r(__webpack_exports__),function(module){var react__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(0),react__WEBPACK_IMPORTED_MODULE_0___default=__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__),_storybook_react__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(98),_storybook_addon_knobs_react__WEBPACK_IMPORTED_MODULE_2__=__webpack_require__(58),_Basic_index__WEBPACK_IMPORTED_MODULE_4__=(__webpack_require__(631),__webpack_require__(281)),_StickyAllSides_index__WEBPACK_IMPORTED_MODULE_5__=__webpack_require__(285),_Borders_index__WEBPACK_IMPORTED_MODULE_6__=__webpack_require__(286),_NoBorders_index__WEBPACK_IMPORTED_MODULE_7__=__webpack_require__(287),_ChangingContent_index__WEBPACK_IMPORTED_MODULE_8__=__webpack_require__(294),_NoColumn_index__WEBPACK_IMPORTED_MODULE_9__=__webpack_require__(288),_NoHeader_index__WEBPACK_IMPORTED_MODULE_10__=__webpack_require__(289),_ResizingCells_index__WEBPACK_IMPORTED_MODULE_11__=__webpack_require__(290),_CustomZ_index__WEBPACK_IMPORTED_MODULE_12__=__webpack_require__(291),_MultipleChangingStickies_index__WEBPACK_IMPORTED_MODULE_13__=__webpack_require__(292),_Playground_index__WEBPACK_IMPORTED_MODULE_14__=__webpack_require__(293),_ref=react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_Basic_index__WEBPACK_IMPORTED_MODULE_4__.a,null),_ref2=react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_MultipleChangingStickies_index__WEBPACK_IMPORTED_MODULE_13__.a,null),_ref3=react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_StickyAllSides_index__WEBPACK_IMPORTED_MODULE_5__.a,null),_ref4=react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_NoColumn_index__WEBPACK_IMPORTED_MODULE_9__.a,null),_ref5=react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_NoHeader_index__WEBPACK_IMPORTED_MODULE_10__.a,null),_ref6=react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_ChangingContent_index__WEBPACK_IMPORTED_MODULE_8__.a,null),_ref7=react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_ResizingCells_index__WEBPACK_IMPORTED_MODULE_11__.a,null),_ref8=react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_Borders_index__WEBPACK_IMPORTED_MODULE_6__.a,null),_ref9=react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_NoBorders_index__WEBPACK_IMPORTED_MODULE_7__.a,null),_ref10=react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_CustomZ_index__WEBPACK_IMPORTED_MODULE_12__.a,null);Object(_storybook_react__WEBPACK_IMPORTED_MODULE_1__.storiesOf)("Basic",module).add("basic",(function(){return _ref})).add("multiple changing stickies",(function(){return _ref2})).add("sticky on all sides",(function(){return _ref3})).add("only sticky header",(function(){return _ref4})).add("only sticky column",(function(){return _ref5})).add("dynamically changing content",(function(){return _ref6})).add("resizing cells",(function(){return _ref7})).add("custom borders",(function(){return _ref8})).add("no borders",(function(){return _ref9})).add("custom z-index",(function(){return _ref10})),Object(_storybook_react__WEBPACK_IMPORTED_MODULE_1__.storiesOf)("Playground").addDecorator(_storybook_addon_knobs_react__WEBPACK_IMPORTED_MODULE_2__.withKnobs).add("sticky tests",(function(){return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_Playground_index__WEBPACK_IMPORTED_MODULE_14__.a,{stickyHeaderCount:Object(_storybook_addon_knobs_react__WEBPACK_IMPORTED_MODULE_2__.number)("HeaderSticky",0,{min:0}),leftStickyColumnCount:Object(_storybook_addon_knobs_react__WEBPACK_IMPORTED_MODULE_2__.number)("LeftSticky",0,{min:0}),rightStickyColumnCount:Object(_storybook_addon_knobs_react__WEBPACK_IMPORTED_MODULE_2__.number)("RightSticky",0,{min:0}),stickyFooterCount:Object(_storybook_addon_knobs_react__WEBPACK_IMPORTED_MODULE_2__.number)("FooterSticky",0,{min:0}),width:Object(_storybook_addon_knobs_react__WEBPACK_IMPORTED_MODULE_2__.text)("width","100%"),height:Object(_storybook_addon_knobs_react__WEBPACK_IMPORTED_MODULE_2__.text)("height","200px")})}))}.call(this,__webpack_require__(276)(module))},631:function(module,exports,__webpack_require__){var api=__webpack_require__(174),content=__webpack_require__(632);"string"==typeof(content=content.__esModule?content.default:content)&&(content=[[module.i,content,""]]);var options={insert:"head",singleton:!1};api(content,options);module.exports=content.locals||{}},632:function(module,exports,__webpack_require__){(exports=__webpack_require__(175)(!1)).push([module.i,'/* Elements */\nbody, html{\n margin: 0;\n padding: 0;\n font-size: 100%;\n}\nbody, a, input, select, textarea, h1, h2, h3{\n color: #000;\n font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";\n font-weight: normal;\n}\nh2, h3{\n font-weight: 400;\n}\nbody, a, input, select, textarea{\n font-size: 0.8rem;\n}\na{\n text-decoration: none;\n}\nh1{\n border-bottom: 2px solid #ddd;\n padding-bottom: 0.5rem;\n font-weight: 300;\n}\n\n/* General */\n.clearfix:after {\n content: "";\n display: table;\n clear: both;\n}\n.left {\n float: left;\n}\n.right {\n float: right;\n}\n',""]),module.exports=exports},634:function(module,exports,__webpack_require__){var api=__webpack_require__(174),content=__webpack_require__(635);"string"==typeof(content=content.__esModule?content.default:content)&&(content=[[module.i,content,""]]);var options={insert:"head",singleton:!1};api(content,options);module.exports=content.locals||{}},635:function(module,exports,__webpack_require__){(exports=__webpack_require__(175)(!1)).push([module.i,".button{\n background-color: #eee;\n padding: 0.5rem 1rem;\n border-bottom: 2px solid #ddd;\n display: inline-block;\n cursor: pointer;\n}\n.button:hover{\n opacity: 0.8;\n}\n",""]),module.exports=exports},636:function(module,exports,__webpack_require__){var api=__webpack_require__(174),content=__webpack_require__(637);"string"==typeof(content=content.__esModule?content.default:content)&&(content=[[module.i,content,""]]);var options={insert:"head",singleton:!1};api(content,options);module.exports=content.locals||{}},637:function(module,exports,__webpack_require__){(exports=__webpack_require__(175)(!1)).push([module.i,".resizing-cells .row:not(:first-child) .cell:not(:first-child){\n cursor: pointer;\n}\n.resizing-cells .row:not(:first-child) .cell:not(:first-child):hover{\n background-color: #f5f5f5;\n}\n",""]),module.exports=exports}},[[295,1,2]]]); 2 | //# sourceMappingURL=main.4d4dbb2cceb1c5ede223.bundle.js.map -------------------------------------------------------------------------------- /docs/main.4d4dbb2cceb1c5ede223.bundle.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"main.4d4dbb2cceb1c5ede223.bundle.js","sources":["webpack:///main.4d4dbb2cceb1c5ede223.bundle.js"],"mappings":"AAAA","sourceRoot":""} -------------------------------------------------------------------------------- /docs/runtime~main.4d4dbb2cceb1c5ede223.bundle.js: -------------------------------------------------------------------------------- 1 | !function(modules){function webpackJsonpCallback(data){for(var moduleId,chunkId,chunkIds=data[0],moreModules=data[1],executeModules=data[2],i=0,resolves=[];i 40 | * 41 | * Copyright (c) 2014-2017, Jon Schlinkert. 42 | * Released under the MIT License. 43 | */ 44 | 45 | /** 46 | * @license 47 | * Lodash 48 | * Copyright OpenJS Foundation and other contributors 49 | * Released under MIT license 50 | * Based on Underscore.js 1.8.3 51 | * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors 52 | */ 53 | 54 | /** @license React v0.18.0 55 | * scheduler.production.min.js 56 | * 57 | * Copyright (c) Facebook, Inc. and its affiliates. 58 | * 59 | * This source code is licensed under the MIT license found in the 60 | * LICENSE file in the root directory of this source tree. 61 | */ 62 | 63 | /** @license React v16.12.0 64 | * react-dom.production.min.js 65 | * 66 | * Copyright (c) Facebook, Inc. and its affiliates. 67 | * 68 | * This source code is licensed under the MIT license found in the 69 | * LICENSE file in the root directory of this source tree. 70 | */ 71 | 72 | /** @license React v16.12.0 73 | * react-is.production.min.js 74 | * 75 | * Copyright (c) Facebook, Inc. and its affiliates. 76 | * 77 | * This source code is licensed under the MIT license found in the 78 | * LICENSE file in the root directory of this source tree. 79 | */ 80 | 81 | /** @license React v16.12.0 82 | * react.production.min.js 83 | * 84 | * Copyright (c) Facebook, Inc. and its affiliates. 85 | * 86 | * This source code is licensed under the MIT license found in the 87 | * LICENSE file in the root directory of this source tree. 88 | */ 89 | 90 | /**! 91 | * @fileOverview Kickass library to create and place poppers near their reference elements. 92 | * @version 1.16.1 93 | * @license 94 | * Copyright (c) 2016 Federico Zivolo and contributors 95 | * 96 | * Permission is hereby granted, free of charge, to any person obtaining a copy 97 | * of this software and associated documentation files (the "Software"), to deal 98 | * in the Software without restriction, including without limitation the rights 99 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 100 | * copies of the Software, and to permit persons to whom the Software is 101 | * furnished to do so, subject to the following conditions: 102 | * 103 | * The above copyright notice and this permission notice shall be included in all 104 | * copies or substantial portions of the Software. 105 | * 106 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 107 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 108 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 109 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 110 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 111 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 112 | * SOFTWARE. 113 | */ 114 | -------------------------------------------------------------------------------- /docs/vendors~main.4d4dbb2cceb1c5ede223.bundle.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /* 2 | object-assign 3 | (c) Sindre Sorhus 4 | @license MIT 5 | */ 6 | 7 | /*! 8 | * escape-html 9 | * Copyright(c) 2012-2013 TJ Holowaychuk 10 | * Copyright(c) 2015 Andreas Lubbe 11 | * Copyright(c) 2015 Tiancheng "Timothy" Gu 12 | * MIT Licensed 13 | */ 14 | 15 | /*! 16 | * https://github.com/es-shims/es5-shim 17 | * @license es5-shim Copyright 2009-2020 by contributors, MIT License 18 | * see https://github.com/es-shims/es5-shim/blob/master/LICENSE 19 | */ 20 | 21 | /*! 22 | * https://github.com/paulmillr/es6-shim 23 | * @license es6-shim Copyright 2013-2016 by Paul Miller (http://paulmillr.com) 24 | * and contributors, MIT License 25 | * es6-shim: v0.35.4 26 | * see https://github.com/paulmillr/es6-shim/blob/0.35.3/LICENSE 27 | * Details and documentation: 28 | * https://github.com/paulmillr/es6-shim/ 29 | */ 30 | 31 | /*! 32 | * is-plain-object 33 | * 34 | * Copyright (c) 2014-2017, Jon Schlinkert. 35 | * Released under the MIT License. 36 | */ 37 | 38 | /*! 39 | * isobject 40 | * 41 | * Copyright (c) 2014-2017, Jon Schlinkert. 42 | * Released under the MIT License. 43 | */ 44 | 45 | /** @license React v0.19.1 46 | * scheduler.production.min.js 47 | * 48 | * Copyright (c) Facebook, Inc. and its affiliates. 49 | * 50 | * This source code is licensed under the MIT license found in the 51 | * LICENSE file in the root directory of this source tree. 52 | */ 53 | 54 | /** @license React v16.13.1 55 | * react-dom.production.min.js 56 | * 57 | * Copyright (c) Facebook, Inc. and its affiliates. 58 | * 59 | * This source code is licensed under the MIT license found in the 60 | * LICENSE file in the root directory of this source tree. 61 | */ 62 | 63 | /** @license React v16.13.1 64 | * react.production.min.js 65 | * 66 | * Copyright (c) Facebook, Inc. and its affiliates. 67 | * 68 | * This source code is licensed under the MIT license found in the 69 | * LICENSE file in the root directory of this source tree. 70 | */ 71 | 72 | /** @license React v16.8.6 73 | * react-is.production.min.js 74 | * 75 | * Copyright (c) Facebook, Inc. and its affiliates. 76 | * 77 | * This source code is licensed under the MIT license found in the 78 | * LICENSE file in the root directory of this source tree. 79 | */ 80 | 81 | //! stable.js 0.1.8, https://github.com/Two-Screen/stable 82 | 83 | //! © 2018 Angry Bytes and contributors. MIT licensed. 84 | -------------------------------------------------------------------------------- /docs/vendors~main.4d4dbb2cceb1c5ede223.bundle.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"vendors~main.4d4dbb2cceb1c5ede223.bundle.js","sources":["webpack:///vendors~main.4d4dbb2cceb1c5ede223.bundle.js"],"mappings":";AAAA","sourceRoot":""} -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./dist/index'); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-sticky-table", 3 | "description": "Dynamically sized fixed header and columns for tables", 4 | "version": "5.1.11", 5 | "author": "Henrybuilt", 6 | "bugs": { 7 | "url": "https://github.com/henrybuilt/react-sticky-table/issues" 8 | }, 9 | "dependencies": { 10 | "styled-components": "^5.1.0" 11 | }, 12 | "devDependencies": { 13 | "@babel/cli": "7.4.4", 14 | "@babel/core": "7.4.5", 15 | "@babel/plugin-proposal-class-properties": "^7.4.4", 16 | "@babel/plugin-transform-modules-umd": "7.2.0", 17 | "@babel/preset-env": "7.4.5", 18 | "@babel/preset-react": "7.0.0", 19 | "@babel/register": "7.4.4", 20 | "@babel/runtime": "7.4.5", 21 | "@storybook/addon-knobs": "^5.3.18", 22 | "@storybook/addons": "^5.3.18", 23 | "@storybook/react": "^5.3.18", 24 | "babel-eslint": "10.0.2", 25 | "babel-loader": "8.0.6", 26 | "chai": "4.2.0", 27 | "core-js": "3.1.4", 28 | "enzyme": "3.10.0", 29 | "enzyme-adapter-react-16": "^1.14.0", 30 | "eslint": "6.0.1", 31 | "eslint-plugin-babel": "5.3.0", 32 | "eslint-plugin-react": "^7.0.1", 33 | "ignore-styles": "^5.0.1", 34 | "jsdom": "15.1.1", 35 | "jsdom-global": "^3.0.2", 36 | "mocha": "^7.1.2", 37 | "nodemon": "^1.9.1", 38 | "prop-types": "^15.5.7", 39 | "react": "^16.13.1", 40 | "react-addons-test-utils": "^15.5.1", 41 | "react-dom": "^16.13.1", 42 | "regenerator-runtime": "^0.13.2", 43 | "sinon": "7.3.2" 44 | }, 45 | "homepage": "https://github.com/henrybuilt/react-sticky-table", 46 | "keywords": [ 47 | "column", 48 | "fixed", 49 | "header", 50 | "react-component", 51 | "sticky", 52 | "table", 53 | "table", 54 | "table" 55 | ], 56 | "license": "MIT", 57 | "main": "dist/index.js", 58 | "options": { 59 | "mocha": "--require scripts/mocha_runner src/**/__tests__/**/*.js --require ignore-styles --require src/__tests__/config.js" 60 | }, 61 | "peerDependencies": { 62 | "prop-types": "^15.5.7", 63 | "react": ">=16.0.0", 64 | "react-dom": " ^16.0.0" 65 | }, 66 | "repository": { 67 | "type": "git", 68 | "url": "https://github.com/henrybuilt/react-sticky-table.git" 69 | }, 70 | "scripts": { 71 | "build": "npm run build-js", 72 | "build-js": "babel --plugins '@babel/plugin-transform-modules-umd' src --ignore __tests__ --out-dir ./dist", 73 | "build-storybook": "build-storybook -o ./docs", 74 | "lint": "eslint ./src", 75 | "lintfix": "eslint ./src --fix", 76 | "storybook": "start-storybook -p 6006", 77 | "test": "npm run lint && npm run testonly", 78 | "test-watch": "npm run testonly -- --watch --watch-extensions js", 79 | "testonly": "BABEL_ENV=test && mocha $npm_package_options_mocha", 80 | "build-all": "npm run build && npm run build-storybook && git add -A && git commit -am \"built\"", 81 | "prepublishOnly": "npm run build && npm version patch && git push" 82 | }, 83 | "source": "src/index.js" 84 | } 85 | -------------------------------------------------------------------------------- /scripts/mocha_runner.js: -------------------------------------------------------------------------------- 1 | require('jsdom-global')(); 2 | 3 | require('@babel/register'); 4 | require('core-js/stable'); 5 | require('regenerator-runtime/runtime'); 6 | 7 | -------------------------------------------------------------------------------- /src/__tests__/Cell.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import {mount, configure } from 'enzyme'; 4 | import Adapter from 'enzyme-adapter-react-16'; 5 | import {expect} from 'chai'; 6 | 7 | import {Cell} from '../index'; 8 | 9 | configure({ adapter: new Adapter() }); 10 | 11 | describe('Cell', () => { 12 | it('should render children properly', () => { 13 | const cell = mount( 14 | 15 | 16 | 17 | 18 | ); 19 | 20 | expect(cell.find(Cell).find('span')).to.have.length(2); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /src/__tests__/Row.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import {mount, configure } from 'enzyme'; 4 | import Adapter from 'enzyme-adapter-react-16'; 5 | import {expect} from 'chai'; 6 | 7 | import {Row, Cell} from '../index'; 8 | 9 | configure({ adapter: new Adapter() }); 10 | 11 | describe('Row', () => { 12 | it('should render children properly', () => { 13 | const row = mount( 14 | 15 | header 1 16 | header 2 17 | 18 | ); 19 | 20 | expect(row.find(Cell)).to.have.length(2); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /src/__tests__/Table.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import {mount, configure } from 'enzyme'; 4 | import Adapter from 'enzyme-adapter-react-16'; 5 | import {expect} from 'chai'; 6 | 7 | import {Table, Row, Cell} from '../index'; 8 | 9 | configure({ adapter: new Adapter() }); 10 | 11 | describe('Table', () => { 12 | it('should render children properly', () => { 13 | const table = mount( 14 | 15 | 16 | header 1 17 | header 2 18 | 19 |
20 | ); 21 | 22 | expect(table.find(Row)).to.have.length(1); 23 | expect(table.find(Cell)).to.have.length(2); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/__tests__/config.js: -------------------------------------------------------------------------------- 1 | require('jsdom-global')(); 2 | -------------------------------------------------------------------------------- /src/__tests__/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import {mount, configure} from 'enzyme'; 4 | import Adapter from 'enzyme-adapter-react-16'; 5 | import {expect} from 'chai'; 6 | 7 | import {StickyTable, Row, Cell} from '../index'; 8 | 9 | configure({ adapter: new Adapter() }); 10 | 11 | describe('StickyTable', () => { 12 | it('should render the correct number of children', () => { 13 | const table = mount( 14 | 15 | 16 | header 1 17 | header 2 18 | 19 | 20 | column 1 cell 21 | column 2 cell 22 | 23 | 24 | ); 25 | 26 | expect(table.find(Cell)).to.have.length(4); 27 | }); 28 | 29 | it('shouldn\'t render columns when opting out', () => { 30 | const table = mount( 31 | 32 | 33 | header 1 34 | header 2 35 | 36 | 37 | column 1 cell 38 | column 2 cell 39 | 40 | 41 | ); 42 | 43 | expect(table.find(Cell)).to.have.length(4); 44 | }); 45 | 46 | it('should render the correct number of leftStickyColumnCount', () => { 47 | const table = mount( 48 | 49 | 50 | header 1 51 | header 2 52 | header 3 53 | header 4 54 | 55 | 56 | column 1 cell 57 | column 2 cell 58 | column 3 cell 59 | column 4 cell 60 | 61 | 62 | ); 63 | 64 | expect(table.find(Cell)).to.have.length(8); 65 | }); 66 | 67 | it('shouldn\'t render headers when opting out', () => { 68 | const table = mount( 69 | 70 | 71 | header 1 72 | header 2 73 | 74 | 75 | column 1 cell 76 | column 2 cell 77 | 78 | 79 | ); 80 | 81 | expect(table.find(Cell)).to.have.length(4); 82 | }); 83 | 84 | it('should support sibling components and arrays', () => { 85 | const table = mount( 86 | 87 | 88 | header 1 89 | {[header 2]} 90 | 91 | 92 | ); 93 | 94 | expect(table.find(Cell)).to.have.length(2); 95 | }); 96 | }); 97 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled, { css } from 'styled-components'; 3 | 4 | var getBorder = (props) => `${props.borderWidth === undefined ? '2px' : (props.borderWidth || '0px')} solid ${props.borderColor || '#e5e5e5'}` 5 | 6 | const Table = styled('div').attrs(() => ({ 7 | className: 'sticky-table-table' 8 | }))` 9 | white-space: nowrap; 10 | display: table; 11 | box-sizing: border-box; 12 | `; 13 | 14 | Table.displayName = 'Table'; 15 | 16 | const Cell = styled('div').attrs(() => ({ 17 | className: 'sticky-table-cell' 18 | }))` 19 | display: table-cell; 20 | box-sizing: border-box; 21 | padding: 0.5rem 0.75rem; 22 | background-color: #fff; 23 | `; 24 | 25 | Cell.displayName = 'Cell'; 26 | 27 | const Row = styled('div').attrs(() => ({ 28 | className: 'sticky-table-row' 29 | }))` 30 | display: table-row; 31 | `; 32 | 33 | Row.displayName = 'Row'; 34 | 35 | const Wrapper = styled('div').attrs(() => ({ 36 | className: 'sticky-table' 37 | }))` 38 | position: relative; 39 | overflow: auto; 40 | height: 100%; 41 | box-sizing: border-box; 42 | 43 | & ${Row}:not(:nth-last-child(-n+${props => (props.stickyFooterCount || 0) + 1})) ${Cell} { 44 | border-bottom: ${getBorder}; 45 | } 46 | 47 | & ${Row}:nth-child(${props => `-n+${props.stickyHeaderCount}`}) ${Cell} { 48 | position: -webkit-sticky; 49 | position: sticky; 50 | top: 0px; 51 | z-index: ${props => props.headerZ || 2}; 52 | } 53 | & ${Row}:nth-last-child(-n+${props => props.stickyFooterCount}) ${Cell} { 54 | position: -webkit-sticky; 55 | position: sticky; 56 | bottom: 0px; 57 | z-index: ${props => props.footerZ || 2}; 58 | border-top: ${getBorder}; 59 | } 60 | & ${Row} ${Cell}:nth-child(-n+${props => props.leftStickyColumnCount}) { 61 | position: -webkit-sticky; 62 | position: sticky; 63 | left: 0px; 64 | z-index: ${props => props.leftColumnZ || 2}; 65 | border-right: ${getBorder}; 66 | } 67 | & ${Row} ${Cell}:nth-last-child(-n+${props => props.rightStickyColumnCount}) { 68 | position: -webkit-sticky; 69 | position: sticky; 70 | right: 0px; 71 | z-index: ${props => props.rightColumnZ || 2}; 72 | border-left: ${getBorder}; 73 | } 74 | 75 | ${props => { 76 | var insets = props.stickyInsets; 77 | var styles = ''; 78 | var i; 79 | 80 | for (i = 0; i < insets.header.length; i++) { 81 | styles += `& ${Row}:nth-child(${i + 1}) ${Cell} { top: ${insets.header[i]}px; }` 82 | } 83 | 84 | for (i = 0; i < insets.footer.length; i++) { 85 | styles += `& ${Row}:nth-last-child(${i + 1}) ${Cell} { bottom: ${insets.footer[i]}px; }` 86 | } 87 | 88 | for (i = 0; i < insets.leftColumn.length; i++) { 89 | styles += `& ${Row} ${Cell}:nth-child(${i + 1}) { left: ${insets.leftColumn[i]}px; }` 90 | } 91 | 92 | for (i = 0; i < insets.rightColumn.length; i++) { 93 | styles += `& ${Row} ${Cell}:nth-last-child(${i + 1}) { right: ${insets.rightColumn[i]}px; }` 94 | } 95 | 96 | return css`${styles}`; 97 | }} 98 | 99 | & ${Row}:nth-child(-n+${props => props.stickyHeaderCount}) ${Cell}:nth-child(-n+${props => props.leftStickyColumnCount}) { 100 | z-index: ${props => Math.max(props.headerZ || 2, props.leftColumnZ || 2) + 1}; 101 | } 102 | & ${Row}:nth-child(-n+${props => props.stickyHeaderCount}) ${Cell}:nth-last-child(-n+${props => props.rightStickyColumnCount}) { 103 | z-index: ${props => Math.max(props.headerZ || 2, props.rightColumnZ || 2) + 1}; 104 | } 105 | & ${Row}:nth-last-child(-n+${props => props.stickyFooterCount}) ${Cell}:nth-child(-n+${props => props.leftStickyColumnCount}) { 106 | z-index: ${props => Math.max(props.footerZ || 2, props.leftColumnZ || 2) + 1}; 107 | } 108 | & ${Row}:nth-last-child(-n+${props => props.stickyFooterCount}) ${Cell}:nth-last-child(-n+${props => props.rightStickyColumnCount}) { 109 | z-index: ${props => Math.max(props.footerZ || 2, props.rightColumnZ || 2) + 1}; 110 | } 111 | `; 112 | 113 | Wrapper.displayName = 'Wrapper'; 114 | 115 | class StickyTable extends React.Component { 116 | state = { 117 | stickyInsets: { 118 | header: [], 119 | footer: [], 120 | leftColumn: [], 121 | rightColumn: [] 122 | } 123 | } 124 | 125 | componentDidMount() { 126 | this.considerSchedulingMultipleStickiesInterval(); 127 | } 128 | 129 | componentDidUpdate() { 130 | this.considerSchedulingMultipleStickiesInterval(); 131 | } 132 | 133 | componentWillUnmount() { 134 | this.clearMultipleStickiesInterval(); 135 | } 136 | 137 | //HINT schedule an interval to poll cell sizes for changes at 60fps 138 | //WARNING avoid doing this unless user has at least 2 stickies somewhere 139 | considerSchedulingMultipleStickiesInterval() { 140 | var p = this.props; 141 | var shouldSchedule = [ 142 | p.stickyHeaderCount, p.stickyFooterCount, p.leftStickyColumnCount, p.rightStickyColumnCount 143 | ].some(count => count > 1); 144 | 145 | //HINT clear out stickyInsets of a new interval won't be set 146 | if (!shouldSchedule && this.multipleStickiesInterval) { 147 | this.setState({stickyInsets: {header: [], footer: [], leftColumn: [], rightColumn: []}}); 148 | } 149 | 150 | this.clearMultipleStickiesInterval(); 151 | 152 | if (shouldSchedule) { 153 | this.multipleStickiesInterval = setInterval(this.checkForStickySizeChanges.bind(this), 1000 / 60); 154 | } 155 | } 156 | 157 | clearMultipleStickiesInterval() { 158 | if (this.multipleStickiesInterval) { 159 | clearInterval(this.multipleStickiesInterval); 160 | 161 | delete this.multipleStickiesInterval; 162 | } 163 | } 164 | 165 | checkForStickySizeChanges() { 166 | var s, stickyInsets = {}; 167 | var {props, tableNode} = this; 168 | var rowNodes = tableNode.querySelectorAll('.sticky-table-row'); 169 | var cellNodes = tableNode.querySelectorAll('.sticky-table-cell'); 170 | 171 | [ 172 | ['header', 'height', 'stickyHeaderCount'], 173 | ['footer', 'height', 'stickyFooterCount'], 174 | ['leftColumn', 'width', 'leftStickyColumnCount'], 175 | ['rightColumn', 'width', 'rightStickyColumnCount'] 176 | ].forEach(([stickyKey, sizeKey, countPropKey]) => { 177 | var insets = []; 178 | 179 | if (props[countPropKey] > 1) { 180 | insets = [0] 181 | var count = props[countPropKey]; 182 | var netInset = 0; 183 | 184 | // HINT we only want this loop for the second sticky and up 185 | for (s = 1; s < count; s++) { 186 | var node = undefined; 187 | 188 | switch (stickyKey) { 189 | case 'header': 190 | node = rowNodes[s - 1].childNodes[0]; 191 | break; 192 | case 'footer': 193 | node = rowNodes[rowNodes.length - s].childNodes[0]; 194 | break; 195 | case 'leftColumn': 196 | node = cellNodes[s - 1]; 197 | break; 198 | case 'rightColumn': 199 | node = cellNodes[cellNodes.length - s]; 200 | break; 201 | } 202 | 203 | if (node) { 204 | var boundingRect = node.getBoundingClientRect(); 205 | 206 | netInset += boundingRect[sizeKey]; 207 | } 208 | 209 | insets.push(netInset); 210 | } 211 | } 212 | 213 | stickyInsets[stickyKey] = insets; 214 | }); 215 | 216 | //HINT avoid a render unless there's actually a change 217 | if (JSON.stringify(stickyInsets) !== JSON.stringify(this.state.stickyInsets)) { 218 | this.setState({stickyInsets}); 219 | } 220 | } 221 | 222 | setTableNodeRef = tableNode => { 223 | this.tableNode = tableNode 224 | } 225 | 226 | render() { 227 | var {leftStickyColumnCount=1, stickyHeaderCount=1, wrapperRef, children, ...restProps} = this.props; 228 | 229 | return ( 230 | 237 | {children}
238 |
239 | ); 240 | } 241 | } 242 | 243 | export { StickyTable, Table, Row, Cell }; 244 | -------------------------------------------------------------------------------- /stories/Basic/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import { StickyTable, Row, Cell } from '../../src'; 4 | 5 | export default class Basic extends Component { 6 | render() { 7 | var rows = []; 8 | var cells; 9 | 10 | for (var r = 0; r < 50; r++) { 11 | cells = []; 12 | 13 | for (var c = 0; c < 20; c++) { 14 | cells.push({(r === 0 ? 'Header ' : 'Cell ') + c}); 15 | } 16 | 17 | rows.push({cells}); 18 | } 19 | 20 | return ( 21 |
22 |
23 | 24 | {rows} 25 | 26 |
27 |
28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /stories/Borders/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import { StickyTable, Row, Cell } from '../../src'; 4 | 5 | export default class Borders extends Component { 6 | render() { 7 | var rows = []; 8 | var cells; 9 | 10 | for (var r = 0; r < 50; r++) { 11 | cells = []; 12 | 13 | for (var c = 0; c < 20; c++) { 14 | cells.push({(r === 0 ? 'Header ' : 'Cell ') + c}); 15 | } 16 | 17 | rows.push({cells}); 18 | } 19 | 20 | return ( 21 |
22 |
23 | 24 | {rows} 25 | 26 |
27 |
28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /stories/Button/index.css: -------------------------------------------------------------------------------- 1 | .button{ 2 | background-color: #eee; 3 | padding: 0.5rem 1rem; 4 | border-bottom: 2px solid #ddd; 5 | display: inline-block; 6 | cursor: pointer; 7 | } 8 | .button:hover{ 9 | opacity: 0.8; 10 | } 11 | -------------------------------------------------------------------------------- /stories/Button/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import './index.css'; 4 | 5 | export default class Button extends Component { 6 | render() { 7 | return ( 8 |
{this.props.children}
9 | ); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /stories/ChangingContent/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import { StickyTable, Row, Cell } from '../../src'; 4 | 5 | import Button from '../Button'; 6 | 7 | export default class ChangingContent extends Component { 8 | constructor(props) { 9 | super(props); 10 | 11 | var rows = []; 12 | var cells; 13 | 14 | for (var r = 0; r < 50; r++) { 15 | cells = []; 16 | 17 | for (var c = 0; c < 20; c++) { 18 | cells.push({(r === 0 ? 'Header ' : 'Cell ') + c}); 19 | } 20 | 21 | rows.push({cells}); 22 | } 23 | 24 | this.state = { 25 | rows: rows 26 | }; 27 | } 28 | 29 | changeContent() { 30 | var rows = []; 31 | var cells; 32 | 33 | for (var r = 0; r < 50; r++) { 34 | cells = []; 35 | 36 | for (var c = 0; c < 20; c++) { 37 | cells.push( 38 | {(r === 0 ? 'New Header ' : 'Cell ') + c} 39 | ); 40 | } 41 | 42 | rows.push({cells}); 43 | } 44 | 45 | this.setState({ rows }); 46 | } 47 | 48 | render() { 49 | return ( 50 |
51 | 52 |
53 |
54 |
55 | {this.state.rows} 56 |
57 |
58 | ); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /stories/CustomZ/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import { StickyTable, Row, Cell } from '../../src'; 4 | 5 | export default class CustomZ extends Component { 6 | render() { 7 | var rows = []; 8 | var cells; 9 | 10 | for (var r = 0; r < 50; r++) { 11 | cells = []; 12 | 13 | for (var c = 0; c < 20; c++) { 14 | cells.push({(r === 0 ? 'Header ' : 'Cell ') + c}); 15 | } 16 | 17 | rows.push({cells}); 18 | } 19 | 20 | return ( 21 |
22 |
23 | 24 | {rows} 25 | 26 |
27 |
28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /stories/MultipleChangingStickies/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { StickyTable, Row, Cell } from '../../src'; 3 | 4 | export default class MultipleResizingStickies extends Component { 5 | onCellClick(event) { 6 | event.target.innerHTML = Math.floor(Math.random() * 1000000000) + '
' + Math.floor(Math.random() * 1000000000); 7 | } 8 | 9 | render() { 10 | var rows = []; 11 | var cells; 12 | 13 | for (var r = 0; r < 50; r++) { 14 | cells = []; 15 | 16 | for (var c = 0; c < 20; c++) { 17 | cells.push({'Click Me!'}); 18 | } 19 | 20 | rows.push({cells}); 21 | } 22 | 23 | return ( 24 |
25 |
26 | 27 | {rows} 28 | 29 |
30 |
31 | ); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /stories/NoBorders/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import { StickyTable, Row, Cell } from '../../src'; 4 | 5 | export default class NoBorders extends Component { 6 | render() { 7 | var rows = []; 8 | var cells; 9 | 10 | for (var r = 0; r < 50; r++) { 11 | cells = []; 12 | 13 | for (var c = 0; c < 20; c++) { 14 | cells.push({(r === 0 ? 'Header ' : 'Cell ') + c}); 15 | } 16 | 17 | rows.push({cells}); 18 | } 19 | 20 | return ( 21 |
22 |
23 | 24 | {rows} 25 | 26 |
27 |
28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /stories/NoColumn/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import { StickyTable, Row, Cell } from '../../src'; 4 | 5 | export default class NoHeader extends Component { 6 | render() { 7 | var rows = []; 8 | var cells; 9 | 10 | for (var r = 0; r < 50; r++) { 11 | cells = []; 12 | 13 | for (var c = 0; c < 20; c++) { 14 | cells.push({(r < 1 ? 'Header ' : 'Cell ') + c}); 15 | } 16 | 17 | rows.push({cells}); 18 | } 19 | 20 | return ( 21 |
22 |
23 | 24 | {rows} 25 | 26 |
27 |
28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /stories/NoHeader/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import { StickyTable, Row, Cell } from '../../src'; 4 | 5 | export default class NoHeader extends Component { 6 | render() { 7 | var rows = []; 8 | var cells; 9 | 10 | for (var r = 0; r < 50; r++) { 11 | cells = []; 12 | 13 | for (var c = 0; c < 20; c++) { 14 | cells.push({(r === 0 ? 'Header ' : 'Cell ') + c}); 15 | } 16 | 17 | rows.push({cells}); 18 | } 19 | 20 | return ( 21 |
22 |
23 | 24 | {rows} 25 | 26 |
27 |
28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /stories/Playground/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { StickyTable, Row, Cell } from '../../src'; 3 | 4 | export default class Playground extends Component { 5 | render() { 6 | var rows = []; 7 | var cells; 8 | 9 | for (var r = 0; r < 50; r++) { 10 | cells = []; 11 | 12 | for (var c = 0; c < 20; c++) { 13 | cells.push({(r === 0 ? `Header ${c}` : `Cell (${r}, ${c})`)}); 14 | } 15 | 16 | rows.push({cells}); 17 | } 18 | const { stickyHeaderCount, leftStickyColumnCount, 19 | rightStickyColumnCount, stickyFooterCount, 20 | height, width } = this.props; 21 | return ( 22 |
23 |
24 | 30 | {rows} 31 | 32 |
33 |
34 | ); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /stories/ResizingCells/index.css: -------------------------------------------------------------------------------- 1 | .resizing-cells .row:not(:first-child) .cell:not(:first-child){ 2 | cursor: pointer; 3 | } 4 | .resizing-cells .row:not(:first-child) .cell:not(:first-child):hover{ 5 | background-color: #f5f5f5; 6 | } 7 | -------------------------------------------------------------------------------- /stories/ResizingCells/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import { StickyTable, Row, Cell } from '../../src'; 4 | 5 | import './index.css'; 6 | 7 | export default class ResizingCells extends Component { 8 | onCellClick(event) { 9 | event.target.innerHTML = Math.floor(Math.random() * 1000000000) + '
' + Math.floor(Math.random() * 1000000000); 10 | } 11 | 12 | render() { 13 | var rows = []; 14 | var cells; 15 | 16 | for (var r = 0; r < 50; r++) { 17 | cells = []; 18 | 19 | for (var c = 0; c < 20; c++) { 20 | cells.push({'Click Me!'}); 21 | } 22 | 23 | rows.push({cells}); 24 | } 25 | 26 | return ( 27 |
28 |
29 | 30 | {rows} 31 | 32 |
33 |
34 | ); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /stories/StickyAllSides/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import { StickyTable, Row, Cell } from '../../src'; 4 | 5 | export default class StickyAllSides extends Component { 6 | render() { 7 | var rows = []; 8 | var cells; 9 | 10 | for (var r = 0; r < 50; r++) { 11 | cells = []; 12 | 13 | for (var c = 0; c < 20; c++) { 14 | var title = 'Cell '; 15 | 16 | if (r === 0) title = 'Header '; 17 | if (r === 50 - 1) title = 'Footer '; 18 | 19 | cells.push({title + c}); 20 | } 21 | 22 | rows.push({cells}); 23 | } 24 | 25 | return ( 26 |
27 |
28 | 29 | {rows} 30 | 31 |
32 |
33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /stories/demo.css: -------------------------------------------------------------------------------- 1 | /* Elements */ 2 | body, html{ 3 | margin: 0; 4 | padding: 0; 5 | font-size: 100%; 6 | } 7 | body, a, input, select, textarea, h1, h2, h3{ 8 | color: #000; 9 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; 10 | font-weight: normal; 11 | } 12 | h2, h3{ 13 | font-weight: 400; 14 | } 15 | body, a, input, select, textarea{ 16 | font-size: 0.8rem; 17 | } 18 | a{ 19 | text-decoration: none; 20 | } 21 | h1{ 22 | border-bottom: 2px solid #ddd; 23 | padding-bottom: 0.5rem; 24 | font-weight: 300; 25 | } 26 | 27 | /* General */ 28 | .clearfix:after { 29 | content: ""; 30 | display: table; 31 | clear: both; 32 | } 33 | .left { 34 | float: left; 35 | } 36 | .right { 37 | float: right; 38 | } 39 | -------------------------------------------------------------------------------- /stories/index.stories.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { storiesOf } from '@storybook/react'; 3 | import { withKnobs, number, text } from '@storybook/addon-knobs/react' 4 | 5 | import './demo.css'; 6 | 7 | import Basic from './Basic/index'; 8 | import StickyAllSides from './StickyAllSides/index'; 9 | import Borders from './Borders/index'; 10 | import NoBorders from './NoBorders/index'; 11 | import ChangingContent from './ChangingContent/index'; 12 | import NoColumn from './NoColumn/index'; 13 | import NoHeader from './NoHeader/index'; 14 | import ResizingCells from './ResizingCells/index'; 15 | import CustomZ from './CustomZ/index'; 16 | import MultipleChangingStickies from './MultipleChangingStickies/index'; 17 | import Playground from './Playground/index'; 18 | 19 | 20 | storiesOf('Basic', module) 21 | .add('basic', () => ) 22 | .add('multiple changing stickies', () => ) 23 | .add('sticky on all sides', () => ) 24 | .add('only sticky header', () => ) 25 | .add('only sticky column', () => ) 26 | .add('dynamically changing content', () => ) 27 | .add('resizing cells', () => ) 28 | .add('custom borders', () => ) 29 | .add('no borders', () => ) 30 | .add('custom z-index', () => ) 31 | 32 | storiesOf('Playground') 33 | .addDecorator(withKnobs) 34 | .add('sticky tests', () => ); 42 | 43 | --------------------------------------------------------------------------------