├── .babelrc ├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── example ├── .babelrc ├── .gitignore ├── gulpfile.js ├── package.json ├── src │ ├── index.html │ └── responsive-table-example.js └── webpack.config.js ├── package.json ├── src └── responsive-fixed-data-table.js ├── test ├── karma.conf.js └── specs │ └── responsive-fixed-data-table.js └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["react", "es2015", "stage-1"], 3 | "env": { 4 | "umd": { 5 | "plugins": [ 6 | "add-module-exports", 7 | "transform-es2015-modules-umd" 8 | ] 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | .DS_Store/ 4 | lib -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | test 2 | src 3 | example 4 | webpack.config.js 5 | .babelrc 6 | .module-cache -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Viky Guerra 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 | # Important: 2 | Due to lack of time, I'm afraid I no longer mantain this package. If you'd like to take over I'll be forever grateful and more than happy to pass the torch along. 3 | 4 | [![npm version](https://badge.fury.io/js/responsive-fixed-data-table.svg)](http://badge.fury.io/js/responsive-fixed-data-table) 5 | # responsive-fixed-data-table 6 | Responsive wrapper for [Facebook's Fixed-Data-Table](https://github.com/facebook/fixed-data-table) grids 7 | 8 | ## Installation 9 | This module is available as an npm package. 10 | 11 | npm install [--save] responsive-fixed-data-table 12 | 13 | ## Usage 14 | This module includes minified and non minified UMD builds as well as an ES6 build. You choose! 15 | 16 | ```js 17 | import React from 'react'; 18 | import ResponsiveFixedDataTable from 'responsive-fixed-data-table'; 19 | import { Column } from 'fixed-data-table'; 20 | 21 | export default class ResponsiveTable extends React.Component { 22 | render() { 23 | return ( 24 | 25 | 26 | 27 | ); 28 | } 29 | } 30 | ``` 31 | 32 | All passed props will be passed to the underlying FixedDataTable component. Please check [FixedDataTable docs](http://facebook.github.io/fixed-data-table/api-table.html) for a list of available options. 33 | Width and height will be overriden to take all the available space of its parent container. 34 | 35 | ### Additional configuration 36 | **containerStyle** *{Object}*: Additional styles to be set on the container div. 37 | **refreshRate** *{Number}*: Time in milliseconds to debounce the resize handler. 38 | 39 | ### React 0.13 compatibility 40 | If you want to use this module with old versions of React and FixedDataTable please check the **v1.5.0-deprecated** branch. 41 | -------------------------------------------------------------------------------- /example/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["react", "es2015", "stage-1"] 3 | } -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | node_modules -------------------------------------------------------------------------------- /example/gulpfile.js: -------------------------------------------------------------------------------- 1 | // LIBRARIES 2 | // - - - - - - - - - - - - - - - 3 | var gulp = require('gulp'), 4 | rimraf = require('rimraf'), 5 | runSequence = require('run-sequence'), 6 | modRewrite = require('connect-modrewrite'), 7 | connect = require('gulp-connect'); 8 | 9 | // FILE PATHS 10 | // - - - - - - - - - - - - - - - 11 | var paths = { 12 | mainHtml: './src/index.html', 13 | mainJs: './src/responsive-table-example.js', 14 | fixedDataTableCss: './node_modules/fixed-data-table/dist/fixed-data-table.min.css' 15 | }; 16 | 17 | var buildPaths = { 18 | main: './build', 19 | js: './build/assets/js/', 20 | css: './build/assets/css/' 21 | }; 22 | 23 | // TASKS 24 | // - - - - - - - - - - - - - - - 25 | // Cleans the build directory. 26 | gulp.task('clean', function(cb) { 27 | rimraf(buildPaths.main, cb); 28 | }); 29 | 30 | // Copies html file 31 | gulp.task('copy-html-css', function() { 32 | gulp.src(paths.mainHtml) 33 | .pipe(gulp.dest(buildPaths.main)); 34 | return gulp.src(paths.fixedDataTableCss) 35 | .pipe(gulp.dest(buildPaths.css)); 36 | }); 37 | 38 | // Starts a test server at http://localhost:8080 39 | gulp.task('server:start', function() { 40 | return connect.server({ 41 | root: './build', 42 | port: 8000, 43 | middleware: function() { 44 | return [ 45 | modRewrite(['^[^\\.]*$ /index.html [L]']) 46 | ]; 47 | } 48 | }); 49 | }); 50 | 51 | // Builds the app prod ready. 52 | gulp.task('build', function() { 53 | runSequence('clean', 'copy-html-css', function() { 54 | console.log('Successfully built.'); 55 | }); 56 | }); 57 | 58 | // Default task: builds your app and starts a server. 59 | gulp.task('default', function() { 60 | runSequence('build', 'server:start'); 61 | }); -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "responsive-fixed-data-table-example", 3 | "version": "1.0.0", 4 | "description": "Example for responsive-fixed-data-table", 5 | "main": "gulpfile.js", 6 | "author": "Viky Guerra ", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/vaiRk/responsive-fixed-data-table" 10 | }, 11 | "bugs": { 12 | "url": "https://github.com/vaiRk/responsive-fixed-data-table/issues" 13 | }, 14 | "keywords": [ 15 | "responsive", 16 | "fixed-data-table", 17 | "fluid", 18 | "react", 19 | "grid", 20 | "react-component" 21 | ], 22 | "license": "MIT", 23 | "scripts": { 24 | "build": "./node_modules/.bin/gulp build && ./node_modules/.bin/webpack", 25 | "start": "npm run build && ./node_modules/.bin/gulp server:start" 26 | }, 27 | "dependencies": { 28 | "fixed-data-table": "^0.6.0", 29 | "react": "^0.14.7", 30 | "react-dom": "^0.14.7", 31 | "responsive-fixed-data-table": "^2.0.0" 32 | }, 33 | "devDependencies": { 34 | "babel-core": "^6.5.2", 35 | "babel-loader": "^6.2.2", 36 | "babel-preset-es2015": "^6.5.0", 37 | "babel-preset-react": "^6.5.0", 38 | "babel-preset-stage-1": "^6.5.0", 39 | "connect-modrewrite": "^0.8.1", 40 | "gulp": "^3.9.0", 41 | "gulp-connect": "^2.2.0", 42 | "rimraf": "^2.4.0", 43 | "run-sequence": "^1.1.0", 44 | "source-map-loader": "^0.1.5", 45 | "webpack": "^1.12.13" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /example/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /example/src/responsive-table-example.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import React from 'react'; 4 | import { render } from 'react-dom'; 5 | import { Column, Cell } from 'fixed-data-table'; 6 | import ResponsiveFixedDataTable from 'responsive-fixed-data-table'; 7 | 8 | const data = [ 9 | { name: 'Olivia Dunham', email: 'odunham@fbi.gov' }, 10 | { name: 'Walter Bishop', email: 'drbishop@harvard.edu' }, 11 | { name: 'Peter Bishop', email: 'peterbishop@fbi.gov' }, 12 | { name: 'Astrid Farnsworth', email: 'afarnsworth@fbi.gov' } 13 | ]; 14 | 15 | class MyCell extends React.Component { 16 | render() { 17 | const { rowIndex, data, field, ...props } = this.props; 18 | return ( 19 | 20 | {data[rowIndex][field]} 21 | 22 | ); 23 | } 24 | } 25 | 26 | render( 27 | 33 | Name} 35 | cell={} 36 | width={200} /> 37 | Email} 39 | cell={} 40 | width={400} 41 | flexGrow={1} /> 42 | 43 | , document.getElementById('example-container')); -------------------------------------------------------------------------------- /example/webpack.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var webpack = require('webpack'); 4 | var path = require('path'); 5 | 6 | module.exports = { 7 | context: __dirname, 8 | entry: path.resolve(__dirname, 'src', 'responsive-table-example.js'), 9 | output: { 10 | path: path.resolve(__dirname, 'build', 'assets', 'js'), 11 | sourceMapFileName: '[file].map', 12 | filename: 'bundle.js', 13 | }, 14 | devtool: 'source-map', 15 | resolve: { 16 | extensions: ['', '.js'] 17 | }, 18 | module: { 19 | preLoaders: [ 20 | { test: /\.js$/, include: /responsive-fixed-data-table/, loader: 'source-map' } 21 | ], 22 | loaders: [ 23 | { test: /\.jsx?$/, exclude: /node_modules/, loader: 'babel' } 24 | ] 25 | } 26 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "responsive-fixed-data-table", 3 | "version": "2.0.0", 4 | "author": "Viky Guerra ", 5 | "description": "Responsive utility wrapper for Facebook's Fixed-Data-Table", 6 | "main": "lib/responsive-fixed-data-table.js", 7 | "jsnext:main": "lib/responsive-fixed-data-table.es.js", 8 | "files": [ 9 | "lib", 10 | "src" 11 | ], 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/vaiRk/responsive-fixed-data-table" 15 | }, 16 | "bugs": { 17 | "url": "https://github.com/vaiRk/responsive-fixed-data-table/issues" 18 | }, 19 | "keywords": [ 20 | "responsive", 21 | "fixed-data-table", 22 | "fluid", 23 | "react", 24 | "grid", 25 | "react-component" 26 | ], 27 | "license": "MIT", 28 | "dependencies": { 29 | "lodash": "^4.3.0" 30 | }, 31 | "peerDependencies": { 32 | "fixed-data-table": ">=0.6.0", 33 | "react": ">=0.14", 34 | "react-dom": ">=0.14" 35 | }, 36 | "devDependencies": { 37 | "babel-core": "^6.5.2", 38 | "babel-loader": "^6.2.2", 39 | "babel-plugin-add-module-exports": "^0.1.2", 40 | "babel-plugin-transform-es2015-modules-umd": "^6.5.0", 41 | "babel-preset-es2015": "^6.5.0", 42 | "babel-preset-react": "^6.5.0", 43 | "babel-preset-stage-1": "^6.5.0", 44 | "cross-env": "^1.0.7", 45 | "fixed-data-table": "^0.6.0", 46 | "jasmine-core": "^2.4.1", 47 | "karma": "^0.13.21", 48 | "karma-chrome-launcher": "^0.2.2", 49 | "karma-jasmine": "^0.3.7", 50 | "karma-sourcemap-loader": "^0.3.7", 51 | "karma-webpack": "^1.7.0", 52 | "ncp": "^2.0.0", 53 | "react": "^0.14.7", 54 | "react-addons-test-utils": "^0.14.7", 55 | "react-dom": "^0.14.7", 56 | "rimraf": "^2.5.1", 57 | "webpack": "^1.12.13" 58 | }, 59 | "scripts": { 60 | "prebuild": "rimraf lib", 61 | "build": "npm run build:umd && npm run build:umd:min && npm run build:es", 62 | "build:umd": "cross-env BABEL_ENV=umd webpack", 63 | "build:umd:min": "cross-env BABEL_ENV=umd NODE_ENV=production webpack", 64 | "build:es": "ncp src/responsive-fixed-data-table.js lib/responsive-fixed-data-table.es.js", 65 | "prepublish": "npm run build", 66 | "test": "./node_modules/karma/bin/karma start test/karma.conf.js", 67 | "test:debug": "./node_modules/karma/bin/karma start test/karma.conf.js --no-single-run --auto-watch --log-level debug" 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/responsive-fixed-data-table.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import React from 'react'; 4 | import { findDOMNode } from 'react-dom'; 5 | import { Table } from 'fixed-data-table'; 6 | import debounce from 'lodash/debounce'; 7 | import assign from 'lodash/assign'; 8 | import isEqual from 'lodash/isEqual'; 9 | 10 | const initialPixels = 1; 11 | 12 | export default class ResponsiveFixedDataTable extends React.Component { 13 | constructor(props, context) { 14 | super(props, context); 15 | } 16 | 17 | static propTypes = { 18 | containerStyle: React.PropTypes.object, 19 | refreshRate: React.PropTypes.number 20 | }; 21 | 22 | static defaultProps = { 23 | containerStyle: {}, 24 | refreshRate: 250 // ms 25 | }; 26 | 27 | state = { 28 | gridWidth: initialPixels, 29 | gridHeight: initialPixels 30 | }; 31 | 32 | shouldComponentUpdate(nextProps, nextState) { 33 | return !isEqual(this.props, nextProps) || !isEqual(this.state, nextState); 34 | } 35 | 36 | componentDidMount() { 37 | this.__isMounted = true; 38 | this._setDimensionsOnState(); 39 | this._attachResizeEvent(); 40 | } 41 | 42 | componentWillMount() { 43 | const { refreshRate } = this.props; 44 | this._setDimensionsOnState = debounce(this._setDimensionsOnState, refreshRate); 45 | } 46 | 47 | componentWillUnmount() { 48 | this.__isMounted = false; 49 | window.removeEventListener('resize', this._setDimensionsOnState); 50 | } 51 | 52 | _attachResizeEvent() { 53 | if (window.addEventListener) { 54 | window.addEventListener('resize', this._setDimensionsOnState, false); 55 | } else if (window.attachEvent) { 56 | window.attachEvent('resize', this._setDimensionsOnState); 57 | } else { 58 | window.onresize = this._setDimensionsOnState; 59 | } 60 | } 61 | 62 | _setDimensionsOnState = () => { 63 | if (this.__isMounted) { 64 | const { offsetWidth, offsetHeight } = findDOMNode(this); 65 | 66 | this.setState({ 67 | gridWidth: offsetWidth || initialPixels, 68 | gridHeight: offsetHeight || initialPixels 69 | }); 70 | } 71 | } 72 | 73 | _getStyle() { 74 | return { 75 | ...this.props.containerStyle, 76 | width: '100%', 77 | height: '100%' 78 | }; 79 | } 80 | 81 | render() { 82 | const { gridWidth, gridHeight } = this.state; 83 | 84 | return ( 85 |
86 | 87 | 88 | ); 89 | } 90 | }; 91 | -------------------------------------------------------------------------------- /test/karma.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var webpackConfig = require('../webpack.config.js'); 4 | 5 | module.exports = function(karma) { 6 | karma.set({ 7 | 8 | // Base path that will be used to resolve all patterns (eg. files, exclude). 9 | basePath: '../', 10 | 11 | // Frameworks to use. 12 | frameworks: [ 'jasmine' ], 13 | 14 | // List of files/patterns to load in the browser. 15 | files: [ 16 | { pattern: 'test/specs/*.js', served: true, included: true, watched: true } 17 | ], 18 | 19 | // List of files to exclude. 20 | exclude: [], 21 | 22 | // Test results reporter to use. Possible values: 'dots', 'progress'. 23 | reporters: [ 'dots' ], 24 | 25 | // Preprocess matching files before serving them to the browser. 26 | preprocessors: { 27 | 'test/specs/*.js': [ 'webpack', 'sourcemap' ] 28 | }, 29 | 30 | // Start this browsers 31 | browsers: [ 'Chrome' ], 32 | 33 | /** 34 | * Level of logging. Possible values: 35 | * config.LOG_DISABLE 36 | * config.LOG_ERROR 37 | * config.LOG_WARN 38 | * config.LOG_INFO 39 | * config.LOG_DEBUG 40 | */ 41 | logLevel: karma.LOG_DISABLE, 42 | 43 | // Enable / disable colors in the output (reporters and logs). 44 | colors: true, 45 | 46 | // Web server port. 47 | port: 9876, 48 | 49 | webpack: { 50 | devtool: 'cheap-eval-source-map', 51 | module: webpackConfig.module, 52 | resolve: webpackConfig.resolve 53 | }, 54 | 55 | // Prevent webpack from logging stuff to the console. 56 | webpackServer: { 57 | noInfo: true 58 | }, 59 | 60 | /** 61 | * Continuous Integration mode. 62 | * If true, Karma captures browsers, runs the tests and exits. 63 | */ 64 | singleRun: true, 65 | 66 | // Enable/disable watching file and executing tests whenever any file changes. 67 | autoWatch: false, 68 | 69 | plugins: [ 70 | 'karma-jasmine', 71 | 'karma-webpack', 72 | 'karma-sourcemap-loader', 73 | 'karma-chrome-launcher' 74 | ] 75 | }); 76 | }; -------------------------------------------------------------------------------- /test/specs/responsive-fixed-data-table.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import React from 'react'; 4 | import ReactDOM from 'react-dom'; 5 | import TestUtils from 'react-addons-test-utils'; 6 | import ResponsiveFixedDataTable from './../../src/responsive-fixed-data-table'; 7 | 8 | describe('responsive-fixed-data-table', function() { 9 | let table; 10 | const container = document.createElement('div'); 11 | container.style.width = '500px'; 12 | container.style.height = '500px'; 13 | 14 | beforeEach(function() { 15 | const props = { 16 | foo: 'bar', 17 | containerStyle: { width: '20%', position: 'absolute' }, 18 | rowHeight: 1, 19 | rowsCount: 1, 20 | headerHeight: 1 21 | }; 22 | table = ReactDOM.render(, container); 23 | }); 24 | 25 | afterEach(function() { 26 | ReactDOM.unmountComponentAtNode(container); 27 | table = null; 28 | }); 29 | 30 | // _____TESTS_________________________________________________________________ // 31 | it('should have 100% width and height', function() { 32 | const tableNode = ReactDOM.findDOMNode(table); 33 | expect(tableNode.style.width).toBe('100%'); 34 | expect(tableNode.style.height).toBe('100%'); 35 | }); 36 | 37 | it('should accept additional styles', function() { 38 | const tableNode = ReactDOM.findDOMNode(table); 39 | expect(tableNode.style.position).toBe('absolute'); 40 | }); 41 | 42 | it('should not update', function() { 43 | const newProps = { ...table.props }; 44 | const newState = { ...table.state }; 45 | expect(table.shouldComponentUpdate(newProps, newState)).toBe(false); 46 | }); 47 | 48 | it('should update', function() { 49 | const newProps = { ...table.props, headerHeight: 100 }; 50 | const newState = { ...table.state, gridWidth: 100 }; 51 | expect(table.shouldComponentUpdate(newProps, newState)).toBe(true); 52 | expect(table.shouldComponentUpdate(newProps, { ...table.state })).toBe(true); 53 | expect(table.shouldComponentUpdate({ ...table.props }, newState)).toBe(true); 54 | }); 55 | 56 | it('should transfer props and add width and height', function() { 57 | const tableState = table.state; 58 | const fixedDataTable = table.refs.table; 59 | expect(fixedDataTable.props.foo).toBe('bar'); 60 | expect(fixedDataTable.props.width).toBe(tableState.gridWidth); 61 | expect(fixedDataTable.props.height).toBe(tableState.gridHeight); 62 | }); 63 | }); -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var webpack = require('webpack'); 4 | var path = require('path'); 5 | 6 | var minify = process.env.NODE_ENV === 'production'; 7 | var plugins = [ 8 | new webpack.optimize.OccurenceOrderPlugin() 9 | ]; 10 | 11 | if (minify) { 12 | plugins.push( 13 | new webpack.optimize.UglifyJsPlugin({ 14 | comments: false, 15 | compress: { 16 | warnings: false, 17 | screw_ie8: true, 18 | dead_code: true, 19 | drop_debugger: true, 20 | drop_console: true 21 | } 22 | }) 23 | ); 24 | } 25 | 26 | module.exports = { 27 | context: __dirname, 28 | entry: path.resolve(__dirname, 'src', 'responsive-fixed-data-table.js'), 29 | output: { 30 | path: path.resolve(__dirname, 'lib'), 31 | filename: 'responsive-fixed-data-table' + (minify ? '.min.js' : '.js'), 32 | library: 'ResponsiveFixedDataTable', 33 | libraryTarget: 'umd' 34 | }, 35 | externals: { 36 | react: { 37 | root: 'React', 38 | commonjs2: 'react', 39 | commonjs: 'react', 40 | amd: 'react' 41 | }, 42 | 'react-dom': { 43 | root: 'ReactDOM', 44 | commonjs2: 'react-dom', 45 | commonjs: 'react-dom', 46 | amd: 'react-dom' 47 | }, 48 | 'fixed-data-table': { 49 | root: 'FixedDataTable', 50 | commonjs2: 'fixed-data-table', 51 | commonjs: 'fixed-data-table', 52 | amd: 'fixed-data-table' 53 | } 54 | }, 55 | resolve: { 56 | extensions: ['', '.js'] 57 | }, 58 | module: { 59 | loaders: [ 60 | { test: /\.jsx?$/, exclude: /node_modules/, loader: 'babel' } 61 | ] 62 | }, 63 | plugins: plugins 64 | } --------------------------------------------------------------------------------