diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 0000000..2a609dd --- /dev/null +++ b/.appveyor.yml @@ -0,0 +1,20 @@ +version: 1.0.{build} +environment: + COVERALLS_REPO_TOKEN: ab4LZQwXbVRwQIn0MEHqaaOjidqu78RFQ + COVERALLS_SERVICE_NAME: appveyor +shallow_clone: true +build_script: +- ps: >- + Install-Product node 0.12.0 x64 + + npm install -g gulp + + npm cache clean + + npm install + + gulp flow-win + + gulp test --release + + gulp coveralls diff --git a/.flowconfig b/.flowconfig new file mode 100644 index 0000000..5d5bb7a --- /dev/null +++ b/.flowconfig @@ -0,0 +1,4 @@ +[include] +./node_modules/immutable +./node_modules/react +./src diff --git a/.gitignore b/.gitignore index a7dd193..c6e7e28 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ bower_components lib **/build test/reports +dist diff --git a/addons.js b/addons.js index 5decaa2..e8803bf 100644 --- a/addons.js +++ b/addons.js @@ -1 +1 @@ -module.exports = require("./dist/ReactGridAddons"); +module.exports = require("./dist/ReactGridWithAddons"); diff --git a/config/webpack.config.js b/config/webpack.config.js new file mode 100644 index 0000000..6ad1750 --- /dev/null +++ b/config/webpack.config.js @@ -0,0 +1,42 @@ +var path = require("path"); +var webpack = require('webpack'); +var release = false; +var path = require("path"); + +module.exports = { + entry: { + 'ReactGrid' : './src/index', + 'ReactGridWithAddons' : './src/addons/index' + }, + output: { + path: path.join(__dirname, "../dist"), + filename: "[name].js", + library: ["ReactGrid"], + libraryTarget: "umd" + }, + externals: { + "react/addons": { + root : 'React', + commonjs : 'react/addons', + commonjs2 : 'react/addons', + amd : 'react/addons' + }, + "moment" : "moment" + }, + module: { + loaders: [ + { test: /\.js$/, loader: 'jsx-loader?stripTypes&harmony' } // loaders can take parameters as a querystring + ] + }, + plugins: [ + new webpack.optimize.DedupePlugin(), + new webpack.optimize.OccurenceOrderPlugin(), + new webpack.optimize.AggressiveMergingPlugin() + ], + postLoaders: [ + { + test: /\.js$/, + exclude: /node_modules|testData/, + loader: 'jshint' + }] +} diff --git a/dist/ReactGrid.js b/dist/ReactGrid.js deleted file mode 100644 index 0af6f57..0000000 --- a/dist/ReactGrid.js +++ /dev/null @@ -1,4260 +0,0 @@ -(function webpackUniversalModuleDefinition(root, factory) { - if(typeof exports === 'object' && typeof module === 'object') - module.exports = factory(require("react/addons")); - else if(typeof define === 'function' && define.amd) - define(["react/addons"], factory); - else if(typeof exports === 'object') - exports["ReactGrid"] = factory(require("react/addons")); - else - root["ReactGrid"] = factory(root["React"]); -})(this, function(__WEBPACK_EXTERNAL_MODULE_10__) { -return /******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) -/******/ return installedModules[moduleId].exports; -/******/ -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ exports: {}, -/******/ id: moduleId, -/******/ loaded: false -/******/ }; -/******/ -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); -/******/ -/******/ // Flag the module as loaded -/******/ module.loaded = true; -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/******/ -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; -/******/ -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; -/******/ -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; -/******/ -/******/ // Load entry module and return exports -/******/ return __webpack_require__(0); -/******/ }) -/************************************************************************/ -/******/ ([ -/* 0 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var Grid = __webpack_require__(1); - var Row = __webpack_require__(2); - var Cell = __webpack_require__(3); - - module.exports = Grid; - module.exports.Row = Row; - module.exports.Cell = Cell; - - -/***/ }, -/* 1 */ -/***/ function(module, exports, __webpack_require__) { - - /* @flow */ - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - "use strict"; - - var React = __webpack_require__(10); - var PropTypes = React.PropTypes; - var BaseGrid = __webpack_require__(16); - var ExcelCell = __webpack_require__(17); - var ExcelRow = __webpack_require__(18); - var merge = __webpack_require__(19); - var SelectableGridMixin = __webpack_require__(20); - var DraggableGridMixin = __webpack_require__(21); - var CopyPasteGridMixin = __webpack_require__(22); - var EditableGridMixin = __webpack_require__(23); - var SortableGridMixin = __webpack_require__(24); - var FilterableGridMixin = __webpack_require__(25); - var CheckboxEditor = __webpack_require__(26); - var MixinHelper = __webpack_require__(27); - - var cloneWithProps = React.addons.cloneWithProps; - - var ExcelGrid = React.createClass({displayName: 'ExcelGrid', - - mixins : [SelectableGridMixin, EditableGridMixin, DraggableGridMixin, CopyPasteGridMixin, SortableGridMixin, FilterableGridMixin], - - getInitialState:function(){ - return {selectedRows : [], expandedRows : []}; - }, - - overrides : { - onCellCommit:function(commit ){ - var committed = commit[0]; - var selected = Object.assign({}, this.state.selected); - selected.active = false; - if (committed.keyCode === 'Tab') { - selected.idx += 1; - } - var expandedRows = this.state.expandedRows; - if(committed.changed && committed.changed.expandedHeight){ - expandedRows = this.expandRow(committed.rowIdx, committed.changed.expandedHeight); - } - this.setState({selected : selected, expandedRows : expandedRows}); - this.props.onRowUpdated(committed); - }, - getColumns : function(){ - var cols = this.getDecoratedColumns(this.props.columns) - if(this.props.enableRowSelect){ - cols.unshift({ - key: 'select-row', - name: '', - formatter : React.createElement(CheckboxEditor, null), - onRowSelect :this.handleRowSelect, - filterable : false, - headerRenderer : React.createElement("input", {type: "checkbox", onChange: this.handleCheckboxChange}), - width : 60 - }); - } - return cols; - } - }, - - getDefaultProps:function() { - return { - rowHeight: 35, - enableRowSelect : false, - minHeight : 350 - }; - }, - - handleCheckboxChange : function(e){ - if(e.currentTarget.checked === true){ - var selectedRows = this.props.rows.map(function() {return true;}); - this.setState({selectedRows : selectedRows}); - }else{ - var selectedRows = this.props.rows.map(function() {return false;}); - this.setState({selectedRows : selectedRows}); - } - }, - - handleRowSelect:function(row){ - var selectedRows = this.state.selectedRows; - if(selectedRows[row] == null || selectedRows[row] == false){ - selectedRows[row] = true; - }else{ - selectedRows[row] = false; - } - this.setState({selectedRows : selectedRows}); - }, - - expandRow:function(row, newHeight){ - var expandedRows = this.state.expandedRows; - if(expandedRows[row]){ - if(expandedRows[row]== null || expandedRows[row] < newHeight){ - expandedRows[row] = newHeight; - } - }else{ - expandedRows[row] = newHeight; - } - return expandedRows; - }, - - addRow:function(){ - - }, - - handleShowMore:function(row, newHeight){ - var expandedRows = this.expandRow(row, newHeight); - this.setState({expandedRows : expandedRows}); - }, - - handleShowLess:function(row){ - var expandedRows = this.state.expandedRows; - if(expandedRows[row]){ - expandedRows[row] = false; - } - this.setState({expandedRows : expandedRows}); - }, - - expandAllRows:function(){ - - }, - - collapseAllRows:function(){ - - }, - - onAfterAddRow:function(numberOfRows){ - this.setState({selected : {idx : 1, rowIdx : numberOfRows - 2}}); - //cheeky - this.refs.base.refs.viewport.refs.canvas.getDOMNode().scrollTop = numberOfRows * this.props.rowHeight; - }, - - componentWillReceiveProps:function(nextProps){ - if(nextProps.rows.length === this.props.rows.length + 1){ - this.onAfterAddRow(nextProps.rows.length + 1); - } - }, - - render: function() { - var cellRenderer = ( - React.createElement(ExcelCell, { - selected: this.state.selected, - copied: this.state.copied, - dragged: this.state.dragged, - onSelect: this.onSelect, - onClick: this.onSelect, - onSetActive: this.onSetActive, - onCommit: this.onCellCommit, - handleCopy: this.handleCopy, - handlePaste: this.handlePaste, - handleDragStart: this.handleDragStart, - handleDragEnter: this.handleDragEnter, - handleDragEnd: this.handleDragEnd, - handleTerminateDrag: this.handleTerminateDrag, - onShowMore: this.handleShowMore, - onShowLess: this.handleShowLess, - expandedRows: this.state.expandedRows} - ) - ); - - var rows = this.filterRows(); - var toolbar = this.renderToolbar(); - return( - React.createElement("div", {className: "react-grid-Container"}, - toolbar, - React.createElement("div", {className: "react-grid-Main"}, - (React.createElement(BaseGrid, React.__spread({ - ref: "base"}, - this.props, - {length: this.props.rows.length, - headerRows: this.getHeaderRows(), - columns: this.getColumns(), - rows: rows, - cellRenderer: cellRenderer, - rowRenderer: React.createElement(ExcelRow, null), - selectedRows: this.state.selectedRows, - expandedRows: this.state.expandedRows, - rowOffsetHeight: this.getRowOffsetHeight(), - minHeight: this.props.minHeight}))) - ) - ) - ) - }, - - renderToolbar:function(){ - var Toolbar = this.props.toolbar; - if(React.isValidElement(Toolbar)){ - return( React.addons.cloneWithProps(Toolbar, {onToggleFilter : this.onToggleFilter, rows : this.props.rows})); - } - - } - - - }) - - - module.exports = ExcelGrid; - - -/***/ }, -/* 2 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var cx = React.addons.classSet; - var Cell = __webpack_require__(3); - var cloneWithProps = React.addons.cloneWithProps; - var ColumnMetrics = __webpack_require__(11); - - var Row = React.createClass({displayName: 'Row', - - render:function() { - var className = cx( - 'react-grid-Row', - ("react-grid-Row--" + (this.props.idx % 2 === 0 ? 'even' : 'odd')) - ); - - var style = { - height: this.getRowHeight(), - overflow: 'hidden' - }; - - var cells = this.getCells(); - return ( - React.createElement("div", React.__spread({}, this.props, {className: className, style: style}), - React.isValidElement(this.props.row) ? - this.props.row : cells - ) - ); - }, - - getCells:function() { - var cells = []; - var lockedCells = []; - - for (var i = 0, len = this.props.columns.length; i < len; i++) { - var column = this.props.columns[i]; - var cell = this.renderCell({ - ref:i, - key:i, - idx:i, - rowIdx:this.props.idx, - filterRowIdx:this.props.row.key, - value:this.getCellValue(column.key || i), - column:column, - height:this.getRowHeight(), - formatter:column.formatter, - rowData : this.props.row}); - if (column.locked) { - lockedCells.push(cell); - } else { - cells.push(cell); - } - } - - return cells.concat(lockedCells); - }, - - getRowHeight:function(){ - if(this.props.expandedRows && this.props.expandedRows[this.props.key]){ - return this.props.expandedRows[this.props.key]; - }else{ - return this.props.height; - } - }, - - getCellValue:function(key){ - if(key === 'select-row'){ - return this.props.isSelected; - }else{ - return this.props.row[key] - } - }, - - renderCell:function(props) { - if (React.isValidElement(this.props.cellRenderer)) { - return cloneWithProps(this.props.cellRenderer, props); - } else { - return this.props.cellRenderer(props); - } - }, - - getDefaultProps:function() { - return { - cellRenderer: Cell - }; - }, - - shouldComponentUpdate:function(nextProps) { - return !(ColumnMetrics.sameColumns(this.props.columns, nextProps.columns, ColumnMetrics.sameColumn)) || - this.doesRowContainSelectedCell() || - this.doesRowContainSelectedCell(nextProps) || - this.willRowBeDraggedOver(nextProps) || - this.hasRowBeenCopied() || - nextProps.row !== this.props.row || - nextProps.height !== this.props.height; - }, - - setScrollLeft:function(scrollLeft) { - for (var i = 0, len = this.props.columns.length; i < len; i++) { - if (this.props.columns[i].locked) { - this.refs[i].setScrollLeft(scrollLeft); - } - } - }, - - doesRowContainSelectedCell:function(propsToCheck){ - var props = propsToCheck || this.props; - var cell = cell || props.cellRenderer; - if(cell.props.selected && cell.props.selected.rowIdx === props.idx){ - return true; - }else{ - return false; - } - }, - - willRowBeDraggedOver:function(props){ - var dragged = props.cellRenderer.props.dragged; - return dragged != null && (dragged.rowIdx || dragged.complete === true); - }, - - hasRowBeenCopied:function(){ - var cell = this.props.cellRenderer; - return cell.props.copied != null && cell.props.copied.rowIdx === this.props.idx; - } - - - }); - - module.exports = Row; - - -/***/ }, -/* 3 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var cx = React.addons.classSet; - var cloneWithProps = React.addons.cloneWithProps; - - var Cell = React.createClass({displayName: 'Cell', - - render:function() { - var style = this.getStyle(); - var className = cx( - 'react-grid-Cell', - this.props.className, - this.props.column.locked ? 'react-grid-Cell--locked' : null - ); - - var cellContent = this.renderCellContent({ - value : this.props.value, - column : this.props.column, - rowIdx : this.props.rowIdx, - isExpanded : this.props.isExpanded - }); - - return ( - React.createElement("div", React.__spread({}, this.props, {className: className, style: style}), - cellContent, - React.createElement("div", {className: "drag-handle", draggable: "true", onDragStart: this.props.handleDragStart} - ) - ) - ); - }, - - renderCellContent:function(props) { - var formatter = React.isValidElement(this.props.formatter) ? cloneWithProps(this.props.formatter, props) : this.props.formatter(props); - return (React.createElement("div", { - className: "react-grid-Cell__value"}, formatter, " ", this.props.cellControls)) - - }, - - getDefaultProps:function() { - return { - formatter: simpleCellFormatter - }; - }, - - getStyle:function() { - var style = { - position: 'absolute', - width: this.props.column.width, - height: this.props.height, - left: this.props.column.left - }; - return style; - }, - - setScrollLeft:function(scrollLeft) { - if (this.isMounted()) { - var node = this.getDOMNode(); - var transform = ("translate3d(" + scrollLeft + "px, 0px, 0px)"); - node.style.webkitTransform = transform; - node.style.transform = transform; - } - } - }); - - function simpleCellFormatter(props) { - return props.value; - } - - module.exports = Cell; - - -/***/ }, -/* 4 */, -/* 5 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - var React = __webpack_require__(10); - var cx = React.addons.classSet; - var isFunction = __webpack_require__(12); - - var EditorMixin = { - - propTypes : { - onCommit : React.PropTypes.func.isRequired - }, - - getStyle:function(){ - return { - height : this.props.height - 1 - } - }, - - getInitialState:function(){ - return {isInvalid : false} - }, - - onPressEnter:function(e){ - e.stopPropagation(); - e.preventDefault(); - this.commit({key : 'Enter'}); - }, - - onPressTab:function(e){ - e.stopPropagation(); - e.preventDefault(); - this.commit({key : 'Tab'}); - }, - - commit:function(args){ - var value = this.getValue(); - var rowDataChanged = {}; - rowDataChanged[this.props.column.key] = value; - if(this.isNewValueValid(value)){ - this.props.onCommit({updated : rowDataChanged, key : args.key}); - } - }, - - isNewValueValid:function(value){ - if(isFunction(this.validate)){ - var isValid = this.validate(value); - this.setState({isInvalid : !isValid}); - return isValid; - }else{ - return true; - } - }, - - getValue:function(){ - return this.getInputNode().value; - }, - - setValue:function(value){ - this.getInputNode().value = value; - }, - - componentDidMount: function() { - if(this.getInputNode() !== undefined){ - this.checkFocus(); - this.getInputNode().className += ' editor-main'; - } - }, - - checkFocus:function(){ - this.getInputNode().focus(); - }, - - getInputNode:function(){ - return this.getDOMNode().getElementsByTagName("input")[0]; - }, - - getContainerClass:function(){ - return cx({ - 'has-error' : this.state.isInvalid === true - }) - }, - - renderStatusIcon:function(){ - if(this.state.isInvalid === true){ - return React.createElement("span", {className: "glyphicon glyphicon-remove form-control-feedback"}) - } - }, - - render:function(){ - if(!isFunction(this.renderEditorNode)){ - throw "Editor Mixin Error : " + this.displayName + " component must implement method renderEditorNode"; - } - var editorNode = this.renderEditorNode(); - return ( - React.createElement("div", {className: this.getContainerClass()}, - editorNode, - this.renderStatusIcon() - ) - ) - } - }; - - module.exports = EditorMixin; - - -/***/ }, -/* 6 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var TextInputMixin = { - - onPressArrowLeft:function(e){ - //prevent event propogation. this disables left cell navigation - e.stopPropagation(); - }, - - onPressArrowRight:function(e){ - //prevent event propogation. this disables right cell navigation - e.stopPropagation(); - }, - - getDefaultValue:function(){ - var keyCode = this.props.initialKeyCode; - if(keyCode === 'Delete' || keyCode === 'Backspace'){ - return ''; - }else if(keyCode === 'Enter'){ - return this.props.value; - }else{ - var text = keyCode ? String.fromCharCode(keyCode) : this.props.value; - return text; - } - - }, - - setCaretAtEndOfInput:function(){ - var input = this.getInputNode(); - //taken from http://stackoverflow.com/questions/511088/use-javascript-to-place-cursor-at-end-of-text-in-text-input-element - var txtLength = input.value.length; - if(input.setSelectionRange){ - input.setSelectionRange(txtLength, txtLength); - }else if(input.createTextRange){ - var fieldRange = input.createTextRange(); - fieldRange.moveStart('character', txt.value.length); - fieldRange.collapse(); - fieldRange.select(); - } - }, - - setTextInputFocus:function(){ - if(!this.isKeyPrintable(this.props.initialKeyCode)){ - this.getInputNode().focus(); - this.setCaretAtEndOfInput(); - }else{ - this.getInputNode().select(); - } - } - - - }; - - module.exports = TextInputMixin; - - -/***/ }, -/* 7 */, -/* 8 */, -/* 9 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - - 'use strict'; - - var React = __webpack_require__(10); - var Perf = React.addons.Perf; - - var hasPerfStarted = false; - - var KeyboardHandlerMixin = { - - onKeyDown:function(e){ - if(this.isCtrlKeyHeldDown(e)){ - this.checkAndCall('onPressKeyWithCtrl', e); - } - else if (this.isKeyIdentified(e.key)) { - //break up individual keyPress events to have their own specific callbacks - //this allows multiple mixins to listen to onKeyDown events and somewhat reduces methodName clashing - var callBack = 'onPress' + e.key; - this.checkAndCall(callBack, e); - }else if(this.isKeyPrintable(e.keyCode)){ - this.checkAndCall('onPressChar', e); - } - }, - - //taken from http://stackoverflow.com/questions/12467240/determine-if-javascript-e-keycode-is-a-printable-non-control-character - isKeyPrintable:function(keycode){ - var valid = - (keycode > 47 && keycode < 58) || // number keys - keycode == 32 || keycode == 13 || // spacebar & return key(s) (if you want to allow carriage returns) - (keycode > 64 && keycode < 91) || // letter keys - (keycode > 95 && keycode < 112) || // numpad keys - (keycode > 185 && keycode < 193) || // ;=,-./` (in order) - (keycode > 218 && keycode < 223); // [\]' (in order) - - return valid; - }, - - isKeyIdentified:function(key){ - return key !== "Unidentified"; - }, - - isCtrlKeyHeldDown:function(e){ - return e.ctrlKey === true && e.key !== "Control"; - }, - - checkAndCall:function(methodName, args){ - if(typeof this[methodName] === 'function'){ - this[methodName](args); - } - } - } - - - - module.exports = KeyboardHandlerMixin; - - -/***/ }, -/* 10 */ -/***/ function(module, exports, __webpack_require__) { - - module.exports = __WEBPACK_EXTERNAL_MODULE_10__; - -/***/ }, -/* 11 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - "use strict"; - - var $__0= __webpack_require__(10),PropTypes=$__0.PropTypes,isValidElement=$__0.isValidElement; - var shallowCloneObject = __webpack_require__(28); - var DOMMetrics = __webpack_require__(29); - var merge = __webpack_require__(19); - - /** - * Update column metrics calculation. - * - * @param {ColumnMetrics} metrics - */ - function calculate(metrics) { - var width = 0; - var unallocatedWidth = metrics.totalWidth; - - var deferredColumns = []; - var columns = metrics.columns.map(shallowCloneObject); - - var i, len, column; - - // compute width for columns which specify width - for (i = 0, len = columns.length; i < len; i++) { - column = columns[i]; - - if (column.width) { - if (/^([0-9]+)%$/.exec(column.width)) { - column.width = Math.floor( - parseInt(column.width, 10) / 100 * metrics.totalWidth); - } - unallocatedWidth -= column.width; - width += column.width; - } else { - deferredColumns.push(column); - } - - } - - // compute width for columns which doesn't specify width - for (i = 0, len = deferredColumns.length; i < len; i++) { - column = deferredColumns[i]; - - if (unallocatedWidth <= 0) { - column.width = metrics.minColumnWidth; - } else { - column.width = Math.floor(unallocatedWidth / deferredColumns.length); - } - width += column.width; - } - - // compute left offset - var left = 0; - for (i = 0, len = columns.length; i < len; i++) { - column = columns[i]; - column.left = left; - left += column.width; - } - - return { - columns:columns, - width:width, - totalWidth: metrics.totalWidth, - minColumnWidth: metrics.minColumnWidth - }; - } - - /** - * Update column metrics calculation by resizing a column. - * - * @param {ColumnMetrics} metrics - * @param {Column} column - * @param {number} width - */ - function resizeColumn(metrics, index, width) { - var column = metrics.columns[index]; - metrics = shallowCloneObject(metrics); - metrics.columns = metrics.columns.slice(0); - - var updatedColumn = shallowCloneObject(column); - updatedColumn.width = Math.max(width, metrics.minColumnWidth); - - metrics.columns.splice(index, 1, updatedColumn); - - return calculate(metrics); - } - - var Mixin = { - mixins: [DOMMetrics.MetricsMixin], - - propTypes: { - columns: PropTypes.array, - minColumnWidth: PropTypes.number, - columnEquality: PropTypes.func - }, - - DOMMetrics: { - gridWidth:function() { - return this.getDOMNode().offsetWidth - 2; - } - }, - - getDefaultProps:function() { - return { - minColumnWidth: 80, - columnEquality: sameColumn - }; - }, - - getInitialState:function() { - return this.getColumnMetrics(this.props, true); - }, - - componentWillReceiveProps:function(nextProps) { - if (nextProps.columns) { - if (!sameColumns(this.props.columns, nextProps.columns, this.props.columnEquality)) { - this.setState(this.getColumnMetrics(nextProps)); - } else { - var index = {}; - this.state.columns.columns.forEach(function(c) { - index[c.key] = {width: c.width, left: c.left}; - }); - var nextColumns = merge(this.state.columns, { - columns: nextProps.columns.map(function(c) {return merge(c, index[c.key]);}) - }); - this.setState({columns: nextColumns}); - } - } - }, - - getColumnMetrics:function(props, initial) { - var totalWidth = initial ? null : this.DOMMetrics.gridWidth(); - return { - columns: calculate({ - columns: props.columns, - width: null, - totalWidth:totalWidth, - minColumnWidth: props.minColumnWidth - }), - gridWidth: totalWidth - }; - }, - - metricsUpdated:function() { - this.setState(this.getColumnMetrics(this.props)); - }, - - onColumnResize:function(index, width) { - var columns = resizeColumn(this.state.columns, index, width); - this.setState({columns:columns}); - } - }; - - function sameColumns(prevColumns, nextColumns, sameColumn) { - var i, len, column; - var prevColumnsByKey = {}; - var nextColumnsByKey = {}; - - - if(prevColumns.length !== nextColumns.length){ - return false; - } - - for (i = 0, len = prevColumns.length; i < len; i++) { - column = prevColumns[i]; - prevColumnsByKey[column.key] = column; - } - - for (i = 0, len = nextColumns.length; i < len; i++) { - column = nextColumns[i]; - nextColumnsByKey[column.key] = column; - var prevColumn = prevColumnsByKey[column.key]; - if (prevColumn === undefined || !sameColumn(prevColumn, column)) { - return false; - } - } - - for (i = 0, len = prevColumns.length; i < len; i++) { - column = prevColumns[i]; - var nextColumn = nextColumnsByKey[column.key]; - if (nextColumn === undefined) { - return false; - } - } - - return true; - } - - function sameColumn(a, b) { - var k; - - for (k in a) { - if (a.hasOwnProperty(k)) { - if ((typeof a[k] === 'function' && typeof b[k] === 'function') || (isValidElement(a[k]) && isValidElement(b[k]))) { - continue; - } - if (!b.hasOwnProperty(k) || a[k] !== b[k]) { - return false; - } - } - } - - for (k in b) { - if (b.hasOwnProperty(k) && !a.hasOwnProperty(k)) { - return false; - } - } - - return true; - } - - module.exports = {Mixin:Mixin, calculate:calculate, resizeColumn:resizeColumn, sameColumns:sameColumns, sameColumn:sameColumn}; - - -/***/ }, -/* 12 */ -/***/ function(module, exports, __webpack_require__) { - - - "use strict"; - - var isFunction = function(functionToCheck){ - var getType = {}; - return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]'; - } - - module.exports = isFunction; - - -/***/ }, -/* 13 */, -/* 14 */, -/* 15 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var cx = React.addons.classSet; - var MixinHelper = __webpack_require__(27); - var EditorMixin = __webpack_require__(5); - var TextInputMixin = __webpack_require__(6); - var keyboardHandlerMixin = __webpack_require__(9); - - var SimpleTextEditor = React.createClass({displayName: 'SimpleTextEditor', - - mixins : [keyboardHandlerMixin, EditorMixin, TextInputMixin], - - overrides : { - checkFocus : function(){ - this.setTextInputFocus(); - } - }, - - renderEditorNode:function(){ - return (React.createElement("input", {type: "text", onBlur: this.commit, className: "form-control", defaultValue: this.getDefaultValue(), style: this.getStyle(), onKeyDown: this.onKeyDown})); - } - - - }); - - module.exports = SimpleTextEditor; - - -/***/ }, -/* 16 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - "use strict"; - - var React = __webpack_require__(10); - var PropTypes = React.PropTypes; - var Header = __webpack_require__(30); - var Viewport = __webpack_require__(31); - var ColumnMetrics = __webpack_require__(11); - var DOMMetrics = __webpack_require__(29); - - - var GridScrollMixin = { - - componentDidMount:function() { - this._scrollLeft = this.refs.viewport.getScroll().scrollLeft; - this._onScroll(); - }, - - componentDidUpdate:function() { - this._onScroll(); - }, - - componentWillMount:function() { - this._scrollLeft = undefined; - }, - - componentWillUnmount:function() { - this._scrollLeft = undefined; - }, - - onScroll:function($__0) {var scrollLeft=$__0.scrollLeft; - if (this._scrollLeft !== scrollLeft) { - this._scrollLeft = scrollLeft; - this._onScroll(); - } - }, - - _onScroll:function() { - if (this._scrollLeft !== undefined) { - this.refs.header.setScrollLeft(this._scrollLeft); - this.refs.viewport.setScrollLeft(this._scrollLeft); - } - } - }; - - var Grid = React.createClass({displayName: 'Grid', - mixins: [ - GridScrollMixin, - ColumnMetrics.Mixin, - DOMMetrics.MetricsComputatorMixin - ], - - propTypes: { - rows: PropTypes.oneOfType([PropTypes.array, PropTypes.func]).isRequired, - columns: PropTypes.array.isRequired - }, - - getStyle: function(){ - return{ - overflow: 'hidden', - outline: 0, - position: 'relative', - minHeight: this.props.minHeight - } - }, - - render:function() { - var headerRows = this.props.headerRows || [{ref : 'row'}]; - return ( - React.createElement("div", React.__spread({}, this.props, {style: this.getStyle(), className: "react-grid-Grid"}), - React.createElement(Header, { - ref: "header", - columns: this.state.columns, - onColumnResize: this.onColumnResize, - height: this.props.rowHeight, - totalWidth: this.DOMMetrics.gridWidth(), - headerRows: headerRows} - ), - React.createElement(Viewport, { - ref: "viewport", - width: this.state.columns.width, - rowHeight: this.props.rowHeight, - rowRenderer: this.props.rowRenderer, - cellRenderer: this.props.cellRenderer, - rows: this.props.rows, - selectedRows: this.props.selectedRows, - expandedRows: this.props.expandedRows, - length: this.props.length, - columns: this.state.columns, - totalWidth: this.DOMMetrics.gridWidth(), - onScroll: this.onScroll, - onRows: this.props.onRows, - rowOffsetHeight: this.props.rowOffsetHeight || this.props.rowHeight * headerRows.length} - ) - ) - ); - }, - - getDefaultProps:function() { - return { - rowHeight: 35, - minHeight: 350 - }; - }, - }); - - module.exports = Grid; - - -/***/ }, -/* 17 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var BaseCell = __webpack_require__(3); - var SelectableMixin = __webpack_require__(32); - var EditableMixin = __webpack_require__(33); - var CopyableMixin = __webpack_require__(34); - var DraggableMixin = __webpack_require__(35); - var MixinHelper = __webpack_require__(27); - var KeyboardHandlerMixin = __webpack_require__(9); - var isFunction = __webpack_require__(12); - var PropTypes = React.PropTypes; - var cx = React.addons.classSet; - var cloneWithProps = React.addons.cloneWithProps; - - - - var CellControls = React.createClass({displayName: 'CellControls', - - onClickEdit : function(e){ - e.stopPropagation(); - e.preventDefault(); - this.props.onClickEdit(); - }, - - onShowMore : function(e){ - e.stopPropagation(); - e.preventDefault(); - var newHeight = this.props.column.getExpandedHeight(this.props.value); - this.props.onShowMore(this.props.rowIdx, newHeight); - }, - - onShowLess : function(e){ - e.stopPropagation(); - e.preventDefault(); - this.props.onShowLess(this.props.rowIdx); - }, - - shouldComponentUpdate:function(nextProps, nextState){ - return this.props.height != nextProps.height; - }, - - renderShowMoreButton:function(){ - if(isFunction(this.props.column.getExpandedHeight) && this.props.column.getExpandedHeight(this.props.value) > 0){ - var newHeight = this.props.column.getExpandedHeight(this.props.value); - if(newHeight > this.props.height){ - return React.createElement("button", {type: "button", className: "btn btn-link btn-xs", onClick: this.onShowMore}, "Show More") - }else{ - return React.createElement("button", {type: "button", className: "btn btn-link btn-xs", onClick: this.onShowLess}, "Show Less") - } - }else{ - return null; - } - }, - - render : function(){ - return (React.createElement("div", {className: "pull-right btn-group"}, - this.renderShowMoreButton(), - React.createElement("button", {onClick: this.onClickEdit, type: "button", className: "btn btn-link btn-xs"}, "Edit") - )) - } - - }) - - - var ExcelCell = React.createClass({displayName: 'ExcelCell', - - mixins : [EditableMixin, CopyableMixin, DraggableMixin], - - overrides : { - getCellClass : function(){ - return cx({ - 'selected' : this.isSelected() && !this.isCopied() && !this.isActive(), - 'editing' : this.isActive(), - 'copied' : this.isCopied(), - 'selected-draggable' : this.isSelected() && !this.isActive() && this.canEdit(), - 'active-drag-cell' : this.isActiveDragCell() && this.canEdit(), - 'is-dragged-over-up' : !this.isSelected() && this.isDraggedOver() && this.props.rowIdx < this.props.dragged.rowIdx, - 'is-dragged-over-down' : !this.isSelected() && this.isDraggedOver() && this.props.rowIdx > this.props.dragged.rowIdx, - 'was-dragged-over' : this.wasDraggedOver() && this.canEdit() - }); - } - }, - - isActiveDragCell : function(){ - return (this.isSelected() || this.isDraggedOver()) && !this.isActive(); - }, - - isExpanded : function(){ - var isExpanded = false; - if(isFunction(this.props.column.getExpandedHeight) && this.props.column.getExpandedHeight(this.props.value) > 0){ - var newHeight = this.props.column.getExpandedHeight(this.props.value); - if(this.props.height >= newHeight){ - isExpanded = true; - }else{ - isExpanded = false; - } - } - return isExpanded; - }, - - - shouldComponentUpdate:function(nextProps, nextState) { - return this.props.column.width !== nextProps.column.width - || this.props.value !== nextProps.value - || this.props.height !== nextProps.height - || this.props.rowIdx !== nextProps.rowIdx - || this.isCellSelectionChanging(nextProps) - || this.isDraggedCellChanging(nextProps); - }, - - - render: function() { - return ( - React.createElement(BaseCell, React.__spread({}, - this.props, - {className: this.getCellClass(), - onKeyDown: this.onKeyDown, - onClick: this.onClick, - onDoubleClick: this.onDoubleClick, - formatter: this.getFormatter(), - handleDragStart: this.handleDragStart, - onDragEnter: this.handleDragEnter, - onDragEnd: this.props.handleDragEnd, - cellControls: this.props.column.showCellControls && !this.isActive() ? React.createElement(CellControls, {height: this.props.height, value: this.props.value, rowIdx: this.props.rowIdx, column: this.props.column, onShowMore: this.props.onShowMore, onShowLess: this.props.onShowLess, onClickEdit: this.setActive}) : null, - isExpanded: this.isExpanded()}) - )) - } - - }) - - module.exports = ExcelCell; - - -/***/ }, -/* 18 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var cx = React.addons.classSet; - var BaseRow = __webpack_require__(2); - var ColumnMetrics = __webpack_require__(11); - var ExcelRow = React.createClass({displayName: 'ExcelRow', - - render:function() { - var row = React.addons.update(this.props.row, {$merge : {'select-row' : this.props.isSelected}}); - - return ( - React.createElement(BaseRow, React.__spread({}, - this.props, - {row: row, - height: this.getRowHeight(this.props)})) - ); - }, - - getRowHeight:function(props){ - if(props.expandedRows && props.expandedRows[props.key]){ - return props.expandedRows[props.key]; - }else{ - return props.height; - } - }, - - hasRowHeightChanged:function(props){ - if(props.expandedRows){ - if(typeof props.expandedRows[props.key] !== 'undefined'){ - return this.props.height !== props.expandedRows[props.key] - }else{ - return false; - } - }else{ - return false; - } - }, - - shouldComponentUpdate:function(nextProps) { - return !(ColumnMetrics.sameColumns(this.props.columns, nextProps.columns, ColumnMetrics.sameColumn)) || - this.doesRowContainSelectedCell() || - this.doesRowContainSelectedCell(nextProps) || - this.willRowBeDraggedOver(nextProps) || - this.hasRowBeenCopied() || - nextProps.row !== this.props.row || - this.props.isSelected !== nextProps.isSelected || - this.hasRowHeightChanged(nextProps); - }, - - doesRowContainSelectedCell:function(propsToCheck){ - var props = propsToCheck || this.props; - var cell = cell || props.cellRenderer; - if(cell.props && cell.props.selected && cell.props.selected.rowIdx === props.idx){ - return true; - }else{ - return false; - } - }, - - willRowBeDraggedOver:function(props){ - if(props.cellRenderer.props){ - var dragged = props.cellRenderer.props.dragged; - return dragged != null && (dragged.rowIdx || dragged.complete === true); - }else{ - return false; - } - - }, - - hasRowBeenCopied:function(){ - if(this.props.cellRenderer.props){ - var cell = this.props.cellRenderer; - return cell.props.copied != null && cell.props.copied.rowIdx === this.props.idx; - }else{ - return false; - } - - }, - - setScrollLeft:function(scrollLeft) { - for (var i = 0, len = this.props.columns.length; i < len; i++) { - if (this.props.columns[i].locked) { - this.refs[i].setScrollLeft(scrollLeft); - } - } - } - - - }); - - module.exports = ExcelRow; - - -/***/ }, -/* 19 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * Copyright 2013-2014 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @providesModule merge - */ - - "use strict"; - - /** - * Shallow merges two structures into a return value, without mutating either. - * - * @param {?object} one Optional object with properties to merge from. - * @param {?object} two Optional object with properties to merge from. - * @return {object} The shallow extension of one by two. - */ - var merge = function(one, two) { - var result = {}; - if (one != null) { - Object.assign(result, one); - } - if (two != null) { - Object.assign(result, two); - } - return result; - }; - - function mergeFallback(obj1,obj2){ - var obj3 = {}; - for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; } - for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; } - return obj3; - } - - module.exports = Object.assign ? merge : mergeFallback; - - -/***/ }, -/* 20 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - "use strict"; - - var SelectableGridMixin = { - - getDefaultProps:function() { - return { - enableCellSelect : false, - }; - }, - - getColumns : function(){ - return this.props.columns - }, - - getInitialState: function() { - if(this.props.enableCellSelect){ - return {selected: {rowIdx: 0, idx: 0}}; - }else{ - return {selected: {rowIdx: -1, idx: -1}}; - } - }, - - onSelect: function(selected) { - if(this.props.enableCellSelect){ - var idx = selected.idx; - var rowIdx = selected.rowIdx; - if ( - idx >= 0 - && rowIdx >= 0 - && idx < this.getColumns().length - && rowIdx < this.props.rows.length - ) { - if(this.props.onSelect){ - this.props.onSelect({selected: selected}); - } - this.setState({selected: selected}); - } - } - } - } - - module.exports = SelectableGridMixin; - - -/***/ }, -/* 21 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - "use strict"; - - var React = __webpack_require__(10); - var PropTypes = React.PropTypes; - var MixinHelper = __webpack_require__(27); - var SelectableGridMixin = __webpack_require__(20); - - MixinHelper.addAlias('SelectableGridMixin'); - - var DraggableGridMixin = { - - mixinDependencies : ['SelectableGridMixin'], - - propTypes : { - onCellsDragged : React.PropTypes.func - }, - - getInitialState: function() { - return {dragged : null}; - }, - - handleDragStart:function(dragged){ - var idx = dragged.idx; - var rowIdx = dragged.rowIdx; - if ( - idx >= 0 - && rowIdx >= 0 - && idx < this.getColumns().length - && rowIdx < this.props.rows.length - ) { - this.setState({dragged: dragged}); - } - }, - - handleDragEnter:function(row){ - var selected = this.state.selected; - var dragged = this.state.dragged; - dragged.overRowIdx = row; - this.setState({dragged : dragged}); - }, - - handleDragEnd:function(){ - var fromRow, toRow; - var selected = this.state.selected; - var dragged = this.state.dragged; - var cellKey = this.getColumns()[this.state.selected.idx].key; - fromRow = selected.rowIdx < dragged.overRowIdx ? selected.rowIdx : dragged.overRowIdx; - toRow = selected.rowIdx > dragged.overRowIdx ? selected.rowIdx : dragged.overRowIdx; - this.props.onCellsDragged({cellKey: cellKey , fromRow: fromRow, toRow : toRow, value : dragged.copiedText}); - this.setState({dragged : {complete : true}}); - }, - - handleTerminateDrag:function(){ - this.setState({dragged: null}); - } - } - - - module.exports = DraggableGridMixin; - - -/***/ }, -/* 22 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - "use strict"; - - var React = __webpack_require__(10); - var PropTypes = React.PropTypes; - - var CopyPasteGridMixin = { - - propTypes : { - onCellCopyPaste : React.PropTypes.func - }, - - getInitialState: function() { - return {copied : null}; - }, - - - handleCopy:function(args){ - var textToCopy = args.value; - var selected = this.state.selected; - var copied = {idx : selected.idx, rowIdx : selected.rowIdx}; - this.setState({textToCopy:textToCopy, copied : copied}); - }, - - handlePaste:function(){ - var selected = this.state.selected; - var cellKey = this.getColumns()[selected.idx].key; - this.props.onCellCopyPaste({cellKey: cellKey , rowIdx: selected.rowIdx, value : this.state.textToCopy, fromRow : this.state.copied.rowIdx, toRow : selected.rowIdx}); - this.setState({copied : null}); - } - } - - module.exports = CopyPasteGridMixin; - - -/***/ }, -/* 23 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - "use strict"; - - var React = __webpack_require__(10); - var PropTypes = React.PropTypes; - var merge = __webpack_require__(19); - - var EditableGridMixin = { - - propTypes : { - onRowUpdated : React.PropTypes.func - }, - - onCellCommit:function(commit){ - var selected = this.state.selected; - selected.active = false; - if(commit.keyCode === 'Tab'){ - selected.idx += 1; - } - this.setState({selected : selected}); - this.props.onRowUpdate(commit); - }, - - onSetActive:function(activeCell) { - var selected = merge(this.state.selected, activeCell); - this.setState({selected: selected}); - } - - }; - - - module.exports = EditableGridMixin; - - -/***/ }, -/* 24 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - "use strict"; - - var React = __webpack_require__(10); - var PropTypes = React.PropTypes; - var SortableHeaderCell = __webpack_require__(36); - var shallowCloneObject = __webpack_require__(28); - - var DEFINE_SORT = { - ASC : 'ASC', - DESC : 'DESC' - } - Object.freeze(DEFINE_SORT); - - var SortableGridMixin = { - - getInitialState: function() { - return {sortDirection: null, sortColumn: null}; - }, - - getDecoratedColumns: function(columns) { - return this.props.columns.map(function(column) { - column = shallowCloneObject(column); - if (column.sortable) { - column.headerRenderer = React.createElement(SortableHeaderCell, null); - column.sortBy = this.sortBy; - if (this.state.sortColumn === column.key) { - column.sorted = this.state.sortDirection; - }else{ - column.sorted = DEFINE_SORT.NONE; - } - } - return column - }, this); - }, - - sortBy: function(column, direction) { - switch(direction){ - case null: - case undefined: - direction = DEFINE_SORT.ASC; - break; - case DEFINE_SORT.ASC: - direction = DEFINE_SORT.DESC; - break; - case DEFINE_SORT.DESC: - direction = null; - break; - } - this.setState({sortDirection: direction, sortColumn: column.key}); - }, - - sortRows: function(rows) { - //feels naughty - rows = [].concat(rows); - var sortColumn = this.state.sortColumn; - var sortDirection = this.state.sortDirection; - if(sortColumn != null && sortDirection !== null){ - return rows.sort(function(row1, row2){ - var k1 = row1[sortColumn], k2 = row2[sortColumn]; - if(sortDirection === DEFINE_SORT.ASC){ - return (k1 > k2) ? 1 : ( (k2 > k1) ? -1 : 0 ); - }else if(sortDirection === DEFINE_SORT.DESC){ - return (k1 > k2) ? -1 : ( (k2 > k1) ? 1 : 0 ); - } - }); - }else{ - return rows; - } - - } - - } - - module.exports = SortableGridMixin; - - -/***/ }, -/* 25 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - "use strict"; - - var React = __webpack_require__(10); - var PropTypes = React.PropTypes; - var FilterableHeaderCell = __webpack_require__(37); - - var FilterableGridMixin = { - - getInitialState : function(){ - return {canFilter : false, columnFilters : {}}; - }, - - filterRows:function(){ - var rows = this.props.rows; - if(this.state.sortColumn){ - rows = this.sortRows(rows); - } - - if(this.hasFilters()){ - rows = rows.map(function(r, i) {r.key = i;return r;}).filter(this.isRowDisplayed); - if(this.props.onFilter){ - this.props.onFilter(rows); - } - } - return rows; - }, - - hasFilters:function(){ - var hasFilters = false; - Object.keys(this.state.columnFilters).every(function(key){ - var filter = this.state.columnFilters[key]; - if(filter != null && filter != undefined && filter != ''){ - hasFilters = true; - return false; - } - return true; - }, this); - return hasFilters; - }, - - isRowDisplayed:function(row){ - var isRowDisplayed = null; - Object.keys(this.state.columnFilters).every(function(key){ - var filter = this.state.columnFilters[key].toLowerCase(); - var cellValue = row[key].toString().toLowerCase(); - if(filter != null && filter != undefined && filter != '' && typeof cellValue === 'string'){ - if(cellValue.indexOf(filter) > -1){ - isRowDisplayed = true; - }else{ - isRowDisplayed = false; - return false; - } - } - return true; - }, this); - return isRowDisplayed == null ? false : isRowDisplayed; - }, - - onToggleFilter:function(){ - this.setState({canFilter : !this.state.canFilter}); - }, - - handleAddFilter:function(filter){ - var columnFilters = this.state.columnFilters; - columnFilters[filter.columnKey] = filter.filterTerm; - this.setState({columnFilters : columnFilters, selected : null}); - }, - - getHeaderRows:function(){ - var rows = [{ref:"row", height: this.props.rowHeight}]; - if(this.state.canFilter === true){ - rows.push({ref:"filterRow", headerCellRenderer : React.createElement(FilterableHeaderCell, {onChange: this.handleAddFilter}), height : 45}); - } - return rows; - }, - - getRowOffsetHeight:function(){ - var offsetHeight = 0; - this.getHeaderRows().forEach(function(row) {return offsetHeight += row.height;} ); - return offsetHeight; - } - - } - - module.exports = FilterableGridMixin; - - -/***/ }, -/* 26 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var cx = React.addons.classSet; - - var CheckBoxEditor = React.createClass({displayName: 'CheckBoxEditor', - - - PropTypes : { - value : React.PropTypes.bool.isRequired - }, - - render:function(){ - return (React.createElement("input", {className: "react-grid-CheckBox", type: "checkbox", checked: this.props.value, onChange: this.handleChange})); - }, - - handleChange:function(e){ - this.props.column.onRowSelect(this.props.rowIdx) - }, - - shouldComponentUpdate:function(nextProps, nextState){ - return this.props.value != nextProps.value; - } - - }); - - module.exports = CheckBoxEditor; - - -/***/ }, -/* 27 */ -/***/ function(module, exports, __webpack_require__) { - - - "use strict"; - - var keyMirror = __webpack_require__(42); - var isFunction = __webpack_require__(12) - var React = __webpack_require__(10); - if (!Object.assign) { - Object.assign = __webpack_require__(38); - } - - /** - * Policies that describe methods in Adazzle React Mixins - * Any methods that do not confirm to one of these policies will be treated as a custom method - * All custom methods will be wrapped to potentially allow override/extension as defined on a component - */ - var SpecPolicy = keyMirror({ - /** - * These methods are React Lifecycle methods and should be mixed into any components - * according to their default behviour as specified in React srcrary - */ - DEFINE_LIFE_CYCLE_METHOD : null, - /** - * These methods may be defined only once by the class specification or mixin. - */ - DEFINE_ONCE: null, - /** - * These methods may be defined by both the class specification and mixins. - * Subsequent definitions will be chained. These methods must return void. - */ - DEFINE_MANY: null, - /** - * These methods are overriding the base ReactCompositeComponent class. - */ - OVERRIDE_BASE: null, - /** - * These methods are similar to DEFINE_MANY, except we assume they return - * objects. We try to merge the keys of the return values of all the mixed in - * functions. If there is a key conflict we throw. - */ - DEFINE_MANY_MERGED: null - - }); - - var MixinInterface = { - - - getDefaultProps : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD, - propTypes : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD, - getInitialState : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD, - statics : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD, - displayName : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD, - componentWillMount : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD, - componentWillReceiveProps : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD, - shouldComponentUpdate : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD, - componentWillUpdate : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD, - componentDidUpdate : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD, - componentWillUnmount : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD - } - - var MixinAliasCache = {}; - - - var Mixin = function(base, dependsOn){ - this.base = base; - this.dependsOn = dependsOn; - }; - - var Dependency = function(dependsOn){ - this.assignTo = function(base){ - return new Mixin(base, dependsOn); - } - }; - - - var wrapEachMethodInObject = function(clone, results){ - //loop over each property and mix according to its spec policy - Object.keys(clone).forEach(function(key){ - if(mixinUtils.isCustomProperty(key)){ - //overwrite each function of object with custom functionlity - if(isFunction(clone[key])){ - clone[key] = mixinUtils.wrapCustomMethod(key, clone[key]); - } - }else{ - - switch(MixinInterface[key]){ - case SpecPolicy.DEFINE_LIFE_CYCLE_METHOD: - var lifeCycleObj = {}; - lifeCycleObj[key] = clone[key]; - //add this to mixin result - will be treated as standard - results.push(lifeCycleObj); - break; - case SpecPolicy.DEFINE_MANY_MERGED: - //TODO imlplement handlers for other spec policies - break; - } - - delete clone[key]; - } - - }, this); - } - - - var MixinHelper = { - - /** - * Mix properties and methods from multiple objects, without mutating any of them - * - * @param {array} array of all mixins to be merged - * @return {array} A new array of mixins, the first object being an object of containing all custom methods wrapped - * Subsequent object in array will be any extracted lifecycle methods which should be treated as standard - */ - mix : function(mixins){ - - var results = []; - var primary = {}; - - var dependencies = mixinUtils.getUniqueDependencies(mixins); - for (var d in dependencies){ - Object.assign(primary, MixinAliasCache[dependencies[d]]); - } - wrapEachMethodInObject(primary, results); - - mixins.forEach(function(obj){ - //clone the object so that original methods are not overwritten - var clone = {}; - //check if mixin was created using Mixin Helper - //If it is then merge the properties object - if(obj instanceof Mixin){ - Object.assign(clone, obj.base); - }else{ - Object.assign(clone, obj); - } - - wrapEachMethodInObject(clone, results); - - Object.assign(primary, clone); - }, this); - - results.push(primary); - - - return results; - }, - - - createDependency : function(deps){ - var dependencyList = []; - for (var d in deps){ - if(deps[d] instanceof Mixin){ - this.addAlias(d, deps[d].base) - }else{ - this.addAlias(d, deps[d]) - } - dependencyList.push(d); - } - var uniqueDependencyList = dependencyList.filter(function(value, index, self) { - return self.indexOf(value) === index; - }); - return new Dependency(uniqueDependencyList); - }, - - addAlias : function(key, object){ - MixinAliasCache[key] = object; - } - - }; - - // idea borrowed from https://github.com/jhudson8/react-mixin-manager/blob/master/react-mixin-manager.js - var _createClass = React.createClass; - React.createClass = function(spec) { - if (spec.mixins) { - spec.mixins = MixinHelper.mix(spec.mixins); - } - return _createClass.apply(React, arguments); - }; - - - var mixinUtils = { - - isCustomProperty : function(key){ - return (!MixinInterface[key]); - }, - - wrapCustomMethod : function(methodName, old){ - return function(){ - //call overridden method if exists - if(mixinUtils.isMethodOverridden.call(this, methodName)){ - return mixinUtils.callOverriddenMethod.call(this, methodName, arguments); - }else{ - //call the original mixin method - return old.apply(this, arguments); - } - } - }, - - checkMethodExtendedAndCall : function(methodName, args){ - if(this.extended && (typeof this.extended[methodName] === 'function')){ - return this.extended[methodName].call(this, args); - } - }, - - checkMethodImplementedAndCall: function(methodName, args){ - if(this.implemented && (typeof this.implemented[methodName] === 'function')){ - return this.implemented[methodName].call(this, args); - } - }, - - isMethodOverridden: function(methodName){ - return this.overrides && (typeof this.overrides[methodName] === 'function'); - }, - - callOverriddenMethod: function(methodName, args){ - return this.overrides[methodName].call(this, args); - }, - - getUniqueDependencies : function(mixins){ - var deps = []; - mixins.forEach(function(m){ - if(m instanceof Mixin){ - deps = deps.concat(m.dependsOn); - } - }, this); - return deps.filter(function(value, index, self) { - return self.indexOf(value) === index; - });; - } - } - module.exports = MixinHelper; - - -/***/ }, -/* 28 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - function shallowCloneObject(obj) { - var result = {}; - for (var k in obj) { - if (obj.hasOwnProperty(k)) { - result[k] = obj[k]; - } - } - return result; - } - - module.exports = shallowCloneObject; - - -/***/ }, -/* 29 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var emptyFunction = __webpack_require__(40); - var shallowCloneObject = __webpack_require__(28); - var invariant = __webpack_require__(41); - - var contextTypes = { - metricsComputator: React.PropTypes.object - }; - - var MetricsComputatorMixin = { - - childContextTypes: contextTypes, - - getChildContext:function() { - return {metricsComputator: this}; - }, - - getMetricImpl:function(name) { - return this._DOMMetrics.metrics[name].value; - }, - - registerMetricsImpl:function(component, metrics) { - var getters = {}; - var s = this._DOMMetrics; - - for (var name in metrics) { - invariant( - s.metrics[name] === undefined, - 'DOM metric ' + name + ' is already defined' - ); - s.metrics[name] = {component:component, computator: metrics[name].bind(component)}; - getters[name] = this.getMetricImpl.bind(null, name); - } - - if (s.components.indexOf(component) === -1) { - s.components.push(component); - } - - return getters; - }, - - unregisterMetricsFor:function(component) { - var s = this._DOMMetrics; - var idx = s.components.indexOf(component); - - if (idx > -1) { - s.components.splice(idx, 1); - - var name; - var metricsToDelete = {}; - - for (name in s.metrics) { - if (s.metrics[name].component === component) { - metricsToDelete[name] = true; - } - } - - for (name in metricsToDelete) { - delete s.metrics[name]; - } - } - }, - - updateMetrics:function() { - var s = this._DOMMetrics; - - var needUpdate = false; - - for (var name in s.metrics) { - var newMetric = s.metrics[name].computator(); - if (newMetric !== s.metrics[name].value) { - needUpdate = true; - } - s.metrics[name].value = newMetric; - } - - if (needUpdate) { - for (var i = 0, len = s.components.length; i < len; i++) { - if (s.components[i].metricsUpdated) { - s.components[i].metricsUpdated(); - } - } - } - }, - - componentWillMount:function() { - this._DOMMetrics = { - metrics: {}, - components: [] - }; - }, - - componentDidMount:function() { - if(window.addEventListener){ - window.addEventListener('resize', this.updateMetrics); - }else{ - window.attachEvent('resize', this.updateMetrics); - } - this.updateMetrics(); - }, - - componentWillUnmount:function() { - window.removeEventListener('resize', this.updateMetrics); - } - - }; - - var MetricsMixin = { - - contextTypes: contextTypes, - - componentWillMount:function() { - if (this.DOMMetrics) { - this._DOMMetricsDefs = shallowCloneObject(this.DOMMetrics); - - this.DOMMetrics = {}; - for (var name in this._DOMMetricsDefs) { - this.DOMMetrics[name] = emptyFunction; - } - } - }, - - componentDidMount:function() { - if (this.DOMMetrics) { - this.DOMMetrics = this.registerMetrics(this._DOMMetricsDefs); - } - }, - - componentWillUnmount:function() { - if (!this.registerMetricsImpl) { - return this.context.metricsComputator.unregisterMetricsFor(this); - } - if (this.hasOwnProperty('DOMMetrics')) { - delete this.DOMMetrics; - } - }, - - registerMetrics:function(metrics) { - if (this.registerMetricsImpl) { - return this.registerMetricsImpl(this, metrics); - } else { - return this.context.metricsComputator.registerMetricsImpl(this, metrics); - } - }, - - getMetric:function(name) { - if (this.getMetricImpl) { - return this.getMetricImpl(name); - } else { - return this.context.metricsComputator.getMetricImpl(name); - } - } - }; - - module.exports = { - MetricsComputatorMixin:MetricsComputatorMixin, - MetricsMixin:MetricsMixin - }; - - -/***/ }, -/* 30 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - "use strict"; - - var React = __webpack_require__(10); - var cx = React.addons.classSet; - var shallowCloneObject = __webpack_require__(28); - var ColumnMetrics = __webpack_require__(11); - var HeaderRow = __webpack_require__(45); - var ColumnMetrics = __webpack_require__(11); - - var Header = React.createClass({displayName: 'Header', - - propTypes: { - columns: React.PropTypes.object.isRequired, - totalWidth: React.PropTypes.number, - height: React.PropTypes.number.isRequired, - headerRows : React.PropTypes.array.isRequired - }, - - render:function() { - var state = this.state.resizing || this.props; - - var className = cx({ - 'react-grid-Header': true, - 'react-grid-Header--resizing': !!this.state.resizing - }); - var headerRows = this.getHeaderRows(); - - return ( - - React.createElement("div", React.__spread({}, this.props, {style: this.getStyle(), className: className}), - headerRows - ) - ); - }, - - shouldComponentUpdate : function(nextProps, nextState){ - return !(ColumnMetrics.sameColumns(this.props.columns.columns, nextProps.columns.columns, ColumnMetrics.sameColumn)) - || this.props.totalWidth != nextProps.totalWidth - || (this.props.headerRows.length != nextProps.headerRows.length) - || (this.state.resizing != nextState.resizing) - }, - - getHeaderRows:function(){ - var state = this.state.resizing || this.props; - var headerRows = []; - this.props.headerRows.forEach((function(row, index){ - var headerRowStyle = { - position: 'absolute', - top: this.props.height * index, - left: 0, - width: this.props.totalWidth - }; - - headerRows.push(React.createElement(HeaderRow, { - key: row.ref, - ref: row.ref, - style: headerRowStyle, - onColumnResize: this.onColumnResize, - onColumnResizeEnd: this.onColumnResizeEnd, - width: state.columns.width, - height: row.height || this.props.height, - columns: state.columns.columns, - resizing: state.column, - headerCellRenderer: row.headerCellRenderer} - )) - }).bind(this)); - return headerRows; - }, - - getInitialState:function() { - return {resizing: null}; - }, - - componentWillReceiveProps:function() { - this.setState({resizing: null}); - }, - - onColumnResize:function(column, width) { - var state = this.state.resizing || this.props; - - var pos = this.getColumnPosition(column); - - if (pos !== null) { - var resizing = { - columns: shallowCloneObject(state.columns) - }; - resizing.columns = ColumnMetrics.resizeColumn( - resizing.columns, pos, width); - - // we don't want to influence scrollLeft while resizing - if (resizing.columns.width < state.columns.width) { - resizing.columns.width = state.columns.width; - } - - resizing.column = resizing.columns.columns[pos]; - this.setState({resizing:resizing}); - } - }, - - getColumnPosition:function(column) { - var state = this.state.resizing || this.props; - var pos = state.columns.columns.indexOf(column); - return pos === -1 ? null : pos; - }, - - onColumnResizeEnd:function(column, width) { - var pos = this.getColumnPosition(column); - if (pos !== null && this.props.onColumnResize) { - this.props.onColumnResize(pos, width || column.width); - } - }, - - setScrollLeft:function(scrollLeft) { - var node = this.refs.row.getDOMNode(); - node.scrollLeft = scrollLeft; - this.refs.row.setScrollLeft(scrollLeft); - }, - - getStyle:function() { - return { - position: 'relative', - height: this.props.height - }; - }, - }); - - - module.exports = Header; - - -/***/ }, -/* 31 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var getWindowSize = __webpack_require__(43); - var DOMMetrics = __webpack_require__(29); - var Canvas = __webpack_require__(44); - - var min = Math.min; - var max = Math.max; - var floor = Math.floor; - var ceil = Math.ceil; - - var ViewportScroll = { - mixins: [DOMMetrics.MetricsMixin], - - DOMMetrics: { - viewportHeight:function() { - return this.getDOMNode().offsetHeight; - } - }, - - propTypes: { - rowHeight: React.PropTypes.number, - length: React.PropTypes.number.isRequired - }, - - getDefaultProps:function() { - return { - rowHeight: 30 - }; - }, - - getInitialState:function() { - return this.getGridState(this.props); - }, - - getGridState:function(props) { - var height = this.state && this.state.height ? - this.state.height : - getWindowSize().height; - var renderedRowsCount = ceil(height / props.rowHeight); - return { - displayStart: 0, - displayEnd: renderedRowsCount * 2, - height: height, - scrollTop: 0, - scrollLeft: 0 - }; - }, - - updateScroll:function(scrollTop, scrollLeft, height, rowHeight, length) { - var renderedRowsCount = ceil(height / rowHeight); - - var visibleStart = floor(scrollTop / rowHeight); - - var visibleEnd = min( - visibleStart + renderedRowsCount, - length); - - var displayStart = max( - 0, - visibleStart - renderedRowsCount * 2); - - var displayEnd = min( - visibleStart + renderedRowsCount * 2, - length); - - var nextScrollState = { - visibleStart:visibleStart, - visibleEnd:visibleEnd, - displayStart:displayStart, - displayEnd:displayEnd, - height:height, - scrollTop:scrollTop, - scrollLeft:scrollLeft - }; - - this.setState(nextScrollState); - }, - - metricsUpdated:function() { - var height = this.DOMMetrics.viewportHeight(); - if (height) { - this.updateScroll( - this.state.scrollTop, - this.state.scrollLeft, - height, - this.props.rowHeight, - this.props.length - ); - } - }, - - componentWillReceiveProps:function(nextProps) { - if (this.props.rowHeight !== nextProps.rowHeight) { - this.setState(this.getGridState(nextProps)); - } else if (this.props.length !== nextProps.length) { - this.updateScroll( - this.state.scrollTop, - this.state.scrollLeft, - this.state.height, - nextProps.rowHeight, - nextProps.length - ); - } - } - }; - - var Viewport = React.createClass({displayName: 'Viewport', - mixins: [ViewportScroll], - - render:function() { - var style = { - padding: 0, - bottom: 0, - left: 0, - right: 0, - overflow: 'hidden', - position: 'absolute', - top: this.props.rowOffsetHeight - }; - return ( - React.createElement("div", { - className: "react-grid-Viewport", - style: style}, - React.createElement(Canvas, { - ref: "canvas", - totalWidth: this.props.totalWidth, - width: this.props.columns.width, - rows: this.props.rows, - selectedRows: this.props.selectedRows, - expandedRows: this.props.expandedRows, - columns: this.props.columns.columns, - cellRenderer: this.props.cellRenderer, - rowRenderer: this.props.rowRenderer, - - visibleStart: this.state.visibleStart, - visibleEnd: this.state.visibleEnd, - displayStart: this.state.displayStart, - displayEnd: this.state.displayEnd, - - length: this.props.length, - height: this.state.height, - rowHeight: this.props.rowHeight, - onScroll: this.onScroll, - onRows: this.props.onRows} - ) - ) - ); - }, - - getScroll:function() { - return this.refs.canvas.getScroll(); - }, - - onScroll:function($__0 ) {var scrollTop=$__0.scrollTop,scrollLeft=$__0.scrollLeft; - this.updateScroll( - scrollTop, scrollLeft, - this.state.height, - this.props.rowHeight, - this.props.length - ); - - if (this.props.onScroll) { - this.props.onScroll({scrollTop:scrollTop, scrollLeft:scrollLeft}); - } - }, - - setScrollLeft:function(scrollLeft) { - this.refs.canvas.setScrollLeft(scrollLeft); - } - }); - - module.exports = Viewport; - - -/***/ }, -/* 32 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var cx = React.addons.classSet; - var cloneWithProps = React.addons.cloneWithProps; - var KeyboardHandlerMixin = __webpack_require__(9); - var MixinHelper = __webpack_require__(27); - - var SelectableMixin = MixinHelper.createDependency({KeyboardHandlerMixin : KeyboardHandlerMixin}).assignTo({ - - getDefaultProps : function(){ - return { - tabIndex : -1, - ref : "cell" - } - }, - - isSelected: function() { - return ( - this.props.selected - && this.props.selected.rowIdx === this.props.rowIdx - && this.props.selected.idx === this.props.idx - ); - }, - - onClick: function() { - var rowIdx = this.props.rowIdx; - var idx = this.props.idx; - this.props.onClick({rowIdx: rowIdx, idx: idx}); - }, - - onPressArrowUp:function(e){ - this.moveSelectedCell(e, -1, 0); - }, - - onPressArrowDown:function(e){ - this.moveSelectedCell(e, 1, 0); - }, - - onPressArrowLeft:function(e){ - this.moveSelectedCell(e, 0, -1); - }, - - onPressArrowRight:function(e){ - this.moveSelectedCell(e, 0, 1); - }, - - onPressTab:function(e){ - this.moveSelectedCell(e, 0, 1); - }, - - moveSelectedCell:function(e, rowDelta, cellDelta){ - e.stopPropagation(); - e.preventDefault(); - var rowIdx = this.props.rowIdx + rowDelta; - var idx = this.props.idx + cellDelta; - this.props.onSelect({idx: idx, rowIdx: rowIdx}); - }, - - setScrollLeft: function(scrollLeft) { - this.refs.row.setScrollLeft(scrollLeft); - }, - - componentDidMount: function() { - this.checkFocus(); - }, - - componentDidUpdate: function() { - this.checkFocus(); - }, - - isCellSelectionChanging:function(nextProps){ - if(this.props.selected && nextProps.selected){ - return this.props.idx === nextProps.selected.idx || this.props.idx === this.props.selected.idx; - }else{ - return true; - } - }, - - checkFocus: function() { - if (this.isSelected()) { - this.getDOMNode().focus(); - } - } - }) - - - - module.exports = SelectableMixin; - - -/***/ }, -/* 33 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var cx = React.addons.classSet; - var cloneWithProps = React.addons.cloneWithProps; - var SimpleTextEditor = __webpack_require__(15); - var PropTypes = React.PropTypes; - var MixinHelper = __webpack_require__(27); - var SelectableMixin = __webpack_require__(32); - var KeyboardHandlerMixin = __webpack_require__(9); - - var EditableMixin = MixinHelper.createDependency({ - - KeyboardHandlerMixin : KeyboardHandlerMixin, - - SelectableMixin : SelectableMixin - - }).assignTo({ - - propTypes : { - onCommit : PropTypes.func.isRequired - }, - - canEdit:function(){ - return (this.props.column.editor != null) || this.props.column.editable; - }, - - - getEditor:function(){ - - var editorProps = {height : this.props.height, onPressEscape : this.onPressEscape, onCommit : this.onCommit, initialKeyCode : this.props.selected.initialKeyCode, editorRowMetaData : this.getEditorRowMetaData()}; - var customEditor = this.props.column.editor; - if(customEditor && React.isValidElement(customEditor)){ - //return custom column editor or SimpleEditor if none specified - return cloneWithProps(customEditor, editorProps); - }else{ - return cloneWithProps(SimpleTextEditor(), editorProps); - } - }, - - getEditorRowMetaData:function(){ - //clone row data so editor cannot actually change this - var columnName = this.props.column.ItemId; - //convention based method to get corresponding Id or Name of any Name or Id property - if(typeof this.props.column.getEditorRowMetaData === 'function'){ - return this.props.column.getEditorRowMetaData(this.props.rowData); - } - }, - - getFormatter:function(){ - var col = this.props.column; - if(this.isActive()){ - return this.getEditor(); - }else{ - return this.props.column.formatter; - } - }, - - onCommit:function(commit){ - var rowIdx = this.props.rowIdx; - var idx = this.props.idx; - var cellKey = this.props.column.key; - this.props.onCommit({cellKey: cellKey, rowIdx: this.props.filterRowIdx || rowIdx, updated : commit.updated, keyCode : commit.key}); - }, - - checkFocus: function() { - if (this.isSelected() && !this.isActive()) { - this.getDOMNode().focus(); - } - }, - - onClick:function() { - if(!this.isActive()){ - var rowIdx = this.props.rowIdx; - var idx = this.props.idx; - this.props.onClick({rowIdx: rowIdx, idx: idx}); - } - - }, - - onDoubleClick:function() { - var rowIdx = this.props.rowIdx; - var idx = this.props.idx; - this.props.onClick({rowIdx: rowIdx, idx: idx, active : this.canEdit()}); - }, - - setActive:function(keyPressed){ - var rowIdx = this.props.rowIdx; - var idx = this.props.idx; - if(this.props.column.key === 'select-row' && this.props.column.onRowSelect){ - this.props.column.onRowSelect(rowIdx); - } - else if(this.canEdit() && !this.isActive()){ - this.props.onSetActive({idx: idx, rowIdx: rowIdx, active : true, initialKeyCode : keyPressed}); - } - }, - - setInactive:function(){ - if(this.canEdit() && this.isActive()){ - var rowIdx = this.props.rowIdx; - var idx = this.props.idx; - this.props.onSetActive({idx: idx, rowIdx: rowIdx, active : false}); - } - }, - - isActive:function(){ - return this.isSelected() && this.props.selected.active === true; - }, - - onPressEnter:function(e){ - this.setActive(e.key); - }, - - onPressDelete:function(e){ - this.setActive(e.key); - }, - - onPressEscape:function(e){ - this.setInactive(e.key); - }, - - onPressBackspace:function(e){ - this.setActive(e.key); - }, - - onPressChar:function(e){ - if(this.isKeyPrintable(e.keyCode)){ - this.setActive(e.keyCode); - } - } - }); - - - - module.exports = EditableMixin; - - -/***/ }, -/* 34 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var cx = React.addons.classSet; - var cloneWithProps = React.addons.cloneWithProps; - var PropTypes = React.PropTypes; - var SimpleTextEditor = __webpack_require__(15); - var MixinHelper = __webpack_require__(27); - var SelectableMixin = __webpack_require__(32); - var KeyboardHandlerMixin = __webpack_require__(9); - - var CopyableMixin = MixinHelper.createDependency({ - - KeyboardHandlerMixin : KeyboardHandlerMixin, - - SelectableMixin : SelectableMixin - - }).assignTo({ - - getCellClass : function(){ - return cx({ - 'selected' : this.isSelected() && !this.isCopied(), - 'copied' : this.isCopied() - }) - }, - - KeyCode_c : '99', - - KeyCode_C : '67', - - KeyCode_V : '86', - - KeyCode_v : '118', - - propTypes : { - handleCopy : React.PropTypes.func.isRequired, - handlePaste : React.PropTypes.func.isRequired - }, - - isCopied : function(){ - return ( - this.props.copied - && this.props.copied.rowIdx === this.props.rowIdx - && this.props.copied.idx === this.props.idx - ); - }, - - onPressKeyWithCtrl:function(e){ - if(this.canEdit()){ - if(e.keyCode == this.KeyCode_c || e.keyCode == this.KeyCode_C){ - this.props.handleCopy({value : this.props.value}); - }else if(e.keyCode == this.KeyCode_v || e.keyCode == this.KeyCode_V){ - this.props.handlePaste({value : this.props.value}); - } - } - } - }); - - - - module.exports = CopyableMixin; - - -/***/ }, -/* 35 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var cx = React.addons.classSet; - var cloneWithProps = React.addons.cloneWithProps; - var PropTypes = React.PropTypes; - var MixinHelper = __webpack_require__(27); - var SelectableMixin = __webpack_require__(32); - var KeyboardHandlerMixin = __webpack_require__(9); - - var DraggableMixin = MixinHelper.createDependency({ - - KeyboardHandlerMixin : KeyboardHandlerMixin, - - SelectableMixin : SelectableMixin - - }).assignTo({ - - getCellClass : function(){ - return cx({ - 'selected-draggable' : this.isSelected(), - 'active-drag-cell' : this.isSelected() || this.isDraggedOver(), - 'is-dragged-over-up' : !this.isSelected() && this.isDraggedOver() && this.props.rowIdx < this.props.dragged.rowIdx, - 'is-dragged-over-down' : !this.isSelected() && this.isDraggedOver() && this.props.rowIdx > this.props.dragged.rowIdx, - 'was-dragged-over' : this.wasDraggedOver() - }); - }, - - getDefaultProps : function(){ - return { - handleDragStart: this.handleDragStart, - onDragEnter: this.handleDragEnter, - onDragEnd: this.handleDragEnd - } - }, - - propTypes : { - handleDragEnter : React.PropTypes.func.isRequired, - handleDragStart : React.PropTypes.func.isRequired, - handleDragEnd : React.PropTypes.func.isRequired, - handleTerminateDrag : React.PropTypes.func.isRequired - }, - - isDraggedOver:function(){ - - return ( - this.props.dragged && - this.props.dragged.overRowIdx === this.props.rowIdx - && this.props.dragged.idx === this.props.idx - ) - }, - - wasDraggedOver:function(){ - return ( - this.props.dragged - && ((this.props.dragged.overRowIdx < this.props.rowIdx && this.props.rowIdx < this.props.dragged.rowIdx) - || (this.props.dragged.overRowIdx > this.props.rowIdx && this.props.rowIdx > this.props.dragged.rowIdx)) - && this.props.dragged.idx === this.props.idx - ); - }, - - handleDragStart:function(e){ - var rowIdx = this.props.rowIdx; - var idx = this.props.idx; - this.props.handleDragStart({rowIdx : rowIdx, idx : idx, copiedText : this.props.value}); - }, - - handleDragEnter:function(){ - this.props.handleDragEnter(this.props.rowIdx); - }, - - handleDragEnd:function(){ - this.props.handleDragEnd(); - }, - - isDraggedCellChanging:function(nextProps){ - if(this.props.dragged){ - return (nextProps.dragged && this.props.idx === nextProps.dragged.idx) - || (this.props.dragged && this.props.idx === this.props.dragged.idx); - }else{ - return false; - } - }, - - componentDidUpdate:function(){ - var dragged = this.props.dragged; - if(dragged && dragged.complete === true){ - this.props.handleTerminateDrag(); - } - } - - }); - - - - module.exports = DraggableMixin; - - -/***/ }, -/* 36 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var cx = React.addons.classSet; - - var SortableHeaderCell = React.createClass({displayName: 'SortableHeaderCell', - - onClick: function() { - this.props.column.sortBy( - this.props.column, - this.props.column.sorted); - }, - - getSortByClass : function(){ - var sorted = this.props.column.sorted; - return cx({ - 'pull-right' : true, - 'glyphicon glyphicon-arrow-up' : sorted === 'ASC', - 'glyphicon glyphicon-arrow-down' : sorted === 'DESC' - }); - }, - - render: function() { - - return ( - React.createElement("div", { - onClick: this.onClick, - style: {cursor: 'pointer'}}, - this.props.column.name, - React.createElement("span", {className: this.getSortByClass()}) - ) - ); - } - }); - - module.exports = SortableHeaderCell; - - -/***/ }, -/* 37 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var cx = React.addons.classSet; - - var FilterableHeaderCell = React.createClass({displayName: 'FilterableHeaderCell', - - getInitialState:function(){ - return {filterTerm : ''} - }, - - handleChange:function(e){ - e.preventDefault(); - e.stopPropagation(); - this.setState({filterTerm : e.currentTarget.value}); - this.props.onChange({filterTerm : e.currentTarget.value, columnKey : this.props.column.key}); - }, - - componentDidUpdate:function(){ - this.getDOMNode().focus(); - }, - - render: function() { - return ( - React.createElement("div", null, - React.createElement("div", {className: "form-group"}, - React.createElement(this.renderInput, null) - ) - ) - ); - }, - - renderInput : function(){ - if(this.props.column.filterable === false){ - return React.createElement("span", null); - }else{ - return (React.createElement("input", {type: "text", className: "form-control input-sm", placeholder: "Search", value: this.state.filterTerm, onChange: this.handleChange})) - } - - } - }); - - module.exports = FilterableHeaderCell; - - -/***/ }, -/* 38 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - function ToObject(val) { - if (val == null) { - throw new TypeError('Object.assign cannot be called with null or undefined'); - } - - return Object(val); - } - - module.exports = Object.assign || function (target, source) { - var from; - var keys; - var to = ToObject(target); - - for (var s = 1; s < arguments.length; s++) { - from = arguments[s]; - keys = Object.keys(Object(from)); - - for (var i = 0; i < keys.length; i++) { - to[keys[i]] = from[keys[i]]; - } - } - - return to; - }; - - -/***/ }, -/* 39 */, -/* 40 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * Copyright 2013-2014 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @providesModule emptyFunction - */ - 'use strict'; - - var copyProperties = __webpack_require__(46); - - function makeEmptyFunction(arg) { - return function() { - return arg; - }; - } - - /** - * This function accepts and discards inputs; it has no side effects. This is - * primarily useful idiomatically for overridable function endpoints which - * always need to be callable, since JS lacks a null-call idiom ala Cocoa. - */ - function emptyFunction() {} - - copyProperties(emptyFunction, { - thatReturns: makeEmptyFunction, - thatReturnsFalse: makeEmptyFunction(false), - thatReturnsTrue: makeEmptyFunction(true), - thatReturnsNull: makeEmptyFunction(null), - thatReturnsThis: function() { return this; }, - thatReturnsArgument: function(arg) { return arg; } - }); - - module.exports = emptyFunction; - - -/***/ }, -/* 41 */ -/***/ function(module, exports, __webpack_require__) { - - /* WEBPACK VAR INJECTION */(function(process) {/** - * Copyright 2013-2014 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @providesModule invariant - */ - - "use strict"; - - /** - * Use invariant() to assert state which your program assumes to be true. - * - * Provide sprintf-style format (only %s is supported) and arguments - * to provide information about what broke and what you were - * expecting. - * - * The invariant message will be stripped in production, but the invariant - * will remain to ensure logic does not differ in production. - */ - - var invariant = function(condition, format, a, b, c, d, e, f) { - if (process.env.NODE_ENV) { - if (format === undefined) { - throw new Error('invariant requires an error message argument'); - } - } - - if (!condition) { - var error; - if (format === undefined) { - error = new Error( - 'Minified exception occurred; use the non-minified dev environment ' + - 'for the full error message and additional helpful warnings.' - ); - } else { - var args = [a, b, c, d, e, f]; - var argIndex = 0; - error = new Error( - 'Invariant Violation: ' + - format.replace(/%s/g, function() { return args[argIndex++]; }) - ); - } - - error.framesToPop = 1; // we don't care about invariant's own frame - throw error; - } - }; - - module.exports = invariant; - - /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(52))) - -/***/ }, -/* 42 */ -/***/ function(module, exports, __webpack_require__) { - - /* WEBPACK VAR INJECTION */(function(process) {/** - * Copyright 2013-2014, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @providesModule keyMirror - * @typechecks static-only - */ - - "use strict"; - - var invariant = __webpack_require__(51); - - /** - * Constructs an enumeration with keys equal to their value. - * - * For example: - * - * var COLORS = keyMirror({blue: null, red: null}); - * var myColor = COLORS.blue; - * var isColorValid = !!COLORS[myColor]; - * - * The last line could not be performed if the values of the generated enum were - * not equal to their keys. - * - * Input: {key1: val1, key2: val2} - * Output: {key1: key1, key2: key2} - * - * @param {object} obj - * @return {object} - */ - var keyMirror = function(obj) { - var ret = {}; - var key; - ("production" !== process.env.NODE_ENV ? invariant( - obj instanceof Object && !Array.isArray(obj), - 'keyMirror(...): Argument must be an object.' - ) : invariant(obj instanceof Object && !Array.isArray(obj))); - for (key in obj) { - if (!obj.hasOwnProperty(key)) { - continue; - } - ret[key] = key; - } - return ret; - }; - - module.exports = keyMirror; - - /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(52))) - -/***/ }, -/* 43 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - /** - * Return window's height and width - * - * @return {Object} height and width of the window - */ - function getWindowSize() { - var width = window.innerWidth; - var height = window.innerHeight; - - if (!width || !height) { - width = document.documentElement.clientWidth; - height = document.documentElement.clientHeight; - } - - if (!width || !height) { - width = document.body.clientWidth; - height = document.body.clientHeight; - } - - return {width:width, height:height}; - } - - module.exports = getWindowSize; - - -/***/ }, -/* 44 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - "use strict"; - - var React = __webpack_require__(10); - var cx = React.addons.classSet; - var PropTypes = React.PropTypes; - var cloneWithProps = React.addons.cloneWithProps; - var shallowEqual = __webpack_require__(47); - var emptyFunction = __webpack_require__(40); - var ScrollShim = __webpack_require__(48); - var Row = __webpack_require__(2); - - var Canvas = React.createClass({displayName: 'Canvas', - mixins: [ScrollShim], - - propTypes: { - cellRenderer: PropTypes.element, - rowRenderer: PropTypes.oneOfType([PropTypes.func, PropTypes.element]), - rowHeight: PropTypes.number.isRequired, - displayStart: PropTypes.number.isRequired, - displayEnd: PropTypes.number.isRequired, - length: PropTypes.number.isRequired, - rows: PropTypes.oneOfType([ - PropTypes.func.isRequired, - PropTypes.array.isRequired - ]), - onRows: PropTypes.func - }, - - render:function() { - var displayStart = this.state.displayStart; - var displayEnd = this.state.displayEnd; - var rowHeight = this.props.rowHeight; - var length = this.props.length; - - var rows = this - .getRows(displayStart, displayEnd) - .map(function(row, idx) {return this.renderRow({ - key: displayStart + idx, - ref: idx, - idx: displayStart + idx, - row: row, - height: rowHeight, - columns: this.props.columns, - cellRenderer: this.props.cellRenderer, - isSelected : this.isRowSelected(displayStart + idx), - expandedRows : this.props.expandedRows - });}.bind(this)); - - this._currentRowsLength = rows.length; - - if (displayStart > 0) { - rows.unshift(this.renderPlaceholder('top', displayStart * rowHeight)); - } - - if (length - displayEnd > 0) { - rows.push( - this.renderPlaceholder('bottom', (length - displayEnd) * rowHeight)); - } - - var style = { - position: 'absolute', - top: 0, - left: 0, - overflowX: 'auto', - overflowY: 'scroll', - width: this.props.totalWidth, - height: this.props.height, - transform: 'translate3d(0, 0, 0)' - }; - - return ( - React.createElement("div", { - style: style, - onScroll: this.onScroll, - className: cx("react-grid-Canvas", this.props.className)}, - React.createElement("div", {style: {width: this.props.width, overflow: 'hidden'}}, - rows - ) - ) - ); - }, - - renderRow:function(props) { - if (React.isValidElement(this.props.rowRenderer)) { - return cloneWithProps(this.props.rowRenderer, props); - } else { - return this.props.rowRenderer(props); - } - }, - - renderPlaceholder:function(key, height) { - return ( - React.createElement("div", {key: key, style: {height: height}}, - this.props.columns.map( - function(column, idx) {return React.createElement("div", {style: {width: column.width}, key: idx});}) - ) - ); - }, - - getDefaultProps:function() { - return { - rowRenderer: React.createElement(Row, null), - onRows: emptyFunction - }; - }, - - isRowSelected:function(rowIdx){ - return this.props.selectedRows && this.props.selectedRows[rowIdx] === true; - }, - - getInitialState:function() { - return { - shouldUpdate: true, - displayStart: this.props.displayStart, - displayEnd: this.props.displayEnd - }; - }, - - componentWillMount:function() { - this._currentRowsLength = undefined; - this._currentRowsRange = undefined; - this._scroll = undefined; - }, - - componentDidMount:function() { - this.onRows(); - }, - - componentDidUpdate:function() { - if (this._scroll !== undefined) { - this.setScrollLeft(this._scroll); - } - this.onRows(); - }, - - componentWillUnmount:function() { - this._currentRowsLength = undefined; - this._currentRowsRange = undefined; - this._scroll = undefined; - }, - - componentWillReceiveProps:function(nextProps) { - var shouldUpdate = !(nextProps.visibleStart > this.state.displayStart - && nextProps.visibleEnd < this.state.displayEnd) - || nextProps.length !== this.props.length - || nextProps.rowHeight !== this.props.rowHeight - || nextProps.columns !== this.props.columns - || nextProps.width !== this.props.width - || !shallowEqual(nextProps.style, this.props.style); - - if (shouldUpdate) { - this.setState({ - shouldUpdate: true, - displayStart: nextProps.displayStart, - displayEnd: nextProps.displayEnd - }); - } else { - this.setState({shouldUpdate: false}); - } - }, - - shouldComponentUpdate:function(nextProps, nextState) { - return nextState.shouldUpdate; - }, - - onRows:function() { - if (this._currentRowsRange !== undefined) { - this.props.onRows(this._currentRowsRange); - this._currentRowsRange = undefined; - } - }, - - getRows:function(displayStart, displayEnd) { - this._currentRowsRange = {start: displayStart, end: displayEnd}; - if (Array.isArray(this.props.rows)) { - return this.props.rows.slice(displayStart, displayEnd); - } else { - return this.props.rows(displayStart, displayEnd); - } - }, - - setScrollLeft:function(scrollLeft) { - if (this._currentRowsLength !== undefined) { - for (var i = 0, len = this._currentRowsLength; i < len; i++) { - if(this.refs[i]) { - this.refs[i].setScrollLeft(scrollLeft); - } - } - } - }, - - getScroll:function() { - var $__0= this.getDOMNode(),scrollTop=$__0.scrollTop,scrollLeft=$__0.scrollLeft; - return {scrollTop:scrollTop, scrollLeft:scrollLeft}; - }, - - onScroll:function(e) { - this.appendScrollShim(); - var $__0= e.target,scrollTop=$__0.scrollTop,scrollLeft=$__0.scrollLeft; - var scroll = {scrollTop:scrollTop, scrollLeft:scrollLeft}; - this._scroll = scroll; - this.props.onScroll(scroll); - } - }); - - - module.exports = Canvas; - - -/***/ }, -/* 45 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - "use strict"; - - var React = __webpack_require__(10); - var PropTypes = React.PropTypes; - var shallowEqual = __webpack_require__(47); - var HeaderCell = __webpack_require__(49); - var getScrollbarSize = __webpack_require__(50); - - var HeaderRow = React.createClass({displayName: 'HeaderRow', - - propTypes: { - width: PropTypes.number, - height: PropTypes.number.isRequired, - columns: PropTypes.array.isRequired, - onColumnResize: PropTypes.func - }, - - render:function() { - var cellsStyle = { - width: this.props.width ? (this.props.width + getScrollbarSize()) : '100%', - height: this.props.height, - whiteSpace: 'nowrap', - overflowX: 'hidden', - overflowY: 'hidden' - }; - - var cells = this.getCells(); - return ( - React.createElement("div", React.__spread({}, this.props, {className: "react-grid-HeaderRow"}), - React.createElement("div", {style: cellsStyle}, - cells - ) - ) - ); - }, - - getCells:function() { - var cells = []; - var lockedCells = []; - - for (var i = 0, len = this.props.columns.length; i < len; i++) { - var column = this.props.columns[i]; - var cell = ( - React.createElement(HeaderCell, { - ref: i, - key: i, - height: this.props.height, - column: column, - renderer: this.props.headerCellRenderer || column.headerRenderer || this.props.cellRenderer, - resizing: this.props.resizing === column, - onResize: this.props.onColumnResize, - onResizeEnd: this.props.onColumnResizeEnd} - ) - ); - if (column.locked) { - lockedCells.push(cell); - } else { - cells.push(cell); - } - } - - return cells.concat(lockedCells); - }, - - setScrollLeft:function(scrollLeft) { - for (var i = 0, len = this.props.columns.length; i < len; i++) { - if (this.props.columns[i].locked) { - this.refs[i].setScrollLeft(scrollLeft); - } - } - }, - - shouldComponentUpdate:function(nextProps) { - return ( - nextProps.width !== this.props.width - || nextProps.height !== this.props.height - || nextProps.columns !== this.props.columns - || !shallowEqual(nextProps.style, this.props.style) - ); - }, - - getStyle:function() { - return { - overflow: 'hidden', - width: '100%', - height: this.props.height, - position: 'absolute' - }; - } - - }); - - module.exports = HeaderRow; - - -/***/ }, -/* 46 */ -/***/ function(module, exports, __webpack_require__) { - - /* WEBPACK VAR INJECTION */(function(process) {/** - * Copyright 2013-2014 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @providesModule copyProperties - */ - 'use strict'; - - /** - * Copy properties from one or more objects (up to 5) into the first object. - * This is a shallow copy. It mutates the first object and also returns it. - * - * NOTE: `arguments` has a very significant performance penalty, which is why - * we don't support unlimited arguments. - */ - function copyProperties(obj, a, b, c, d, e, f) { - obj = obj || {}; - - if (process.env.NODE_ENV) { - if (f) { - throw new Error('Too many arguments passed to copyProperties'); - } - } - - var args = [a, b, c, d, e]; - var ii = 0, v; - while (args[ii]) { - v = args[ii++]; - for (var k in v) { - obj[k] = v[k]; - } - - // IE ignores toString in object iteration.. See: - // webreflection.blogspot.com/2007/07/quick-fix-internet-explorer-and.html - if (v.hasOwnProperty && v.hasOwnProperty('toString') && - (typeof v.toString != 'undefined') && (obj.toString !== v.toString)) { - obj.toString = v.toString; - } - } - - return obj; - } - - module.exports = copyProperties; - - /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(52))) - -/***/ }, -/* 47 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - function shallowEqual(a, b) { - if (a === b) { - return true; - } - - var k; - - for (k in a) { - if (a.hasOwnProperty(k) && - (!b.hasOwnProperty(k) || a[k] !== b[k])) { - return false; - } - } - - for (k in b) { - if (b.hasOwnProperty(k) && !a.hasOwnProperty(k)) { - return false; - } - } - - return true; - } - - module.exports = shallowEqual; - - -/***/ }, -/* 48 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var ScrollShim = { - - appendScrollShim:function() { - if (!this._scrollShim) { - var size = this._scrollShimSize(); - var shim = document.createElement('div'); - shim.classList.add('react-grid-ScrollShim'); - shim.style.position = 'absolute'; - shim.style.top = 0; - shim.style.left = 0; - shim.style.width = (size.width + "px"); - shim.style.height = (size.height + "px"); - this.getDOMNode().appendChild(shim); - this._scrollShim = shim; - } - this._scheduleRemoveScrollShim(); - }, - - _scrollShimSize:function() { - return { - width: this.props.width, - height: this.props.length * this.props.rowHeight - }; - }, - - _scheduleRemoveScrollShim:function() { - if (this._scheduleRemoveScrollShimTimer) { - clearTimeout(this._scheduleRemoveScrollShimTimer); - } - this._scheduleRemoveScrollShimTimer = setTimeout( - this._removeScrollShim, 200); - }, - - _removeScrollShim:function() { - if (this._scrollShim) { - this._scrollShim.parentNode.removeChild(this._scrollShim); - this._scrollShim = undefined; - } - } - }; - - module.exports = ScrollShim; - - -/***/ }, -/* 49 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - "use strict"; - - var React = __webpack_require__(10); - var cx = React.addons.classSet; - var Draggable = __webpack_require__(53); - var PropTypes = React.PropTypes; - - var ResizeHandle = React.createClass({displayName: 'ResizeHandle', - - style: { - position: 'absolute', - top: 0, - right: 0, - width: 6, - height: '100%' - }, - - render:function() { - return ( - React.createElement(Draggable, React.__spread({}, this.props, - {className: "react-grid-HeaderCell__resizeHandle", - style: this.style}) - ) - ); - } - }); - - var HeaderCell = React.createClass({displayName: 'HeaderCell', - - propTypes: { - renderer: PropTypes.oneOfType([PropTypes.func, PropTypes.element]).isRequired, - column: PropTypes.object.isRequired, - onResize: PropTypes.func - }, - - render:function() { - var className = cx({ - 'react-grid-HeaderCell': true, - 'react-grid-HeaderCell--resizing': this.state.resizing, - 'react-grid-HeaderCell--locked': this.props.column.locked - }); - className = cx(className, this.props.className); - var cell = this.getCell(); - return ( - React.createElement("div", {className: className, style: this.getStyle()}, - cell, - this.props.column.resizeable ? - React.createElement(ResizeHandle, { - onDrag: this.onDrag, - onDragStart: this.onDragStart, - onDragEnd: this.onDragEnd} - ) : - null - ) - ); - }, - - getCell:function() { - if (React.isValidElement(this.props.renderer)) { - return React.addons.cloneWithProps(this.props.renderer, {column : this.props.column}); - } else { - return this.props.renderer({column: this.props.column}); - } - }, - - getDefaultProps:function() { - return { - renderer: simpleCellRenderer - }; - }, - - getInitialState:function() { - return {resizing: false}; - }, - - setScrollLeft:function(scrollLeft) { - var node = this.getDOMNode(); - node.style.webkitTransform = ("translate3d(" + scrollLeft + "px, 0px, 0px)"); - node.style.transform = ("translate3d(" + scrollLeft + "px, 0px, 0px)"); - }, - - getStyle:function() { - return { - width: this.props.column.width, - left: this.props.column.left, - display: 'inline-block', - position: 'absolute', - overflow: 'hidden', - height: this.props.height, - margin: 0, - textOverflow: 'ellipsis', - whiteSpace: 'nowrap' - }; - }, - - onDragStart:function() { - this.setState({resizing: true}); - }, - - onDrag:function(e) { - var width = this.getWidthFromMouseEvent(e); - if (width > 0 && this.props.onResize) { - this.props.onResize(this.props.column, width); - } - }, - - onDragEnd:function(e) { - var width = this.getWidthFromMouseEvent(e); - this.props.onResizeEnd(this.props.column, width); - this.setState({resizing: false}); - }, - - getWidthFromMouseEvent:function(e) { - var right = e.pageX; - var left = this.getDOMNode().getBoundingClientRect().left; - return right - left; - } - }); - - function simpleCellRenderer(props) { - return React.createElement("div", {className: "rex-widget-HeaderCell__value"}, props.column.name); - } - - module.exports = HeaderCell; - - -/***/ }, -/* 50 */ -/***/ function(module, exports, __webpack_require__) { - - "use strict"; - - var size; - - function getScrollbarSize() { - if (size === undefined) { - - var outer = document.createElement('div'); - outer.style.width = '50px'; - outer.style.height = '50px'; - outer.style.overflowY = 'scroll'; - outer.style.position = 'absolute'; - outer.style.top = '-200px'; - outer.style.left = '-200px'; - - var inner = document.createElement('div'); - inner.style.height = '100px'; - inner.style.width = '100%'; - - outer.appendChild(inner); - document.body.appendChild(outer); - - var outerWidth = outer.offsetWidth; - var innerWidth = inner.offsetWidth; - - document.body.removeChild(outer); - - size = outerWidth - innerWidth; - } - - return size; - } - - module.exports = getScrollbarSize; - - -/***/ }, -/* 51 */ -/***/ function(module, exports, __webpack_require__) { - - /* WEBPACK VAR INJECTION */(function(process) {/** - * Copyright 2013-2014, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @providesModule invariant - */ - - "use strict"; - - /** - * Use invariant() to assert state which your program assumes to be true. - * - * Provide sprintf-style format (only %s is supported) and arguments - * to provide information about what broke and what you were - * expecting. - * - * The invariant message will be stripped in production, but the invariant - * will remain to ensure logic does not differ in production. - */ - - var invariant = function(condition, format, a, b, c, d, e, f) { - if ("production" !== process.env.NODE_ENV) { - if (format === undefined) { - throw new Error('invariant requires an error message argument'); - } - } - - if (!condition) { - var error; - if (format === undefined) { - error = new Error( - 'Minified exception occurred; use the non-minified dev environment ' + - 'for the full error message and additional helpful warnings.' - ); - } else { - var args = [a, b, c, d, e, f]; - var argIndex = 0; - error = new Error( - 'Invariant Violation: ' + - format.replace(/%s/g, function() { return args[argIndex++]; }) - ); - } - - error.framesToPop = 1; // we don't care about invariant's own frame - throw error; - } - }; - - module.exports = invariant; - - /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(52))) - -/***/ }, -/* 52 */ -/***/ function(module, exports, __webpack_require__) { - - // shim for using process in browser - - var process = module.exports = {}; - - process.nextTick = (function () { - var canSetImmediate = typeof window !== 'undefined' - && window.setImmediate; - var canMutationObserver = typeof window !== 'undefined' - && window.MutationObserver; - var canPost = typeof window !== 'undefined' - && window.postMessage && window.addEventListener - ; - - if (canSetImmediate) { - return function (f) { return window.setImmediate(f) }; - } - - var queue = []; - - if (canMutationObserver) { - var hiddenDiv = document.createElement("div"); - var observer = new MutationObserver(function () { - var queueList = queue.slice(); - queue.length = 0; - queueList.forEach(function (fn) { - fn(); - }); - }); - - observer.observe(hiddenDiv, { attributes: true }); - - return function nextTick(fn) { - if (!queue.length) { - hiddenDiv.setAttribute('yes', 'no'); - } - queue.push(fn); - }; - } - - if (canPost) { - window.addEventListener('message', function (ev) { - var source = ev.source; - if ((source === window || source === null) && ev.data === 'process-tick') { - ev.stopPropagation(); - if (queue.length > 0) { - var fn = queue.shift(); - fn(); - } - } - }, true); - - return function nextTick(fn) { - queue.push(fn); - window.postMessage('process-tick', '*'); - }; - } - - return function nextTick(fn) { - setTimeout(fn, 0); - }; - })(); - - process.title = 'browser'; - process.browser = true; - process.env = {}; - process.argv = []; - - function noop() {} - - process.on = noop; - process.addListener = noop; - process.once = noop; - process.off = noop; - process.removeListener = noop; - process.removeAllListeners = noop; - process.emit = noop; - - process.binding = function (name) { - throw new Error('process.binding is not supported'); - }; - - // TODO(shtylman) - process.cwd = function () { return '/' }; - process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); - }; - - -/***/ }, -/* 53 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var PropTypes = React.PropTypes; - var emptyFunction = __webpack_require__(40); - - var Draggable = React.createClass({displayName: 'Draggable', - - propTypes: { - onDragStart: PropTypes.func, - onDragEnd: PropTypes.func, - onDrag: PropTypes.func, - component: PropTypes.oneOfType([PropTypes.func, PropTypes.constructor]) - }, - - render:function() { - var Component = this.props.component; - return ( - React.createElement(Component, React.__spread({}, this.props, {onMouseDown: this.onMouseDown})) - ); - }, - - getDefaultProps:function() { - return { - component: React.DOM.div, - onDragStart: emptyFunction.thatReturnsTrue, - onDragEnd: emptyFunction, - onDrag: emptyFunction - }; - }, - - getInitialState:function() { - return { - drag: null - }; - }, - - onMouseDown:function(e) { - var drag = this.props.onDragStart(e); - - if (drag === null && e.button !== 0) { - return; - } - - window.addEventListener('mouseup', this.onMouseUp); - window.addEventListener('mousemove', this.onMouseMove); - - this.setState({drag:drag}); - }, - - onMouseMove:function(e) { - if (this.state.drag === null) { - return; - } - - if (e.stopPropagation) { - e.stopPropagation(); - } - - if (e.preventDefault) { - e.preventDefault(); - } - - this.props.onDrag(e); - }, - - onMouseUp:function(e) { - this.cleanUp(); - this.props.onDragEnd(e, this.state.drag); - this.setState({drag: null}); - }, - - componentWillUnmount:function() { - this.cleanUp(); - }, - - cleanUp:function() { - window.removeEventListener('mouseup', this.onMouseUp); - window.removeEventListener('mousemove', this.onMouseMove); - } - }); - - module.exports = Draggable; - - -/***/ } -/******/ ]) -}); diff --git a/dist/ReactGrid.min.js b/dist/ReactGrid.min.js deleted file mode 100644 index 55c2c59..0000000 --- a/dist/ReactGrid.min.js +++ /dev/null @@ -1,2 +0,0 @@ -!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react/addons")):"function"==typeof define&&define.amd?define(["react/addons"],t):"object"==typeof exports?exports.ReactGrid=t(require("react/addons")):e.ReactGrid=t(e.React)}(this,function(e){return function(e){function t(r){if(s[r])return s[r].exports;var i=s[r]={exports:{},id:r,loaded:!1};return e[r].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var s={};return t.m=e,t.c=s,t.p="",t(0)}([function(e,t,s){"use strict";var r=s(1),i=s(2),o=s(3);e.exports=r,e.exports.Row=i,e.exports.Cell=o},function(e,t,s){"use strict";var r=s(10),i=(r.PropTypes,s(16)),o=s(17),n=s(18),l=(s(19),s(20)),a=s(21),c=s(22),p=s(23),h=s(24),d=s(25),u=s(26),f=(s(27),r.addons.cloneWithProps,r.createClass({displayName:"ExcelGrid",mixins:[l,p,a,c,h,d],getInitialState:function(){return{selectedRows:[],expandedRows:[]}},overrides:{onCellCommit:function(e){var t=e[0],s=Object.assign({},this.state.selected);s.active=!1,"Tab"===t.keyCode&&(s.idx+=1);var r=this.state.expandedRows;t.changed&&t.changed.expandedHeight&&(r=this.expandRow(t.rowIdx,t.changed.expandedHeight)),this.setState({selected:s,expandedRows:r}),this.props.onRowUpdated(t)},getColumns:function(){var e=this.getDecoratedColumns(this.props.columns);return this.props.enableRowSelect&&e.unshift({key:"select-row",name:"",formatter:r.createElement(u,null),onRowSelect:this.handleRowSelect,filterable:!1,headerRenderer:r.createElement("input",{type:"checkbox",onChange:this.handleCheckboxChange}),width:60}),e}},getDefaultProps:function(){return{rowHeight:35,enableRowSelect:!1,minHeight:350}},handleCheckboxChange:function(e){if(e.currentTarget.checked===!0){var t=this.props.rows.map(function(){return!0});this.setState({selectedRows:t})}else{var t=this.props.rows.map(function(){return!1});this.setState({selectedRows:t})}},handleRowSelect:function(e){var t=this.state.selectedRows;t[e]=null==t[e]||0==t[e]?!0:!1,this.setState({selectedRows:t})},expandRow:function(e,t){var s=this.state.expandedRows;return s[e]?(null==s[e]||s[e]s;s++){var i=this.props.columns[s],o=this.renderCell({ref:s,key:s,idx:s,rowIdx:this.props.idx,filterRowIdx:this.props.row.key,value:this.getCellValue(i.key||s),column:i,height:this.getRowHeight(),formatter:i.formatter,rowData:this.props.row});i.locked?t.push(o):e.push(o)}return e.concat(t)},getRowHeight:function(){return this.props.expandedRows&&this.props.expandedRows[this.props.key]?this.props.expandedRows[this.props.key]:this.props.height},getCellValue:function(e){return"select-row"===e?this.props.isSelected:this.props.row[e]},renderCell:function(e){return r.isValidElement(this.props.cellRenderer)?n(this.props.cellRenderer,e):this.props.cellRenderer(e)},getDefaultProps:function(){return{cellRenderer:o}},shouldComponentUpdate:function(e){return!l.sameColumns(this.props.columns,e.columns,l.sameColumn)||this.doesRowContainSelectedCell()||this.doesRowContainSelectedCell(e)||this.willRowBeDraggedOver(e)||this.hasRowBeenCopied()||e.row!==this.props.row||e.height!==this.props.height},setScrollLeft:function(e){for(var t=0,s=this.props.columns.length;s>t;t++)this.props.columns[t].locked&&this.refs[t].setScrollLeft(e)},doesRowContainSelectedCell:function(e){var t=e||this.props,s=s||t.cellRenderer;return s.props.selected&&s.props.selected.rowIdx===t.idx?!0:!1},willRowBeDraggedOver:function(e){var t=e.cellRenderer.props.dragged;return null!=t&&(t.rowIdx||t.complete===!0)},hasRowBeenCopied:function(){var e=this.props.cellRenderer;return null!=e.props.copied&&e.props.copied.rowIdx===this.props.idx}});e.exports=a},function(e,t,s){"use strict";function r(e){return e.value}var i=s(10),o=i.addons.classSet,n=i.addons.cloneWithProps,l=i.createClass({displayName:"Cell",render:function(){var e=this.getStyle(),t=o("react-grid-Cell",this.props.className,this.props.column.locked?"react-grid-Cell--locked":null),s=this.renderCellContent({value:this.props.value,column:this.props.column,rowIdx:this.props.rowIdx,isExpanded:this.props.isExpanded});return i.createElement("div",i.__spread({},this.props,{className:t,style:e}),s,i.createElement("div",{className:"drag-handle",draggable:"true",onDragStart:this.props.handleDragStart}))},renderCellContent:function(e){var t=i.isValidElement(this.props.formatter)?n(this.props.formatter,e):this.props.formatter(e);return i.createElement("div",{className:"react-grid-Cell__value"},t," ",this.props.cellControls)},getDefaultProps:function(){return{formatter:r}},getStyle:function(){var e={position:"absolute",width:this.props.column.width,height:this.props.height,left:this.props.column.left};return e},setScrollLeft:function(e){if(this.isMounted()){var t=this.getDOMNode(),s="translate3d("+e+"px, 0px, 0px)";t.style.webkitTransform=s,t.style.transform=s}}});e.exports=l},,function(e,t,s){"use strict";var r=s(10),i=r.addons.classSet,o=s(12),n={propTypes:{onCommit:r.PropTypes.func.isRequired},getStyle:function(){return{height:this.props.height-1}},getInitialState:function(){return{isInvalid:!1}},onPressEnter:function(e){e.stopPropagation(),e.preventDefault(),this.commit({key:"Enter"})},onPressTab:function(e){e.stopPropagation(),e.preventDefault(),this.commit({key:"Tab"})},commit:function(e){var t=this.getValue(),s={};s[this.props.column.key]=t,this.isNewValueValid(t)&&this.props.onCommit({updated:s,key:e.key})},isNewValueValid:function(e){if(o(this.validate)){var t=this.validate(e);return this.setState({isInvalid:!t}),t}return!0},getValue:function(){return this.getInputNode().value},setValue:function(e){this.getInputNode().value=e},componentDidMount:function(){void 0!==this.getInputNode()&&(this.checkFocus(),this.getInputNode().className+=" editor-main")},checkFocus:function(){this.getInputNode().focus()},getInputNode:function(){return this.getDOMNode().getElementsByTagName("input")[0]},getContainerClass:function(){return i({"has-error":this.state.isInvalid===!0})},renderStatusIcon:function(){return this.state.isInvalid===!0?r.createElement("span",{className:"glyphicon glyphicon-remove form-control-feedback"}):void 0},render:function(){if(!o(this.renderEditorNode))throw"Editor Mixin Error : "+this.displayName+" component must implement method renderEditorNode";var e=this.renderEditorNode();return r.createElement("div",{className:this.getContainerClass()},e,this.renderStatusIcon())}};e.exports=n},function(e){"use strict";var t={onPressArrowLeft:function(e){e.stopPropagation()},onPressArrowRight:function(e){e.stopPropagation()},getDefaultValue:function(){var e=this.props.initialKeyCode;if("Delete"===e||"Backspace"===e)return"";if("Enter"===e)return this.props.value;var t=e?String.fromCharCode(e):this.props.value;return t},setCaretAtEndOfInput:function(){var e=this.getInputNode(),t=e.value.length;if(e.setSelectionRange)e.setSelectionRange(t,t);else if(e.createTextRange){var s=e.createTextRange();s.moveStart("character",txt.value.length),s.collapse(),s.select()}},setTextInputFocus:function(){this.isKeyPrintable(this.props.initialKeyCode)?this.getInputNode().select():(this.getInputNode().focus(),this.setCaretAtEndOfInput())}};e.exports=t},,,function(e,t,s){"use strict";var r=s(10),i=(r.addons.Perf,{onKeyDown:function(e){if(this.isCtrlKeyHeldDown(e))this.checkAndCall("onPressKeyWithCtrl",e);else if(this.isKeyIdentified(e.key)){var t="onPress"+e.key;this.checkAndCall(t,e)}else this.isKeyPrintable(e.keyCode)&&this.checkAndCall("onPressChar",e)},isKeyPrintable:function(e){var t=e>47&&58>e||32==e||13==e||e>64&&91>e||e>95&&112>e||e>185&&193>e||e>218&&223>e;return t},isKeyIdentified:function(e){return"Unidentified"!==e},isCtrlKeyHeldDown:function(e){return e.ctrlKey===!0&&"Control"!==e.key},checkAndCall:function(e,t){"function"==typeof this[e]&&this[e](t)}});e.exports=i},function(t){t.exports=e},function(e,t,s){"use strict";function r(e){var t,s,r,i=0,o=e.totalWidth,n=[],l=e.columns.map(p);for(t=0,s=l.length;s>t;t++)r=l[t],r.width?(/^([0-9]+)%$/.exec(r.width)&&(r.width=Math.floor(parseInt(r.width,10)/100*e.totalWidth)),o-=r.width,i+=r.width):n.push(r);for(t=0,s=n.length;s>t;t++)r=n[t],r.width=0>=o?e.minColumnWidth:Math.floor(o/n.length),i+=r.width;var a=0;for(t=0,s=l.length;s>t;t++)r=l[t],r.left=a,a+=r.width;return{columns:l,width:i,totalWidth:e.totalWidth,minColumnWidth:e.minColumnWidth}}function i(e,t,s){var i=e.columns[t];e=p(e),e.columns=e.columns.slice(0);var o=p(i);return o.width=Math.max(s,e.minColumnWidth),e.columns.splice(t,1,o),r(e)}function o(e,t,s){var r,i,o,n={},l={};if(e.length!==t.length)return!1;for(r=0,i=e.length;i>r;r++)o=e[r],n[o.key]=o;for(r=0,i=t.length;i>r;r++){o=t[r],l[o.key]=o;var a=n[o.key];if(void 0===a||!s(a,o))return!1}for(r=0,i=e.length;i>r;r++){o=e[r];var c=l[o.key];if(void 0===c)return!1}return!0}function n(e,t){var s;for(s in e)if(e.hasOwnProperty(s)){if("function"==typeof e[s]&&"function"==typeof t[s]||c(e[s])&&c(t[s]))continue;if(!t.hasOwnProperty(s)||e[s]!==t[s])return!1}for(s in t)if(t.hasOwnProperty(s)&&!e.hasOwnProperty(s))return!1;return!0}var l=s(10),a=l.PropTypes,c=l.isValidElement,p=s(28),h=s(29),d=s(19),u={mixins:[h.MetricsMixin],propTypes:{columns:a.array,minColumnWidth:a.number,columnEquality:a.func},DOMMetrics:{gridWidth:function(){return this.getDOMNode().offsetWidth-2}},getDefaultProps:function(){return{minColumnWidth:80,columnEquality:n}},getInitialState:function(){return this.getColumnMetrics(this.props,!0)},componentWillReceiveProps:function(e){if(e.columns)if(o(this.props.columns,e.columns,this.props.columnEquality)){var t={};this.state.columns.columns.forEach(function(e){t[e.key]={width:e.width,left:e.left}});var s=d(this.state.columns,{columns:e.columns.map(function(e){return d(e,t[e.key])})});this.setState({columns:s})}else this.setState(this.getColumnMetrics(e))},getColumnMetrics:function(e,t){var s=t?null:this.DOMMetrics.gridWidth();return{columns:r({columns:e.columns,width:null,totalWidth:s,minColumnWidth:e.minColumnWidth}),gridWidth:s}},metricsUpdated:function(){this.setState(this.getColumnMetrics(this.props))},onColumnResize:function(e,t){var s=i(this.state.columns,e,t);this.setState({columns:s})}};e.exports={Mixin:u,calculate:r,resizeColumn:i,sameColumns:o,sameColumn:n}},function(e){"use strict";var t=function(e){var t={};return e&&"[object Function]"===t.toString.call(e)};e.exports=t},,,function(e,t,s){"use strict";var r=s(10),i=(r.addons.classSet,s(27),s(5)),o=s(6),n=s(9),l=r.createClass({displayName:"SimpleTextEditor",mixins:[n,i,o],overrides:{checkFocus:function(){this.setTextInputFocus()}},renderEditorNode:function(){return r.createElement("input",{type:"text",onBlur:this.commit,className:"form-control",defaultValue:this.getDefaultValue(),style:this.getStyle(),onKeyDown:this.onKeyDown})}});e.exports=l},function(e,t,s){"use strict";var r=s(10),i=r.PropTypes,o=s(30),n=s(31),l=s(11),a=s(29),c={componentDidMount:function(){this._scrollLeft=this.refs.viewport.getScroll().scrollLeft,this._onScroll()},componentDidUpdate:function(){this._onScroll()},componentWillMount:function(){this._scrollLeft=void 0},componentWillUnmount:function(){this._scrollLeft=void 0},onScroll:function(e){var t=e.scrollLeft;this._scrollLeft!==t&&(this._scrollLeft=t,this._onScroll())},_onScroll:function(){void 0!==this._scrollLeft&&(this.refs.header.setScrollLeft(this._scrollLeft),this.refs.viewport.setScrollLeft(this._scrollLeft))}},p=r.createClass({displayName:"Grid",mixins:[c,l.Mixin,a.MetricsComputatorMixin],propTypes:{rows:i.oneOfType([i.array,i.func]).isRequired,columns:i.array.isRequired},getStyle:function(){return{overflow:"hidden",outline:0,position:"relative",minHeight:this.props.minHeight}},render:function(){var e=this.props.headerRows||[{ref:"row"}];return r.createElement("div",r.__spread({},this.props,{style:this.getStyle(),className:"react-grid-Grid"}),r.createElement(o,{ref:"header",columns:this.state.columns,onColumnResize:this.onColumnResize,height:this.props.rowHeight,totalWidth:this.DOMMetrics.gridWidth(),headerRows:e}),r.createElement(n,{ref:"viewport",width:this.state.columns.width,rowHeight:this.props.rowHeight,rowRenderer:this.props.rowRenderer,cellRenderer:this.props.cellRenderer,rows:this.props.rows,selectedRows:this.props.selectedRows,expandedRows:this.props.expandedRows,length:this.props.length,columns:this.state.columns,totalWidth:this.DOMMetrics.gridWidth(),onScroll:this.onScroll,onRows:this.props.onRows,rowOffsetHeight:this.props.rowOffsetHeight||this.props.rowHeight*e.length}))},getDefaultProps:function(){return{rowHeight:35,minHeight:350}}});e.exports=p},function(e,t,s){"use strict";var r=s(10),i=s(3),o=(s(32),s(33)),n=s(34),l=s(35),a=(s(27),s(9),s(12)),c=(r.PropTypes,r.addons.classSet),p=(r.addons.cloneWithProps,r.createClass({displayName:"CellControls",onClickEdit:function(e){e.stopPropagation(),e.preventDefault(),this.props.onClickEdit()},onShowMore:function(e){e.stopPropagation(),e.preventDefault();var t=this.props.column.getExpandedHeight(this.props.value);this.props.onShowMore(this.props.rowIdx,t)},onShowLess:function(e){e.stopPropagation(),e.preventDefault(),this.props.onShowLess(this.props.rowIdx)},shouldComponentUpdate:function(e){return this.props.height!=e.height},renderShowMoreButton:function(){if(a(this.props.column.getExpandedHeight)&&this.props.column.getExpandedHeight(this.props.value)>0){var e=this.props.column.getExpandedHeight(this.props.value);return e>this.props.height?r.createElement("button",{type:"button",className:"btn btn-link btn-xs",onClick:this.onShowMore},"Show More"):r.createElement("button",{type:"button",className:"btn btn-link btn-xs",onClick:this.onShowLess},"Show Less")}return null},render:function(){return r.createElement("div",{className:"pull-right btn-group"},this.renderShowMoreButton(),r.createElement("button",{onClick:this.onClickEdit,type:"button",className:"btn btn-link btn-xs"},"Edit"))}})),h=r.createClass({displayName:"ExcelCell",mixins:[o,n,l],overrides:{getCellClass:function(){return c({selected:this.isSelected()&&!this.isCopied()&&!this.isActive(),editing:this.isActive(),copied:this.isCopied(),"selected-draggable":this.isSelected()&&!this.isActive()&&this.canEdit(),"active-drag-cell":this.isActiveDragCell()&&this.canEdit(),"is-dragged-over-up":!this.isSelected()&&this.isDraggedOver()&&this.props.rowIdxthis.props.dragged.rowIdx,"was-dragged-over":this.wasDraggedOver()&&this.canEdit()})}},isActiveDragCell:function(){return(this.isSelected()||this.isDraggedOver())&&!this.isActive()},isExpanded:function(){var e=!1;if(a(this.props.column.getExpandedHeight)&&this.props.column.getExpandedHeight(this.props.value)>0){var t=this.props.column.getExpandedHeight(this.props.value);e=this.props.height>=t?!0:!1}return e},shouldComponentUpdate:function(e){return this.props.column.width!==e.column.width||this.props.value!==e.value||this.props.height!==e.height||this.props.rowIdx!==e.rowIdx||this.isCellSelectionChanging(e)||this.isDraggedCellChanging(e)},render:function(){return r.createElement(i,r.__spread({},this.props,{className:this.getCellClass(),onKeyDown:this.onKeyDown,onClick:this.onClick,onDoubleClick:this.onDoubleClick,formatter:this.getFormatter(),handleDragStart:this.handleDragStart,onDragEnter:this.handleDragEnter,onDragEnd:this.props.handleDragEnd,cellControls:this.props.column.showCellControls&&!this.isActive()?r.createElement(p,{height:this.props.height,value:this.props.value,rowIdx:this.props.rowIdx,column:this.props.column,onShowMore:this.props.onShowMore,onShowLess:this.props.onShowLess,onClickEdit:this.setActive}):null,isExpanded:this.isExpanded()}))}});e.exports=h},function(e,t,s){"use strict";var r=s(10),i=(r.addons.classSet,s(2)),o=s(11),n=r.createClass({displayName:"ExcelRow",render:function(){var e=r.addons.update(this.props.row,{$merge:{"select-row":this.props.isSelected}});return r.createElement(i,r.__spread({},this.props,{row:e,height:this.getRowHeight(this.props)}))},getRowHeight:function(e){return e.expandedRows&&e.expandedRows[e.key]?e.expandedRows[e.key]:e.height},hasRowHeightChanged:function(e){return e.expandedRows&&"undefined"!=typeof e.expandedRows[e.key]?this.props.height!==e.expandedRows[e.key]:!1},shouldComponentUpdate:function(e){return!o.sameColumns(this.props.columns,e.columns,o.sameColumn)||this.doesRowContainSelectedCell()||this.doesRowContainSelectedCell(e)||this.willRowBeDraggedOver(e)||this.hasRowBeenCopied()||e.row!==this.props.row||this.props.isSelected!==e.isSelected||this.hasRowHeightChanged(e)},doesRowContainSelectedCell:function(e){var t=e||this.props,s=s||t.cellRenderer;return s.props&&s.props.selected&&s.props.selected.rowIdx===t.idx?!0:!1},willRowBeDraggedOver:function(e){if(e.cellRenderer.props){var t=e.cellRenderer.props.dragged;return null!=t&&(t.rowIdx||t.complete===!0)}return!1},hasRowBeenCopied:function(){if(this.props.cellRenderer.props){var e=this.props.cellRenderer;return null!=e.props.copied&&e.props.copied.rowIdx===this.props.idx}return!1},setScrollLeft:function(e){for(var t=0,s=this.props.columns.length;s>t;t++)this.props.columns[t].locked&&this.refs[t].setScrollLeft(e)}});e.exports=n},function(e){"use strict";function t(e,t){var s={};for(var r in e)s[r]=e[r];for(var r in t)s[r]=t[r];return s}var s=function(e,t){var s={};return null!=e&&Object.assign(s,e),null!=t&&Object.assign(s,t),s};e.exports=Object.assign?s:t},function(e){"use strict";var t={getDefaultProps:function(){return{enableCellSelect:!1}},getColumns:function(){return this.props.columns},getInitialState:function(){return this.props.enableCellSelect?{selected:{rowIdx:0,idx:0}}:{selected:{rowIdx:-1,idx:-1}}},onSelect:function(e){if(this.props.enableCellSelect){var t=e.idx,s=e.rowIdx;t>=0&&s>=0&&t=0&&s>=0&&tr.overRowIdx?s.rowIdx:r.overRowIdx,this.props.onCellsDragged({cellKey:i,fromRow:e,toRow:t,value:r.copiedText}),this.setState({dragged:{complete:!0}})},handleTerminateDrag:function(){this.setState({dragged:null})}};e.exports=o},function(e,t,s){"use strict";var r=s(10),i=(r.PropTypes,{propTypes:{onCellCopyPaste:r.PropTypes.func},getInitialState:function(){return{copied:null}},handleCopy:function(e){var t=e.value,s=this.state.selected,r={idx:s.idx,rowIdx:s.rowIdx};this.setState({textToCopy:t,copied:r})},handlePaste:function(){var e=this.state.selected,t=this.getColumns()[e.idx].key;this.props.onCellCopyPaste({cellKey:t,rowIdx:e.rowIdx,value:this.state.textToCopy,fromRow:this.state.copied.rowIdx,toRow:e.rowIdx}),this.setState({copied:null})}});e.exports=i},function(e,t,s){"use strict";var r=s(10),i=(r.PropTypes,s(19)),o={propTypes:{onRowUpdated:r.PropTypes.func},onCellCommit:function(e){var t=this.state.selected;t.active=!1,"Tab"===e.keyCode&&(t.idx+=1),this.setState({selected:t}),this.props.onRowUpdate(e)},onSetActive:function(e){var t=i(this.state.selected,e);this.setState({selected:t})}};e.exports=o},function(e,t,s){"use strict";var r=s(10),i=(r.PropTypes,s(36)),o=s(28),n={ASC:"ASC",DESC:"DESC"};Object.freeze(n);var l={getInitialState:function(){return{sortDirection:null,sortColumn:null}},getDecoratedColumns:function(){return this.props.columns.map(function(e){return e=o(e),e.sortable&&(e.headerRenderer=r.createElement(i,null),e.sortBy=this.sortBy,e.sorted=this.state.sortColumn===e.key?this.state.sortDirection:n.NONE),e},this)},sortBy:function(e,t){switch(t){case null:case void 0:t=n.ASC;break;case n.ASC:t=n.DESC;break;case n.DESC:t=null}this.setState({sortDirection:t,sortColumn:e.key})},sortRows:function(e){e=[].concat(e);var t=this.state.sortColumn,s=this.state.sortDirection;return null!=t&&null!==s?e.sort(function(e,r){var i=e[t],o=r[t];return s===n.ASC?i>o?1:o>i?-1:0:s===n.DESC?i>o?-1:o>i?1:0:void 0}):e}};e.exports=l},function(e,t,s){"use strict";var r=s(10),i=(r.PropTypes,s(37)),o={getInitialState:function(){return{canFilter:!1,columnFilters:{}}},filterRows:function(){var e=this.props.rows;return this.state.sortColumn&&(e=this.sortRows(e)),this.hasFilters()&&(e=e.map(function(e,t){return e.key=t,e}).filter(this.isRowDisplayed),this.props.onFilter&&this.props.onFilter(e)),e},hasFilters:function(){var e=!1;return Object.keys(this.state.columnFilters).every(function(t){var s=this.state.columnFilters[t];return null!=s&&void 0!=s&&""!=s?(e=!0,!1):!0},this),e},isRowDisplayed:function(e){var t=null;return Object.keys(this.state.columnFilters).every(function(s){var r=this.state.columnFilters[s].toLowerCase(),i=e[s].toString().toLowerCase();if(null!=r&&void 0!=r&&""!=r&&"string"==typeof i){if(!(i.indexOf(r)>-1))return t=!1,!1;t=!0}return!0},this),null==t?!1:t},onToggleFilter:function(){this.setState({canFilter:!this.state.canFilter})},handleAddFilter:function(e){var t=this.state.columnFilters;t[e.columnKey]=e.filterTerm,this.setState({columnFilters:t,selected:null})},getHeaderRows:function(){var e=[{ref:"row",height:this.props.rowHeight}];return this.state.canFilter===!0&&e.push({ref:"filterRow",headerCellRenderer:r.createElement(i,{onChange:this.handleAddFilter}),height:45}),e},getRowOffsetHeight:function(){var e=0;return this.getHeaderRows().forEach(function(t){return e+=t.height}),e}};e.exports=o},function(e,t,s){"use strict";var r=s(10),i=(r.addons.classSet,r.createClass({displayName:"CheckBoxEditor",PropTypes:{value:r.PropTypes.bool.isRequired},render:function(){return r.createElement("input",{className:"react-grid-CheckBox",type:"checkbox",checked:this.props.value,onChange:this.handleChange})},handleChange:function(){this.props.column.onRowSelect(this.props.rowIdx)},shouldComponentUpdate:function(e){return this.props.value!=e.value}}));e.exports=i},function(e,t,s){"use strict";var r=s(42),i=s(12),o=s(10);Object.assign||(Object.assign=s(38));var n=r({DEFINE_LIFE_CYCLE_METHOD:null,DEFINE_ONCE:null,DEFINE_MANY:null,OVERRIDE_BASE:null,DEFINE_MANY_MERGED:null}),l={getDefaultProps:n.DEFINE_LIFE_CYCLE_METHOD,propTypes:n.DEFINE_LIFE_CYCLE_METHOD,getInitialState:n.DEFINE_LIFE_CYCLE_METHOD,statics:n.DEFINE_LIFE_CYCLE_METHOD,displayName:n.DEFINE_LIFE_CYCLE_METHOD,componentWillMount:n.DEFINE_LIFE_CYCLE_METHOD,componentWillReceiveProps:n.DEFINE_LIFE_CYCLE_METHOD,shouldComponentUpdate:n.DEFINE_LIFE_CYCLE_METHOD,componentWillUpdate:n.DEFINE_LIFE_CYCLE_METHOD,componentDidUpdate:n.DEFINE_LIFE_CYCLE_METHOD,componentWillUnmount:n.DEFINE_LIFE_CYCLE_METHOD},a={},c=function(e,t){this.base=e,this.dependsOn=t},p=function(e){this.assignTo=function(t){return new c(t,e)}},h=function(e,t){Object.keys(e).forEach(function(s){if(f.isCustomProperty(s))i(e[s])&&(e[s]=f.wrapCustomMethod(s,e[s]));else{switch(l[s]){case n.DEFINE_LIFE_CYCLE_METHOD:var r={};r[s]=e[s],t.push(r);break;case n.DEFINE_MANY_MERGED:}delete e[s]}},this)},d={mix:function(e){var t=[],s={},r=f.getUniqueDependencies(e);for(var i in r)Object.assign(s,a[r[i]]);return h(s,t),e.forEach(function(e){var r={};e instanceof c?Object.assign(r,e.base):Object.assign(r,e),h(r,t),Object.assign(s,r)},this),t.push(s),t},createDependency:function(e){var t=[];for(var s in e)e[s]instanceof c?this.addAlias(s,e[s].base):this.addAlias(s,e[s]),t.push(s);var r=t.filter(function(e,t,s){return s.indexOf(e)===t});return new p(r)},addAlias:function(e,t){a[e]=t}},u=o.createClass;o.createClass=function(e){return e.mixins&&(e.mixins=d.mix(e.mixins)),u.apply(o,arguments)};var f={isCustomProperty:function(e){return!l[e]},wrapCustomMethod:function(e,t){return function(){return f.isMethodOverridden.call(this,e)?f.callOverriddenMethod.call(this,e,arguments):t.apply(this,arguments)}},checkMethodExtendedAndCall:function(e,t){return this.extended&&"function"==typeof this.extended[e]?this.extended[e].call(this,t):void 0},checkMethodImplementedAndCall:function(e,t){return this.implemented&&"function"==typeof this.implemented[e]?this.implemented[e].call(this,t):void 0},isMethodOverridden:function(e){return this.overrides&&"function"==typeof this.overrides[e]},callOverriddenMethod:function(e,t){return this.overrides[e].call(this,t)},getUniqueDependencies:function(e){var t=[];return e.forEach(function(e){e instanceof c&&(t=t.concat(e.dependsOn))},this),t.filter(function(e,t,s){return s.indexOf(e)===t})}};e.exports=d},function(e){"use strict";function t(e){var t={};for(var s in e)e.hasOwnProperty(s)&&(t[s]=e[s]);return t}e.exports=t},function(e,t,s){"use strict";var r=s(10),i=s(40),o=s(28),n=s(41),l={metricsComputator:r.PropTypes.object},a={childContextTypes:l,getChildContext:function(){return{metricsComputator:this}},getMetricImpl:function(e){return this._DOMMetrics.metrics[e].value},registerMetricsImpl:function(e,t){var s={},r=this._DOMMetrics;for(var i in t)n(void 0===r.metrics[i],"DOM metric "+i+" is already defined"),r.metrics[i]={component:e,computator:t[i].bind(e)},s[i]=this.getMetricImpl.bind(null,i);return-1===r.components.indexOf(e)&&r.components.push(e),s},unregisterMetricsFor:function(e){var t=this._DOMMetrics,s=t.components.indexOf(e);if(s>-1){t.components.splice(s,1);var r,i={};for(r in t.metrics)t.metrics[r].component===e&&(i[r]=!0);for(r in i)delete t.metrics[r]}},updateMetrics:function(){var e=this._DOMMetrics,t=!1;for(var s in e.metrics){var r=e.metrics[s].computator();r!==e.metrics[s].value&&(t=!0),e.metrics[s].value=r}if(t)for(var i=0,o=e.components.length;o>i;i++)e.components[i].metricsUpdated&&e.components[i].metricsUpdated()},componentWillMount:function(){this._DOMMetrics={metrics:{},components:[]}},componentDidMount:function(){window.addEventListener?window.addEventListener("resize",this.updateMetrics):window.attachEvent("resize",this.updateMetrics),this.updateMetrics()},componentWillUnmount:function(){window.removeEventListener("resize",this.updateMetrics)}},c={contextTypes:l,componentWillMount:function(){if(this.DOMMetrics){this._DOMMetricsDefs=o(this.DOMMetrics),this.DOMMetrics={};for(var e in this._DOMMetricsDefs)this.DOMMetrics[e]=i}},componentDidMount:function(){this.DOMMetrics&&(this.DOMMetrics=this.registerMetrics(this._DOMMetricsDefs))},componentWillUnmount:function(){return this.registerMetricsImpl?void(this.hasOwnProperty("DOMMetrics")&&delete this.DOMMetrics):this.context.metricsComputator.unregisterMetricsFor(this)},registerMetrics:function(e){return this.registerMetricsImpl?this.registerMetricsImpl(this,e):this.context.metricsComputator.registerMetricsImpl(this,e)},getMetric:function(e){return this.getMetricImpl?this.getMetricImpl(e):this.context.metricsComputator.getMetricImpl(e)}};e.exports={MetricsComputatorMixin:a,MetricsMixin:c}},function(e,t,s){"use strict";var r=s(10),i=r.addons.classSet,o=s(28),n=s(11),l=s(45),n=s(11),a=r.createClass({displayName:"Header",propTypes:{columns:r.PropTypes.object.isRequired,totalWidth:r.PropTypes.number,height:r.PropTypes.number.isRequired,headerRows:r.PropTypes.array.isRequired},render:function(){var e=(this.state.resizing||this.props,i({"react-grid-Header":!0,"react-grid-Header--resizing":!!this.state.resizing})),t=this.getHeaderRows();return r.createElement("div",r.__spread({},this.props,{style:this.getStyle(),className:e}),t)},shouldComponentUpdate:function(e,t){return!n.sameColumns(this.props.columns.columns,e.columns.columns,n.sameColumn)||this.props.totalWidth!=e.totalWidth||this.props.headerRows.length!=e.headerRows.length||this.state.resizing!=t.resizing},getHeaderRows:function(){var e=this.state.resizing||this.props,t=[];return this.props.headerRows.forEach(function(s,i){var o={position:"absolute",top:this.props.height*i,left:0,width:this.props.totalWidth};t.push(r.createElement(l,{key:s.ref,ref:s.ref,style:o,onColumnResize:this.onColumnResize,onColumnResizeEnd:this.onColumnResizeEnd,width:e.columns.width,height:s.height||this.props.height,columns:e.columns.columns,resizing:e.column,headerCellRenderer:s.headerCellRenderer}))}.bind(this)),t},getInitialState:function(){return{resizing:null}},componentWillReceiveProps:function(){this.setState({resizing:null})},onColumnResize:function(e,t){var s=this.state.resizing||this.props,r=this.getColumnPosition(e);if(null!==r){var i={columns:o(s.columns)};i.columns=n.resizeColumn(i.columns,r,t),i.columns.widththis.props.dragged.rowIdx,"was-dragged-over":this.wasDraggedOver()})},getDefaultProps:function(){return{handleDragStart:this.handleDragStart,onDragEnter:this.handleDragEnter,onDragEnd:this.handleDragEnd}},propTypes:{handleDragEnter:r.PropTypes.func.isRequired,handleDragStart:r.PropTypes.func.isRequired,handleDragEnd:r.PropTypes.func.isRequired,handleTerminateDrag:r.PropTypes.func.isRequired},isDraggedOver:function(){return this.props.dragged&&this.props.dragged.overRowIdx===this.props.rowIdx&&this.props.dragged.idx===this.props.idx},wasDraggedOver:function(){return this.props.dragged&&(this.props.dragged.overRowIdxthis.props.rowIdx&&this.props.rowIdx>this.props.dragged.rowIdx)&&this.props.dragged.idx===this.props.idx},handleDragStart:function(){var e=this.props.rowIdx,t=this.props.idx;this.props.handleDragStart({rowIdx:e,idx:t,copiedText:this.props.value})},handleDragEnter:function(){this.props.handleDragEnter(this.props.rowIdx)},handleDragEnd:function(){this.props.handleDragEnd()},isDraggedCellChanging:function(e){return this.props.dragged?e.dragged&&this.props.idx===e.dragged.idx||this.props.dragged&&this.props.idx===this.props.dragged.idx:!1},componentDidUpdate:function(){var e=this.props.dragged;e&&e.complete===!0&&this.props.handleTerminateDrag()}});e.exports=a},function(e,t,s){"use strict";var r=s(10),i=r.addons.classSet,o=r.createClass({displayName:"SortableHeaderCell",onClick:function(){this.props.column.sortBy(this.props.column,this.props.column.sorted)},getSortByClass:function(){var e=this.props.column.sorted;return i({"pull-right":!0,"glyphicon glyphicon-arrow-up":"ASC"===e,"glyphicon glyphicon-arrow-down":"DESC"===e})},render:function(){return r.createElement("div",{onClick:this.onClick,style:{cursor:"pointer"}},this.props.column.name,r.createElement("span",{className:this.getSortByClass()}))}});e.exports=o},function(e,t,s){"use strict";var r=s(10),i=(r.addons.classSet,r.createClass({displayName:"FilterableHeaderCell",getInitialState:function(){return{filterTerm:""}},handleChange:function(e){e.preventDefault(),e.stopPropagation(),this.setState({filterTerm:e.currentTarget.value}),this.props.onChange({filterTerm:e.currentTarget.value,columnKey:this.props.column.key})},componentDidUpdate:function(){this.getDOMNode().focus()},render:function(){return r.createElement("div",null,r.createElement("div",{className:"form-group"},r.createElement(this.renderInput,null)))},renderInput:function(){return this.props.column.filterable===!1?r.createElement("span",null):r.createElement("input",{type:"text",className:"form-control input-sm",placeholder:"Search",value:this.state.filterTerm,onChange:this.handleChange})}}));e.exports=i},function(e){"use strict";function t(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}e.exports=Object.assign||function(e){for(var s,r,i=t(e),o=1;o0&&n.unshift(this.renderPlaceholder("top",e*s)),o-t>0&&n.push(this.renderPlaceholder("bottom",(o-t)*s));var l={position:"absolute",top:0,left:0,overflowX:"auto",overflowY:"scroll",width:this.props.totalWidth,height:this.props.height,transform:"translate3d(0, 0, 0)"};return r.createElement("div",{style:l,onScroll:this.onScroll,className:i("react-grid-Canvas",this.props.className)},r.createElement("div",{style:{width:this.props.width,overflow:"hidden"}},n))},renderRow:function(e){return r.isValidElement(this.props.rowRenderer)?n(this.props.rowRenderer,e):this.props.rowRenderer(e)},renderPlaceholder:function(e,t){return r.createElement("div",{key:e,style:{height:t}},this.props.columns.map(function(e,t){return r.createElement("div",{style:{width:e.width},key:t})}))},getDefaultProps:function(){return{rowRenderer:r.createElement(p,null),onRows:a}},isRowSelected:function(e){return this.props.selectedRows&&this.props.selectedRows[e]===!0},getInitialState:function(){return{shouldUpdate:!0,displayStart:this.props.displayStart,displayEnd:this.props.displayEnd}},componentWillMount:function(){this._currentRowsLength=void 0,this._currentRowsRange=void 0,this._scroll=void 0},componentDidMount:function(){this.onRows()},componentDidUpdate:function(){void 0!==this._scroll&&this.setScrollLeft(this._scroll),this.onRows()},componentWillUnmount:function(){this._currentRowsLength=void 0,this._currentRowsRange=void 0,this._scroll=void 0},componentWillReceiveProps:function(e){var t=!(e.visibleStart>this.state.displayStart&&e.visibleEndt;t++)this.refs[t]&&this.refs[t].setScrollLeft(e)},getScroll:function(){var e=this.getDOMNode(),t=e.scrollTop,s=e.scrollLeft;return{scrollTop:t,scrollLeft:s}},onScroll:function(e){this.appendScrollShim();var t=e.target,s=t.scrollTop,r=t.scrollLeft,i={scrollTop:s,scrollLeft:r};this._scroll=i,this.props.onScroll(i)}});e.exports=h},function(e,t,s){"use strict";var r=s(10),i=r.PropTypes,o=s(47),n=s(49),l=s(50),a=r.createClass({displayName:"HeaderRow",propTypes:{width:i.number,height:i.number.isRequired,columns:i.array.isRequired,onColumnResize:i.func},render:function(){var e={width:this.props.width?this.props.width+l():"100%",height:this.props.height,whiteSpace:"nowrap",overflowX:"hidden",overflowY:"hidden"},t=this.getCells();return r.createElement("div",r.__spread({},this.props,{className:"react-grid-HeaderRow"}),r.createElement("div",{style:e},t))},getCells:function(){for(var e=[],t=[],s=0,i=this.props.columns.length;i>s;s++){var o=this.props.columns[s],l=r.createElement(n,{ref:s,key:s,height:this.props.height,column:o,renderer:this.props.headerCellRenderer||o.headerRenderer||this.props.cellRenderer,resizing:this.props.resizing===o,onResize:this.props.onColumnResize,onResizeEnd:this.props.onColumnResizeEnd});o.locked?t.push(l):e.push(l)}return e.concat(t)},setScrollLeft:function(e){for(var t=0,s=this.props.columns.length;s>t;t++)this.props.columns[t].locked&&this.refs[t].setScrollLeft(e)},shouldComponentUpdate:function(e){return e.width!==this.props.width||e.height!==this.props.height||e.columns!==this.props.columns||!o(e.style,this.props.style)},getStyle:function(){return{overflow:"hidden",width:"100%",height:this.props.height,position:"absolute"}}});e.exports=a},function(e,t,s){(function(t){"use strict";function s(e,s,r,i,o,n,l){if(e=e||{},t.env.NODE_ENV&&l)throw new Error("Too many arguments passed to copyProperties");for(var a,c=[s,r,i,o,n],p=0;c[p];){a=c[p++];for(var h in a)e[h]=a[h];a.hasOwnProperty&&a.hasOwnProperty("toString")&&"undefined"!=typeof a.toString&&e.toString!==a.toString&&(e.toString=a.toString)}return e}e.exports=s}).call(t,s(52))},function(e){"use strict";function t(e,t){if(e===t)return!0;var s;for(s in e)if(e.hasOwnProperty(s)&&(!t.hasOwnProperty(s)||e[s]!==t[s]))return!1;for(s in t)if(t.hasOwnProperty(s)&&!e.hasOwnProperty(s))return!1;return!0}e.exports=t},function(e){"use strict";var t={appendScrollShim:function(){if(!this._scrollShim){var e=this._scrollShimSize(),t=document.createElement("div");t.classList.add("react-grid-ScrollShim"),t.style.position="absolute",t.style.top=0,t.style.left=0,t.style.width=e.width+"px",t.style.height=e.height+"px",this.getDOMNode().appendChild(t),this._scrollShim=t}this._scheduleRemoveScrollShim()},_scrollShimSize:function(){return{width:this.props.width,height:this.props.length*this.props.rowHeight}},_scheduleRemoveScrollShim:function(){this._scheduleRemoveScrollShimTimer&&clearTimeout(this._scheduleRemoveScrollShimTimer),this._scheduleRemoveScrollShimTimer=setTimeout(this._removeScrollShim,200)},_removeScrollShim:function(){this._scrollShim&&(this._scrollShim.parentNode.removeChild(this._scrollShim),this._scrollShim=void 0)}};e.exports=t},function(e,t,s){"use strict";function r(e){return i.createElement("div",{className:"rex-widget-HeaderCell__value"},e.column.name)}var i=s(10),o=i.addons.classSet,n=s(53),l=i.PropTypes,a=i.createClass({displayName:"ResizeHandle",style:{position:"absolute",top:0,right:0,width:6,height:"100%"},render:function(){return i.createElement(n,i.__spread({},this.props,{className:"react-grid-HeaderCell__resizeHandle",style:this.style}))}}),c=i.createClass({displayName:"HeaderCell",propTypes:{renderer:l.oneOfType([l.func,l.element]).isRequired,column:l.object.isRequired,onResize:l.func},render:function(){var e=o({"react-grid-HeaderCell":!0,"react-grid-HeaderCell--resizing":this.state.resizing,"react-grid-HeaderCell--locked":this.props.column.locked});e=o(e,this.props.className);var t=this.getCell();return i.createElement("div",{className:e,style:this.getStyle()},t,this.props.column.resizeable?i.createElement(a,{onDrag:this.onDrag,onDragStart:this.onDragStart,onDragEnd:this.onDragEnd}):null)},getCell:function(){return i.isValidElement(this.props.renderer)?i.addons.cloneWithProps(this.props.renderer,{column:this.props.column}):this.props.renderer({column:this.props.column})},getDefaultProps:function(){return{renderer:r}},getInitialState:function(){return{resizing:!1}},setScrollLeft:function(e){var t=this.getDOMNode();t.style.webkitTransform="translate3d("+e+"px, 0px, 0px)",t.style.transform="translate3d("+e+"px, 0px, 0px)"},getStyle:function(){return{width:this.props.column.width,left:this.props.column.left,display:"inline-block",position:"absolute",overflow:"hidden",height:this.props.height,margin:0,textOverflow:"ellipsis",whiteSpace:"nowrap"}},onDragStart:function(){this.setState({resizing:!0})},onDrag:function(e){var t=this.getWidthFromMouseEvent(e);t>0&&this.props.onResize&&this.props.onResize(this.props.column,t)},onDragEnd:function(e){var t=this.getWidthFromMouseEvent(e);this.props.onResizeEnd(this.props.column,t),this.setState({resizing:!1})},getWidthFromMouseEvent:function(e){var t=e.pageX,s=this.getDOMNode().getBoundingClientRect().left;return t-s}});e.exports=c},function(e){"use strict";function t(){if(void 0===s){var e=document.createElement("div");e.style.width="50px",e.style.height="50px",e.style.overflowY="scroll",e.style.position="absolute",e.style.top="-200px",e.style.left="-200px";var t=document.createElement("div");t.style.height="100px",t.style.width="100%",e.appendChild(t),document.body.appendChild(e);var r=e.offsetWidth,i=t.offsetWidth;document.body.removeChild(e),s=r-i}return s}var s;e.exports=t},function(e,t,s){(function(t){"use strict";var s=function(e,s,r,i,o,n,l,a){if("production"!==t.env.NODE_ENV&&void 0===s)throw new Error("invariant requires an error message argument");if(!e){var c;if(void 0===s)c=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var p=[r,i,o,n,l,a],h=0;c=new Error("Invariant Violation: "+s.replace(/%s/g,function(){return p[h++]}))}throw c.framesToPop=1,c}};e.exports=s}).call(t,s(52))},function(e){function t(){}var s=e.exports={};s.nextTick=function(){var e="undefined"!=typeof window&&window.setImmediate,t="undefined"!=typeof window&&window.MutationObserver,s="undefined"!=typeof window&&window.postMessage&&window.addEventListener;if(e)return function(e){return window.setImmediate(e)};var r=[];if(t){var i=document.createElement("div"),o=new MutationObserver(function(){var e=r.slice();r.length=0,e.forEach(function(e){e()})});return o.observe(i,{attributes:!0}),function(e){r.length||i.setAttribute("yes","no"),r.push(e)}}return s?(window.addEventListener("message",function(e){var t=e.source;if((t===window||null===t)&&"process-tick"===e.data&&(e.stopPropagation(),r.length>0)){var s=r.shift();s()}},!0),function(e){r.push(e),window.postMessage("process-tick","*")}):function(e){setTimeout(e,0)}}(),s.title="browser",s.browser=!0,s.env={},s.argv=[],s.on=t,s.addListener=t,s.once=t,s.off=t,s.removeListener=t,s.removeAllListeners=t,s.emit=t,s.binding=function(){throw new Error("process.binding is not supported")},s.cwd=function(){return"/"},s.chdir=function(){throw new Error("process.chdir is not supported")}},function(e,t,s){"use strict";var r=s(10),i=r.PropTypes,o=s(40),n=r.createClass({displayName:"Draggable",propTypes:{onDragStart:i.func,onDragEnd:i.func,onDrag:i.func,component:i.oneOfType([i.func,i.constructor])},render:function(){var e=this.props.component;return r.createElement(e,r.__spread({},this.props,{onMouseDown:this.onMouseDown}))},getDefaultProps:function(){return{component:r.DOM.div,onDragStart:o.thatReturnsTrue,onDragEnd:o,onDrag:o}},getInitialState:function(){return{drag:null}},onMouseDown:function(e){var t=this.props.onDragStart(e);(null!==t||0===e.button)&&(window.addEventListener("mouseup",this.onMouseUp),window.addEventListener("mousemove",this.onMouseMove),this.setState({drag:t}))},onMouseMove:function(e){null!==this.state.drag&&(e.stopPropagation&&e.stopPropagation(),e.preventDefault&&e.preventDefault(),this.props.onDrag(e))},onMouseUp:function(e){this.cleanUp(),this.props.onDragEnd(e,this.state.drag),this.setState({drag:null})},componentWillUnmount:function(){this.cleanUp()},cleanUp:function(){window.removeEventListener("mouseup",this.onMouseUp),window.removeEventListener("mousemove",this.onMouseMove)}});e.exports=n}])}); \ No newline at end of file diff --git a/dist/ReactGridWithAddons.js b/dist/ReactGridWithAddons.js deleted file mode 100644 index 5540953..0000000 --- a/dist/ReactGridWithAddons.js +++ /dev/null @@ -1,4980 +0,0 @@ -(function webpackUniversalModuleDefinition(root, factory) { - if(typeof exports === 'object' && typeof module === 'object') - module.exports = factory(require("react/addons")); - else if(typeof define === 'function' && define.amd) - define(["react/addons"], factory); - else if(typeof exports === 'object') - exports["ReactGrid"] = factory(require("react/addons")); - else - root["ReactGrid"] = factory(root["React"]); -})(this, function(__WEBPACK_EXTERNAL_MODULE_10__) { -return /******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) -/******/ return installedModules[moduleId].exports; -/******/ -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ exports: {}, -/******/ id: moduleId, -/******/ loaded: false -/******/ }; -/******/ -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); -/******/ -/******/ // Flag the module as loaded -/******/ module.loaded = true; -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/******/ -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; -/******/ -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; -/******/ -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; -/******/ -/******/ // Load entry module and return exports -/******/ return __webpack_require__(0); -/******/ }) -/************************************************************************/ -/******/ ([ -/* 0 */ -/***/ function(module, exports, __webpack_require__) { - - module.exports = { - Grid : __webpack_require__(1), - Editors : __webpack_require__(7), - Formatters : __webpack_require__(8), - Toolbar : __webpack_require__(4), - Mixins : { - EditorMixin : __webpack_require__(5), - TextInputMixin : __webpack_require__(6), - KeyboardHandlerMixin : __webpack_require__(9) - } - } - - -/***/ }, -/* 1 */ -/***/ function(module, exports, __webpack_require__) { - - /* @flow */ - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - "use strict"; - - var React = __webpack_require__(10); - var PropTypes = React.PropTypes; - var BaseGrid = __webpack_require__(16); - var ExcelCell = __webpack_require__(17); - var ExcelRow = __webpack_require__(18); - var merge = __webpack_require__(19); - var SelectableGridMixin = __webpack_require__(20); - var DraggableGridMixin = __webpack_require__(21); - var CopyPasteGridMixin = __webpack_require__(22); - var EditableGridMixin = __webpack_require__(23); - var SortableGridMixin = __webpack_require__(24); - var FilterableGridMixin = __webpack_require__(25); - var CheckboxEditor = __webpack_require__(26); - var MixinHelper = __webpack_require__(27); - - var cloneWithProps = React.addons.cloneWithProps; - - var ExcelGrid = React.createClass({displayName: 'ExcelGrid', - - mixins : [SelectableGridMixin, EditableGridMixin, DraggableGridMixin, CopyPasteGridMixin, SortableGridMixin, FilterableGridMixin], - - getInitialState:function(){ - return {selectedRows : [], expandedRows : []}; - }, - - overrides : { - onCellCommit:function(commit ){ - var committed = commit[0]; - var selected = Object.assign({}, this.state.selected); - selected.active = false; - if (committed.keyCode === 'Tab') { - selected.idx += 1; - } - var expandedRows = this.state.expandedRows; - if(committed.changed && committed.changed.expandedHeight){ - expandedRows = this.expandRow(committed.rowIdx, committed.changed.expandedHeight); - } - this.setState({selected : selected, expandedRows : expandedRows}); - this.props.onRowUpdated(committed); - }, - getColumns : function(){ - var cols = this.getDecoratedColumns(this.props.columns) - if(this.props.enableRowSelect){ - cols.unshift({ - key: 'select-row', - name: '', - formatter : React.createElement(CheckboxEditor, null), - onRowSelect :this.handleRowSelect, - filterable : false, - headerRenderer : React.createElement("input", {type: "checkbox", onChange: this.handleCheckboxChange}), - width : 60 - }); - } - return cols; - } - }, - - getDefaultProps:function() { - return { - rowHeight: 35, - enableRowSelect : false, - minHeight : 350 - }; - }, - - handleCheckboxChange : function(e){ - if(e.currentTarget.checked === true){ - var selectedRows = this.props.rows.map(function() {return true;}); - this.setState({selectedRows : selectedRows}); - }else{ - var selectedRows = this.props.rows.map(function() {return false;}); - this.setState({selectedRows : selectedRows}); - } - }, - - handleRowSelect:function(row){ - var selectedRows = this.state.selectedRows; - if(selectedRows[row] == null || selectedRows[row] == false){ - selectedRows[row] = true; - }else{ - selectedRows[row] = false; - } - this.setState({selectedRows : selectedRows}); - }, - - expandRow:function(row, newHeight){ - var expandedRows = this.state.expandedRows; - if(expandedRows[row]){ - if(expandedRows[row]== null || expandedRows[row] < newHeight){ - expandedRows[row] = newHeight; - } - }else{ - expandedRows[row] = newHeight; - } - return expandedRows; - }, - - addRow:function(){ - - }, - - handleShowMore:function(row, newHeight){ - var expandedRows = this.expandRow(row, newHeight); - this.setState({expandedRows : expandedRows}); - }, - - handleShowLess:function(row){ - var expandedRows = this.state.expandedRows; - if(expandedRows[row]){ - expandedRows[row] = false; - } - this.setState({expandedRows : expandedRows}); - }, - - expandAllRows:function(){ - - }, - - collapseAllRows:function(){ - - }, - - onAfterAddRow:function(numberOfRows){ - this.setState({selected : {idx : 1, rowIdx : numberOfRows - 2}}); - //cheeky - this.refs.base.refs.viewport.refs.canvas.getDOMNode().scrollTop = numberOfRows * this.props.rowHeight; - }, - - componentWillReceiveProps:function(nextProps){ - if(nextProps.rows.length === this.props.rows.length + 1){ - this.onAfterAddRow(nextProps.rows.length + 1); - } - }, - - render: function() { - var cellRenderer = ( - React.createElement(ExcelCell, { - selected: this.state.selected, - copied: this.state.copied, - dragged: this.state.dragged, - onSelect: this.onSelect, - onClick: this.onSelect, - onSetActive: this.onSetActive, - onCommit: this.onCellCommit, - handleCopy: this.handleCopy, - handlePaste: this.handlePaste, - handleDragStart: this.handleDragStart, - handleDragEnter: this.handleDragEnter, - handleDragEnd: this.handleDragEnd, - handleTerminateDrag: this.handleTerminateDrag, - onShowMore: this.handleShowMore, - onShowLess: this.handleShowLess, - expandedRows: this.state.expandedRows} - ) - ); - - var rows = this.filterRows(); - var toolbar = this.renderToolbar(); - return( - React.createElement("div", {className: "react-grid-Container"}, - toolbar, - React.createElement("div", {className: "react-grid-Main"}, - (React.createElement(BaseGrid, React.__spread({ - ref: "base"}, - this.props, - {length: this.props.rows.length, - headerRows: this.getHeaderRows(), - columns: this.getColumns(), - rows: rows, - cellRenderer: cellRenderer, - rowRenderer: React.createElement(ExcelRow, null), - selectedRows: this.state.selectedRows, - expandedRows: this.state.expandedRows, - rowOffsetHeight: this.getRowOffsetHeight(), - minHeight: this.props.minHeight}))) - ) - ) - ) - }, - - renderToolbar:function(){ - var Toolbar = this.props.toolbar; - if(React.isValidElement(Toolbar)){ - return( React.addons.cloneWithProps(Toolbar, {onToggleFilter : this.onToggleFilter, rows : this.props.rows})); - } - - } - - - }) - - - module.exports = ExcelGrid; - - -/***/ }, -/* 2 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var cx = React.addons.classSet; - var Cell = __webpack_require__(3); - var cloneWithProps = React.addons.cloneWithProps; - var ColumnMetrics = __webpack_require__(11); - - var Row = React.createClass({displayName: 'Row', - - render:function() { - var className = cx( - 'react-grid-Row', - ("react-grid-Row--" + (this.props.idx % 2 === 0 ? 'even' : 'odd')) - ); - - var style = { - height: this.getRowHeight(), - overflow: 'hidden' - }; - - var cells = this.getCells(); - return ( - React.createElement("div", React.__spread({}, this.props, {className: className, style: style}), - React.isValidElement(this.props.row) ? - this.props.row : cells - ) - ); - }, - - getCells:function() { - var cells = []; - var lockedCells = []; - - for (var i = 0, len = this.props.columns.length; i < len; i++) { - var column = this.props.columns[i]; - var cell = this.renderCell({ - ref:i, - key:i, - idx:i, - rowIdx:this.props.idx, - filterRowIdx:this.props.row.key, - value:this.getCellValue(column.key || i), - column:column, - height:this.getRowHeight(), - formatter:column.formatter, - rowData : this.props.row}); - if (column.locked) { - lockedCells.push(cell); - } else { - cells.push(cell); - } - } - - return cells.concat(lockedCells); - }, - - getRowHeight:function(){ - if(this.props.expandedRows && this.props.expandedRows[this.props.key]){ - return this.props.expandedRows[this.props.key]; - }else{ - return this.props.height; - } - }, - - getCellValue:function(key){ - if(key === 'select-row'){ - return this.props.isSelected; - }else{ - return this.props.row[key] - } - }, - - renderCell:function(props) { - if (React.isValidElement(this.props.cellRenderer)) { - return cloneWithProps(this.props.cellRenderer, props); - } else { - return this.props.cellRenderer(props); - } - }, - - getDefaultProps:function() { - return { - cellRenderer: Cell - }; - }, - - shouldComponentUpdate:function(nextProps) { - return !(ColumnMetrics.sameColumns(this.props.columns, nextProps.columns, ColumnMetrics.sameColumn)) || - this.doesRowContainSelectedCell() || - this.doesRowContainSelectedCell(nextProps) || - this.willRowBeDraggedOver(nextProps) || - this.hasRowBeenCopied() || - nextProps.row !== this.props.row || - nextProps.height !== this.props.height; - }, - - setScrollLeft:function(scrollLeft) { - for (var i = 0, len = this.props.columns.length; i < len; i++) { - if (this.props.columns[i].locked) { - this.refs[i].setScrollLeft(scrollLeft); - } - } - }, - - doesRowContainSelectedCell:function(propsToCheck){ - var props = propsToCheck || this.props; - var cell = cell || props.cellRenderer; - if(cell.props.selected && cell.props.selected.rowIdx === props.idx){ - return true; - }else{ - return false; - } - }, - - willRowBeDraggedOver:function(props){ - var dragged = props.cellRenderer.props.dragged; - return dragged != null && (dragged.rowIdx || dragged.complete === true); - }, - - hasRowBeenCopied:function(){ - var cell = this.props.cellRenderer; - return cell.props.copied != null && cell.props.copied.rowIdx === this.props.idx; - } - - - }); - - module.exports = Row; - - -/***/ }, -/* 3 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var cx = React.addons.classSet; - var cloneWithProps = React.addons.cloneWithProps; - - var Cell = React.createClass({displayName: 'Cell', - - render:function() { - var style = this.getStyle(); - var className = cx( - 'react-grid-Cell', - this.props.className, - this.props.column.locked ? 'react-grid-Cell--locked' : null - ); - - var cellContent = this.renderCellContent({ - value : this.props.value, - column : this.props.column, - rowIdx : this.props.rowIdx, - isExpanded : this.props.isExpanded - }); - - return ( - React.createElement("div", React.__spread({}, this.props, {className: className, style: style}), - cellContent, - React.createElement("div", {className: "drag-handle", draggable: "true", onDragStart: this.props.handleDragStart} - ) - ) - ); - }, - - renderCellContent:function(props) { - var formatter = React.isValidElement(this.props.formatter) ? cloneWithProps(this.props.formatter, props) : this.props.formatter(props); - return (React.createElement("div", { - className: "react-grid-Cell__value"}, formatter, " ", this.props.cellControls)) - - }, - - getDefaultProps:function() { - return { - formatter: simpleCellFormatter - }; - }, - - getStyle:function() { - var style = { - position: 'absolute', - width: this.props.column.width, - height: this.props.height, - left: this.props.column.left - }; - return style; - }, - - setScrollLeft:function(scrollLeft) { - if (this.isMounted()) { - var node = this.getDOMNode(); - var transform = ("translate3d(" + scrollLeft + "px, 0px, 0px)"); - node.style.webkitTransform = transform; - node.style.transform = transform; - } - } - }); - - function simpleCellFormatter(props) { - return props.value; - } - - module.exports = Cell; - - -/***/ }, -/* 4 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var Toolbar = React.createClass({displayName: 'Toolbar', - - onAddRow:function(){ - if(this.props.onAddRow){ - this.props.onAddRow({newRowIndex : this.props.rows.length}); - } - }, - - getDefaultProps:function(){ - return { - enableAddRow : true - } - }, - - getAddRowButton:function(){ - if(this.props.enableAddRow){ - return(React.createElement("button", {type: "button", className: "btn", onClick: this.onAddRow}, - "Add Row" - )) - } - }, - - render:function(){ - return ( - React.createElement("div", {className: "react-grid-Toolbar"}, - React.createElement("div", {className: "tools"}, - this.getAddRowButton(), - React.createElement("button", {type: "button", className: "btn", onClick: this.props.onToggleFilter}, - "Filter Rows" - ) - ) - )) - } - }); - - module.exports = Toolbar; - - -/***/ }, -/* 5 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - var React = __webpack_require__(10); - var cx = React.addons.classSet; - var isFunction = __webpack_require__(12); - - var EditorMixin = { - - propTypes : { - onCommit : React.PropTypes.func.isRequired - }, - - getStyle:function(){ - return { - height : this.props.height - 1 - } - }, - - getInitialState:function(){ - return {isInvalid : false} - }, - - onPressEnter:function(e){ - e.stopPropagation(); - e.preventDefault(); - this.commit({key : 'Enter'}); - }, - - onPressTab:function(e){ - e.stopPropagation(); - e.preventDefault(); - this.commit({key : 'Tab'}); - }, - - commit:function(args){ - var value = this.getValue(); - var rowDataChanged = {}; - rowDataChanged[this.props.column.key] = value; - if(this.isNewValueValid(value)){ - this.props.onCommit({updated : rowDataChanged, key : args.key}); - } - }, - - isNewValueValid:function(value){ - if(isFunction(this.validate)){ - var isValid = this.validate(value); - this.setState({isInvalid : !isValid}); - return isValid; - }else{ - return true; - } - }, - - getValue:function(){ - return this.getInputNode().value; - }, - - setValue:function(value){ - this.getInputNode().value = value; - }, - - componentDidMount: function() { - if(this.getInputNode() !== undefined){ - this.checkFocus(); - this.getInputNode().className += ' editor-main'; - } - }, - - checkFocus:function(){ - this.getInputNode().focus(); - }, - - getInputNode:function(){ - return this.getDOMNode().getElementsByTagName("input")[0]; - }, - - getContainerClass:function(){ - return cx({ - 'has-error' : this.state.isInvalid === true - }) - }, - - renderStatusIcon:function(){ - if(this.state.isInvalid === true){ - return React.createElement("span", {className: "glyphicon glyphicon-remove form-control-feedback"}) - } - }, - - render:function(){ - if(!isFunction(this.renderEditorNode)){ - throw "Editor Mixin Error : " + this.displayName + " component must implement method renderEditorNode"; - } - var editorNode = this.renderEditorNode(); - return ( - React.createElement("div", {className: this.getContainerClass()}, - editorNode, - this.renderStatusIcon() - ) - ) - } - }; - - module.exports = EditorMixin; - - -/***/ }, -/* 6 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var TextInputMixin = { - - onPressArrowLeft:function(e){ - //prevent event propogation. this disables left cell navigation - e.stopPropagation(); - }, - - onPressArrowRight:function(e){ - //prevent event propogation. this disables right cell navigation - e.stopPropagation(); - }, - - getDefaultValue:function(){ - var keyCode = this.props.initialKeyCode; - if(keyCode === 'Delete' || keyCode === 'Backspace'){ - return ''; - }else if(keyCode === 'Enter'){ - return this.props.value; - }else{ - var text = keyCode ? String.fromCharCode(keyCode) : this.props.value; - return text; - } - - }, - - setCaretAtEndOfInput:function(){ - var input = this.getInputNode(); - //taken from http://stackoverflow.com/questions/511088/use-javascript-to-place-cursor-at-end-of-text-in-text-input-element - var txtLength = input.value.length; - if(input.setSelectionRange){ - input.setSelectionRange(txtLength, txtLength); - }else if(input.createTextRange){ - var fieldRange = input.createTextRange(); - fieldRange.moveStart('character', txt.value.length); - fieldRange.collapse(); - fieldRange.select(); - } - }, - - setTextInputFocus:function(){ - if(!this.isKeyPrintable(this.props.initialKeyCode)){ - this.getInputNode().focus(); - this.setCaretAtEndOfInput(); - }else{ - this.getInputNode().select(); - } - } - - - }; - - module.exports = TextInputMixin; - - -/***/ }, -/* 7 */ -/***/ function(module, exports, __webpack_require__) { - - var Editors = { - AutoComplete : __webpack_require__(13), - DropDownEditor : __webpack_require__(14), - SimpleTextEditor : __webpack_require__(15) - - } - - module.exports = Editors; - - -/***/ }, -/* 8 */ -/***/ function(module, exports, __webpack_require__) { - - var formatters = { - - } - - module.exports = formatters; - - -/***/ }, -/* 9 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - - 'use strict'; - - var React = __webpack_require__(10); - var Perf = React.addons.Perf; - - var hasPerfStarted = false; - - var KeyboardHandlerMixin = { - - onKeyDown:function(e){ - if(this.isCtrlKeyHeldDown(e)){ - this.checkAndCall('onPressKeyWithCtrl', e); - } - else if (this.isKeyIdentified(e.key)) { - //break up individual keyPress events to have their own specific callbacks - //this allows multiple mixins to listen to onKeyDown events and somewhat reduces methodName clashing - var callBack = 'onPress' + e.key; - this.checkAndCall(callBack, e); - }else if(this.isKeyPrintable(e.keyCode)){ - this.checkAndCall('onPressChar', e); - } - }, - - //taken from http://stackoverflow.com/questions/12467240/determine-if-javascript-e-keycode-is-a-printable-non-control-character - isKeyPrintable:function(keycode){ - var valid = - (keycode > 47 && keycode < 58) || // number keys - keycode == 32 || keycode == 13 || // spacebar & return key(s) (if you want to allow carriage returns) - (keycode > 64 && keycode < 91) || // letter keys - (keycode > 95 && keycode < 112) || // numpad keys - (keycode > 185 && keycode < 193) || // ;=,-./` (in order) - (keycode > 218 && keycode < 223); // [\]' (in order) - - return valid; - }, - - isKeyIdentified:function(key){ - return key !== "Unidentified"; - }, - - isCtrlKeyHeldDown:function(e){ - return e.ctrlKey === true && e.key !== "Control"; - }, - - checkAndCall:function(methodName, args){ - if(typeof this[methodName] === 'function'){ - this[methodName](args); - } - } - } - - - - module.exports = KeyboardHandlerMixin; - - -/***/ }, -/* 10 */ -/***/ function(module, exports, __webpack_require__) { - - module.exports = __WEBPACK_EXTERNAL_MODULE_10__; - -/***/ }, -/* 11 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - "use strict"; - - var $__0= __webpack_require__(10),PropTypes=$__0.PropTypes,isValidElement=$__0.isValidElement; - var shallowCloneObject = __webpack_require__(28); - var DOMMetrics = __webpack_require__(29); - var merge = __webpack_require__(19); - - /** - * Update column metrics calculation. - * - * @param {ColumnMetrics} metrics - */ - function calculate(metrics) { - var width = 0; - var unallocatedWidth = metrics.totalWidth; - - var deferredColumns = []; - var columns = metrics.columns.map(shallowCloneObject); - - var i, len, column; - - // compute width for columns which specify width - for (i = 0, len = columns.length; i < len; i++) { - column = columns[i]; - - if (column.width) { - if (/^([0-9]+)%$/.exec(column.width)) { - column.width = Math.floor( - parseInt(column.width, 10) / 100 * metrics.totalWidth); - } - unallocatedWidth -= column.width; - width += column.width; - } else { - deferredColumns.push(column); - } - - } - - // compute width for columns which doesn't specify width - for (i = 0, len = deferredColumns.length; i < len; i++) { - column = deferredColumns[i]; - - if (unallocatedWidth <= 0) { - column.width = metrics.minColumnWidth; - } else { - column.width = Math.floor(unallocatedWidth / deferredColumns.length); - } - width += column.width; - } - - // compute left offset - var left = 0; - for (i = 0, len = columns.length; i < len; i++) { - column = columns[i]; - column.left = left; - left += column.width; - } - - return { - columns:columns, - width:width, - totalWidth: metrics.totalWidth, - minColumnWidth: metrics.minColumnWidth - }; - } - - /** - * Update column metrics calculation by resizing a column. - * - * @param {ColumnMetrics} metrics - * @param {Column} column - * @param {number} width - */ - function resizeColumn(metrics, index, width) { - var column = metrics.columns[index]; - metrics = shallowCloneObject(metrics); - metrics.columns = metrics.columns.slice(0); - - var updatedColumn = shallowCloneObject(column); - updatedColumn.width = Math.max(width, metrics.minColumnWidth); - - metrics.columns.splice(index, 1, updatedColumn); - - return calculate(metrics); - } - - var Mixin = { - mixins: [DOMMetrics.MetricsMixin], - - propTypes: { - columns: PropTypes.array, - minColumnWidth: PropTypes.number, - columnEquality: PropTypes.func - }, - - DOMMetrics: { - gridWidth:function() { - return this.getDOMNode().offsetWidth - 2; - } - }, - - getDefaultProps:function() { - return { - minColumnWidth: 80, - columnEquality: sameColumn - }; - }, - - getInitialState:function() { - return this.getColumnMetrics(this.props, true); - }, - - componentWillReceiveProps:function(nextProps) { - if (nextProps.columns) { - if (!sameColumns(this.props.columns, nextProps.columns, this.props.columnEquality)) { - this.setState(this.getColumnMetrics(nextProps)); - } else { - var index = {}; - this.state.columns.columns.forEach(function(c) { - index[c.key] = {width: c.width, left: c.left}; - }); - var nextColumns = merge(this.state.columns, { - columns: nextProps.columns.map(function(c) {return merge(c, index[c.key]);}) - }); - this.setState({columns: nextColumns}); - } - } - }, - - getColumnMetrics:function(props, initial) { - var totalWidth = initial ? null : this.DOMMetrics.gridWidth(); - return { - columns: calculate({ - columns: props.columns, - width: null, - totalWidth:totalWidth, - minColumnWidth: props.minColumnWidth - }), - gridWidth: totalWidth - }; - }, - - metricsUpdated:function() { - this.setState(this.getColumnMetrics(this.props)); - }, - - onColumnResize:function(index, width) { - var columns = resizeColumn(this.state.columns, index, width); - this.setState({columns:columns}); - } - }; - - function sameColumns(prevColumns, nextColumns, sameColumn) { - var i, len, column; - var prevColumnsByKey = {}; - var nextColumnsByKey = {}; - - - if(prevColumns.length !== nextColumns.length){ - return false; - } - - for (i = 0, len = prevColumns.length; i < len; i++) { - column = prevColumns[i]; - prevColumnsByKey[column.key] = column; - } - - for (i = 0, len = nextColumns.length; i < len; i++) { - column = nextColumns[i]; - nextColumnsByKey[column.key] = column; - var prevColumn = prevColumnsByKey[column.key]; - if (prevColumn === undefined || !sameColumn(prevColumn, column)) { - return false; - } - } - - for (i = 0, len = prevColumns.length; i < len; i++) { - column = prevColumns[i]; - var nextColumn = nextColumnsByKey[column.key]; - if (nextColumn === undefined) { - return false; - } - } - - return true; - } - - function sameColumn(a, b) { - var k; - - for (k in a) { - if (a.hasOwnProperty(k)) { - if ((typeof a[k] === 'function' && typeof b[k] === 'function') || (isValidElement(a[k]) && isValidElement(b[k]))) { - continue; - } - if (!b.hasOwnProperty(k) || a[k] !== b[k]) { - return false; - } - } - } - - for (k in b) { - if (b.hasOwnProperty(k) && !a.hasOwnProperty(k)) { - return false; - } - } - - return true; - } - - module.exports = {Mixin:Mixin, calculate:calculate, resizeColumn:resizeColumn, sameColumns:sameColumns, sameColumn:sameColumn}; - - -/***/ }, -/* 12 */ -/***/ function(module, exports, __webpack_require__) { - - - "use strict"; - - var isFunction = function(functionToCheck){ - var getType = {}; - return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]'; - } - - module.exports = isFunction; - - -/***/ }, -/* 13 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var cx = React.addons.classSet; - var MixinHelper = __webpack_require__(27); - var EditorMixin = __webpack_require__(5); - var TextInputMixin = __webpack_require__(6); - var ReactAutocomplete = __webpack_require__(39); - var keyboardHandlerMixin = __webpack_require__(9); - - var optionPropType = React.PropTypes.shape({ - id : React.PropTypes.required, - title : React.PropTypes.string - }); - - var AutoCompleteEditor = React.createClass({displayName: 'AutoCompleteEditor', - - propTypes : { - options : React.PropTypes.arrayOf(optionPropType) - }, - - mixins : MixinHelper.mix([keyboardHandlerMixin, EditorMixin, TextInputMixin]), - - overrides : { - checkFocus : function(){ - this.setTextInputFocus(); - }, - getInputNode:function(){ - return this.getSearchComponent().getDOMNode(); - }, - onPressEnter:function(args){ - var e = args[0]; - this.handleEnter(e); - }, - onPressTab:function(args){ - var e = args[0]; - this.handleTab(e); - } - }, - - handleTab:function(e){ - e.stopPropagation(); - e.preventDefault(); - if(!this.isFocusedOnSuggestion()){ - this.handleChange(null, 'Tab'); - }else{ - this.handleChange(this.getFocusedSuggestion(), 'Tab'); - } - }, - - handleEnter:function(e){ - e.stopPropagation(); - e.preventDefault(); - if(!this.isFocusedOnSuggestion()){ - this.props.onCommit({value : this.refs.autoComplete.state.searchTerm, key : 'Enter'}); - } - }, - - getSearchComponent:function(){ - return this.refs.autoComplete.refs.search; - }, - - isFocusedOnSuggestion:function(){ - var autoComplete = this.refs.autoComplete; - return autoComplete.state.focusedValue != null; - }, - - getFocusedSuggestion:function(){ - return this.refs.autoComplete.state.focusedValue; - }, - - onPressArrowDown:function(e){ - //prevent event propogation. this disables downwards cell navigation - e.stopPropagation(); - e.preventDefault(); - }, - - onPressArrowUp:function(e){ - //prevent event propogation. this disables upwards cell navigation - e.stopPropagation(); - }, - - getLabel:function(result) { - var label = this.props.label != null ? this.props.label : 'title'; - if (typeof label === "function") { - return label(result); - } else if (typeof label === "string") { - return result[label]; - } - }, - - handleChange:function(item, key){ - var rowDataChanged = {}; - var value = this.props.value; - if(item!=null){ - value = this.getLabel(item); - if(this.props.valueParams){ - value = this.constuctValueFromParams(item, this.props.valueParams); - } - rowDataChanged[this.props.column.key] = value; - } - key = key ? key : 'Enter'; - this.props.onCommit({value : value, key : key, updated : rowDataChanged}); - }, - - constuctValueFromParams:function(obj, props) { - var ret = []; - for (var i = 0, ii = props.length; i < ii; i++) { - ret.push(obj[props[i]]); - } - return ret.join('|'); - }, - - renderEditorNode:function(){ - var val = {title : this.getDefaultValue()}; - var label = this.props.label != null ? this.props.label : 'title'; - return (React.createElement("div", {style: this.getStyle(), onKeyDown: this.onKeyDown}, - React.createElement(ReactAutocomplete, {search: this.props.search, ref: "autoComplete", label: label, resultIdentifier: this.props.resultIdentifier, options: this.props.options, value: val, onChange: this.handleChange}) - )); - } - - }); - - module.exports = AutoCompleteEditor; - - -/***/ }, -/* 14 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var cx = React.addons.classSet; - var MixinHelper = __webpack_require__(27); - var keyboardHandlerMixin = __webpack_require__(9); - var EditorMixin = __webpack_require__(5); - var cloneWithProps = React.addons.cloneWithProps; - - var DropDownEditor = React.createClass({displayName: 'DropDownEditor', - - mixins : [keyboardHandlerMixin, EditorMixin], - - overrides : { - getInputNode : function(){ - return this.refs.select.getDOMNode(); - } - }, - - propTypes : { - options : React.PropTypes.array.isRequired - }, - - renderEditorNode:function(){ - return ( - React.createElement("select", {ref: "select", style: this.getStyle(), defaultValue: this.props.value, onChange: this.onChange}, - this.renderOptions() - )); - }, - - renderOptions:function(){ - var options = []; - this.props.options.forEach(function(name){ - options.push(React.createElement("option", {key: name, value: name}, name)); - }, this); - return options; - }, - - - onChange:function(e){ - this.commit({key : 'Enter'}); - }, - - onClick:function(e){ - e.stopPropagation(); - e.preventDefault(); - } - - }); - - module.exports = DropDownEditor; - - -/***/ }, -/* 15 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var cx = React.addons.classSet; - var MixinHelper = __webpack_require__(27); - var EditorMixin = __webpack_require__(5); - var TextInputMixin = __webpack_require__(6); - var keyboardHandlerMixin = __webpack_require__(9); - - var SimpleTextEditor = React.createClass({displayName: 'SimpleTextEditor', - - mixins : [keyboardHandlerMixin, EditorMixin, TextInputMixin], - - overrides : { - checkFocus : function(){ - this.setTextInputFocus(); - } - }, - - renderEditorNode:function(){ - return (React.createElement("input", {type: "text", onBlur: this.commit, className: "form-control", defaultValue: this.getDefaultValue(), style: this.getStyle(), onKeyDown: this.onKeyDown})); - } - - - }); - - module.exports = SimpleTextEditor; - - -/***/ }, -/* 16 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - "use strict"; - - var React = __webpack_require__(10); - var PropTypes = React.PropTypes; - var Header = __webpack_require__(30); - var Viewport = __webpack_require__(31); - var ColumnMetrics = __webpack_require__(11); - var DOMMetrics = __webpack_require__(29); - - - var GridScrollMixin = { - - componentDidMount:function() { - this._scrollLeft = this.refs.viewport.getScroll().scrollLeft; - this._onScroll(); - }, - - componentDidUpdate:function() { - this._onScroll(); - }, - - componentWillMount:function() { - this._scrollLeft = undefined; - }, - - componentWillUnmount:function() { - this._scrollLeft = undefined; - }, - - onScroll:function($__0) {var scrollLeft=$__0.scrollLeft; - if (this._scrollLeft !== scrollLeft) { - this._scrollLeft = scrollLeft; - this._onScroll(); - } - }, - - _onScroll:function() { - if (this._scrollLeft !== undefined) { - this.refs.header.setScrollLeft(this._scrollLeft); - this.refs.viewport.setScrollLeft(this._scrollLeft); - } - } - }; - - var Grid = React.createClass({displayName: 'Grid', - mixins: [ - GridScrollMixin, - ColumnMetrics.Mixin, - DOMMetrics.MetricsComputatorMixin - ], - - propTypes: { - rows: PropTypes.oneOfType([PropTypes.array, PropTypes.func]).isRequired, - columns: PropTypes.array.isRequired - }, - - getStyle: function(){ - return{ - overflow: 'hidden', - outline: 0, - position: 'relative', - minHeight: this.props.minHeight - } - }, - - render:function() { - var headerRows = this.props.headerRows || [{ref : 'row'}]; - return ( - React.createElement("div", React.__spread({}, this.props, {style: this.getStyle(), className: "react-grid-Grid"}), - React.createElement(Header, { - ref: "header", - columns: this.state.columns, - onColumnResize: this.onColumnResize, - height: this.props.rowHeight, - totalWidth: this.DOMMetrics.gridWidth(), - headerRows: headerRows} - ), - React.createElement(Viewport, { - ref: "viewport", - width: this.state.columns.width, - rowHeight: this.props.rowHeight, - rowRenderer: this.props.rowRenderer, - cellRenderer: this.props.cellRenderer, - rows: this.props.rows, - selectedRows: this.props.selectedRows, - expandedRows: this.props.expandedRows, - length: this.props.length, - columns: this.state.columns, - totalWidth: this.DOMMetrics.gridWidth(), - onScroll: this.onScroll, - onRows: this.props.onRows, - rowOffsetHeight: this.props.rowOffsetHeight || this.props.rowHeight * headerRows.length} - ) - ) - ); - }, - - getDefaultProps:function() { - return { - rowHeight: 35, - minHeight: 350 - }; - }, - }); - - module.exports = Grid; - - -/***/ }, -/* 17 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var BaseCell = __webpack_require__(3); - var SelectableMixin = __webpack_require__(32); - var EditableMixin = __webpack_require__(33); - var CopyableMixin = __webpack_require__(34); - var DraggableMixin = __webpack_require__(35); - var MixinHelper = __webpack_require__(27); - var KeyboardHandlerMixin = __webpack_require__(9); - var isFunction = __webpack_require__(12); - var PropTypes = React.PropTypes; - var cx = React.addons.classSet; - var cloneWithProps = React.addons.cloneWithProps; - - - - var CellControls = React.createClass({displayName: 'CellControls', - - onClickEdit : function(e){ - e.stopPropagation(); - e.preventDefault(); - this.props.onClickEdit(); - }, - - onShowMore : function(e){ - e.stopPropagation(); - e.preventDefault(); - var newHeight = this.props.column.getExpandedHeight(this.props.value); - this.props.onShowMore(this.props.rowIdx, newHeight); - }, - - onShowLess : function(e){ - e.stopPropagation(); - e.preventDefault(); - this.props.onShowLess(this.props.rowIdx); - }, - - shouldComponentUpdate:function(nextProps, nextState){ - return this.props.height != nextProps.height; - }, - - renderShowMoreButton:function(){ - if(isFunction(this.props.column.getExpandedHeight) && this.props.column.getExpandedHeight(this.props.value) > 0){ - var newHeight = this.props.column.getExpandedHeight(this.props.value); - if(newHeight > this.props.height){ - return React.createElement("button", {type: "button", className: "btn btn-link btn-xs", onClick: this.onShowMore}, "Show More") - }else{ - return React.createElement("button", {type: "button", className: "btn btn-link btn-xs", onClick: this.onShowLess}, "Show Less") - } - }else{ - return null; - } - }, - - render : function(){ - return (React.createElement("div", {className: "pull-right btn-group"}, - this.renderShowMoreButton(), - React.createElement("button", {onClick: this.onClickEdit, type: "button", className: "btn btn-link btn-xs"}, "Edit") - )) - } - - }) - - - var ExcelCell = React.createClass({displayName: 'ExcelCell', - - mixins : [EditableMixin, CopyableMixin, DraggableMixin], - - overrides : { - getCellClass : function(){ - return cx({ - 'selected' : this.isSelected() && !this.isCopied() && !this.isActive(), - 'editing' : this.isActive(), - 'copied' : this.isCopied(), - 'selected-draggable' : this.isSelected() && !this.isActive() && this.canEdit(), - 'active-drag-cell' : this.isActiveDragCell() && this.canEdit(), - 'is-dragged-over-up' : !this.isSelected() && this.isDraggedOver() && this.props.rowIdx < this.props.dragged.rowIdx, - 'is-dragged-over-down' : !this.isSelected() && this.isDraggedOver() && this.props.rowIdx > this.props.dragged.rowIdx, - 'was-dragged-over' : this.wasDraggedOver() && this.canEdit() - }); - } - }, - - isActiveDragCell : function(){ - return (this.isSelected() || this.isDraggedOver()) && !this.isActive(); - }, - - isExpanded : function(){ - var isExpanded = false; - if(isFunction(this.props.column.getExpandedHeight) && this.props.column.getExpandedHeight(this.props.value) > 0){ - var newHeight = this.props.column.getExpandedHeight(this.props.value); - if(this.props.height >= newHeight){ - isExpanded = true; - }else{ - isExpanded = false; - } - } - return isExpanded; - }, - - - shouldComponentUpdate:function(nextProps, nextState) { - return this.props.column.width !== nextProps.column.width - || this.props.value !== nextProps.value - || this.props.height !== nextProps.height - || this.props.rowIdx !== nextProps.rowIdx - || this.isCellSelectionChanging(nextProps) - || this.isDraggedCellChanging(nextProps); - }, - - - render: function() { - return ( - React.createElement(BaseCell, React.__spread({}, - this.props, - {className: this.getCellClass(), - onKeyDown: this.onKeyDown, - onClick: this.onClick, - onDoubleClick: this.onDoubleClick, - formatter: this.getFormatter(), - handleDragStart: this.handleDragStart, - onDragEnter: this.handleDragEnter, - onDragEnd: this.props.handleDragEnd, - cellControls: this.props.column.showCellControls && !this.isActive() ? React.createElement(CellControls, {height: this.props.height, value: this.props.value, rowIdx: this.props.rowIdx, column: this.props.column, onShowMore: this.props.onShowMore, onShowLess: this.props.onShowLess, onClickEdit: this.setActive}) : null, - isExpanded: this.isExpanded()}) - )) - } - - }) - - module.exports = ExcelCell; - - -/***/ }, -/* 18 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var cx = React.addons.classSet; - var BaseRow = __webpack_require__(2); - var ColumnMetrics = __webpack_require__(11); - var ExcelRow = React.createClass({displayName: 'ExcelRow', - - render:function() { - var row = React.addons.update(this.props.row, {$merge : {'select-row' : this.props.isSelected}}); - - return ( - React.createElement(BaseRow, React.__spread({}, - this.props, - {row: row, - height: this.getRowHeight(this.props)})) - ); - }, - - getRowHeight:function(props){ - if(props.expandedRows && props.expandedRows[props.key]){ - return props.expandedRows[props.key]; - }else{ - return props.height; - } - }, - - hasRowHeightChanged:function(props){ - if(props.expandedRows){ - if(typeof props.expandedRows[props.key] !== 'undefined'){ - return this.props.height !== props.expandedRows[props.key] - }else{ - return false; - } - }else{ - return false; - } - }, - - shouldComponentUpdate:function(nextProps) { - return !(ColumnMetrics.sameColumns(this.props.columns, nextProps.columns, ColumnMetrics.sameColumn)) || - this.doesRowContainSelectedCell() || - this.doesRowContainSelectedCell(nextProps) || - this.willRowBeDraggedOver(nextProps) || - this.hasRowBeenCopied() || - nextProps.row !== this.props.row || - this.props.isSelected !== nextProps.isSelected || - this.hasRowHeightChanged(nextProps); - }, - - doesRowContainSelectedCell:function(propsToCheck){ - var props = propsToCheck || this.props; - var cell = cell || props.cellRenderer; - if(cell.props && cell.props.selected && cell.props.selected.rowIdx === props.idx){ - return true; - }else{ - return false; - } - }, - - willRowBeDraggedOver:function(props){ - if(props.cellRenderer.props){ - var dragged = props.cellRenderer.props.dragged; - return dragged != null && (dragged.rowIdx || dragged.complete === true); - }else{ - return false; - } - - }, - - hasRowBeenCopied:function(){ - if(this.props.cellRenderer.props){ - var cell = this.props.cellRenderer; - return cell.props.copied != null && cell.props.copied.rowIdx === this.props.idx; - }else{ - return false; - } - - }, - - setScrollLeft:function(scrollLeft) { - for (var i = 0, len = this.props.columns.length; i < len; i++) { - if (this.props.columns[i].locked) { - this.refs[i].setScrollLeft(scrollLeft); - } - } - } - - - }); - - module.exports = ExcelRow; - - -/***/ }, -/* 19 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * Copyright 2013-2014 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @providesModule merge - */ - - "use strict"; - - /** - * Shallow merges two structures into a return value, without mutating either. - * - * @param {?object} one Optional object with properties to merge from. - * @param {?object} two Optional object with properties to merge from. - * @return {object} The shallow extension of one by two. - */ - var merge = function(one, two) { - var result = {}; - if (one != null) { - Object.assign(result, one); - } - if (two != null) { - Object.assign(result, two); - } - return result; - }; - - function mergeFallback(obj1,obj2){ - var obj3 = {}; - for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; } - for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; } - return obj3; - } - - module.exports = Object.assign ? merge : mergeFallback; - - -/***/ }, -/* 20 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - "use strict"; - - var SelectableGridMixin = { - - getDefaultProps:function() { - return { - enableCellSelect : false, - }; - }, - - getColumns : function(){ - return this.props.columns - }, - - getInitialState: function() { - if(this.props.enableCellSelect){ - return {selected: {rowIdx: 0, idx: 0}}; - }else{ - return {selected: {rowIdx: -1, idx: -1}}; - } - }, - - onSelect: function(selected) { - if(this.props.enableCellSelect){ - var idx = selected.idx; - var rowIdx = selected.rowIdx; - if ( - idx >= 0 - && rowIdx >= 0 - && idx < this.getColumns().length - && rowIdx < this.props.rows.length - ) { - if(this.props.onSelect){ - this.props.onSelect({selected: selected}); - } - this.setState({selected: selected}); - } - } - } - } - - module.exports = SelectableGridMixin; - - -/***/ }, -/* 21 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - "use strict"; - - var React = __webpack_require__(10); - var PropTypes = React.PropTypes; - var MixinHelper = __webpack_require__(27); - var SelectableGridMixin = __webpack_require__(20); - - MixinHelper.addAlias('SelectableGridMixin'); - - var DraggableGridMixin = { - - mixinDependencies : ['SelectableGridMixin'], - - propTypes : { - onCellsDragged : React.PropTypes.func - }, - - getInitialState: function() { - return {dragged : null}; - }, - - handleDragStart:function(dragged){ - var idx = dragged.idx; - var rowIdx = dragged.rowIdx; - if ( - idx >= 0 - && rowIdx >= 0 - && idx < this.getColumns().length - && rowIdx < this.props.rows.length - ) { - this.setState({dragged: dragged}); - } - }, - - handleDragEnter:function(row){ - var selected = this.state.selected; - var dragged = this.state.dragged; - dragged.overRowIdx = row; - this.setState({dragged : dragged}); - }, - - handleDragEnd:function(){ - var fromRow, toRow; - var selected = this.state.selected; - var dragged = this.state.dragged; - var cellKey = this.getColumns()[this.state.selected.idx].key; - fromRow = selected.rowIdx < dragged.overRowIdx ? selected.rowIdx : dragged.overRowIdx; - toRow = selected.rowIdx > dragged.overRowIdx ? selected.rowIdx : dragged.overRowIdx; - this.props.onCellsDragged({cellKey: cellKey , fromRow: fromRow, toRow : toRow, value : dragged.copiedText}); - this.setState({dragged : {complete : true}}); - }, - - handleTerminateDrag:function(){ - this.setState({dragged: null}); - } - } - - - module.exports = DraggableGridMixin; - - -/***/ }, -/* 22 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - "use strict"; - - var React = __webpack_require__(10); - var PropTypes = React.PropTypes; - - var CopyPasteGridMixin = { - - propTypes : { - onCellCopyPaste : React.PropTypes.func - }, - - getInitialState: function() { - return {copied : null}; - }, - - - handleCopy:function(args){ - var textToCopy = args.value; - var selected = this.state.selected; - var copied = {idx : selected.idx, rowIdx : selected.rowIdx}; - this.setState({textToCopy:textToCopy, copied : copied}); - }, - - handlePaste:function(){ - var selected = this.state.selected; - var cellKey = this.getColumns()[selected.idx].key; - this.props.onCellCopyPaste({cellKey: cellKey , rowIdx: selected.rowIdx, value : this.state.textToCopy, fromRow : this.state.copied.rowIdx, toRow : selected.rowIdx}); - this.setState({copied : null}); - } - } - - module.exports = CopyPasteGridMixin; - - -/***/ }, -/* 23 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - "use strict"; - - var React = __webpack_require__(10); - var PropTypes = React.PropTypes; - var merge = __webpack_require__(19); - - var EditableGridMixin = { - - propTypes : { - onRowUpdated : React.PropTypes.func - }, - - onCellCommit:function(commit){ - var selected = this.state.selected; - selected.active = false; - if(commit.keyCode === 'Tab'){ - selected.idx += 1; - } - this.setState({selected : selected}); - this.props.onRowUpdate(commit); - }, - - onSetActive:function(activeCell) { - var selected = merge(this.state.selected, activeCell); - this.setState({selected: selected}); - } - - }; - - - module.exports = EditableGridMixin; - - -/***/ }, -/* 24 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - "use strict"; - - var React = __webpack_require__(10); - var PropTypes = React.PropTypes; - var SortableHeaderCell = __webpack_require__(36); - var shallowCloneObject = __webpack_require__(28); - - var DEFINE_SORT = { - ASC : 'ASC', - DESC : 'DESC' - } - Object.freeze(DEFINE_SORT); - - var SortableGridMixin = { - - getInitialState: function() { - return {sortDirection: null, sortColumn: null}; - }, - - getDecoratedColumns: function(columns) { - return this.props.columns.map(function(column) { - column = shallowCloneObject(column); - if (column.sortable) { - column.headerRenderer = React.createElement(SortableHeaderCell, null); - column.sortBy = this.sortBy; - if (this.state.sortColumn === column.key) { - column.sorted = this.state.sortDirection; - }else{ - column.sorted = DEFINE_SORT.NONE; - } - } - return column - }, this); - }, - - sortBy: function(column, direction) { - switch(direction){ - case null: - case undefined: - direction = DEFINE_SORT.ASC; - break; - case DEFINE_SORT.ASC: - direction = DEFINE_SORT.DESC; - break; - case DEFINE_SORT.DESC: - direction = null; - break; - } - this.setState({sortDirection: direction, sortColumn: column.key}); - }, - - sortRows: function(rows) { - //feels naughty - rows = [].concat(rows); - var sortColumn = this.state.sortColumn; - var sortDirection = this.state.sortDirection; - if(sortColumn != null && sortDirection !== null){ - return rows.sort(function(row1, row2){ - var k1 = row1[sortColumn], k2 = row2[sortColumn]; - if(sortDirection === DEFINE_SORT.ASC){ - return (k1 > k2) ? 1 : ( (k2 > k1) ? -1 : 0 ); - }else if(sortDirection === DEFINE_SORT.DESC){ - return (k1 > k2) ? -1 : ( (k2 > k1) ? 1 : 0 ); - } - }); - }else{ - return rows; - } - - } - - } - - module.exports = SortableGridMixin; - - -/***/ }, -/* 25 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - "use strict"; - - var React = __webpack_require__(10); - var PropTypes = React.PropTypes; - var FilterableHeaderCell = __webpack_require__(37); - - var FilterableGridMixin = { - - getInitialState : function(){ - return {canFilter : false, columnFilters : {}}; - }, - - filterRows:function(){ - var rows = this.props.rows; - if(this.state.sortColumn){ - rows = this.sortRows(rows); - } - - if(this.hasFilters()){ - rows = rows.map(function(r, i) {r.key = i;return r;}).filter(this.isRowDisplayed); - if(this.props.onFilter){ - this.props.onFilter(rows); - } - } - return rows; - }, - - hasFilters:function(){ - var hasFilters = false; - Object.keys(this.state.columnFilters).every(function(key){ - var filter = this.state.columnFilters[key]; - if(filter != null && filter != undefined && filter != ''){ - hasFilters = true; - return false; - } - return true; - }, this); - return hasFilters; - }, - - isRowDisplayed:function(row){ - var isRowDisplayed = null; - Object.keys(this.state.columnFilters).every(function(key){ - var filter = this.state.columnFilters[key].toLowerCase(); - var cellValue = row[key].toString().toLowerCase(); - if(filter != null && filter != undefined && filter != '' && typeof cellValue === 'string'){ - if(cellValue.indexOf(filter) > -1){ - isRowDisplayed = true; - }else{ - isRowDisplayed = false; - return false; - } - } - return true; - }, this); - return isRowDisplayed == null ? false : isRowDisplayed; - }, - - onToggleFilter:function(){ - this.setState({canFilter : !this.state.canFilter}); - }, - - handleAddFilter:function(filter){ - var columnFilters = this.state.columnFilters; - columnFilters[filter.columnKey] = filter.filterTerm; - this.setState({columnFilters : columnFilters, selected : null}); - }, - - getHeaderRows:function(){ - var rows = [{ref:"row", height: this.props.rowHeight}]; - if(this.state.canFilter === true){ - rows.push({ref:"filterRow", headerCellRenderer : React.createElement(FilterableHeaderCell, {onChange: this.handleAddFilter}), height : 45}); - } - return rows; - }, - - getRowOffsetHeight:function(){ - var offsetHeight = 0; - this.getHeaderRows().forEach(function(row) {return offsetHeight += row.height;} ); - return offsetHeight; - } - - } - - module.exports = FilterableGridMixin; - - -/***/ }, -/* 26 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var cx = React.addons.classSet; - - var CheckBoxEditor = React.createClass({displayName: 'CheckBoxEditor', - - - PropTypes : { - value : React.PropTypes.bool.isRequired - }, - - render:function(){ - return (React.createElement("input", {className: "react-grid-CheckBox", type: "checkbox", checked: this.props.value, onChange: this.handleChange})); - }, - - handleChange:function(e){ - this.props.column.onRowSelect(this.props.rowIdx) - }, - - shouldComponentUpdate:function(nextProps, nextState){ - return this.props.value != nextProps.value; - } - - }); - - module.exports = CheckBoxEditor; - - -/***/ }, -/* 27 */ -/***/ function(module, exports, __webpack_require__) { - - - "use strict"; - - var keyMirror = __webpack_require__(42); - var isFunction = __webpack_require__(12) - var React = __webpack_require__(10); - if (!Object.assign) { - Object.assign = __webpack_require__(38); - } - - /** - * Policies that describe methods in Adazzle React Mixins - * Any methods that do not confirm to one of these policies will be treated as a custom method - * All custom methods will be wrapped to potentially allow override/extension as defined on a component - */ - var SpecPolicy = keyMirror({ - /** - * These methods are React Lifecycle methods and should be mixed into any components - * according to their default behviour as specified in React srcrary - */ - DEFINE_LIFE_CYCLE_METHOD : null, - /** - * These methods may be defined only once by the class specification or mixin. - */ - DEFINE_ONCE: null, - /** - * These methods may be defined by both the class specification and mixins. - * Subsequent definitions will be chained. These methods must return void. - */ - DEFINE_MANY: null, - /** - * These methods are overriding the base ReactCompositeComponent class. - */ - OVERRIDE_BASE: null, - /** - * These methods are similar to DEFINE_MANY, except we assume they return - * objects. We try to merge the keys of the return values of all the mixed in - * functions. If there is a key conflict we throw. - */ - DEFINE_MANY_MERGED: null - - }); - - var MixinInterface = { - - - getDefaultProps : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD, - propTypes : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD, - getInitialState : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD, - statics : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD, - displayName : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD, - componentWillMount : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD, - componentWillReceiveProps : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD, - shouldComponentUpdate : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD, - componentWillUpdate : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD, - componentDidUpdate : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD, - componentWillUnmount : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD - } - - var MixinAliasCache = {}; - - - var Mixin = function(base, dependsOn){ - this.base = base; - this.dependsOn = dependsOn; - }; - - var Dependency = function(dependsOn){ - this.assignTo = function(base){ - return new Mixin(base, dependsOn); - } - }; - - - var wrapEachMethodInObject = function(clone, results){ - //loop over each property and mix according to its spec policy - Object.keys(clone).forEach(function(key){ - if(mixinUtils.isCustomProperty(key)){ - //overwrite each function of object with custom functionlity - if(isFunction(clone[key])){ - clone[key] = mixinUtils.wrapCustomMethod(key, clone[key]); - } - }else{ - - switch(MixinInterface[key]){ - case SpecPolicy.DEFINE_LIFE_CYCLE_METHOD: - var lifeCycleObj = {}; - lifeCycleObj[key] = clone[key]; - //add this to mixin result - will be treated as standard - results.push(lifeCycleObj); - break; - case SpecPolicy.DEFINE_MANY_MERGED: - //TODO imlplement handlers for other spec policies - break; - } - - delete clone[key]; - } - - }, this); - } - - - var MixinHelper = { - - /** - * Mix properties and methods from multiple objects, without mutating any of them - * - * @param {array} array of all mixins to be merged - * @return {array} A new array of mixins, the first object being an object of containing all custom methods wrapped - * Subsequent object in array will be any extracted lifecycle methods which should be treated as standard - */ - mix : function(mixins){ - - var results = []; - var primary = {}; - - var dependencies = mixinUtils.getUniqueDependencies(mixins); - for (var d in dependencies){ - Object.assign(primary, MixinAliasCache[dependencies[d]]); - } - wrapEachMethodInObject(primary, results); - - mixins.forEach(function(obj){ - //clone the object so that original methods are not overwritten - var clone = {}; - //check if mixin was created using Mixin Helper - //If it is then merge the properties object - if(obj instanceof Mixin){ - Object.assign(clone, obj.base); - }else{ - Object.assign(clone, obj); - } - - wrapEachMethodInObject(clone, results); - - Object.assign(primary, clone); - }, this); - - results.push(primary); - - - return results; - }, - - - createDependency : function(deps){ - var dependencyList = []; - for (var d in deps){ - if(deps[d] instanceof Mixin){ - this.addAlias(d, deps[d].base) - }else{ - this.addAlias(d, deps[d]) - } - dependencyList.push(d); - } - var uniqueDependencyList = dependencyList.filter(function(value, index, self) { - return self.indexOf(value) === index; - }); - return new Dependency(uniqueDependencyList); - }, - - addAlias : function(key, object){ - MixinAliasCache[key] = object; - } - - }; - - // idea borrowed from https://github.com/jhudson8/react-mixin-manager/blob/master/react-mixin-manager.js - var _createClass = React.createClass; - React.createClass = function(spec) { - if (spec.mixins) { - spec.mixins = MixinHelper.mix(spec.mixins); - } - return _createClass.apply(React, arguments); - }; - - - var mixinUtils = { - - isCustomProperty : function(key){ - return (!MixinInterface[key]); - }, - - wrapCustomMethod : function(methodName, old){ - return function(){ - //call overridden method if exists - if(mixinUtils.isMethodOverridden.call(this, methodName)){ - return mixinUtils.callOverriddenMethod.call(this, methodName, arguments); - }else{ - //call the original mixin method - return old.apply(this, arguments); - } - } - }, - - checkMethodExtendedAndCall : function(methodName, args){ - if(this.extended && (typeof this.extended[methodName] === 'function')){ - return this.extended[methodName].call(this, args); - } - }, - - checkMethodImplementedAndCall: function(methodName, args){ - if(this.implemented && (typeof this.implemented[methodName] === 'function')){ - return this.implemented[methodName].call(this, args); - } - }, - - isMethodOverridden: function(methodName){ - return this.overrides && (typeof this.overrides[methodName] === 'function'); - }, - - callOverriddenMethod: function(methodName, args){ - return this.overrides[methodName].call(this, args); - }, - - getUniqueDependencies : function(mixins){ - var deps = []; - mixins.forEach(function(m){ - if(m instanceof Mixin){ - deps = deps.concat(m.dependsOn); - } - }, this); - return deps.filter(function(value, index, self) { - return self.indexOf(value) === index; - });; - } - } - module.exports = MixinHelper; - - -/***/ }, -/* 28 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - function shallowCloneObject(obj) { - var result = {}; - for (var k in obj) { - if (obj.hasOwnProperty(k)) { - result[k] = obj[k]; - } - } - return result; - } - - module.exports = shallowCloneObject; - - -/***/ }, -/* 29 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var emptyFunction = __webpack_require__(40); - var shallowCloneObject = __webpack_require__(28); - var invariant = __webpack_require__(41); - - var contextTypes = { - metricsComputator: React.PropTypes.object - }; - - var MetricsComputatorMixin = { - - childContextTypes: contextTypes, - - getChildContext:function() { - return {metricsComputator: this}; - }, - - getMetricImpl:function(name) { - return this._DOMMetrics.metrics[name].value; - }, - - registerMetricsImpl:function(component, metrics) { - var getters = {}; - var s = this._DOMMetrics; - - for (var name in metrics) { - invariant( - s.metrics[name] === undefined, - 'DOM metric ' + name + ' is already defined' - ); - s.metrics[name] = {component:component, computator: metrics[name].bind(component)}; - getters[name] = this.getMetricImpl.bind(null, name); - } - - if (s.components.indexOf(component) === -1) { - s.components.push(component); - } - - return getters; - }, - - unregisterMetricsFor:function(component) { - var s = this._DOMMetrics; - var idx = s.components.indexOf(component); - - if (idx > -1) { - s.components.splice(idx, 1); - - var name; - var metricsToDelete = {}; - - for (name in s.metrics) { - if (s.metrics[name].component === component) { - metricsToDelete[name] = true; - } - } - - for (name in metricsToDelete) { - delete s.metrics[name]; - } - } - }, - - updateMetrics:function() { - var s = this._DOMMetrics; - - var needUpdate = false; - - for (var name in s.metrics) { - var newMetric = s.metrics[name].computator(); - if (newMetric !== s.metrics[name].value) { - needUpdate = true; - } - s.metrics[name].value = newMetric; - } - - if (needUpdate) { - for (var i = 0, len = s.components.length; i < len; i++) { - if (s.components[i].metricsUpdated) { - s.components[i].metricsUpdated(); - } - } - } - }, - - componentWillMount:function() { - this._DOMMetrics = { - metrics: {}, - components: [] - }; - }, - - componentDidMount:function() { - if(window.addEventListener){ - window.addEventListener('resize', this.updateMetrics); - }else{ - window.attachEvent('resize', this.updateMetrics); - } - this.updateMetrics(); - }, - - componentWillUnmount:function() { - window.removeEventListener('resize', this.updateMetrics); - } - - }; - - var MetricsMixin = { - - contextTypes: contextTypes, - - componentWillMount:function() { - if (this.DOMMetrics) { - this._DOMMetricsDefs = shallowCloneObject(this.DOMMetrics); - - this.DOMMetrics = {}; - for (var name in this._DOMMetricsDefs) { - this.DOMMetrics[name] = emptyFunction; - } - } - }, - - componentDidMount:function() { - if (this.DOMMetrics) { - this.DOMMetrics = this.registerMetrics(this._DOMMetricsDefs); - } - }, - - componentWillUnmount:function() { - if (!this.registerMetricsImpl) { - return this.context.metricsComputator.unregisterMetricsFor(this); - } - if (this.hasOwnProperty('DOMMetrics')) { - delete this.DOMMetrics; - } - }, - - registerMetrics:function(metrics) { - if (this.registerMetricsImpl) { - return this.registerMetricsImpl(this, metrics); - } else { - return this.context.metricsComputator.registerMetricsImpl(this, metrics); - } - }, - - getMetric:function(name) { - if (this.getMetricImpl) { - return this.getMetricImpl(name); - } else { - return this.context.metricsComputator.getMetricImpl(name); - } - } - }; - - module.exports = { - MetricsComputatorMixin:MetricsComputatorMixin, - MetricsMixin:MetricsMixin - }; - - -/***/ }, -/* 30 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - "use strict"; - - var React = __webpack_require__(10); - var cx = React.addons.classSet; - var shallowCloneObject = __webpack_require__(28); - var ColumnMetrics = __webpack_require__(11); - var HeaderRow = __webpack_require__(45); - var ColumnMetrics = __webpack_require__(11); - - var Header = React.createClass({displayName: 'Header', - - propTypes: { - columns: React.PropTypes.object.isRequired, - totalWidth: React.PropTypes.number, - height: React.PropTypes.number.isRequired, - headerRows : React.PropTypes.array.isRequired - }, - - render:function() { - var state = this.state.resizing || this.props; - - var className = cx({ - 'react-grid-Header': true, - 'react-grid-Header--resizing': !!this.state.resizing - }); - var headerRows = this.getHeaderRows(); - - return ( - - React.createElement("div", React.__spread({}, this.props, {style: this.getStyle(), className: className}), - headerRows - ) - ); - }, - - shouldComponentUpdate : function(nextProps, nextState){ - return !(ColumnMetrics.sameColumns(this.props.columns.columns, nextProps.columns.columns, ColumnMetrics.sameColumn)) - || this.props.totalWidth != nextProps.totalWidth - || (this.props.headerRows.length != nextProps.headerRows.length) - || (this.state.resizing != nextState.resizing) - }, - - getHeaderRows:function(){ - var state = this.state.resizing || this.props; - var headerRows = []; - this.props.headerRows.forEach((function(row, index){ - var headerRowStyle = { - position: 'absolute', - top: this.props.height * index, - left: 0, - width: this.props.totalWidth - }; - - headerRows.push(React.createElement(HeaderRow, { - key: row.ref, - ref: row.ref, - style: headerRowStyle, - onColumnResize: this.onColumnResize, - onColumnResizeEnd: this.onColumnResizeEnd, - width: state.columns.width, - height: row.height || this.props.height, - columns: state.columns.columns, - resizing: state.column, - headerCellRenderer: row.headerCellRenderer} - )) - }).bind(this)); - return headerRows; - }, - - getInitialState:function() { - return {resizing: null}; - }, - - componentWillReceiveProps:function() { - this.setState({resizing: null}); - }, - - onColumnResize:function(column, width) { - var state = this.state.resizing || this.props; - - var pos = this.getColumnPosition(column); - - if (pos !== null) { - var resizing = { - columns: shallowCloneObject(state.columns) - }; - resizing.columns = ColumnMetrics.resizeColumn( - resizing.columns, pos, width); - - // we don't want to influence scrollLeft while resizing - if (resizing.columns.width < state.columns.width) { - resizing.columns.width = state.columns.width; - } - - resizing.column = resizing.columns.columns[pos]; - this.setState({resizing:resizing}); - } - }, - - getColumnPosition:function(column) { - var state = this.state.resizing || this.props; - var pos = state.columns.columns.indexOf(column); - return pos === -1 ? null : pos; - }, - - onColumnResizeEnd:function(column, width) { - var pos = this.getColumnPosition(column); - if (pos !== null && this.props.onColumnResize) { - this.props.onColumnResize(pos, width || column.width); - } - }, - - setScrollLeft:function(scrollLeft) { - var node = this.refs.row.getDOMNode(); - node.scrollLeft = scrollLeft; - this.refs.row.setScrollLeft(scrollLeft); - }, - - getStyle:function() { - return { - position: 'relative', - height: this.props.height - }; - }, - }); - - - module.exports = Header; - - -/***/ }, -/* 31 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var getWindowSize = __webpack_require__(43); - var DOMMetrics = __webpack_require__(29); - var Canvas = __webpack_require__(44); - - var min = Math.min; - var max = Math.max; - var floor = Math.floor; - var ceil = Math.ceil; - - var ViewportScroll = { - mixins: [DOMMetrics.MetricsMixin], - - DOMMetrics: { - viewportHeight:function() { - return this.getDOMNode().offsetHeight; - } - }, - - propTypes: { - rowHeight: React.PropTypes.number, - length: React.PropTypes.number.isRequired - }, - - getDefaultProps:function() { - return { - rowHeight: 30 - }; - }, - - getInitialState:function() { - return this.getGridState(this.props); - }, - - getGridState:function(props) { - var height = this.state && this.state.height ? - this.state.height : - getWindowSize().height; - var renderedRowsCount = ceil(height / props.rowHeight); - return { - displayStart: 0, - displayEnd: renderedRowsCount * 2, - height: height, - scrollTop: 0, - scrollLeft: 0 - }; - }, - - updateScroll:function(scrollTop, scrollLeft, height, rowHeight, length) { - var renderedRowsCount = ceil(height / rowHeight); - - var visibleStart = floor(scrollTop / rowHeight); - - var visibleEnd = min( - visibleStart + renderedRowsCount, - length); - - var displayStart = max( - 0, - visibleStart - renderedRowsCount * 2); - - var displayEnd = min( - visibleStart + renderedRowsCount * 2, - length); - - var nextScrollState = { - visibleStart:visibleStart, - visibleEnd:visibleEnd, - displayStart:displayStart, - displayEnd:displayEnd, - height:height, - scrollTop:scrollTop, - scrollLeft:scrollLeft - }; - - this.setState(nextScrollState); - }, - - metricsUpdated:function() { - var height = this.DOMMetrics.viewportHeight(); - if (height) { - this.updateScroll( - this.state.scrollTop, - this.state.scrollLeft, - height, - this.props.rowHeight, - this.props.length - ); - } - }, - - componentWillReceiveProps:function(nextProps) { - if (this.props.rowHeight !== nextProps.rowHeight) { - this.setState(this.getGridState(nextProps)); - } else if (this.props.length !== nextProps.length) { - this.updateScroll( - this.state.scrollTop, - this.state.scrollLeft, - this.state.height, - nextProps.rowHeight, - nextProps.length - ); - } - } - }; - - var Viewport = React.createClass({displayName: 'Viewport', - mixins: [ViewportScroll], - - render:function() { - var style = { - padding: 0, - bottom: 0, - left: 0, - right: 0, - overflow: 'hidden', - position: 'absolute', - top: this.props.rowOffsetHeight - }; - return ( - React.createElement("div", { - className: "react-grid-Viewport", - style: style}, - React.createElement(Canvas, { - ref: "canvas", - totalWidth: this.props.totalWidth, - width: this.props.columns.width, - rows: this.props.rows, - selectedRows: this.props.selectedRows, - expandedRows: this.props.expandedRows, - columns: this.props.columns.columns, - cellRenderer: this.props.cellRenderer, - rowRenderer: this.props.rowRenderer, - - visibleStart: this.state.visibleStart, - visibleEnd: this.state.visibleEnd, - displayStart: this.state.displayStart, - displayEnd: this.state.displayEnd, - - length: this.props.length, - height: this.state.height, - rowHeight: this.props.rowHeight, - onScroll: this.onScroll, - onRows: this.props.onRows} - ) - ) - ); - }, - - getScroll:function() { - return this.refs.canvas.getScroll(); - }, - - onScroll:function($__0 ) {var scrollTop=$__0.scrollTop,scrollLeft=$__0.scrollLeft; - this.updateScroll( - scrollTop, scrollLeft, - this.state.height, - this.props.rowHeight, - this.props.length - ); - - if (this.props.onScroll) { - this.props.onScroll({scrollTop:scrollTop, scrollLeft:scrollLeft}); - } - }, - - setScrollLeft:function(scrollLeft) { - this.refs.canvas.setScrollLeft(scrollLeft); - } - }); - - module.exports = Viewport; - - -/***/ }, -/* 32 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var cx = React.addons.classSet; - var cloneWithProps = React.addons.cloneWithProps; - var KeyboardHandlerMixin = __webpack_require__(9); - var MixinHelper = __webpack_require__(27); - - var SelectableMixin = MixinHelper.createDependency({KeyboardHandlerMixin : KeyboardHandlerMixin}).assignTo({ - - getDefaultProps : function(){ - return { - tabIndex : -1, - ref : "cell" - } - }, - - isSelected: function() { - return ( - this.props.selected - && this.props.selected.rowIdx === this.props.rowIdx - && this.props.selected.idx === this.props.idx - ); - }, - - onClick: function() { - var rowIdx = this.props.rowIdx; - var idx = this.props.idx; - this.props.onClick({rowIdx: rowIdx, idx: idx}); - }, - - onPressArrowUp:function(e){ - this.moveSelectedCell(e, -1, 0); - }, - - onPressArrowDown:function(e){ - this.moveSelectedCell(e, 1, 0); - }, - - onPressArrowLeft:function(e){ - this.moveSelectedCell(e, 0, -1); - }, - - onPressArrowRight:function(e){ - this.moveSelectedCell(e, 0, 1); - }, - - onPressTab:function(e){ - this.moveSelectedCell(e, 0, 1); - }, - - moveSelectedCell:function(e, rowDelta, cellDelta){ - e.stopPropagation(); - e.preventDefault(); - var rowIdx = this.props.rowIdx + rowDelta; - var idx = this.props.idx + cellDelta; - this.props.onSelect({idx: idx, rowIdx: rowIdx}); - }, - - setScrollLeft: function(scrollLeft) { - this.refs.row.setScrollLeft(scrollLeft); - }, - - componentDidMount: function() { - this.checkFocus(); - }, - - componentDidUpdate: function() { - this.checkFocus(); - }, - - isCellSelectionChanging:function(nextProps){ - if(this.props.selected && nextProps.selected){ - return this.props.idx === nextProps.selected.idx || this.props.idx === this.props.selected.idx; - }else{ - return true; - } - }, - - checkFocus: function() { - if (this.isSelected()) { - this.getDOMNode().focus(); - } - } - }) - - - - module.exports = SelectableMixin; - - -/***/ }, -/* 33 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var cx = React.addons.classSet; - var cloneWithProps = React.addons.cloneWithProps; - var SimpleTextEditor = __webpack_require__(15); - var PropTypes = React.PropTypes; - var MixinHelper = __webpack_require__(27); - var SelectableMixin = __webpack_require__(32); - var KeyboardHandlerMixin = __webpack_require__(9); - - var EditableMixin = MixinHelper.createDependency({ - - KeyboardHandlerMixin : KeyboardHandlerMixin, - - SelectableMixin : SelectableMixin - - }).assignTo({ - - propTypes : { - onCommit : PropTypes.func.isRequired - }, - - canEdit:function(){ - return (this.props.column.editor != null) || this.props.column.editable; - }, - - - getEditor:function(){ - - var editorProps = {height : this.props.height, onPressEscape : this.onPressEscape, onCommit : this.onCommit, initialKeyCode : this.props.selected.initialKeyCode, editorRowMetaData : this.getEditorRowMetaData()}; - var customEditor = this.props.column.editor; - if(customEditor && React.isValidElement(customEditor)){ - //return custom column editor or SimpleEditor if none specified - return cloneWithProps(customEditor, editorProps); - }else{ - return cloneWithProps(SimpleTextEditor(), editorProps); - } - }, - - getEditorRowMetaData:function(){ - //clone row data so editor cannot actually change this - var columnName = this.props.column.ItemId; - //convention based method to get corresponding Id or Name of any Name or Id property - if(typeof this.props.column.getEditorRowMetaData === 'function'){ - return this.props.column.getEditorRowMetaData(this.props.rowData); - } - }, - - getFormatter:function(){ - var col = this.props.column; - if(this.isActive()){ - return this.getEditor(); - }else{ - return this.props.column.formatter; - } - }, - - onCommit:function(commit){ - var rowIdx = this.props.rowIdx; - var idx = this.props.idx; - var cellKey = this.props.column.key; - this.props.onCommit({cellKey: cellKey, rowIdx: this.props.filterRowIdx || rowIdx, updated : commit.updated, keyCode : commit.key}); - }, - - checkFocus: function() { - if (this.isSelected() && !this.isActive()) { - this.getDOMNode().focus(); - } - }, - - onClick:function() { - if(!this.isActive()){ - var rowIdx = this.props.rowIdx; - var idx = this.props.idx; - this.props.onClick({rowIdx: rowIdx, idx: idx}); - } - - }, - - onDoubleClick:function() { - var rowIdx = this.props.rowIdx; - var idx = this.props.idx; - this.props.onClick({rowIdx: rowIdx, idx: idx, active : this.canEdit()}); - }, - - setActive:function(keyPressed){ - var rowIdx = this.props.rowIdx; - var idx = this.props.idx; - if(this.props.column.key === 'select-row' && this.props.column.onRowSelect){ - this.props.column.onRowSelect(rowIdx); - } - else if(this.canEdit() && !this.isActive()){ - this.props.onSetActive({idx: idx, rowIdx: rowIdx, active : true, initialKeyCode : keyPressed}); - } - }, - - setInactive:function(){ - if(this.canEdit() && this.isActive()){ - var rowIdx = this.props.rowIdx; - var idx = this.props.idx; - this.props.onSetActive({idx: idx, rowIdx: rowIdx, active : false}); - } - }, - - isActive:function(){ - return this.isSelected() && this.props.selected.active === true; - }, - - onPressEnter:function(e){ - this.setActive(e.key); - }, - - onPressDelete:function(e){ - this.setActive(e.key); - }, - - onPressEscape:function(e){ - this.setInactive(e.key); - }, - - onPressBackspace:function(e){ - this.setActive(e.key); - }, - - onPressChar:function(e){ - if(this.isKeyPrintable(e.keyCode)){ - this.setActive(e.keyCode); - } - } - }); - - - - module.exports = EditableMixin; - - -/***/ }, -/* 34 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var cx = React.addons.classSet; - var cloneWithProps = React.addons.cloneWithProps; - var PropTypes = React.PropTypes; - var SimpleTextEditor = __webpack_require__(15); - var MixinHelper = __webpack_require__(27); - var SelectableMixin = __webpack_require__(32); - var KeyboardHandlerMixin = __webpack_require__(9); - - var CopyableMixin = MixinHelper.createDependency({ - - KeyboardHandlerMixin : KeyboardHandlerMixin, - - SelectableMixin : SelectableMixin - - }).assignTo({ - - getCellClass : function(){ - return cx({ - 'selected' : this.isSelected() && !this.isCopied(), - 'copied' : this.isCopied() - }) - }, - - KeyCode_c : '99', - - KeyCode_C : '67', - - KeyCode_V : '86', - - KeyCode_v : '118', - - propTypes : { - handleCopy : React.PropTypes.func.isRequired, - handlePaste : React.PropTypes.func.isRequired - }, - - isCopied : function(){ - return ( - this.props.copied - && this.props.copied.rowIdx === this.props.rowIdx - && this.props.copied.idx === this.props.idx - ); - }, - - onPressKeyWithCtrl:function(e){ - if(this.canEdit()){ - if(e.keyCode == this.KeyCode_c || e.keyCode == this.KeyCode_C){ - this.props.handleCopy({value : this.props.value}); - }else if(e.keyCode == this.KeyCode_v || e.keyCode == this.KeyCode_V){ - this.props.handlePaste({value : this.props.value}); - } - } - } - }); - - - - module.exports = CopyableMixin; - - -/***/ }, -/* 35 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var cx = React.addons.classSet; - var cloneWithProps = React.addons.cloneWithProps; - var PropTypes = React.PropTypes; - var MixinHelper = __webpack_require__(27); - var SelectableMixin = __webpack_require__(32); - var KeyboardHandlerMixin = __webpack_require__(9); - - var DraggableMixin = MixinHelper.createDependency({ - - KeyboardHandlerMixin : KeyboardHandlerMixin, - - SelectableMixin : SelectableMixin - - }).assignTo({ - - getCellClass : function(){ - return cx({ - 'selected-draggable' : this.isSelected(), - 'active-drag-cell' : this.isSelected() || this.isDraggedOver(), - 'is-dragged-over-up' : !this.isSelected() && this.isDraggedOver() && this.props.rowIdx < this.props.dragged.rowIdx, - 'is-dragged-over-down' : !this.isSelected() && this.isDraggedOver() && this.props.rowIdx > this.props.dragged.rowIdx, - 'was-dragged-over' : this.wasDraggedOver() - }); - }, - - getDefaultProps : function(){ - return { - handleDragStart: this.handleDragStart, - onDragEnter: this.handleDragEnter, - onDragEnd: this.handleDragEnd - } - }, - - propTypes : { - handleDragEnter : React.PropTypes.func.isRequired, - handleDragStart : React.PropTypes.func.isRequired, - handleDragEnd : React.PropTypes.func.isRequired, - handleTerminateDrag : React.PropTypes.func.isRequired - }, - - isDraggedOver:function(){ - - return ( - this.props.dragged && - this.props.dragged.overRowIdx === this.props.rowIdx - && this.props.dragged.idx === this.props.idx - ) - }, - - wasDraggedOver:function(){ - return ( - this.props.dragged - && ((this.props.dragged.overRowIdx < this.props.rowIdx && this.props.rowIdx < this.props.dragged.rowIdx) - || (this.props.dragged.overRowIdx > this.props.rowIdx && this.props.rowIdx > this.props.dragged.rowIdx)) - && this.props.dragged.idx === this.props.idx - ); - }, - - handleDragStart:function(e){ - var rowIdx = this.props.rowIdx; - var idx = this.props.idx; - this.props.handleDragStart({rowIdx : rowIdx, idx : idx, copiedText : this.props.value}); - }, - - handleDragEnter:function(){ - this.props.handleDragEnter(this.props.rowIdx); - }, - - handleDragEnd:function(){ - this.props.handleDragEnd(); - }, - - isDraggedCellChanging:function(nextProps){ - if(this.props.dragged){ - return (nextProps.dragged && this.props.idx === nextProps.dragged.idx) - || (this.props.dragged && this.props.idx === this.props.dragged.idx); - }else{ - return false; - } - }, - - componentDidUpdate:function(){ - var dragged = this.props.dragged; - if(dragged && dragged.complete === true){ - this.props.handleTerminateDrag(); - } - } - - }); - - - - module.exports = DraggableMixin; - - -/***/ }, -/* 36 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var cx = React.addons.classSet; - - var SortableHeaderCell = React.createClass({displayName: 'SortableHeaderCell', - - onClick: function() { - this.props.column.sortBy( - this.props.column, - this.props.column.sorted); - }, - - getSortByClass : function(){ - var sorted = this.props.column.sorted; - return cx({ - 'pull-right' : true, - 'glyphicon glyphicon-arrow-up' : sorted === 'ASC', - 'glyphicon glyphicon-arrow-down' : sorted === 'DESC' - }); - }, - - render: function() { - - return ( - React.createElement("div", { - onClick: this.onClick, - style: {cursor: 'pointer'}}, - this.props.column.name, - React.createElement("span", {className: this.getSortByClass()}) - ) - ); - } - }); - - module.exports = SortableHeaderCell; - - -/***/ }, -/* 37 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var cx = React.addons.classSet; - - var FilterableHeaderCell = React.createClass({displayName: 'FilterableHeaderCell', - - getInitialState:function(){ - return {filterTerm : ''} - }, - - handleChange:function(e){ - e.preventDefault(); - e.stopPropagation(); - this.setState({filterTerm : e.currentTarget.value}); - this.props.onChange({filterTerm : e.currentTarget.value, columnKey : this.props.column.key}); - }, - - componentDidUpdate:function(){ - this.getDOMNode().focus(); - }, - - render: function() { - return ( - React.createElement("div", null, - React.createElement("div", {className: "form-group"}, - React.createElement(this.renderInput, null) - ) - ) - ); - }, - - renderInput : function(){ - if(this.props.column.filterable === false){ - return React.createElement("span", null); - }else{ - return (React.createElement("input", {type: "text", className: "form-control input-sm", placeholder: "Search", value: this.state.filterTerm, onChange: this.handleChange})) - } - - } - }); - - module.exports = FilterableHeaderCell; - - -/***/ }, -/* 38 */ -/***/ function(module, exports, __webpack_require__) { - - 'use strict'; - - function ToObject(val) { - if (val == null) { - throw new TypeError('Object.assign cannot be called with null or undefined'); - } - - return Object(val); - } - - module.exports = Object.assign || function (target, source) { - var from; - var keys; - var to = ToObject(target); - - for (var s = 1; s < arguments.length; s++) { - from = arguments[s]; - keys = Object.keys(Object(from)); - - for (var i = 0; i < keys.length; i++) { - to[keys[i]] = from[keys[i]]; - } - } - - return to; - }; - - -/***/ }, -/* 39 */ -/***/ function(module, exports, __webpack_require__) { - - (function webpackUniversalModuleDefinition(root, factory) { - if(true) - module.exports = factory(__webpack_require__(10)); - else if(typeof define === 'function' && define.amd) - define(["react/addons"], factory); - else if(typeof exports === 'object') - exports["ReactAutocomplete"] = factory(require("react/addons")); - else - root["ReactAutocomplete"] = factory(root["React"]); - })(this, function(__WEBPACK_EXTERNAL_MODULE_1__) { - return /******/ (function(modules) { // webpackBootstrap - /******/ // The module cache - /******/ var installedModules = {}; - /******/ - /******/ // The require function - /******/ function __webpack_require__(moduleId) { - /******/ - /******/ // Check if module is in cache - /******/ if(installedModules[moduleId]) - /******/ return installedModules[moduleId].exports; - /******/ - /******/ // Create a new module (and put it into the cache) - /******/ var module = installedModules[moduleId] = { - /******/ exports: {}, - /******/ id: moduleId, - /******/ loaded: false - /******/ }; - /******/ - /******/ // Execute the module function - /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); - /******/ - /******/ // Flag the module as loaded - /******/ module.loaded = true; - /******/ - /******/ // Return the exports of the module - /******/ return module.exports; - /******/ } - /******/ - /******/ - /******/ // expose the modules object (__webpack_modules__) - /******/ __webpack_require__.m = modules; - /******/ - /******/ // expose the module cache - /******/ __webpack_require__.c = installedModules; - /******/ - /******/ // __webpack_public_path__ - /******/ __webpack_require__.p = ""; - /******/ - /******/ // Load entry module and return exports - /******/ return __webpack_require__(0); - /******/ }) - /************************************************************************/ - /******/ ([ - /* 0 */ - /***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - */ - "use strict"; - - var React = __webpack_require__(1); - var cx = React.addons.classSet; - - var Autocomplete = React.createClass({ displayName: "Autocomplete", - - propTypes: { - options: React.PropTypes.any, - search: React.PropTypes.func, - resultRenderer: React.PropTypes.oneOfType([React.PropTypes.component, React.PropTypes.func]), - value: React.PropTypes.object, - onChange: React.PropTypes.func, - onError: React.PropTypes.func - }, - - getDefaultProps: function () { - return { search: searchArray }; - }, - - getInitialState: function () { - var searchTerm = this.props.searchTerm ? this.props.searchTerm : this.props.value ? this.props.value.title : ""; - return { - results: [], - showResults: false, - showResultsInProgress: false, - searchTerm: searchTerm, - focusedValue: null - }; - }, - - getResultIdentifier: function (result) { - if (this.props.resultIdentifier === undefined) { - return result.id; - } else { - return result[this.props.resultIdentifier]; - } - }, - - - render: function () { - var className = cx(this.props.className, "react-autocomplete-Autocomplete", this.state.showResults ? "react-autocomplete-Autocomplete--resultsShown" : undefined); - var style = { - position: "relative", - outline: "none" - }; - return React.createElement("div", { - tabIndex: "1", - className: className, - onFocus: this.onFocus, - onBlur: this.onBlur, - style: style }, React.createElement("input", { - ref: "search", - className: "react-autocomplete-Autocomplete__search", - style: { width: "100%" }, - onClick: this.showAllResults, - onChange: this.onQueryChange, - onFocus: this.showAllResults, - onBlur: this.onQueryBlur, - onKeyDown: this.onQueryKeyDown, - value: this.state.searchTerm }), React.createElement(Results, { - className: "react-autocomplete-Autocomplete__results", - onSelect: this.onValueChange, - onFocus: this.onValueFocus, - results: this.state.results, - focusedValue: this.state.focusedValue, - show: this.state.showResults, - renderer: this.props.resultRenderer, - label: this.props.label, - resultIdentifier: this.props.resultIdentifier })); - }, - - componentWillReceiveProps: function (nextProps) { - var searchTerm = nextProps.searchTerm ? nextProps.searchTerm : nextProps.value ? nextProps.value.title : ""; - this.setState({ searchTerm: searchTerm }); - }, - - componentWillMount: function () { - this.blurTimer = null; - }, - - /** - * Show results for a search term value. - * - * This method doesn't update search term value itself. - * - * @param {Search} searchTerm - */ - showResults: function (searchTerm) { - this.setState({ showResultsInProgress: true }); - this.props.search(this.props.options, searchTerm.trim(), this.onSearchComplete); - }, - - showAllResults: function () { - if (!this.state.showResultsInProgress && !this.state.showResults) { - this.showResults(""); - } - }, - - onValueChange: function (value) { - var state = { - value: value, - showResults: false - }; - - if (value) { - state.searchTerm = value.title; - } - - this.setState(state); - - if (this.props.onChange) { - this.props.onChange(value); - } - }, - - onSearchComplete: function (err, results) { - if (err) { - if (this.props.onError) { - this.props.onError(err); - } else { - throw err; - } - } - - this.setState({ - showResultsInProgress: false, - showResults: true, - results: results - }); - }, - - onValueFocus: function (value) { - this.setState({ focusedValue: value }); - }, - - onQueryChange: function (e) { - var searchTerm = e.target.value; - this.setState({ - searchTerm: searchTerm, - focusedValue: null - }); - this.showResults(searchTerm); - }, - - onFocus: function () { - if (this.blurTimer) { - clearTimeout(this.blurTimer); - this.blurTimer = null; - } - this.refs.search.getDOMNode().focus(); - }, - - onBlur: function () { - // wrap in setTimeout so we can catch a click on results - this.blurTimer = setTimeout((function () { - if (this.isMounted()) { - this.setState({ showResults: false }); - } - }).bind(this), 100); - }, - - onQueryKeyDown: function (e) { - if (e.key === "Enter") { - e.preventDefault(); - if (this.state.focusedValue) { - this.onValueChange(this.state.focusedValue); - } - } else if (e.key === "ArrowUp" && this.state.showResults) { - e.preventDefault(); - var prevIdx = Math.max(this.focusedValueIndex() - 1, 0); - this.setState({ - focusedValue: this.state.results[prevIdx] - }); - } else if (e.key === "ArrowDown") { - e.preventDefault(); - if (this.state.showResults) { - var nextIdx = Math.min(this.focusedValueIndex() + (this.state.showResults ? 1 : 0), this.state.results.length - 1); - this.setState({ - showResults: true, - focusedValue: this.state.results[nextIdx] - }); - } else { - this.showAllResults(); - } - } - }, - - focusedValueIndex: function () { - if (!this.state.focusedValue) { - return -1; - } - for (var i = 0, - len = this.state.results.length; i < len; i++) { - if (this.getResultIdentifier(this.state.results[i]) === this.getResultIdentifier(this.state.focusedValue)) { - return i; - } - } - return -1; - } - }); - - var Results = React.createClass({ displayName: "Results", - - getResultIdentifier: function (result) { - if (this.props.resultIdentifier === undefined) { - if (!result.id) { - throw "id property not found on result. You must specify a resultIdentifier and pass as props to autocomplete component"; - } - return result.id; - } else { - return result[this.props.resultIdentifier]; - } - }, - - render: function () { - var style = { - display: this.props.show ? "block" : "none", - position: "absolute", - listStyleType: "none" - }; - var $__0 = this.props, - className = $__0.className, - props = (function (source, exclusion) { - var rest = {};var hasOwn = Object.prototype.hasOwnProperty;if (source == null) { - throw new TypeError(); - }for (var key in source) { - if (hasOwn.call(source, key) && !hasOwn.call(exclusion, key)) { - rest[key] = source[key]; - } - }return rest; - })($__0, { className: 1 }); - - return React.createElement("ul", React.__spread({}, props, { style: style, className: className + " react-autocomplete-Results" }), this.props.results.map(this.renderResult)); - }, - - renderResult: function (result) { - var focused = this.props.focusedValue && this.getResultIdentifier(this.props.focusedValue) === this.getResultIdentifier(result); - var renderer = this.props.renderer || Result; - return renderer({ - ref: focused ? "focused" : undefined, - key: this.getResultIdentifier(result), - result: result, - focused: focused, - onMouseEnter: this.onMouseEnterResult, - onClick: this.props.onSelect, - label: this.props.label - }); - }, - - componentDidUpdate: function () { - this.scrollToFocused(); - }, - - componentDidMount: function () { - this.scrollToFocused(); - }, - - componentWillMount: function () { - this.ignoreFocus = false; - }, - - scrollToFocused: function () { - var focused = this.refs && this.refs.focused; - if (focused) { - var containerNode = this.getDOMNode(); - var scroll = containerNode.scrollTop; - var height = containerNode.offsetHeight; - - var node = focused.getDOMNode(); - var top = node.offsetTop; - var bottom = top + node.offsetHeight; - - // we update ignoreFocus to true if we change the scroll position so - // the mouseover event triggered because of that won't have an - // effect - if (top < scroll) { - this.ignoreFocus = true; - containerNode.scrollTop = top; - } else if (bottom - scroll > height) { - this.ignoreFocus = true; - containerNode.scrollTop = bottom - height; - } - } - }, - - onMouseEnterResult: function (e, result) { - // check if we need to prevent the next onFocus event because it was - // probably caused by a mouseover due to scroll position change - if (this.ignoreFocus) { - this.ignoreFocus = false; - } else { - // we need to make sure focused node is visible - // for some reason mouse events fire on visible nodes due to - // box-shadow - var containerNode = this.getDOMNode(); - var scroll = containerNode.scrollTop; - var height = containerNode.offsetHeight; - - var node = e.target; - var top = node.offsetTop; - var bottom = top + node.offsetHeight; - - if (bottom > scroll && top < scroll + height) { - this.props.onFocus(result); - } - } - } - }); - - var Result = React.createClass({ displayName: "Result", - - getDefaultProps: function () { - return { - label: function (result) { - return result.title; - } - }; - }, - - getLabel: function (result) { - if (typeof this.props.label === "function") { - return this.props.label(result); - } else if (typeof this.props.label === "string") { - return result[this.props.label]; - } - }, - - render: function () { - var className = cx({ - "react-autocomplete-Result": true, - "react-autocomplete-Result--active": this.props.focused - }); - - return React.createElement("li", { - style: { listStyleType: "none" }, - className: className, - onClick: this.onClick, - onMouseEnter: this.onMouseEnter }, React.createElement("a", null, this.getLabel(this.props.result))); - }, - - onClick: function () { - this.props.onClick(this.props.result); - }, - - onMouseEnter: function (e) { - if (this.props.onMouseEnter) { - this.props.onMouseEnter(e, this.props.result); - } - }, - - shouldComponentUpdate: function (nextProps) { - return nextProps.result.id !== this.props.result.id || nextProps.focused !== this.props.focused; - } - }); - - /** - * Search options using specified search term treating options as an array - * of candidates. - * - * @param {Array.} options - * @param {String} searchTerm - * @param {Callback} cb - */ - function searchArray(options, searchTerm, cb) { - if (!options) { - return cb(null, []); - } - - searchTerm = new RegExp(searchTerm, "i"); - - var results = []; - - for (var i = 0, - len = options.length; i < len; i++) { - if (searchTerm.exec(options[i].title)) { - results.push(options[i]); - } - } - - cb(null, results); - } - - module.exports = Autocomplete; - - /***/ }, - /* 1 */ - /***/ function(module, exports, __webpack_require__) { - - module.exports = __WEBPACK_EXTERNAL_MODULE_1__; - - /***/ } - /******/ ]) - }); - - -/***/ }, -/* 40 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * Copyright 2013-2014 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @providesModule emptyFunction - */ - 'use strict'; - - var copyProperties = __webpack_require__(46); - - function makeEmptyFunction(arg) { - return function() { - return arg; - }; - } - - /** - * This function accepts and discards inputs; it has no side effects. This is - * primarily useful idiomatically for overridable function endpoints which - * always need to be callable, since JS lacks a null-call idiom ala Cocoa. - */ - function emptyFunction() {} - - copyProperties(emptyFunction, { - thatReturns: makeEmptyFunction, - thatReturnsFalse: makeEmptyFunction(false), - thatReturnsTrue: makeEmptyFunction(true), - thatReturnsNull: makeEmptyFunction(null), - thatReturnsThis: function() { return this; }, - thatReturnsArgument: function(arg) { return arg; } - }); - - module.exports = emptyFunction; - - -/***/ }, -/* 41 */ -/***/ function(module, exports, __webpack_require__) { - - /* WEBPACK VAR INJECTION */(function(process) {/** - * Copyright 2013-2014 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @providesModule invariant - */ - - "use strict"; - - /** - * Use invariant() to assert state which your program assumes to be true. - * - * Provide sprintf-style format (only %s is supported) and arguments - * to provide information about what broke and what you were - * expecting. - * - * The invariant message will be stripped in production, but the invariant - * will remain to ensure logic does not differ in production. - */ - - var invariant = function(condition, format, a, b, c, d, e, f) { - if (process.env.NODE_ENV) { - if (format === undefined) { - throw new Error('invariant requires an error message argument'); - } - } - - if (!condition) { - var error; - if (format === undefined) { - error = new Error( - 'Minified exception occurred; use the non-minified dev environment ' + - 'for the full error message and additional helpful warnings.' - ); - } else { - var args = [a, b, c, d, e, f]; - var argIndex = 0; - error = new Error( - 'Invariant Violation: ' + - format.replace(/%s/g, function() { return args[argIndex++]; }) - ); - } - - error.framesToPop = 1; // we don't care about invariant's own frame - throw error; - } - }; - - module.exports = invariant; - - /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(52))) - -/***/ }, -/* 42 */ -/***/ function(module, exports, __webpack_require__) { - - /* WEBPACK VAR INJECTION */(function(process) {/** - * Copyright 2013-2014, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @providesModule keyMirror - * @typechecks static-only - */ - - "use strict"; - - var invariant = __webpack_require__(51); - - /** - * Constructs an enumeration with keys equal to their value. - * - * For example: - * - * var COLORS = keyMirror({blue: null, red: null}); - * var myColor = COLORS.blue; - * var isColorValid = !!COLORS[myColor]; - * - * The last line could not be performed if the values of the generated enum were - * not equal to their keys. - * - * Input: {key1: val1, key2: val2} - * Output: {key1: key1, key2: key2} - * - * @param {object} obj - * @return {object} - */ - var keyMirror = function(obj) { - var ret = {}; - var key; - ("production" !== process.env.NODE_ENV ? invariant( - obj instanceof Object && !Array.isArray(obj), - 'keyMirror(...): Argument must be an object.' - ) : invariant(obj instanceof Object && !Array.isArray(obj))); - for (key in obj) { - if (!obj.hasOwnProperty(key)) { - continue; - } - ret[key] = key; - } - return ret; - }; - - module.exports = keyMirror; - - /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(52))) - -/***/ }, -/* 43 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - /** - * Return window's height and width - * - * @return {Object} height and width of the window - */ - function getWindowSize() { - var width = window.innerWidth; - var height = window.innerHeight; - - if (!width || !height) { - width = document.documentElement.clientWidth; - height = document.documentElement.clientHeight; - } - - if (!width || !height) { - width = document.body.clientWidth; - height = document.body.clientHeight; - } - - return {width:width, height:height}; - } - - module.exports = getWindowSize; - - -/***/ }, -/* 44 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - "use strict"; - - var React = __webpack_require__(10); - var cx = React.addons.classSet; - var PropTypes = React.PropTypes; - var cloneWithProps = React.addons.cloneWithProps; - var shallowEqual = __webpack_require__(47); - var emptyFunction = __webpack_require__(40); - var ScrollShim = __webpack_require__(48); - var Row = __webpack_require__(2); - - var Canvas = React.createClass({displayName: 'Canvas', - mixins: [ScrollShim], - - propTypes: { - cellRenderer: PropTypes.element, - rowRenderer: PropTypes.oneOfType([PropTypes.func, PropTypes.element]), - rowHeight: PropTypes.number.isRequired, - displayStart: PropTypes.number.isRequired, - displayEnd: PropTypes.number.isRequired, - length: PropTypes.number.isRequired, - rows: PropTypes.oneOfType([ - PropTypes.func.isRequired, - PropTypes.array.isRequired - ]), - onRows: PropTypes.func - }, - - render:function() { - var displayStart = this.state.displayStart; - var displayEnd = this.state.displayEnd; - var rowHeight = this.props.rowHeight; - var length = this.props.length; - - var rows = this - .getRows(displayStart, displayEnd) - .map(function(row, idx) {return this.renderRow({ - key: displayStart + idx, - ref: idx, - idx: displayStart + idx, - row: row, - height: rowHeight, - columns: this.props.columns, - cellRenderer: this.props.cellRenderer, - isSelected : this.isRowSelected(displayStart + idx), - expandedRows : this.props.expandedRows - });}.bind(this)); - - this._currentRowsLength = rows.length; - - if (displayStart > 0) { - rows.unshift(this.renderPlaceholder('top', displayStart * rowHeight)); - } - - if (length - displayEnd > 0) { - rows.push( - this.renderPlaceholder('bottom', (length - displayEnd) * rowHeight)); - } - - var style = { - position: 'absolute', - top: 0, - left: 0, - overflowX: 'auto', - overflowY: 'scroll', - width: this.props.totalWidth, - height: this.props.height, - transform: 'translate3d(0, 0, 0)' - }; - - return ( - React.createElement("div", { - style: style, - onScroll: this.onScroll, - className: cx("react-grid-Canvas", this.props.className)}, - React.createElement("div", {style: {width: this.props.width, overflow: 'hidden'}}, - rows - ) - ) - ); - }, - - renderRow:function(props) { - if (React.isValidElement(this.props.rowRenderer)) { - return cloneWithProps(this.props.rowRenderer, props); - } else { - return this.props.rowRenderer(props); - } - }, - - renderPlaceholder:function(key, height) { - return ( - React.createElement("div", {key: key, style: {height: height}}, - this.props.columns.map( - function(column, idx) {return React.createElement("div", {style: {width: column.width}, key: idx});}) - ) - ); - }, - - getDefaultProps:function() { - return { - rowRenderer: React.createElement(Row, null), - onRows: emptyFunction - }; - }, - - isRowSelected:function(rowIdx){ - return this.props.selectedRows && this.props.selectedRows[rowIdx] === true; - }, - - getInitialState:function() { - return { - shouldUpdate: true, - displayStart: this.props.displayStart, - displayEnd: this.props.displayEnd - }; - }, - - componentWillMount:function() { - this._currentRowsLength = undefined; - this._currentRowsRange = undefined; - this._scroll = undefined; - }, - - componentDidMount:function() { - this.onRows(); - }, - - componentDidUpdate:function() { - if (this._scroll !== undefined) { - this.setScrollLeft(this._scroll); - } - this.onRows(); - }, - - componentWillUnmount:function() { - this._currentRowsLength = undefined; - this._currentRowsRange = undefined; - this._scroll = undefined; - }, - - componentWillReceiveProps:function(nextProps) { - var shouldUpdate = !(nextProps.visibleStart > this.state.displayStart - && nextProps.visibleEnd < this.state.displayEnd) - || nextProps.length !== this.props.length - || nextProps.rowHeight !== this.props.rowHeight - || nextProps.columns !== this.props.columns - || nextProps.width !== this.props.width - || !shallowEqual(nextProps.style, this.props.style); - - if (shouldUpdate) { - this.setState({ - shouldUpdate: true, - displayStart: nextProps.displayStart, - displayEnd: nextProps.displayEnd - }); - } else { - this.setState({shouldUpdate: false}); - } - }, - - shouldComponentUpdate:function(nextProps, nextState) { - return nextState.shouldUpdate; - }, - - onRows:function() { - if (this._currentRowsRange !== undefined) { - this.props.onRows(this._currentRowsRange); - this._currentRowsRange = undefined; - } - }, - - getRows:function(displayStart, displayEnd) { - this._currentRowsRange = {start: displayStart, end: displayEnd}; - if (Array.isArray(this.props.rows)) { - return this.props.rows.slice(displayStart, displayEnd); - } else { - return this.props.rows(displayStart, displayEnd); - } - }, - - setScrollLeft:function(scrollLeft) { - if (this._currentRowsLength !== undefined) { - for (var i = 0, len = this._currentRowsLength; i < len; i++) { - if(this.refs[i]) { - this.refs[i].setScrollLeft(scrollLeft); - } - } - } - }, - - getScroll:function() { - var $__0= this.getDOMNode(),scrollTop=$__0.scrollTop,scrollLeft=$__0.scrollLeft; - return {scrollTop:scrollTop, scrollLeft:scrollLeft}; - }, - - onScroll:function(e) { - this.appendScrollShim(); - var $__0= e.target,scrollTop=$__0.scrollTop,scrollLeft=$__0.scrollLeft; - var scroll = {scrollTop:scrollTop, scrollLeft:scrollLeft}; - this._scroll = scroll; - this.props.onScroll(scroll); - } - }); - - - module.exports = Canvas; - - -/***/ }, -/* 45 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - "use strict"; - - var React = __webpack_require__(10); - var PropTypes = React.PropTypes; - var shallowEqual = __webpack_require__(47); - var HeaderCell = __webpack_require__(49); - var getScrollbarSize = __webpack_require__(50); - - var HeaderRow = React.createClass({displayName: 'HeaderRow', - - propTypes: { - width: PropTypes.number, - height: PropTypes.number.isRequired, - columns: PropTypes.array.isRequired, - onColumnResize: PropTypes.func - }, - - render:function() { - var cellsStyle = { - width: this.props.width ? (this.props.width + getScrollbarSize()) : '100%', - height: this.props.height, - whiteSpace: 'nowrap', - overflowX: 'hidden', - overflowY: 'hidden' - }; - - var cells = this.getCells(); - return ( - React.createElement("div", React.__spread({}, this.props, {className: "react-grid-HeaderRow"}), - React.createElement("div", {style: cellsStyle}, - cells - ) - ) - ); - }, - - getCells:function() { - var cells = []; - var lockedCells = []; - - for (var i = 0, len = this.props.columns.length; i < len; i++) { - var column = this.props.columns[i]; - var cell = ( - React.createElement(HeaderCell, { - ref: i, - key: i, - height: this.props.height, - column: column, - renderer: this.props.headerCellRenderer || column.headerRenderer || this.props.cellRenderer, - resizing: this.props.resizing === column, - onResize: this.props.onColumnResize, - onResizeEnd: this.props.onColumnResizeEnd} - ) - ); - if (column.locked) { - lockedCells.push(cell); - } else { - cells.push(cell); - } - } - - return cells.concat(lockedCells); - }, - - setScrollLeft:function(scrollLeft) { - for (var i = 0, len = this.props.columns.length; i < len; i++) { - if (this.props.columns[i].locked) { - this.refs[i].setScrollLeft(scrollLeft); - } - } - }, - - shouldComponentUpdate:function(nextProps) { - return ( - nextProps.width !== this.props.width - || nextProps.height !== this.props.height - || nextProps.columns !== this.props.columns - || !shallowEqual(nextProps.style, this.props.style) - ); - }, - - getStyle:function() { - return { - overflow: 'hidden', - width: '100%', - height: this.props.height, - position: 'absolute' - }; - } - - }); - - module.exports = HeaderRow; - - -/***/ }, -/* 46 */ -/***/ function(module, exports, __webpack_require__) { - - /* WEBPACK VAR INJECTION */(function(process) {/** - * Copyright 2013-2014 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @providesModule copyProperties - */ - 'use strict'; - - /** - * Copy properties from one or more objects (up to 5) into the first object. - * This is a shallow copy. It mutates the first object and also returns it. - * - * NOTE: `arguments` has a very significant performance penalty, which is why - * we don't support unlimited arguments. - */ - function copyProperties(obj, a, b, c, d, e, f) { - obj = obj || {}; - - if (process.env.NODE_ENV) { - if (f) { - throw new Error('Too many arguments passed to copyProperties'); - } - } - - var args = [a, b, c, d, e]; - var ii = 0, v; - while (args[ii]) { - v = args[ii++]; - for (var k in v) { - obj[k] = v[k]; - } - - // IE ignores toString in object iteration.. See: - // webreflection.blogspot.com/2007/07/quick-fix-internet-explorer-and.html - if (v.hasOwnProperty && v.hasOwnProperty('toString') && - (typeof v.toString != 'undefined') && (obj.toString !== v.toString)) { - obj.toString = v.toString; - } - } - - return obj; - } - - module.exports = copyProperties; - - /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(52))) - -/***/ }, -/* 47 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - function shallowEqual(a, b) { - if (a === b) { - return true; - } - - var k; - - for (k in a) { - if (a.hasOwnProperty(k) && - (!b.hasOwnProperty(k) || a[k] !== b[k])) { - return false; - } - } - - for (k in b) { - if (b.hasOwnProperty(k) && !a.hasOwnProperty(k)) { - return false; - } - } - - return true; - } - - module.exports = shallowEqual; - - -/***/ }, -/* 48 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var ScrollShim = { - - appendScrollShim:function() { - if (!this._scrollShim) { - var size = this._scrollShimSize(); - var shim = document.createElement('div'); - shim.classList.add('react-grid-ScrollShim'); - shim.style.position = 'absolute'; - shim.style.top = 0; - shim.style.left = 0; - shim.style.width = (size.width + "px"); - shim.style.height = (size.height + "px"); - this.getDOMNode().appendChild(shim); - this._scrollShim = shim; - } - this._scheduleRemoveScrollShim(); - }, - - _scrollShimSize:function() { - return { - width: this.props.width, - height: this.props.length * this.props.rowHeight - }; - }, - - _scheduleRemoveScrollShim:function() { - if (this._scheduleRemoveScrollShimTimer) { - clearTimeout(this._scheduleRemoveScrollShimTimer); - } - this._scheduleRemoveScrollShimTimer = setTimeout( - this._removeScrollShim, 200); - }, - - _removeScrollShim:function() { - if (this._scrollShim) { - this._scrollShim.parentNode.removeChild(this._scrollShim); - this._scrollShim = undefined; - } - } - }; - - module.exports = ScrollShim; - - -/***/ }, -/* 49 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - "use strict"; - - var React = __webpack_require__(10); - var cx = React.addons.classSet; - var Draggable = __webpack_require__(53); - var PropTypes = React.PropTypes; - - var ResizeHandle = React.createClass({displayName: 'ResizeHandle', - - style: { - position: 'absolute', - top: 0, - right: 0, - width: 6, - height: '100%' - }, - - render:function() { - return ( - React.createElement(Draggable, React.__spread({}, this.props, - {className: "react-grid-HeaderCell__resizeHandle", - style: this.style}) - ) - ); - } - }); - - var HeaderCell = React.createClass({displayName: 'HeaderCell', - - propTypes: { - renderer: PropTypes.oneOfType([PropTypes.func, PropTypes.element]).isRequired, - column: PropTypes.object.isRequired, - onResize: PropTypes.func - }, - - render:function() { - var className = cx({ - 'react-grid-HeaderCell': true, - 'react-grid-HeaderCell--resizing': this.state.resizing, - 'react-grid-HeaderCell--locked': this.props.column.locked - }); - className = cx(className, this.props.className); - var cell = this.getCell(); - return ( - React.createElement("div", {className: className, style: this.getStyle()}, - cell, - this.props.column.resizeable ? - React.createElement(ResizeHandle, { - onDrag: this.onDrag, - onDragStart: this.onDragStart, - onDragEnd: this.onDragEnd} - ) : - null - ) - ); - }, - - getCell:function() { - if (React.isValidElement(this.props.renderer)) { - return React.addons.cloneWithProps(this.props.renderer, {column : this.props.column}); - } else { - return this.props.renderer({column: this.props.column}); - } - }, - - getDefaultProps:function() { - return { - renderer: simpleCellRenderer - }; - }, - - getInitialState:function() { - return {resizing: false}; - }, - - setScrollLeft:function(scrollLeft) { - var node = this.getDOMNode(); - node.style.webkitTransform = ("translate3d(" + scrollLeft + "px, 0px, 0px)"); - node.style.transform = ("translate3d(" + scrollLeft + "px, 0px, 0px)"); - }, - - getStyle:function() { - return { - width: this.props.column.width, - left: this.props.column.left, - display: 'inline-block', - position: 'absolute', - overflow: 'hidden', - height: this.props.height, - margin: 0, - textOverflow: 'ellipsis', - whiteSpace: 'nowrap' - }; - }, - - onDragStart:function() { - this.setState({resizing: true}); - }, - - onDrag:function(e) { - var width = this.getWidthFromMouseEvent(e); - if (width > 0 && this.props.onResize) { - this.props.onResize(this.props.column, width); - } - }, - - onDragEnd:function(e) { - var width = this.getWidthFromMouseEvent(e); - this.props.onResizeEnd(this.props.column, width); - this.setState({resizing: false}); - }, - - getWidthFromMouseEvent:function(e) { - var right = e.pageX; - var left = this.getDOMNode().getBoundingClientRect().left; - return right - left; - } - }); - - function simpleCellRenderer(props) { - return React.createElement("div", {className: "rex-widget-HeaderCell__value"}, props.column.name); - } - - module.exports = HeaderCell; - - -/***/ }, -/* 50 */ -/***/ function(module, exports, __webpack_require__) { - - "use strict"; - - var size; - - function getScrollbarSize() { - if (size === undefined) { - - var outer = document.createElement('div'); - outer.style.width = '50px'; - outer.style.height = '50px'; - outer.style.overflowY = 'scroll'; - outer.style.position = 'absolute'; - outer.style.top = '-200px'; - outer.style.left = '-200px'; - - var inner = document.createElement('div'); - inner.style.height = '100px'; - inner.style.width = '100%'; - - outer.appendChild(inner); - document.body.appendChild(outer); - - var outerWidth = outer.offsetWidth; - var innerWidth = inner.offsetWidth; - - document.body.removeChild(outer); - - size = outerWidth - innerWidth; - } - - return size; - } - - module.exports = getScrollbarSize; - - -/***/ }, -/* 51 */ -/***/ function(module, exports, __webpack_require__) { - - /* WEBPACK VAR INJECTION */(function(process) {/** - * Copyright 2013-2014, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @providesModule invariant - */ - - "use strict"; - - /** - * Use invariant() to assert state which your program assumes to be true. - * - * Provide sprintf-style format (only %s is supported) and arguments - * to provide information about what broke and what you were - * expecting. - * - * The invariant message will be stripped in production, but the invariant - * will remain to ensure logic does not differ in production. - */ - - var invariant = function(condition, format, a, b, c, d, e, f) { - if ("production" !== process.env.NODE_ENV) { - if (format === undefined) { - throw new Error('invariant requires an error message argument'); - } - } - - if (!condition) { - var error; - if (format === undefined) { - error = new Error( - 'Minified exception occurred; use the non-minified dev environment ' + - 'for the full error message and additional helpful warnings.' - ); - } else { - var args = [a, b, c, d, e, f]; - var argIndex = 0; - error = new Error( - 'Invariant Violation: ' + - format.replace(/%s/g, function() { return args[argIndex++]; }) - ); - } - - error.framesToPop = 1; // we don't care about invariant's own frame - throw error; - } - }; - - module.exports = invariant; - - /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(52))) - -/***/ }, -/* 52 */ -/***/ function(module, exports, __webpack_require__) { - - // shim for using process in browser - - var process = module.exports = {}; - - process.nextTick = (function () { - var canSetImmediate = typeof window !== 'undefined' - && window.setImmediate; - var canMutationObserver = typeof window !== 'undefined' - && window.MutationObserver; - var canPost = typeof window !== 'undefined' - && window.postMessage && window.addEventListener - ; - - if (canSetImmediate) { - return function (f) { return window.setImmediate(f) }; - } - - var queue = []; - - if (canMutationObserver) { - var hiddenDiv = document.createElement("div"); - var observer = new MutationObserver(function () { - var queueList = queue.slice(); - queue.length = 0; - queueList.forEach(function (fn) { - fn(); - }); - }); - - observer.observe(hiddenDiv, { attributes: true }); - - return function nextTick(fn) { - if (!queue.length) { - hiddenDiv.setAttribute('yes', 'no'); - } - queue.push(fn); - }; - } - - if (canPost) { - window.addEventListener('message', function (ev) { - var source = ev.source; - if ((source === window || source === null) && ev.data === 'process-tick') { - ev.stopPropagation(); - if (queue.length > 0) { - var fn = queue.shift(); - fn(); - } - } - }, true); - - return function nextTick(fn) { - queue.push(fn); - window.postMessage('process-tick', '*'); - }; - } - - return function nextTick(fn) { - setTimeout(fn, 0); - }; - })(); - - process.title = 'browser'; - process.browser = true; - process.env = {}; - process.argv = []; - - function noop() {} - - process.on = noop; - process.addListener = noop; - process.once = noop; - process.off = noop; - process.removeListener = noop; - process.removeAllListeners = noop; - process.emit = noop; - - process.binding = function (name) { - throw new Error('process.binding is not supported'); - }; - - // TODO(shtylman) - process.cwd = function () { return '/' }; - process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); - }; - - -/***/ }, -/* 53 */ -/***/ function(module, exports, __webpack_require__) { - - /** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ - 'use strict'; - - var React = __webpack_require__(10); - var PropTypes = React.PropTypes; - var emptyFunction = __webpack_require__(40); - - var Draggable = React.createClass({displayName: 'Draggable', - - propTypes: { - onDragStart: PropTypes.func, - onDragEnd: PropTypes.func, - onDrag: PropTypes.func, - component: PropTypes.oneOfType([PropTypes.func, PropTypes.constructor]) - }, - - render:function() { - var Component = this.props.component; - return ( - React.createElement(Component, React.__spread({}, this.props, {onMouseDown: this.onMouseDown})) - ); - }, - - getDefaultProps:function() { - return { - component: React.DOM.div, - onDragStart: emptyFunction.thatReturnsTrue, - onDragEnd: emptyFunction, - onDrag: emptyFunction - }; - }, - - getInitialState:function() { - return { - drag: null - }; - }, - - onMouseDown:function(e) { - var drag = this.props.onDragStart(e); - - if (drag === null && e.button !== 0) { - return; - } - - window.addEventListener('mouseup', this.onMouseUp); - window.addEventListener('mousemove', this.onMouseMove); - - this.setState({drag:drag}); - }, - - onMouseMove:function(e) { - if (this.state.drag === null) { - return; - } - - if (e.stopPropagation) { - e.stopPropagation(); - } - - if (e.preventDefault) { - e.preventDefault(); - } - - this.props.onDrag(e); - }, - - onMouseUp:function(e) { - this.cleanUp(); - this.props.onDragEnd(e, this.state.drag); - this.setState({drag: null}); - }, - - componentWillUnmount:function() { - this.cleanUp(); - }, - - cleanUp:function() { - window.removeEventListener('mouseup', this.onMouseUp); - window.removeEventListener('mousemove', this.onMouseMove); - } - }); - - module.exports = Draggable; - - -/***/ } -/******/ ]) -}); diff --git a/dist/ReactGridWithAddons.min.js b/dist/ReactGridWithAddons.min.js deleted file mode 100644 index 599deed..0000000 --- a/dist/ReactGridWithAddons.min.js +++ /dev/null @@ -1,3 +0,0 @@ -!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react/addons")):"function"==typeof define&&define.amd?define(["react/addons"],t):"object"==typeof exports?exports.ReactGrid=t(require("react/addons")):e.ReactGrid=t(e.React)}(this,function(e){return function(e){function t(o){if(s[o])return s[o].exports;var r=s[o]={exports:{},id:o,loaded:!1};return e[o].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var s={};return t.m=e,t.c=s,t.p="",t(0)}([function(e,t,s){e.exports={Grid:s(1),Editors:s(7),Formatters:s(8),Toolbar:s(4),Mixins:{EditorMixin:s(5),TextInputMixin:s(6),KeyboardHandlerMixin:s(9)}}},function(e,t,s){"use strict";var o=s(10),r=(o.PropTypes,s(16)),i=s(17),n=s(18),l=(s(19),s(20)),a=s(21),c=s(22),p=s(23),h=s(24),u=s(25),d=s(26),f=(s(27),o.addons.cloneWithProps,o.createClass({displayName:"ExcelGrid",mixins:[l,p,a,c,h,u],getInitialState:function(){return{selectedRows:[],expandedRows:[]}},overrides:{onCellCommit:function(e){var t=e[0],s=Object.assign({},this.state.selected);s.active=!1,"Tab"===t.keyCode&&(s.idx+=1);var o=this.state.expandedRows;t.changed&&t.changed.expandedHeight&&(o=this.expandRow(t.rowIdx,t.changed.expandedHeight)),this.setState({selected:s,expandedRows:o}),this.props.onRowUpdated(t)},getColumns:function(){var e=this.getDecoratedColumns(this.props.columns);return this.props.enableRowSelect&&e.unshift({key:"select-row",name:"",formatter:o.createElement(d,null),onRowSelect:this.handleRowSelect,filterable:!1,headerRenderer:o.createElement("input",{type:"checkbox",onChange:this.handleCheckboxChange}),width:60}),e}},getDefaultProps:function(){return{rowHeight:35,enableRowSelect:!1,minHeight:350}},handleCheckboxChange:function(e){if(e.currentTarget.checked===!0){var t=this.props.rows.map(function(){return!0});this.setState({selectedRows:t})}else{var t=this.props.rows.map(function(){return!1});this.setState({selectedRows:t})}},handleRowSelect:function(e){var t=this.state.selectedRows;t[e]=null==t[e]||0==t[e]?!0:!1,this.setState({selectedRows:t})},expandRow:function(e,t){var s=this.state.expandedRows;return s[e]?(null==s[e]||s[e]s;s++){var r=this.props.columns[s],i=this.renderCell({ref:s,key:s,idx:s,rowIdx:this.props.idx,filterRowIdx:this.props.row.key,value:this.getCellValue(r.key||s),column:r,height:this.getRowHeight(),formatter:r.formatter,rowData:this.props.row});r.locked?t.push(i):e.push(i)}return e.concat(t)},getRowHeight:function(){return this.props.expandedRows&&this.props.expandedRows[this.props.key]?this.props.expandedRows[this.props.key]:this.props.height},getCellValue:function(e){return"select-row"===e?this.props.isSelected:this.props.row[e]},renderCell:function(e){return o.isValidElement(this.props.cellRenderer)?n(this.props.cellRenderer,e):this.props.cellRenderer(e)},getDefaultProps:function(){return{cellRenderer:i}},shouldComponentUpdate:function(e){return!l.sameColumns(this.props.columns,e.columns,l.sameColumn)||this.doesRowContainSelectedCell()||this.doesRowContainSelectedCell(e)||this.willRowBeDraggedOver(e)||this.hasRowBeenCopied()||e.row!==this.props.row||e.height!==this.props.height},setScrollLeft:function(e){for(var t=0,s=this.props.columns.length;s>t;t++)this.props.columns[t].locked&&this.refs[t].setScrollLeft(e)},doesRowContainSelectedCell:function(e){var t=e||this.props,s=s||t.cellRenderer;return s.props.selected&&s.props.selected.rowIdx===t.idx?!0:!1},willRowBeDraggedOver:function(e){var t=e.cellRenderer.props.dragged;return null!=t&&(t.rowIdx||t.complete===!0)},hasRowBeenCopied:function(){var e=this.props.cellRenderer;return null!=e.props.copied&&e.props.copied.rowIdx===this.props.idx}});e.exports=a},function(e,t,s){"use strict";function o(e){return e.value}var r=s(10),i=r.addons.classSet,n=r.addons.cloneWithProps,l=r.createClass({displayName:"Cell",render:function(){var e=this.getStyle(),t=i("react-grid-Cell",this.props.className,this.props.column.locked?"react-grid-Cell--locked":null),s=this.renderCellContent({value:this.props.value,column:this.props.column,rowIdx:this.props.rowIdx,isExpanded:this.props.isExpanded});return r.createElement("div",r.__spread({},this.props,{className:t,style:e}),s,r.createElement("div",{className:"drag-handle",draggable:"true",onDragStart:this.props.handleDragStart}))},renderCellContent:function(e){var t=r.isValidElement(this.props.formatter)?n(this.props.formatter,e):this.props.formatter(e);return r.createElement("div",{className:"react-grid-Cell__value"},t," ",this.props.cellControls)},getDefaultProps:function(){return{formatter:o}},getStyle:function(){var e={position:"absolute",width:this.props.column.width,height:this.props.height,left:this.props.column.left};return e},setScrollLeft:function(e){if(this.isMounted()){var t=this.getDOMNode(),s="translate3d("+e+"px, 0px, 0px)";t.style.webkitTransform=s,t.style.transform=s}}});e.exports=l},function(e,t,s){"use strict";var o=s(10),r=o.createClass({displayName:"Toolbar",onAddRow:function(){this.props.onAddRow&&this.props.onAddRow({newRowIndex:this.props.rows.length})},getDefaultProps:function(){return{enableAddRow:!0}},getAddRowButton:function(){return this.props.enableAddRow?o.createElement("button",{type:"button",className:"btn",onClick:this.onAddRow},"Add Row"):void 0},render:function(){return o.createElement("div",{className:"react-grid-Toolbar"},o.createElement("div",{className:"tools"},this.getAddRowButton(),o.createElement("button",{type:"button",className:"btn",onClick:this.props.onToggleFilter},"Filter Rows")))}});e.exports=r},function(e,t,s){"use strict";var o=s(10),r=o.addons.classSet,i=s(12),n={propTypes:{onCommit:o.PropTypes.func.isRequired},getStyle:function(){return{height:this.props.height-1}},getInitialState:function(){return{isInvalid:!1}},onPressEnter:function(e){e.stopPropagation(),e.preventDefault(),this.commit({key:"Enter"})},onPressTab:function(e){e.stopPropagation(),e.preventDefault(),this.commit({key:"Tab"})},commit:function(e){var t=this.getValue(),s={};s[this.props.column.key]=t,this.isNewValueValid(t)&&this.props.onCommit({updated:s,key:e.key})},isNewValueValid:function(e){if(i(this.validate)){var t=this.validate(e);return this.setState({isInvalid:!t}),t}return!0},getValue:function(){return this.getInputNode().value},setValue:function(e){this.getInputNode().value=e},componentDidMount:function(){void 0!==this.getInputNode()&&(this.checkFocus(),this.getInputNode().className+=" editor-main")},checkFocus:function(){this.getInputNode().focus()},getInputNode:function(){return this.getDOMNode().getElementsByTagName("input")[0]},getContainerClass:function(){return r({"has-error":this.state.isInvalid===!0})},renderStatusIcon:function(){return this.state.isInvalid===!0?o.createElement("span",{className:"glyphicon glyphicon-remove form-control-feedback"}):void 0},render:function(){if(!i(this.renderEditorNode))throw"Editor Mixin Error : "+this.displayName+" component must implement method renderEditorNode";var e=this.renderEditorNode();return o.createElement("div",{className:this.getContainerClass()},e,this.renderStatusIcon())}};e.exports=n},function(e){"use strict";var t={onPressArrowLeft:function(e){e.stopPropagation()},onPressArrowRight:function(e){e.stopPropagation()},getDefaultValue:function(){var e=this.props.initialKeyCode;if("Delete"===e||"Backspace"===e)return"";if("Enter"===e)return this.props.value;var t=e?String.fromCharCode(e):this.props.value;return t},setCaretAtEndOfInput:function(){var e=this.getInputNode(),t=e.value.length;if(e.setSelectionRange)e.setSelectionRange(t,t);else if(e.createTextRange){var s=e.createTextRange();s.moveStart("character",txt.value.length),s.collapse(),s.select()}},setTextInputFocus:function(){this.isKeyPrintable(this.props.initialKeyCode)?this.getInputNode().select():(this.getInputNode().focus(),this.setCaretAtEndOfInput())}};e.exports=t},function(e,t,s){var o={AutoComplete:s(13),DropDownEditor:s(14),SimpleTextEditor:s(15)};e.exports=o},function(e){var t={};e.exports=t},function(e,t,s){"use strict";var o=s(10),r=(o.addons.Perf,{onKeyDown:function(e){if(this.isCtrlKeyHeldDown(e))this.checkAndCall("onPressKeyWithCtrl",e);else if(this.isKeyIdentified(e.key)){var t="onPress"+e.key;this.checkAndCall(t,e)}else this.isKeyPrintable(e.keyCode)&&this.checkAndCall("onPressChar",e)},isKeyPrintable:function(e){var t=e>47&&58>e||32==e||13==e||e>64&&91>e||e>95&&112>e||e>185&&193>e||e>218&&223>e;return t},isKeyIdentified:function(e){return"Unidentified"!==e},isCtrlKeyHeldDown:function(e){return e.ctrlKey===!0&&"Control"!==e.key},checkAndCall:function(e,t){"function"==typeof this[e]&&this[e](t)}});e.exports=r},function(t){t.exports=e},function(e,t,s){"use strict";function o(e){var t,s,o,r=0,i=e.totalWidth,n=[],l=e.columns.map(p);for(t=0,s=l.length;s>t;t++)o=l[t],o.width?(/^([0-9]+)%$/.exec(o.width)&&(o.width=Math.floor(parseInt(o.width,10)/100*e.totalWidth)),i-=o.width,r+=o.width):n.push(o);for(t=0,s=n.length;s>t;t++)o=n[t],o.width=0>=i?e.minColumnWidth:Math.floor(i/n.length),r+=o.width;var a=0;for(t=0,s=l.length;s>t;t++)o=l[t],o.left=a,a+=o.width;return{columns:l,width:r,totalWidth:e.totalWidth,minColumnWidth:e.minColumnWidth}}function r(e,t,s){var r=e.columns[t];e=p(e),e.columns=e.columns.slice(0);var i=p(r);return i.width=Math.max(s,e.minColumnWidth),e.columns.splice(t,1,i),o(e)}function i(e,t,s){var o,r,i,n={},l={};if(e.length!==t.length)return!1;for(o=0,r=e.length;r>o;o++)i=e[o],n[i.key]=i;for(o=0,r=t.length;r>o;o++){i=t[o],l[i.key]=i;var a=n[i.key];if(void 0===a||!s(a,i))return!1}for(o=0,r=e.length;r>o;o++){i=e[o];var c=l[i.key];if(void 0===c)return!1}return!0}function n(e,t){var s;for(s in e)if(e.hasOwnProperty(s)){if("function"==typeof e[s]&&"function"==typeof t[s]||c(e[s])&&c(t[s]))continue;if(!t.hasOwnProperty(s)||e[s]!==t[s])return!1}for(s in t)if(t.hasOwnProperty(s)&&!e.hasOwnProperty(s))return!1;return!0}var l=s(10),a=l.PropTypes,c=l.isValidElement,p=s(28),h=s(29),u=s(19),d={mixins:[h.MetricsMixin],propTypes:{columns:a.array,minColumnWidth:a.number,columnEquality:a.func},DOMMetrics:{gridWidth:function(){return this.getDOMNode().offsetWidth-2}},getDefaultProps:function(){return{minColumnWidth:80,columnEquality:n}},getInitialState:function(){return this.getColumnMetrics(this.props,!0)},componentWillReceiveProps:function(e){if(e.columns)if(i(this.props.columns,e.columns,this.props.columnEquality)){var t={};this.state.columns.columns.forEach(function(e){t[e.key]={width:e.width,left:e.left}});var s=u(this.state.columns,{columns:e.columns.map(function(e){return u(e,t[e.key])})});this.setState({columns:s})}else this.setState(this.getColumnMetrics(e))},getColumnMetrics:function(e,t){var s=t?null:this.DOMMetrics.gridWidth();return{columns:o({columns:e.columns,width:null,totalWidth:s,minColumnWidth:e.minColumnWidth}),gridWidth:s}},metricsUpdated:function(){this.setState(this.getColumnMetrics(this.props))},onColumnResize:function(e,t){var s=r(this.state.columns,e,t);this.setState({columns:s})}};e.exports={Mixin:d,calculate:o,resizeColumn:r,sameColumns:i,sameColumn:n}},function(e){"use strict";var t=function(e){var t={};return e&&"[object Function]"===t.toString.call(e)};e.exports=t},function(e,t,s){"use strict";var o=s(10),r=(o.addons.classSet,s(27)),i=s(5),n=s(6),l=s(39),a=s(9),c=o.PropTypes.shape({id:o.PropTypes.required,title:o.PropTypes.string}),p=o.createClass({displayName:"AutoCompleteEditor",propTypes:{options:o.PropTypes.arrayOf(c)},mixins:r.mix([a,i,n]),overrides:{checkFocus:function(){this.setTextInputFocus()},getInputNode:function(){return this.getSearchComponent().getDOMNode()},onPressEnter:function(e){var t=e[0];this.handleEnter(t)},onPressTab:function(e){var t=e[0];this.handleTab(t)}},handleTab:function(e){e.stopPropagation(),e.preventDefault(),this.isFocusedOnSuggestion()?this.handleChange(this.getFocusedSuggestion(),"Tab"):this.handleChange(null,"Tab")},handleEnter:function(e){e.stopPropagation(),e.preventDefault(),this.isFocusedOnSuggestion()||this.props.onCommit({value:this.refs.autoComplete.state.searchTerm,key:"Enter"})},getSearchComponent:function(){return this.refs.autoComplete.refs.search},isFocusedOnSuggestion:function(){var e=this.refs.autoComplete;return null!=e.state.focusedValue},getFocusedSuggestion:function(){return this.refs.autoComplete.state.focusedValue},onPressArrowDown:function(e){e.stopPropagation(),e.preventDefault()},onPressArrowUp:function(e){e.stopPropagation()},getLabel:function(e){var t=null!=this.props.label?this.props.label:"title";return"function"==typeof t?t(e):"string"==typeof t?e[t]:void 0},handleChange:function(e,t){var s={},o=this.props.value;null!=e&&(o=this.getLabel(e),this.props.valueParams&&(o=this.constuctValueFromParams(e,this.props.valueParams)),s[this.props.column.key]=o),t=t?t:"Enter",this.props.onCommit({value:o,key:t,updated:s})},constuctValueFromParams:function(e,t){for(var s=[],o=0,r=t.length;r>o;o++)s.push(e[t[o]]);return s.join("|")},renderEditorNode:function(){var e={title:this.getDefaultValue()},t=null!=this.props.label?this.props.label:"title";return o.createElement("div",{style:this.getStyle(),onKeyDown:this.onKeyDown},o.createElement(l,{search:this.props.search,ref:"autoComplete",label:t,resultIdentifier:this.props.resultIdentifier,options:this.props.options,value:e,onChange:this.handleChange}))}});e.exports=p},function(e,t,s){"use strict";var o=s(10),r=(o.addons.classSet,s(27),s(9)),i=s(5),n=(o.addons.cloneWithProps,o.createClass({displayName:"DropDownEditor",mixins:[r,i],overrides:{getInputNode:function(){return this.refs.select.getDOMNode()}},propTypes:{options:o.PropTypes.array.isRequired},renderEditorNode:function(){return o.createElement("select",{ref:"select",style:this.getStyle(),defaultValue:this.props.value,onChange:this.onChange},this.renderOptions())},renderOptions:function(){var e=[];return this.props.options.forEach(function(t){e.push(o.createElement("option",{key:t,value:t},t))},this),e},onChange:function(){this.commit({key:"Enter"})},onClick:function(e){e.stopPropagation(),e.preventDefault()}}));e.exports=n},function(e,t,s){"use strict";var o=s(10),r=(o.addons.classSet,s(27),s(5)),i=s(6),n=s(9),l=o.createClass({displayName:"SimpleTextEditor",mixins:[n,r,i],overrides:{checkFocus:function(){this.setTextInputFocus()}},renderEditorNode:function(){return o.createElement("input",{type:"text",onBlur:this.commit,className:"form-control",defaultValue:this.getDefaultValue(),style:this.getStyle(),onKeyDown:this.onKeyDown})}});e.exports=l},function(e,t,s){"use strict";var o=s(10),r=o.PropTypes,i=s(30),n=s(31),l=s(11),a=s(29),c={componentDidMount:function(){this._scrollLeft=this.refs.viewport.getScroll().scrollLeft,this._onScroll()},componentDidUpdate:function(){this._onScroll()},componentWillMount:function(){this._scrollLeft=void 0},componentWillUnmount:function(){this._scrollLeft=void 0},onScroll:function(e){var t=e.scrollLeft;this._scrollLeft!==t&&(this._scrollLeft=t,this._onScroll())},_onScroll:function(){void 0!==this._scrollLeft&&(this.refs.header.setScrollLeft(this._scrollLeft),this.refs.viewport.setScrollLeft(this._scrollLeft))}},p=o.createClass({displayName:"Grid",mixins:[c,l.Mixin,a.MetricsComputatorMixin],propTypes:{rows:r.oneOfType([r.array,r.func]).isRequired,columns:r.array.isRequired},getStyle:function(){return{overflow:"hidden",outline:0,position:"relative",minHeight:this.props.minHeight}},render:function(){var e=this.props.headerRows||[{ref:"row"}];return o.createElement("div",o.__spread({},this.props,{style:this.getStyle(),className:"react-grid-Grid"}),o.createElement(i,{ref:"header",columns:this.state.columns,onColumnResize:this.onColumnResize,height:this.props.rowHeight,totalWidth:this.DOMMetrics.gridWidth(),headerRows:e}),o.createElement(n,{ref:"viewport",width:this.state.columns.width,rowHeight:this.props.rowHeight,rowRenderer:this.props.rowRenderer,cellRenderer:this.props.cellRenderer,rows:this.props.rows,selectedRows:this.props.selectedRows,expandedRows:this.props.expandedRows,length:this.props.length,columns:this.state.columns,totalWidth:this.DOMMetrics.gridWidth(),onScroll:this.onScroll,onRows:this.props.onRows,rowOffsetHeight:this.props.rowOffsetHeight||this.props.rowHeight*e.length}))},getDefaultProps:function(){return{rowHeight:35,minHeight:350}}});e.exports=p},function(e,t,s){"use strict";var o=s(10),r=s(3),i=(s(32),s(33)),n=s(34),l=s(35),a=(s(27),s(9),s(12)),c=(o.PropTypes,o.addons.classSet),p=(o.addons.cloneWithProps,o.createClass({displayName:"CellControls",onClickEdit:function(e){e.stopPropagation(),e.preventDefault(),this.props.onClickEdit()},onShowMore:function(e){e.stopPropagation(),e.preventDefault();var t=this.props.column.getExpandedHeight(this.props.value);this.props.onShowMore(this.props.rowIdx,t)},onShowLess:function(e){e.stopPropagation(),e.preventDefault(),this.props.onShowLess(this.props.rowIdx)},shouldComponentUpdate:function(e){return this.props.height!=e.height},renderShowMoreButton:function(){if(a(this.props.column.getExpandedHeight)&&this.props.column.getExpandedHeight(this.props.value)>0){var e=this.props.column.getExpandedHeight(this.props.value);return e>this.props.height?o.createElement("button",{type:"button",className:"btn btn-link btn-xs",onClick:this.onShowMore},"Show More"):o.createElement("button",{type:"button",className:"btn btn-link btn-xs",onClick:this.onShowLess},"Show Less")}return null},render:function(){return o.createElement("div",{className:"pull-right btn-group"},this.renderShowMoreButton(),o.createElement("button",{onClick:this.onClickEdit,type:"button",className:"btn btn-link btn-xs"},"Edit"))}})),h=o.createClass({displayName:"ExcelCell",mixins:[i,n,l],overrides:{getCellClass:function(){return c({selected:this.isSelected()&&!this.isCopied()&&!this.isActive(),editing:this.isActive(),copied:this.isCopied(),"selected-draggable":this.isSelected()&&!this.isActive()&&this.canEdit(),"active-drag-cell":this.isActiveDragCell()&&this.canEdit(),"is-dragged-over-up":!this.isSelected()&&this.isDraggedOver()&&this.props.rowIdxthis.props.dragged.rowIdx,"was-dragged-over":this.wasDraggedOver()&&this.canEdit()})}},isActiveDragCell:function(){return(this.isSelected()||this.isDraggedOver())&&!this.isActive()},isExpanded:function(){var e=!1;if(a(this.props.column.getExpandedHeight)&&this.props.column.getExpandedHeight(this.props.value)>0){var t=this.props.column.getExpandedHeight(this.props.value);e=this.props.height>=t?!0:!1}return e},shouldComponentUpdate:function(e){return this.props.column.width!==e.column.width||this.props.value!==e.value||this.props.height!==e.height||this.props.rowIdx!==e.rowIdx||this.isCellSelectionChanging(e)||this.isDraggedCellChanging(e)},render:function(){return o.createElement(r,o.__spread({},this.props,{className:this.getCellClass(),onKeyDown:this.onKeyDown,onClick:this.onClick,onDoubleClick:this.onDoubleClick,formatter:this.getFormatter(),handleDragStart:this.handleDragStart,onDragEnter:this.handleDragEnter,onDragEnd:this.props.handleDragEnd,cellControls:this.props.column.showCellControls&&!this.isActive()?o.createElement(p,{height:this.props.height,value:this.props.value,rowIdx:this.props.rowIdx,column:this.props.column,onShowMore:this.props.onShowMore,onShowLess:this.props.onShowLess,onClickEdit:this.setActive}):null,isExpanded:this.isExpanded()}))}});e.exports=h},function(e,t,s){"use strict";var o=s(10),r=(o.addons.classSet,s(2)),i=s(11),n=o.createClass({displayName:"ExcelRow",render:function(){var e=o.addons.update(this.props.row,{$merge:{"select-row":this.props.isSelected}});return o.createElement(r,o.__spread({},this.props,{row:e,height:this.getRowHeight(this.props)}))},getRowHeight:function(e){return e.expandedRows&&e.expandedRows[e.key]?e.expandedRows[e.key]:e.height},hasRowHeightChanged:function(e){return e.expandedRows&&"undefined"!=typeof e.expandedRows[e.key]?this.props.height!==e.expandedRows[e.key]:!1},shouldComponentUpdate:function(e){return!i.sameColumns(this.props.columns,e.columns,i.sameColumn)||this.doesRowContainSelectedCell()||this.doesRowContainSelectedCell(e)||this.willRowBeDraggedOver(e)||this.hasRowBeenCopied()||e.row!==this.props.row||this.props.isSelected!==e.isSelected||this.hasRowHeightChanged(e)},doesRowContainSelectedCell:function(e){var t=e||this.props,s=s||t.cellRenderer;return s.props&&s.props.selected&&s.props.selected.rowIdx===t.idx?!0:!1},willRowBeDraggedOver:function(e){if(e.cellRenderer.props){var t=e.cellRenderer.props.dragged;return null!=t&&(t.rowIdx||t.complete===!0)}return!1},hasRowBeenCopied:function(){if(this.props.cellRenderer.props){var e=this.props.cellRenderer;return null!=e.props.copied&&e.props.copied.rowIdx===this.props.idx}return!1},setScrollLeft:function(e){for(var t=0,s=this.props.columns.length;s>t;t++)this.props.columns[t].locked&&this.refs[t].setScrollLeft(e)}});e.exports=n},function(e){"use strict";function t(e,t){var s={};for(var o in e)s[o]=e[o];for(var o in t)s[o]=t[o];return s}var s=function(e,t){var s={};return null!=e&&Object.assign(s,e),null!=t&&Object.assign(s,t),s};e.exports=Object.assign?s:t},function(e){"use strict";var t={getDefaultProps:function(){return{enableCellSelect:!1}},getColumns:function(){return this.props.columns},getInitialState:function(){return this.props.enableCellSelect?{selected:{rowIdx:0,idx:0}}:{selected:{rowIdx:-1,idx:-1}}},onSelect:function(e){if(this.props.enableCellSelect){var t=e.idx,s=e.rowIdx;t>=0&&s>=0&&t=0&&s>=0&&to.overRowIdx?s.rowIdx:o.overRowIdx,this.props.onCellsDragged({cellKey:r,fromRow:e,toRow:t,value:o.copiedText}),this.setState({dragged:{complete:!0}})},handleTerminateDrag:function(){this.setState({dragged:null})}};e.exports=i},function(e,t,s){"use strict";var o=s(10),r=(o.PropTypes,{propTypes:{onCellCopyPaste:o.PropTypes.func},getInitialState:function(){return{copied:null}},handleCopy:function(e){var t=e.value,s=this.state.selected,o={idx:s.idx,rowIdx:s.rowIdx};this.setState({textToCopy:t,copied:o})},handlePaste:function(){var e=this.state.selected,t=this.getColumns()[e.idx].key;this.props.onCellCopyPaste({cellKey:t,rowIdx:e.rowIdx,value:this.state.textToCopy,fromRow:this.state.copied.rowIdx,toRow:e.rowIdx}),this.setState({copied:null})}});e.exports=r},function(e,t,s){"use strict";var o=s(10),r=(o.PropTypes,s(19)),i={propTypes:{onRowUpdated:o.PropTypes.func},onCellCommit:function(e){var t=this.state.selected;t.active=!1,"Tab"===e.keyCode&&(t.idx+=1),this.setState({selected:t}),this.props.onRowUpdate(e)},onSetActive:function(e){var t=r(this.state.selected,e);this.setState({selected:t})}};e.exports=i},function(e,t,s){"use strict";var o=s(10),r=(o.PropTypes,s(36)),i=s(28),n={ASC:"ASC",DESC:"DESC"};Object.freeze(n);var l={getInitialState:function(){return{sortDirection:null,sortColumn:null}},getDecoratedColumns:function(){return this.props.columns.map(function(e){return e=i(e),e.sortable&&(e.headerRenderer=o.createElement(r,null),e.sortBy=this.sortBy,e.sorted=this.state.sortColumn===e.key?this.state.sortDirection:n.NONE),e},this)},sortBy:function(e,t){switch(t){case null:case void 0:t=n.ASC;break;case n.ASC:t=n.DESC;break;case n.DESC:t=null}this.setState({sortDirection:t,sortColumn:e.key})},sortRows:function(e){e=[].concat(e);var t=this.state.sortColumn,s=this.state.sortDirection;return null!=t&&null!==s?e.sort(function(e,o){var r=e[t],i=o[t];return s===n.ASC?r>i?1:i>r?-1:0:s===n.DESC?r>i?-1:i>r?1:0:void 0}):e}};e.exports=l},function(e,t,s){"use strict";var o=s(10),r=(o.PropTypes,s(37)),i={getInitialState:function(){return{canFilter:!1,columnFilters:{}}},filterRows:function(){var e=this.props.rows;return this.state.sortColumn&&(e=this.sortRows(e)),this.hasFilters()&&(e=e.map(function(e,t){return e.key=t,e}).filter(this.isRowDisplayed),this.props.onFilter&&this.props.onFilter(e)),e},hasFilters:function(){var e=!1;return Object.keys(this.state.columnFilters).every(function(t){var s=this.state.columnFilters[t];return null!=s&&void 0!=s&&""!=s?(e=!0,!1):!0},this),e},isRowDisplayed:function(e){var t=null;return Object.keys(this.state.columnFilters).every(function(s){var o=this.state.columnFilters[s].toLowerCase(),r=e[s].toString().toLowerCase();if(null!=o&&void 0!=o&&""!=o&&"string"==typeof r){if(!(r.indexOf(o)>-1))return t=!1,!1;t=!0}return!0},this),null==t?!1:t},onToggleFilter:function(){this.setState({canFilter:!this.state.canFilter})},handleAddFilter:function(e){var t=this.state.columnFilters;t[e.columnKey]=e.filterTerm,this.setState({columnFilters:t,selected:null})},getHeaderRows:function(){var e=[{ref:"row",height:this.props.rowHeight}];return this.state.canFilter===!0&&e.push({ref:"filterRow",headerCellRenderer:o.createElement(r,{onChange:this.handleAddFilter}),height:45}),e},getRowOffsetHeight:function(){var e=0;return this.getHeaderRows().forEach(function(t){return e+=t.height}),e}};e.exports=i},function(e,t,s){"use strict";var o=s(10),r=(o.addons.classSet,o.createClass({displayName:"CheckBoxEditor",PropTypes:{value:o.PropTypes.bool.isRequired},render:function(){return o.createElement("input",{className:"react-grid-CheckBox",type:"checkbox",checked:this.props.value,onChange:this.handleChange})},handleChange:function(){this.props.column.onRowSelect(this.props.rowIdx)},shouldComponentUpdate:function(e){return this.props.value!=e.value}}));e.exports=r},function(e,t,s){"use strict";var o=s(42),r=s(12),i=s(10);Object.assign||(Object.assign=s(38));var n=o({DEFINE_LIFE_CYCLE_METHOD:null,DEFINE_ONCE:null,DEFINE_MANY:null,OVERRIDE_BASE:null,DEFINE_MANY_MERGED:null}),l={getDefaultProps:n.DEFINE_LIFE_CYCLE_METHOD,propTypes:n.DEFINE_LIFE_CYCLE_METHOD,getInitialState:n.DEFINE_LIFE_CYCLE_METHOD,statics:n.DEFINE_LIFE_CYCLE_METHOD,displayName:n.DEFINE_LIFE_CYCLE_METHOD,componentWillMount:n.DEFINE_LIFE_CYCLE_METHOD,componentWillReceiveProps:n.DEFINE_LIFE_CYCLE_METHOD,shouldComponentUpdate:n.DEFINE_LIFE_CYCLE_METHOD,componentWillUpdate:n.DEFINE_LIFE_CYCLE_METHOD,componentDidUpdate:n.DEFINE_LIFE_CYCLE_METHOD,componentWillUnmount:n.DEFINE_LIFE_CYCLE_METHOD},a={},c=function(e,t){this.base=e,this.dependsOn=t},p=function(e){this.assignTo=function(t){return new c(t,e)}},h=function(e,t){Object.keys(e).forEach(function(s){if(f.isCustomProperty(s))r(e[s])&&(e[s]=f.wrapCustomMethod(s,e[s]));else{switch(l[s]){case n.DEFINE_LIFE_CYCLE_METHOD:var o={};o[s]=e[s],t.push(o);break;case n.DEFINE_MANY_MERGED:}delete e[s]}},this)},u={mix:function(e){var t=[],s={},o=f.getUniqueDependencies(e);for(var r in o)Object.assign(s,a[o[r]]);return h(s,t),e.forEach(function(e){var o={};e instanceof c?Object.assign(o,e.base):Object.assign(o,e),h(o,t),Object.assign(s,o)},this),t.push(s),t},createDependency:function(e){var t=[];for(var s in e)e[s]instanceof c?this.addAlias(s,e[s].base):this.addAlias(s,e[s]),t.push(s);var o=t.filter(function(e,t,s){return s.indexOf(e)===t});return new p(o)},addAlias:function(e,t){a[e]=t}},d=i.createClass;i.createClass=function(e){return e.mixins&&(e.mixins=u.mix(e.mixins)),d.apply(i,arguments)};var f={isCustomProperty:function(e){return!l[e]},wrapCustomMethod:function(e,t){return function(){return f.isMethodOverridden.call(this,e)?f.callOverriddenMethod.call(this,e,arguments):t.apply(this,arguments)}},checkMethodExtendedAndCall:function(e,t){return this.extended&&"function"==typeof this.extended[e]?this.extended[e].call(this,t):void 0},checkMethodImplementedAndCall:function(e,t){return this.implemented&&"function"==typeof this.implemented[e]?this.implemented[e].call(this,t):void 0},isMethodOverridden:function(e){return this.overrides&&"function"==typeof this.overrides[e]},callOverriddenMethod:function(e,t){return this.overrides[e].call(this,t)},getUniqueDependencies:function(e){var t=[];return e.forEach(function(e){e instanceof c&&(t=t.concat(e.dependsOn))},this),t.filter(function(e,t,s){return s.indexOf(e)===t})}};e.exports=u},function(e){"use strict";function t(e){var t={};for(var s in e)e.hasOwnProperty(s)&&(t[s]=e[s]);return t}e.exports=t},function(e,t,s){"use strict";var o=s(10),r=s(40),i=s(28),n=s(41),l={metricsComputator:o.PropTypes.object},a={childContextTypes:l,getChildContext:function(){return{metricsComputator:this}},getMetricImpl:function(e){return this._DOMMetrics.metrics[e].value},registerMetricsImpl:function(e,t){var s={},o=this._DOMMetrics;for(var r in t)n(void 0===o.metrics[r],"DOM metric "+r+" is already defined"),o.metrics[r]={component:e,computator:t[r].bind(e)},s[r]=this.getMetricImpl.bind(null,r);return-1===o.components.indexOf(e)&&o.components.push(e),s},unregisterMetricsFor:function(e){var t=this._DOMMetrics,s=t.components.indexOf(e);if(s>-1){t.components.splice(s,1);var o,r={};for(o in t.metrics)t.metrics[o].component===e&&(r[o]=!0);for(o in r)delete t.metrics[o]}},updateMetrics:function(){var e=this._DOMMetrics,t=!1;for(var s in e.metrics){var o=e.metrics[s].computator();o!==e.metrics[s].value&&(t=!0),e.metrics[s].value=o}if(t)for(var r=0,i=e.components.length;i>r;r++)e.components[r].metricsUpdated&&e.components[r].metricsUpdated() -},componentWillMount:function(){this._DOMMetrics={metrics:{},components:[]}},componentDidMount:function(){window.addEventListener?window.addEventListener("resize",this.updateMetrics):window.attachEvent("resize",this.updateMetrics),this.updateMetrics()},componentWillUnmount:function(){window.removeEventListener("resize",this.updateMetrics)}},c={contextTypes:l,componentWillMount:function(){if(this.DOMMetrics){this._DOMMetricsDefs=i(this.DOMMetrics),this.DOMMetrics={};for(var e in this._DOMMetricsDefs)this.DOMMetrics[e]=r}},componentDidMount:function(){this.DOMMetrics&&(this.DOMMetrics=this.registerMetrics(this._DOMMetricsDefs))},componentWillUnmount:function(){return this.registerMetricsImpl?void(this.hasOwnProperty("DOMMetrics")&&delete this.DOMMetrics):this.context.metricsComputator.unregisterMetricsFor(this)},registerMetrics:function(e){return this.registerMetricsImpl?this.registerMetricsImpl(this,e):this.context.metricsComputator.registerMetricsImpl(this,e)},getMetric:function(e){return this.getMetricImpl?this.getMetricImpl(e):this.context.metricsComputator.getMetricImpl(e)}};e.exports={MetricsComputatorMixin:a,MetricsMixin:c}},function(e,t,s){"use strict";var o=s(10),r=o.addons.classSet,i=s(28),n=s(11),l=s(45),n=s(11),a=o.createClass({displayName:"Header",propTypes:{columns:o.PropTypes.object.isRequired,totalWidth:o.PropTypes.number,height:o.PropTypes.number.isRequired,headerRows:o.PropTypes.array.isRequired},render:function(){var e=(this.state.resizing||this.props,r({"react-grid-Header":!0,"react-grid-Header--resizing":!!this.state.resizing})),t=this.getHeaderRows();return o.createElement("div",o.__spread({},this.props,{style:this.getStyle(),className:e}),t)},shouldComponentUpdate:function(e,t){return!n.sameColumns(this.props.columns.columns,e.columns.columns,n.sameColumn)||this.props.totalWidth!=e.totalWidth||this.props.headerRows.length!=e.headerRows.length||this.state.resizing!=t.resizing},getHeaderRows:function(){var e=this.state.resizing||this.props,t=[];return this.props.headerRows.forEach(function(s,r){var i={position:"absolute",top:this.props.height*r,left:0,width:this.props.totalWidth};t.push(o.createElement(l,{key:s.ref,ref:s.ref,style:i,onColumnResize:this.onColumnResize,onColumnResizeEnd:this.onColumnResizeEnd,width:e.columns.width,height:s.height||this.props.height,columns:e.columns.columns,resizing:e.column,headerCellRenderer:s.headerCellRenderer}))}.bind(this)),t},getInitialState:function(){return{resizing:null}},componentWillReceiveProps:function(){this.setState({resizing:null})},onColumnResize:function(e,t){var s=this.state.resizing||this.props,o=this.getColumnPosition(e);if(null!==o){var r={columns:i(s.columns)};r.columns=n.resizeColumn(r.columns,o,t),r.columns.widththis.props.dragged.rowIdx,"was-dragged-over":this.wasDraggedOver()})},getDefaultProps:function(){return{handleDragStart:this.handleDragStart,onDragEnter:this.handleDragEnter,onDragEnd:this.handleDragEnd}},propTypes:{handleDragEnter:o.PropTypes.func.isRequired,handleDragStart:o.PropTypes.func.isRequired,handleDragEnd:o.PropTypes.func.isRequired,handleTerminateDrag:o.PropTypes.func.isRequired},isDraggedOver:function(){return this.props.dragged&&this.props.dragged.overRowIdx===this.props.rowIdx&&this.props.dragged.idx===this.props.idx},wasDraggedOver:function(){return this.props.dragged&&(this.props.dragged.overRowIdxthis.props.rowIdx&&this.props.rowIdx>this.props.dragged.rowIdx)&&this.props.dragged.idx===this.props.idx},handleDragStart:function(){var e=this.props.rowIdx,t=this.props.idx;this.props.handleDragStart({rowIdx:e,idx:t,copiedText:this.props.value})},handleDragEnter:function(){this.props.handleDragEnter(this.props.rowIdx)},handleDragEnd:function(){this.props.handleDragEnd()},isDraggedCellChanging:function(e){return this.props.dragged?e.dragged&&this.props.idx===e.dragged.idx||this.props.dragged&&this.props.idx===this.props.dragged.idx:!1},componentDidUpdate:function(){var e=this.props.dragged;e&&e.complete===!0&&this.props.handleTerminateDrag()}});e.exports=a},function(e,t,s){"use strict";var o=s(10),r=o.addons.classSet,i=o.createClass({displayName:"SortableHeaderCell",onClick:function(){this.props.column.sortBy(this.props.column,this.props.column.sorted)},getSortByClass:function(){var e=this.props.column.sorted;return r({"pull-right":!0,"glyphicon glyphicon-arrow-up":"ASC"===e,"glyphicon glyphicon-arrow-down":"DESC"===e})},render:function(){return o.createElement("div",{onClick:this.onClick,style:{cursor:"pointer"}},this.props.column.name,o.createElement("span",{className:this.getSortByClass()}))}});e.exports=i},function(e,t,s){"use strict";var o=s(10),r=(o.addons.classSet,o.createClass({displayName:"FilterableHeaderCell",getInitialState:function(){return{filterTerm:""}},handleChange:function(e){e.preventDefault(),e.stopPropagation(),this.setState({filterTerm:e.currentTarget.value}),this.props.onChange({filterTerm:e.currentTarget.value,columnKey:this.props.column.key})},componentDidUpdate:function(){this.getDOMNode().focus()},render:function(){return o.createElement("div",null,o.createElement("div",{className:"form-group"},o.createElement(this.renderInput,null)))},renderInput:function(){return this.props.column.filterable===!1?o.createElement("span",null):o.createElement("input",{type:"text",className:"form-control input-sm",placeholder:"Search",value:this.state.filterTerm,onChange:this.handleChange})}}));e.exports=r},function(e){"use strict";function t(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}e.exports=Object.assign||function(e){for(var s,o,r=t(e),i=1;ir;r++)t.exec(e[r].title)&&o.push(e[r]);s(null,o)}var r=s(1),i=r.addons.classSet,n=r.createClass({displayName:"Autocomplete",propTypes:{options:r.PropTypes.any,search:r.PropTypes.func,resultRenderer:r.PropTypes.oneOfType([r.PropTypes.component,r.PropTypes.func]),value:r.PropTypes.object,onChange:r.PropTypes.func,onError:r.PropTypes.func},getDefaultProps:function(){return{search:o}},getInitialState:function(){var e=this.props.searchTerm?this.props.searchTerm:this.props.value?this.props.value.title:"";return{results:[],showResults:!1,showResultsInProgress:!1,searchTerm:e,focusedValue:null}},getResultIdentifier:function(e){return void 0===this.props.resultIdentifier?e.id:e[this.props.resultIdentifier]},render:function(){var e=i(this.props.className,"react-autocomplete-Autocomplete",this.state.showResults?"react-autocomplete-Autocomplete--resultsShown":void 0),t={position:"relative",outline:"none"};return r.createElement("div",{tabIndex:"1",className:e,onFocus:this.onFocus,onBlur:this.onBlur,style:t},r.createElement("input",{ref:"search",className:"react-autocomplete-Autocomplete__search",style:{width:"100%"},onClick:this.showAllResults,onChange:this.onQueryChange,onFocus:this.showAllResults,onBlur:this.onQueryBlur,onKeyDown:this.onQueryKeyDown,value:this.state.searchTerm}),r.createElement(l,{className:"react-autocomplete-Autocomplete__results",onSelect:this.onValueChange,onFocus:this.onValueFocus,results:this.state.results,focusedValue:this.state.focusedValue,show:this.state.showResults,renderer:this.props.resultRenderer,label:this.props.label,resultIdentifier:this.props.resultIdentifier}))},componentWillReceiveProps:function(e){var t=e.searchTerm?e.searchTerm:e.value?e.value.title:"";this.setState({searchTerm:t})},componentWillMount:function(){this.blurTimer=null},showResults:function(e){this.setState({showResultsInProgress:!0}),this.props.search(this.props.options,e.trim(),this.onSearchComplete)},showAllResults:function(){this.state.showResultsInProgress||this.state.showResults||this.showResults("")},onValueChange:function(e){var t={value:e,showResults:!1};e&&(t.searchTerm=e.title),this.setState(t),this.props.onChange&&this.props.onChange(e)},onSearchComplete:function(e,t){if(e){if(!this.props.onError)throw e;this.props.onError(e)}this.setState({showResultsInProgress:!1,showResults:!0,results:t})},onValueFocus:function(e){this.setState({focusedValue:e})},onQueryChange:function(e){var t=e.target.value;this.setState({searchTerm:t,focusedValue:null}),this.showResults(t)},onFocus:function(){this.blurTimer&&(clearTimeout(this.blurTimer),this.blurTimer=null),this.refs.search.getDOMNode().focus()},onBlur:function(){this.blurTimer=setTimeout(function(){this.isMounted()&&this.setState({showResults:!1})}.bind(this),100)},onQueryKeyDown:function(e){if("Enter"===e.key)e.preventDefault(),this.state.focusedValue&&this.onValueChange(this.state.focusedValue);else if("ArrowUp"===e.key&&this.state.showResults){e.preventDefault();var t=Math.max(this.focusedValueIndex()-1,0);this.setState({focusedValue:this.state.results[t]})}else if("ArrowDown"===e.key)if(e.preventDefault(),this.state.showResults){var s=Math.min(this.focusedValueIndex()+(this.state.showResults?1:0),this.state.results.length-1);this.setState({showResults:!0,focusedValue:this.state.results[s]})}else this.showAllResults()},focusedValueIndex:function(){if(!this.state.focusedValue)return-1;for(var e=0,t=this.state.results.length;t>e;e++)if(this.getResultIdentifier(this.state.results[e])===this.getResultIdentifier(this.state.focusedValue))return e;return-1}}),l=r.createClass({displayName:"Results",getResultIdentifier:function(e){if(void 0===this.props.resultIdentifier){if(!e.id)throw"id property not found on result. You must specify a resultIdentifier and pass as props to autocomplete component";return e.id}return e[this.props.resultIdentifier]},render:function(){var e={display:this.props.show?"block":"none",position:"absolute",listStyleType:"none"},t=this.props,s=t.className,o=function(e,t){var s={},o=Object.prototype.hasOwnProperty;if(null==e)throw new TypeError;for(var r in e)o.call(e,r)&&!o.call(t,r)&&(s[r]=e[r]);return s}(t,{className:1});return r.createElement("ul",r.__spread({},o,{style:e,className:s+" react-autocomplete-Results"}),this.props.results.map(this.renderResult))},renderResult:function(e){var t=this.props.focusedValue&&this.getResultIdentifier(this.props.focusedValue)===this.getResultIdentifier(e),s=this.props.renderer||a;return s({ref:t?"focused":void 0,key:this.getResultIdentifier(e),result:e,focused:t,onMouseEnter:this.onMouseEnterResult,onClick:this.props.onSelect,label:this.props.label})},componentDidUpdate:function(){this.scrollToFocused()},componentDidMount:function(){this.scrollToFocused()},componentWillMount:function(){this.ignoreFocus=!1},scrollToFocused:function(){var e=this.refs&&this.refs.focused;if(e){var t=this.getDOMNode(),s=t.scrollTop,o=t.offsetHeight,r=e.getDOMNode(),i=r.offsetTop,n=i+r.offsetHeight;s>i?(this.ignoreFocus=!0,t.scrollTop=i):n-s>o&&(this.ignoreFocus=!0,t.scrollTop=n-o)}},onMouseEnterResult:function(e,t){if(this.ignoreFocus)this.ignoreFocus=!1;else{var s=this.getDOMNode(),o=s.scrollTop,r=s.offsetHeight,i=e.target,n=i.offsetTop,l=n+i.offsetHeight;l>o&&o+r>n&&this.props.onFocus(t)}}}),a=r.createClass({displayName:"Result",getDefaultProps:function(){return{label:function(e){return e.title}}},getLabel:function(e){return"function"==typeof this.props.label?this.props.label(e):"string"==typeof this.props.label?e[this.props.label]:void 0},render:function(){var e=i({"react-autocomplete-Result":!0,"react-autocomplete-Result--active":this.props.focused});return r.createElement("li",{style:{listStyleType:"none"},className:e,onClick:this.onClick,onMouseEnter:this.onMouseEnter},r.createElement("a",null,this.getLabel(this.props.result)))},onClick:function(){this.props.onClick(this.props.result)},onMouseEnter:function(e){this.props.onMouseEnter&&this.props.onMouseEnter(e,this.props.result)},shouldComponentUpdate:function(e){return e.result.id!==this.props.result.id||e.focused!==this.props.focused}});e.exports=n},function(t){t.exports=e}])})},function(e,t,s){"use strict";function o(e){return function(){return e}}function r(){}var i=s(46);i(r,{thatReturns:o,thatReturnsFalse:o(!1),thatReturnsTrue:o(!0),thatReturnsNull:o(null),thatReturnsThis:function(){return this},thatReturnsArgument:function(e){return e}}),e.exports=r},function(e,t,s){(function(t){"use strict";var s=function(e,s,o,r,i,n,l,a){if(t.env.NODE_ENV&&void 0===s)throw new Error("invariant requires an error message argument");if(!e){var c;if(void 0===s)c=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var p=[o,r,i,n,l,a],h=0;c=new Error("Invariant Violation: "+s.replace(/%s/g,function(){return p[h++]}))}throw c.framesToPop=1,c}};e.exports=s}).call(t,s(52))},function(e,t,s){(function(t){"use strict";var o=s(51),r=function(e){var s,r={};"production"!==t.env.NODE_ENV?o(e instanceof Object&&!Array.isArray(e),"keyMirror(...): Argument must be an object."):o(e instanceof Object&&!Array.isArray(e));for(s in e)e.hasOwnProperty(s)&&(r[s]=s);return r};e.exports=r}).call(t,s(52))},function(e){"use strict";function t(){var e=window.innerWidth,t=window.innerHeight;return e&&t||(e=document.documentElement.clientWidth,t=document.documentElement.clientHeight),e&&t||(e=document.body.clientWidth,t=document.body.clientHeight),{width:e,height:t}}e.exports=t},function(e,t,s){"use strict";var o=s(10),r=o.addons.classSet,i=o.PropTypes,n=o.addons.cloneWithProps,l=s(47),a=s(40),c=s(48),p=s(2),h=o.createClass({displayName:"Canvas",mixins:[c],propTypes:{cellRenderer:i.element,rowRenderer:i.oneOfType([i.func,i.element]),rowHeight:i.number.isRequired,displayStart:i.number.isRequired,displayEnd:i.number.isRequired,length:i.number.isRequired,rows:i.oneOfType([i.func.isRequired,i.array.isRequired]),onRows:i.func},render:function(){var e=this.state.displayStart,t=this.state.displayEnd,s=this.props.rowHeight,i=this.props.length,n=this.getRows(e,t).map(function(t,o){return this.renderRow({key:e+o,ref:o,idx:e+o,row:t,height:s,columns:this.props.columns,cellRenderer:this.props.cellRenderer,isSelected:this.isRowSelected(e+o),expandedRows:this.props.expandedRows})}.bind(this));this._currentRowsLength=n.length,e>0&&n.unshift(this.renderPlaceholder("top",e*s)),i-t>0&&n.push(this.renderPlaceholder("bottom",(i-t)*s));var l={position:"absolute",top:0,left:0,overflowX:"auto",overflowY:"scroll",width:this.props.totalWidth,height:this.props.height,transform:"translate3d(0, 0, 0)"};return o.createElement("div",{style:l,onScroll:this.onScroll,className:r("react-grid-Canvas",this.props.className)},o.createElement("div",{style:{width:this.props.width,overflow:"hidden"}},n))},renderRow:function(e){return o.isValidElement(this.props.rowRenderer)?n(this.props.rowRenderer,e):this.props.rowRenderer(e)},renderPlaceholder:function(e,t){return o.createElement("div",{key:e,style:{height:t}},this.props.columns.map(function(e,t){return o.createElement("div",{style:{width:e.width},key:t})}))},getDefaultProps:function(){return{rowRenderer:o.createElement(p,null),onRows:a}},isRowSelected:function(e){return this.props.selectedRows&&this.props.selectedRows[e]===!0},getInitialState:function(){return{shouldUpdate:!0,displayStart:this.props.displayStart,displayEnd:this.props.displayEnd}},componentWillMount:function(){this._currentRowsLength=void 0,this._currentRowsRange=void 0,this._scroll=void 0},componentDidMount:function(){this.onRows()},componentDidUpdate:function(){void 0!==this._scroll&&this.setScrollLeft(this._scroll),this.onRows()},componentWillUnmount:function(){this._currentRowsLength=void 0,this._currentRowsRange=void 0,this._scroll=void 0},componentWillReceiveProps:function(e){var t=!(e.visibleStart>this.state.displayStart&&e.visibleEndt;t++)this.refs[t]&&this.refs[t].setScrollLeft(e)},getScroll:function(){var e=this.getDOMNode(),t=e.scrollTop,s=e.scrollLeft;return{scrollTop:t,scrollLeft:s}},onScroll:function(e){this.appendScrollShim();var t=e.target,s=t.scrollTop,o=t.scrollLeft,r={scrollTop:s,scrollLeft:o};this._scroll=r,this.props.onScroll(r)}});e.exports=h},function(e,t,s){"use strict";var o=s(10),r=o.PropTypes,i=s(47),n=s(49),l=s(50),a=o.createClass({displayName:"HeaderRow",propTypes:{width:r.number,height:r.number.isRequired,columns:r.array.isRequired,onColumnResize:r.func},render:function(){var e={width:this.props.width?this.props.width+l():"100%",height:this.props.height,whiteSpace:"nowrap",overflowX:"hidden",overflowY:"hidden"},t=this.getCells();return o.createElement("div",o.__spread({},this.props,{className:"react-grid-HeaderRow"}),o.createElement("div",{style:e},t))},getCells:function(){for(var e=[],t=[],s=0,r=this.props.columns.length;r>s;s++){var i=this.props.columns[s],l=o.createElement(n,{ref:s,key:s,height:this.props.height,column:i,renderer:this.props.headerCellRenderer||i.headerRenderer||this.props.cellRenderer,resizing:this.props.resizing===i,onResize:this.props.onColumnResize,onResizeEnd:this.props.onColumnResizeEnd});i.locked?t.push(l):e.push(l)}return e.concat(t)},setScrollLeft:function(e){for(var t=0,s=this.props.columns.length;s>t;t++)this.props.columns[t].locked&&this.refs[t].setScrollLeft(e)},shouldComponentUpdate:function(e){return e.width!==this.props.width||e.height!==this.props.height||e.columns!==this.props.columns||!i(e.style,this.props.style)},getStyle:function(){return{overflow:"hidden",width:"100%",height:this.props.height,position:"absolute"}}});e.exports=a},function(e,t,s){(function(t){"use strict";function s(e,s,o,r,i,n,l){if(e=e||{},t.env.NODE_ENV&&l)throw new Error("Too many arguments passed to copyProperties");for(var a,c=[s,o,r,i,n],p=0;c[p];){a=c[p++];for(var h in a)e[h]=a[h];a.hasOwnProperty&&a.hasOwnProperty("toString")&&"undefined"!=typeof a.toString&&e.toString!==a.toString&&(e.toString=a.toString)}return e}e.exports=s}).call(t,s(52))},function(e){"use strict";function t(e,t){if(e===t)return!0;var s;for(s in e)if(e.hasOwnProperty(s)&&(!t.hasOwnProperty(s)||e[s]!==t[s]))return!1;for(s in t)if(t.hasOwnProperty(s)&&!e.hasOwnProperty(s))return!1;return!0}e.exports=t},function(e){"use strict";var t={appendScrollShim:function(){if(!this._scrollShim){var e=this._scrollShimSize(),t=document.createElement("div");t.classList.add("react-grid-ScrollShim"),t.style.position="absolute",t.style.top=0,t.style.left=0,t.style.width=e.width+"px",t.style.height=e.height+"px",this.getDOMNode().appendChild(t),this._scrollShim=t}this._scheduleRemoveScrollShim()},_scrollShimSize:function(){return{width:this.props.width,height:this.props.length*this.props.rowHeight}},_scheduleRemoveScrollShim:function(){this._scheduleRemoveScrollShimTimer&&clearTimeout(this._scheduleRemoveScrollShimTimer),this._scheduleRemoveScrollShimTimer=setTimeout(this._removeScrollShim,200)},_removeScrollShim:function(){this._scrollShim&&(this._scrollShim.parentNode.removeChild(this._scrollShim),this._scrollShim=void 0)}};e.exports=t},function(e,t,s){"use strict";function o(e){return r.createElement("div",{className:"rex-widget-HeaderCell__value"},e.column.name)}var r=s(10),i=r.addons.classSet,n=s(53),l=r.PropTypes,a=r.createClass({displayName:"ResizeHandle",style:{position:"absolute",top:0,right:0,width:6,height:"100%"},render:function(){return r.createElement(n,r.__spread({},this.props,{className:"react-grid-HeaderCell__resizeHandle",style:this.style}))}}),c=r.createClass({displayName:"HeaderCell",propTypes:{renderer:l.oneOfType([l.func,l.element]).isRequired,column:l.object.isRequired,onResize:l.func},render:function(){var e=i({"react-grid-HeaderCell":!0,"react-grid-HeaderCell--resizing":this.state.resizing,"react-grid-HeaderCell--locked":this.props.column.locked});e=i(e,this.props.className);var t=this.getCell();return r.createElement("div",{className:e,style:this.getStyle()},t,this.props.column.resizeable?r.createElement(a,{onDrag:this.onDrag,onDragStart:this.onDragStart,onDragEnd:this.onDragEnd}):null)},getCell:function(){return r.isValidElement(this.props.renderer)?r.addons.cloneWithProps(this.props.renderer,{column:this.props.column}):this.props.renderer({column:this.props.column})},getDefaultProps:function(){return{renderer:o}},getInitialState:function(){return{resizing:!1}},setScrollLeft:function(e){var t=this.getDOMNode();t.style.webkitTransform="translate3d("+e+"px, 0px, 0px)",t.style.transform="translate3d("+e+"px, 0px, 0px)"},getStyle:function(){return{width:this.props.column.width,left:this.props.column.left,display:"inline-block",position:"absolute",overflow:"hidden",height:this.props.height,margin:0,textOverflow:"ellipsis",whiteSpace:"nowrap"}},onDragStart:function(){this.setState({resizing:!0})},onDrag:function(e){var t=this.getWidthFromMouseEvent(e);t>0&&this.props.onResize&&this.props.onResize(this.props.column,t)},onDragEnd:function(e){var t=this.getWidthFromMouseEvent(e);this.props.onResizeEnd(this.props.column,t),this.setState({resizing:!1})},getWidthFromMouseEvent:function(e){var t=e.pageX,s=this.getDOMNode().getBoundingClientRect().left;return t-s}});e.exports=c},function(e){"use strict";function t(){if(void 0===s){var e=document.createElement("div");e.style.width="50px",e.style.height="50px",e.style.overflowY="scroll",e.style.position="absolute",e.style.top="-200px",e.style.left="-200px";var t=document.createElement("div");t.style.height="100px",t.style.width="100%",e.appendChild(t),document.body.appendChild(e);var o=e.offsetWidth,r=t.offsetWidth;document.body.removeChild(e),s=o-r}return s}var s;e.exports=t},function(e,t,s){(function(t){"use strict";var s=function(e,s,o,r,i,n,l,a){if("production"!==t.env.NODE_ENV&&void 0===s)throw new Error("invariant requires an error message argument");if(!e){var c;if(void 0===s)c=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var p=[o,r,i,n,l,a],h=0;c=new Error("Invariant Violation: "+s.replace(/%s/g,function(){return p[h++]}))}throw c.framesToPop=1,c}};e.exports=s}).call(t,s(52))},function(e){function t(){}var s=e.exports={};s.nextTick=function(){var e="undefined"!=typeof window&&window.setImmediate,t="undefined"!=typeof window&&window.MutationObserver,s="undefined"!=typeof window&&window.postMessage&&window.addEventListener;if(e)return function(e){return window.setImmediate(e)};var o=[];if(t){var r=document.createElement("div"),i=new MutationObserver(function(){var e=o.slice();o.length=0,e.forEach(function(e){e()})});return i.observe(r,{attributes:!0}),function(e){o.length||r.setAttribute("yes","no"),o.push(e)}}return s?(window.addEventListener("message",function(e){var t=e.source;if((t===window||null===t)&&"process-tick"===e.data&&(e.stopPropagation(),o.length>0)){var s=o.shift();s()}},!0),function(e){o.push(e),window.postMessage("process-tick","*")}):function(e){setTimeout(e,0)}}(),s.title="browser",s.browser=!0,s.env={},s.argv=[],s.on=t,s.addListener=t,s.once=t,s.off=t,s.removeListener=t,s.removeAllListeners=t,s.emit=t,s.binding=function(){throw new Error("process.binding is not supported")},s.cwd=function(){return"/"},s.chdir=function(){throw new Error("process.chdir is not supported") -}},function(e,t,s){"use strict";var o=s(10),r=o.PropTypes,i=s(40),n=o.createClass({displayName:"Draggable",propTypes:{onDragStart:r.func,onDragEnd:r.func,onDrag:r.func,component:r.oneOfType([r.func,r.constructor])},render:function(){var e=this.props.component;return o.createElement(e,o.__spread({},this.props,{onMouseDown:this.onMouseDown}))},getDefaultProps:function(){return{component:o.DOM.div,onDragStart:i.thatReturnsTrue,onDragEnd:i,onDrag:i}},getInitialState:function(){return{drag:null}},onMouseDown:function(e){var t=this.props.onDragStart(e);(null!==t||0===e.button)&&(window.addEventListener("mouseup",this.onMouseUp),window.addEventListener("mousemove",this.onMouseMove),this.setState({drag:t}))},onMouseMove:function(e){null!==this.state.drag&&(e.stopPropagation&&e.stopPropagation(),e.preventDefault&&e.preventDefault(),this.props.onDrag(e))},onMouseUp:function(e){this.cleanUp(),this.props.onDragEnd(e,this.state.drag),this.setState({drag:null})},componentWillUnmount:function(){this.cleanUp()},cleanUp:function(){window.removeEventListener("mouseup",this.onMouseUp),window.removeEventListener("mousemove",this.onMouseMove)}});e.exports=n}])}); \ No newline at end of file diff --git a/examples/examples.html b/examples/examples.html index 58bb5de..766585d 100644 --- a/examples/examples.html +++ b/examples/examples.html @@ -1,77 +1,61 @@ - - - - - - React Grid - Excel-like grid component built with React - - - - - - - - - - - here - - - - - - - - - - - + + + + + +React Grid - Excel-like grid component built with React + + + + + + +here + + + + + + + - - - - - - - - -
-
- -
-
-
-
- - - - - - - - - + + + +
+
+ +
+
+
+
+ + + + + + + + + diff --git a/examples/examples.js b/examples/examples.js index 5e81cfb..56497bf 100644 --- a/examples/examples.js +++ b/examples/examples.js @@ -1,13 +1,12 @@ - -var { Route, RouteHandler, Link } = ReactRouter; +var React = require('react/addons'); +var ReactRouter = require('react-router'); var basicExample = require('./scripts/exampleBasic'); var editableExample = require('./scripts/exampleEditable'); -var App = React.createClass({ - - +var { Route, RouteHandler, Link } = ReactRouter; +var App = React.createClass({ render: function () { return (
diff --git a/examples/index.html b/examples/index.html index f4ae437..fadf41b 100644 --- a/examples/index.html +++ b/examples/index.html @@ -10,16 +10,16 @@ - - - + + + - - - + + + - @@ -48,7 +48,10 @@

React Grid

Excel-like grid component built with React

-

DEMO DOWNLOAD NOW

+

+ DEMO + DOWNLOAD NOW +

diff --git a/examples/scripts/ExcelGrid.js b/examples/scripts/ExcelGrid.js index 27b488e..7db8bb7 100644 --- a/examples/scripts/ExcelGrid.js +++ b/examples/scripts/ExcelGrid.js @@ -9,9 +9,46 @@ var DropDownEditor = Editors.DropDownEditor; var cx = React.addons.classSet; var cloneWithProps = React.addons.cloneWithProps; - + var FakeObjectDataStoreList = require('./FakeObjectDataStoreList'); var developers = ['Conor','Curtis','Danny','Joao','Mo','Rich']; - var epics = [{id : 0, title : 'Unification Of Media'}, { id : 1, title : 'Trading Desk'}, { id : 2, title : 'Tech Costs'}, { id : 3, title : 'Tactical'}, { id : 4, title : 'Barter'}, { id : 5, title :'Lego'}, {id : 6, title : 'Media Plan'}, {id : 7, title : 'Infrastructure'}]; + var counties = [{id : 0, title : 'Bedfordshire'}, { id : 1, title : 'Berkshire'}, { id : 2, title : 'Buckinghamshire'}, { id : 3, title : 'Cambridgeshire'}, { id : 4, title : 'Cheshire'}, { id : 5, title :'Cornwall'}, {id : 6, title : 'Cumbria, (Cumberland)'}, {id : 7, title : 'Derbyshire'}, { id : 8, title :'Devon'}, { id : 9, title :'Dorset'}, + { id : 10, title :'Durham'}, + { id : 11, title :'Essex'}, + { id : 12, title :'Gloucestershire'}, + { id : 13, title :'Hampshire'}, + { id : 14, title :'Hertfordshire'}, + { id : 15, title :'Huntingdonshire'}, + { id : 16, title :'Kent'}, + { id : 17, title :'Lancashire'}, + { id : 18, title :'Leicestershire'}, + { id : 19, title :'Lincolnshire'}, + { id : 20, title :'Middlesex'}, + { id : 21, title :'Norfolk'}, + { id : 22, title :'Northamptonshire'}, + { id : 23, title :'Northumberland'}, + { id : 24, title :'Nottinghamshire'}, + { id : 25, title :'Northamptonshire'}, + { id : 26, title :'Oxfordshire'}, + { id : 27, title :'Northamptonshire'}, + { id : 28, title :'Rutland'}, + { id : 29, title :'Shropshire'}, + { id : 30, title :'Somerset'}, + { id : 31, title :'Staffordshire'}, + { id : 32, title :'Suffolk'}, + { id : 33, title :'Surrey'}, + { id : 34, title :'Sussex'}, + { id : 35, title :'Warwickshire'}, + { id : 36, title :'Westmoreland'}, + { id : 37, title :'Wiltshire'}, + { id : 38, title :'Worcestershire'}, + { id : 39, title :'Yorkshire'}] + +var titles = ['Mr.', 'Mrs.', 'Miss', 'Ms.']; + + function renderImage(cellData) { + var ImageFormatter = ReactGrid.Formatters.ImageFormatter; + return ; + } var columns = [ { @@ -20,47 +57,95 @@ width : 80 }, { - key: 'userStory', - name: 'User Story', - editable : true, - sortable : true, - resizeable : true, - showCellControls : true + key: 'avartar', + name: 'Avartar', + width : 60, + formatter : renderImage + }, + { + key: 'county', + name: 'County', + editor: , + width : 200 + }, + { + key: 'title', + name: 'Title', + editor : , + width : 200 + }, + { + key: 'firstName', + name: 'First Name', + editable:true, + width : 200 + }, + { + key: 'lastName', + name: 'Last Name', + editable:true, + width : 200 + }, + { + key: 'email', + name: 'Email', + editable:true, + width : 200 + }, + { + key: 'street', + name: 'Street', + editable:true, + width : 200 }, { - key: 'developer', - name: 'Developer', - editor : , - sortable : true, - resizeable : true + key: 'zipCode', + name: 'ZipCode', + editable:true, + width : 200 }, { - key: 'epic', - name: 'Epic', - editor : , - sortable : true + key: 'date', + name: 'Date', + editable:true, + width : 200 + }, + { + key: 'bs', + name: 'bs', + editable:true, + width : 200 + }, + { + key: 'catchPhrase', + name: 'Catch Phrase', + editable:true, + width : 200 + }, + { + key: 'companyName', + name: 'Company Name', + editable:true, + width : 200 + }, + { + key: 'words', + name: 'Words', + editable:true, + width : 200 + }, + { + key: 'sentence', + name: 'Sentence', + editable:true, + width : 200 } - ] - var getRows = function(start, end) { - var result = [] - for (var i = start; i < end; i++) { - result.push({ - id: i, - userStory: 'User Story ' + i, - developer : developers[i%6], - epic : epics[i%8].title - }); - } - return result; - } - - var Component = React.createClass({displayName: 'component', getInitialState : function(){ - return {rows : getRows(0, 1000)}; + return {rows : FakeObjectDataStoreList.getRows(1000)}; }, handleRowUpdated : function(commit){ @@ -108,7 +193,8 @@ onCellCopyPaste={this.handleCellCopyPaste} toolbar={} enableRowSelect={true} - + rowHeight={50} + minHeight={600} /> ); } diff --git a/examples/scripts/FakeObjectDataStoreList.js b/examples/scripts/FakeObjectDataStoreList.js new file mode 100644 index 0000000..5ffbe68 --- /dev/null +++ b/examples/scripts/FakeObjectDataStoreList.js @@ -0,0 +1,38 @@ +var faker = require('faker'); +faker.locale = 'en_GB'; +var SIZE = 2000; +var _cache = []; + +function createFakeRowObjectData(/*number*/ index) { + return { + id: 'id_' + index, + avartar: faker.image.avatar(), + county: faker.address.county(), + email: faker.internet.email(), + title: faker.name.prefix(), + firstName: faker.name.firstName(), + lastName: faker.name.lastName(), + street: faker.address.streetName(), + zipCode: faker.address.zipCode(), + date: faker.date.past(), + bs: faker.company.bs(), + catchPhrase: faker.company.catchPhrase(), + companyName: faker.company.companyName(), + words: faker.lorem.words(), + sentence: faker.lorem.sentence() + }; +} + +function getRows(noRows){ + var rows = []; + for (var i = 0; i < noRows; i++){ + rows.push(createFakeRowObjectData(i)); + } + return rows; +} + +var FakeObjectDataListStore = { + getRows: getRows +}; + +module.exports = FakeObjectDataListStore; diff --git a/examples/scripts/exampleBasic.js b/examples/scripts/exampleBasic.js index 9fa6952..151d55f 100644 --- a/examples/scripts/exampleBasic.js +++ b/examples/scripts/exampleBasic.js @@ -1,3 +1,5 @@ +/* @flow */ +var React = require('react/addons'); var ReactGrid = require('../build/ReactGrid'); var getRows = require('./getRows'); var QuickStartDescription = require('./components/QuickStartDescription') @@ -16,10 +18,9 @@ var columns = [ name: 'Count' } ] +var Example = React.createClass({ -module.exports = React.createClass({ - - render:function(){ + render:function(): ?ReactElement { return(
@@ -29,3 +30,5 @@ module.exports = React.createClass({ } }); + +module.exports = Example; diff --git a/examples/scripts/exampleEditable.js b/examples/scripts/exampleEditable.js index 39b85dc..63503dc 100644 --- a/examples/scripts/exampleEditable.js +++ b/examples/scripts/exampleEditable.js @@ -1,3 +1,5 @@ +/* @flow */ +var React = require('react/addons'); var ReactGrid = require('../build/ReactGrid'); var getRows = require('./getRows'); var RowsDescription = require('./components/RowsDescription') @@ -7,7 +9,7 @@ var Description = React.createClass({ mixins : [HightlightMixin], - render : function(){ + render : function(): ?ReactElement { return(

Editable Example

@@ -61,14 +63,14 @@ var EditableGrid = React.createClass({ this.setState({rows:rows}); }, - render : function(){ + render : function(): ?ReactElement { return(); } }); -module.exports = React.createClass({ +var Example = React.createClass({ - render:function(){ + render:function(): ?ReactElement { return(
@@ -78,3 +80,4 @@ module.exports = React.createClass({ } }); +module.exports = Example; diff --git a/examples/scripts/getRows.js b/examples/scripts/getRows.js index 3961da1..4484dd3 100644 --- a/examples/scripts/getRows.js +++ b/examples/scripts/getRows.js @@ -1,4 +1,6 @@ -module.exports = function(start, end) { +/* @flow */ +var Row = require('../build/ReactGrid').Row; +module.exports = function(start: number, end: number): Array { var result = [] for (var i = start; i < end; i++) { result.push({ diff --git a/examples/scripts/highlightMixin.js b/examples/scripts/highlightMixin.js index 246ed35..deae5d2 100644 --- a/examples/scripts/highlightMixin.js +++ b/examples/scripts/highlightMixin.js @@ -1,3 +1,5 @@ +/* TODO@flow */ +var Highlight = require('highlight.js'); module.exports = { componentDidMount : function(){ this.highlight(); @@ -10,7 +12,7 @@ module.exports = { highlight : function(){ var aCodes = document.getElementsByTagName('pre'); for (var i=0; i < aCodes.length; i++) { - hljs.highlightBlock(aCodes[i]); + Highlight.highlightBlock(aCodes[i]); } } } diff --git a/flow/.flowconfig b/flow/.flowconfig new file mode 100644 index 0000000..910bc17 --- /dev/null +++ b/flow/.flowconfig @@ -0,0 +1,6 @@ +[include] +../node_modules/immutable +../node_modules/react +../node_modules/ron-react-autocomplete +../node_modules/moment +../src diff --git a/flow/examples/.flowconfig b/flow/examples/.flowconfig new file mode 100644 index 0000000..8fdaa78 --- /dev/null +++ b/flow/examples/.flowconfig @@ -0,0 +1,3 @@ +[include] +../../node_modules/react +../../examples diff --git a/flow/flow.exe b/flow/flow.exe new file mode 100644 index 0000000..2fcd4bc Binary files /dev/null and b/flow/flow.exe differ diff --git a/flow/libs/CellCopyPasteEvent.js b/flow/libs/CellCopyPasteEvent.js new file mode 100644 index 0000000..a33e9b6 --- /dev/null +++ b/flow/libs/CellCopyPasteEvent.js @@ -0,0 +1,7 @@ +type CellCopyPasteEvent = { + rowIdx: number; + value : any; + fromRow: number; + toRow: number; + cellKey: string +}; diff --git a/flow/libs/CellDragEvent.js b/flow/libs/CellDragEvent.js new file mode 100644 index 0000000..a9da85a --- /dev/null +++ b/flow/libs/CellDragEvent.js @@ -0,0 +1,6 @@ +type CellDragEvent = { + rowIdx: number; + fromRow: number; + toRow: number; + value: any +}; diff --git a/flow/libs/Editor.js b/flow/libs/Editor.js new file mode 100644 index 0000000..8188d48 --- /dev/null +++ b/flow/libs/Editor.js @@ -0,0 +1,5 @@ +declare class Editor extends ReactClass { + getValue: () => string; + getInputNode: () => HTMLInputElement; + hasResults: () => boolean; +}; diff --git a/flow/libs/SyntheticKeyboardEvent.js b/flow/libs/SyntheticKeyboardEvent.js new file mode 100644 index 0000000..7557308 --- /dev/null +++ b/flow/libs/SyntheticKeyboardEvent.js @@ -0,0 +1,151 @@ +declare class SyntheticEvent { + bubbles: boolean; + cancelable: boolean; + currentTarget: EventTarget; + defaultPrevented: boolean; + eventPhase: number; + isTrusted: boolean; + nativeEvent: Event; + preventDefault(): void; + stopPropagation(): void; + target: EventTarget; + timeStamp: number; + type: string; +} + + +declare class SyntheticKeyboardEvent extends SyntheticEvent { + altKey: boolean; + charCode: number; + ctrlKey: boolean; + getModifierState: (key: string) => void; + key: string; + keyCode: number; + locale: string; + location: number; + metaKey: boolean; + repeat: boolean; + shiftKey: boolean; + which: number; +} + + +declare class SyntheticMouseEvent extends SyntheticEvent { + button: number; + buttons: number; + clientX: number; + clientY: number; + pageX: number; + pageY: number; + screenX: number; + screenY: number; + relatedTarget: EventTarget; + + getModifierState: (key: string) => void; + altKey: boolean; + ctrlKey: boolean; + metaKey: boolean; +} + +//https://github.com/facebook/flow/blob/master/lib/dom.js#L371 +declare class HTMLFormElement extends HTMLElement { + [name: string]: any; + acceptCharset: string; + action: string; + elements: HTMLCollection; + encoding: string; + enctype: string; + length: number; + method: string; + name: string; + target: string; + + item(name?: any, index?: any): any; + namedItem(name: string): any; + reset(): void; + submit(): void; +} + +//https://github.com/facebook/flow/blob/master/lib/dom.js#L402 +declare class HTMLInputElement extends HTMLElement { + accept: string; + align: string; + alt: string; + border: string; + checked: boolean; + complete: boolean; + defaultChecked: boolean; + defaultValue: string; + dynsrc: string; + form: HTMLFormElement; + height: string; + hspace: number; + indeterminate: boolean; + loop: number; + lowsrc: string; + maxLength: number; + name: string; + readOnly: boolean; + selectionEnd: number; + selectionStart: number; + size: number; + src: string; + start: string; + status: boolean; + type: string; + useMap: string; + value: string; + vrml: string; + vspace: number; + width: string; + + createTextRange(): TextRange; + select(): void; + setSelectionRange(start: number, end: number): void; + + //manually added + focus(): void; + +} + +//https://github.com/facebook/flow/blob/master/lib/dom.js#L449 + +declare class TextRange { + boundingLeft: number; + htmlText: string; + offsetLeft: number; + boundingWidth: number; + boundingHeight: number; + boundingTop: number; + text: string; + offsetTop: number; + moveToPoint(x: number, y: number): void; + queryCommandValue(cmdID: string): any; + getBookmark(): string; + move(unit: string, count?: number): number; + queryCommandIndeterm(cmdID: string): boolean; + scrollIntoView(fStart?: boolean): void; + findText(string: string, count?: number, flags?: number): boolean; + execCommand(cmdID: string, showUI?: boolean, value?: any): boolean; + getBoundingClientRect(): ClientRect; + moveToBookmark(bookmark: string): boolean; + isEqual(range: TextRange): boolean; + duplicate(): TextRange; + collapse(start?: boolean): void; + queryCommandText(cmdID: string): string; + select(): void; + pasteHTML(html: string): void; + inRange(range: TextRange): boolean; + moveEnd(unit: string, count?: number): number; + getClientRects(): ClientRectList; + moveStart(unit: string, count?: number): number; + parentElement(): Element; + queryCommandState(cmdID: string): boolean; + compareEndPoints(how: string, sourceRange: TextRange): number; + execCommandShowHelp(cmdID: string): boolean; + moveToElementText(element: Element): void; + expand(Unit: string): boolean; + queryCommandSupported(cmdID: string): boolean; + setEndPoint(how: string, SourceRange: TextRange): void; + queryCommandEnabled(cmdID: string): boolean; +} diff --git a/gulp/tasks/build.js b/gulp/tasks/build.js deleted file mode 100644 index f0e5b41..0000000 --- a/gulp/tasks/build.js +++ /dev/null @@ -1,3 +0,0 @@ -var gulp = require('gulp'); - -gulp.task('build', ['dist','styles']); diff --git a/gulp/tasks/bundle.js b/gulp/tasks/bundle.js new file mode 100644 index 0000000..f8ee332 --- /dev/null +++ b/gulp/tasks/bundle.js @@ -0,0 +1,32 @@ +var Webpack = require("webpack"); +var gutil = require("gulp-util"); + +var defaultErrorHandler = function(err, ctx) { + throw new gutil.PluginError(ctx, err); +}; + +module.exports = function (config, done, handlers) { + handlers = handlers || {}; + handlers = { + onFatalError: handlers.onFatalError || defaultErrorHandler, + onError: handlers.onError || defaultErrorHandler, + onWarning: handlers.onWarning || defaultErrorHandler + }; + Webpack(config, function(err, stats) { + + if(err) return handlers.onFatalError(err, 'Fatal error'); + var jsonStats = stats.toJson(); + if(!jsonStats) { + + } + if(jsonStats.errors.length > 0) { + return handlers.onError(jsonStats.errors.toString(), 'Stats error'); + } + if(jsonStats.warnings.length > 0) { + return handlers.onWarning(jsonStats.warnings.toString(), 'Stats warning'); + } + done(); + + + }); +} diff --git a/gulp/tasks/clean.js b/gulp/tasks/clean.js index 54123ac..7ef0fa8 100644 --- a/gulp/tasks/clean.js +++ b/gulp/tasks/clean.js @@ -1,6 +1,6 @@ var gulp = require('gulp'); -var clean = require('gulp-clean'); +var del = require('del'); -gulp.task('clean', function() { - return gulp.src(['examples/build/', 'lib', 'dist'], {read: false}).pipe(clean()); +gulp.task('clean', function(cb) { + del(['examples/build/', 'lib', 'dist'], cb); }); diff --git a/gulp/tasks/default.js b/gulp/tasks/default.js index 5a6c63a..948cbc1 100644 --- a/gulp/tasks/default.js +++ b/gulp/tasks/default.js @@ -1,5 +1,5 @@ var gulp = require('gulp'); -gulp.task('default', ['clean'], function(){ +gulp.task('default', ['clean', 'flow-win'], function(){ gulp.start('watch'); }); diff --git a/gulp/tasks/dist.js b/gulp/tasks/dist.js index 6da2d6d..507df94 100644 --- a/gulp/tasks/dist.js +++ b/gulp/tasks/dist.js @@ -1,34 +1,30 @@ var gulp = require("gulp"); var gutil = require("gulp-util"); -var webpack = require("webpack"); +var bundle = require("./bundle"); var uglify = require('gulp-uglify'); -var webpackConfig = require("../../webpack.config.js"); +var webpackConfig = require("../../config/webpack.config.js"); var gulp = require('gulp'); var rename = require('gulp-rename'); -gulp.task("webpack", function(callback) { +gulp.task("dist", function(callback) { - // run webpack - webpack(Object.create(webpackConfig), function(err, stats) { - if(err) throw new gutil.PluginError("webpack", err); - gutil.log("[standalone]", stats.toString({ - // output options - })); - callback(); - }); -}); + var onBundle = function(){ + gulp.src('dist/ReactGridWithAddons.js') + .pipe(uglify()) + .pipe(rename('ReactGridWithAddons.min.js')) + .pipe(gulp.dest('dist')) + .on('error', gutil.log) + + gulp.src('dist/ReactGrid.js') + .pipe(uglify()) + .pipe(rename('ReactGrid.min.js')) + .pipe(gulp.dest('dist')) + .on('error', gutil.log) + callback(); + } + + bundle(Object.create(webpackConfig), onBundle); -gulp.task("dist", ['webpack'], function() { - gulp.src('dist/ReactGridWithAddons.js') - .pipe(uglify()) - .pipe(rename('ReactGridWithAddons.min.js')) - .pipe(gulp.dest('dist')) - .on('error', gutil.log) - return gulp.src('dist/ReactGrid.js') - .pipe(uglify()) - .pipe(rename('ReactGrid.min.js')) - .pipe(gulp.dest('dist')) - .on('error', gutil.log) }); diff --git a/gulp/tasks/examples.js b/gulp/tasks/examples.js index da489e0..2779215 100644 --- a/gulp/tasks/examples.js +++ b/gulp/tasks/examples.js @@ -1,6 +1,7 @@ var gulp = require('gulp'); var concat = require('gulp-concat'); var webpack = require("webpack"); +var bundle = require('./bundle'); var gutil = require("gulp-util"); var path = require("path"); @@ -48,7 +49,7 @@ gulp.task('script-deps', function() { }); -gulp.task("copy-dist", ['build'], function(){ +gulp.task("copy-dist", ['dist'], function(){ //copy dist folder to examples return gulp.src([ 'dist/**', @@ -66,12 +67,5 @@ gulp.task('styles', function () { gulp.task("examples", ['script-deps', 'copy-dist', 'styles'], function(callback) { // run webpack - webpack(Object.create(webpackConfig), function(err, stats) { - if(err) throw new gutil.PluginError("webpack", err); - gutil.log("[standalone]", stats.toString({ - // output options - })); - - callback(); - }); + bundle(Object.create(webpackConfig), callback); }); diff --git a/gulp/tasks/flow.js b/gulp/tasks/flow.js new file mode 100644 index 0000000..6ad3f62 --- /dev/null +++ b/gulp/tasks/flow.js @@ -0,0 +1,37 @@ +var gulp = require('gulp'); +var execFile = require('child_process').execFile; + +gulp.task('flow-win', function() { + execFile('./flow/flow.exe', ['check','--lib','./flow/libs','--strip-root','./flow'],function (err, stdout, stderr) { + if(err) console.log('Error:' + err); + if(stdout) console.log(stdout); + }); +}); + + +gulp.task('flow-examples', ['examples'], function() { + execFile('./flow/flow.exe', ['check','--lib','./flow/libs','--strip-root','./flow/examples'],function (err, stdout, stderr) { + if(err) console.log('Error:' + err); + if(stdout) console.log(stdout); + }); +}); + +//this is how we WANT to run flow +//but due to flow-bin not working on windows (because there isnt an official build https://github.com/facebook/flow/issues/6) +//we cant require it as then npm install fails on any win environment (err.. appveyor) +//if you are on *nix platform, npm install flow-bin, and then uncomment this task + +// var flow = require('gulp-flowtype'); +// +// gulp.task('flow', function() { +// return gulp.src('./flow') +// .pipe(flow({ +// all: false, +// weak: false, +// declarations: './flow/libs', +// killFlow: false, +// beep: true, +// generalErrorRegEx: /./ +// })); +// +// }) diff --git a/gulp/tasks/tests-karma.js b/gulp/tasks/tests-karma.js deleted file mode 100644 index 24d6dba..0000000 --- a/gulp/tasks/tests-karma.js +++ /dev/null @@ -1,35 +0,0 @@ -var es6 = require('es6-shim'); -var gulp = require('gulp'); -var karma = require('karma').server; -var merge = require('../../src/merge'); - - -//one could also externalize common config into a separate file, -//ex.: var karmaCommonConf = require('./karma-common-conf.js'); -var karmaCommonConf = { - browsers: ['Chrome'], - frameworks: ['jasmine'], - files: [ - 'test/build/specs-all.js' - ] -}; - -/** - * Run test once and exit - */ -gulp.task('tests',['tests-build'], function (done) { - var conf = merge({autoWatch: false, singleRun: true}, karmaCommonConf); - karma.start(conf, done); -}); - -/** - * Watch for file changes and re-run tests on each change - * ---NOT WORKING---- - * Currently its only looking for test files changing - * Need to plugin in browserify if we want to watch all our files - * means it will only reload if you change the main entry file (ie run gulp tests-build) - */ -gulp.task('tdd', function (done) { - var conf = merge({autoWatch: true, singleRun: false}, karmaCommonConf); - karma.start(karmaCommonConf, done); -}); diff --git a/gulp/tasks/tests.js b/gulp/tasks/tests.js index 98598b1..8afc1ce 100644 --- a/gulp/tasks/tests.js +++ b/gulp/tasks/tests.js @@ -2,7 +2,7 @@ var gulp = require('gulp'); var jasmine = require('gulp-jasmine'); var karma = require('karma').server; -gulp.task('test', function (cb) { +gulp.task('test', ['build'], function (cb) { karma.start({ configFile: '../../../config/karma.js', singleRun: true diff --git a/gulp/tasks/watch.js b/gulp/tasks/watch.js index 400f6c8..45cc869 100644 --- a/gulp/tasks/watch.js +++ b/gulp/tasks/watch.js @@ -1,7 +1,7 @@ var gulp = require('gulp'); - +var del = require('del'); gulp.task('watch', ['setWatch', 'browserSync'], function() { gulp.watch('themes/**', ['styles']); gulp.watch('src/**', ['examples']); - // Note: The browserify task handles js recompiling with watchify + }); diff --git a/gulp/util/bundleBuilder.js b/gulp/util/bundleBuilder.js index 37a3cc5..d5b364e 100644 --- a/gulp/util/bundleBuilder.js +++ b/gulp/util/bundleBuilder.js @@ -16,11 +16,10 @@ function buildBundle(bundleConfig, outFile, outFldr, watch, options) { if(Array.isArray(options.excludes)){ options.excludes.forEach(function(toExclude){ bundler.exclude(toExclude); - }) + }); } } - return bundler .bundle() // Report compile errors diff --git a/package.json b/package.json index e840150..3709db3 100644 --- a/package.json +++ b/package.json @@ -35,15 +35,19 @@ "browserify": "^7.0.0", "connect": "^2.24.3", "coveralls": "^2.11.2", + "del": "^1.1.1", "es5-shim": "^4.0.1", "es6-shim": "^0.15.0", - "eslint-jsx": "git+https://github.com/andreypopp/eslint#jsx", + "faker": "^2.1.2", + "flow-bin": "~0.1.2", + "gh-pages": "^0.2.0", "gulp": "^3.8.7", "gulp-changed": "^0.4.1", - "gulp-clean": "^0.3.1", "gulp-concat": "^2.3.4", "gulp-flatten": "0.0.2", + "gulp-flowtype": "^0.4.1", "gulp-jasmine": "^0.3.0", + "gulp-jshint": "^1.9.2", "gulp-less": "^1.3.3", "gulp-notify": "^1.4.1", "gulp-open": "^0.2.8", @@ -53,6 +57,9 @@ "gulp-util": "^3.0.0", "istanbul-instrumenter-loader": "^0.1.2", "jasmine-react": "^1.0.7", + "jshint": "^2.6.2", + "jshint-loader": "^0.8.3", + "jshint-stylish": "^1.0.1", "jsx-loader": "^0.12.2", "karma": "^0.12.28", "karma-chrome-launcher": "^0.1.4", @@ -73,8 +80,7 @@ "rewire-webpack": "^1.0.0", "sinon": "^1.9.1", "vinyl-source-stream": "^0.1.1", - "webpack": "^1.5.3", - "gh-pages": "~0.2.0" + "webpack": "^1.5.3" }, "author": "Adazzle", "license": "MIT", diff --git a/src/.flowconfig b/src/.flowconfig deleted file mode 100644 index 03fa4e9..0000000 --- a/src/.flowconfig +++ /dev/null @@ -1,7 +0,0 @@ -[ignore] - -[include] -/node_modules/ -../node_modules/ -../node_modules -../node_modules/** diff --git a/src/Canvas.js b/src/Canvas.js index c04efae..6498398 100644 --- a/src/Canvas.js +++ b/src/Canvas.js @@ -1,6 +1,6 @@ +/* @flow */ /** * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 */ "use strict"; @@ -12,29 +12,30 @@ var shallowEqual = require('./shallowEqual'); var emptyFunction = require('./emptyFunction'); var ScrollShim = require('./ScrollShim'); var Row = require('./Row'); - +var ExcelColumn = require('./addons/grids/ExcelColumn'); var Canvas = React.createClass({ mixins: [ScrollShim], propTypes: { - cellRenderer: PropTypes.element, rowRenderer: PropTypes.oneOfType([PropTypes.func, PropTypes.element]), rowHeight: PropTypes.number.isRequired, + height: PropTypes.number.isRequired, displayStart: PropTypes.number.isRequired, displayEnd: PropTypes.number.isRequired, - length: PropTypes.number.isRequired, + totalRows: PropTypes.number.isRequired, rows: PropTypes.oneOfType([ PropTypes.func.isRequired, PropTypes.array.isRequired ]), - onRows: PropTypes.func + onRows: PropTypes.func, + columns: PropTypes.arrayOf(ExcelColumn).isRequired }, - render() { + render(): ?ReactElement { var displayStart = this.state.displayStart; var displayEnd = this.state.displayEnd; var rowHeight = this.props.rowHeight; - var length = this.props.length; + var length = this.props.totalRows; var rows = this .getRows(displayStart, displayEnd) @@ -45,9 +46,9 @@ var Canvas = React.createClass({ row: row, height: rowHeight, columns: this.props.columns, - cellRenderer: this.props.cellRenderer, isSelected : this.isRowSelected(displayStart + idx), - expandedRows : this.props.expandedRows + expandedRows : this.props.expandedRows, + cellMetaData : this.props.cellMetaData })); this._currentRowsLength = rows.length; @@ -84,15 +85,18 @@ var Canvas = React.createClass({ ); }, - renderRow(props) { - if (React.isValidElement(this.props.rowRenderer)) { + renderRow(props: any) { + if(typeof this.props.rowRenderer === 'function') { + return this.props.rowRenderer.call(this,props); + } + else if (React.isValidElement(this.props.rowRenderer)) { return cloneWithProps(this.props.rowRenderer, props); } else { return this.props.rowRenderer(props); } }, - renderPlaceholder(key, height) { + renderPlaceholder(key: string, height: number): ?ReactElement { return (
{this.props.columns.map( @@ -103,15 +107,19 @@ var Canvas = React.createClass({ getDefaultProps() { return { - rowRenderer: , + rowRenderer: Row, onRows: emptyFunction }; }, - isRowSelected(rowIdx){ + isRowSelected(rowIdx: number): boolean{ return this.props.selectedRows && this.props.selectedRows[rowIdx] === true; }, + _currentRowsLength : 0, + _currentRowsRange : { start: 0, end: 0 }, + _scroll : { scrollTop : 0, scrollLeft: 0 }, + getInitialState() { return { shouldUpdate: true, @@ -121,32 +129,35 @@ var Canvas = React.createClass({ }, componentWillMount() { - this._currentRowsLength = undefined; - this._currentRowsRange = undefined; - this._scroll = undefined; + this._currentRowsLength = 0; + this._currentRowsRange = {start: 0, end: 0}; + this._scroll = {scrollTop : 0, scrollLeft: 0}; }, componentDidMount() { this.onRows(); }, - componentDidUpdate() { - if (this._scroll !== undefined) { - this.setScrollLeft(this._scroll); + componentDidUpdate(nextProps: any) { + if (this._scroll !== {start: 0, end: 0}) { + this.setScrollLeft(this._scroll.scrollLeft); } this.onRows(); }, componentWillUnmount() { - this._currentRowsLength = undefined; - this._currentRowsRange = undefined; - this._scroll = undefined; + this._currentRowsLength = 0; + this._currentRowsRange = {start: 0, end: 0}; + this._scroll = {scrollTop : 0, scrollLeft: 0}; }, - componentWillReceiveProps(nextProps) { + componentWillReceiveProps(nextProps: any) { + if(nextProps.rows.length > this.props.rows.length){ + this.getDOMNode().scrollTop =nextProps.rows.length * this.props.rowHeight; + } var shouldUpdate = !(nextProps.visibleStart > this.state.displayStart && nextProps.visibleEnd < this.state.displayEnd) - || nextProps.length !== this.props.length + || nextProps.totalRows !== this.props.totalRows || nextProps.rowHeight !== this.props.rowHeight || nextProps.columns !== this.props.columns || nextProps.width !== this.props.width @@ -163,18 +174,18 @@ var Canvas = React.createClass({ } }, - shouldComponentUpdate(nextProps, nextState) { - return nextState.shouldUpdate; + shouldComponentUpdate(nextProps: any, nextState: any): boolean { + return !nextState || nextState.shouldUpdate; }, onRows() { - if (this._currentRowsRange !== undefined) { + if (this._currentRowsRange !== {start: 0, end: 0}) { this.props.onRows(this._currentRowsRange); - this._currentRowsRange = undefined; + this._currentRowsRange = {start: 0, end: 0}; } }, - getRows(displayStart, displayEnd) { + getRows(displayStart: number, displayEnd: number): Array { this._currentRowsRange = {start: displayStart, end: displayEnd}; if (Array.isArray(this.props.rows)) { return this.props.rows.slice(displayStart, displayEnd); @@ -183,8 +194,8 @@ var Canvas = React.createClass({ } }, - setScrollLeft(scrollLeft) { - if (this._currentRowsLength !== undefined) { + setScrollLeft(scrollLeft: number) { + if (this._currentRowsLength !== 0) { for (var i = 0, len = this._currentRowsLength; i < len; i++) { if(this.refs[i]) { this.refs[i].setScrollLeft(scrollLeft); @@ -193,12 +204,12 @@ var Canvas = React.createClass({ } }, - getScroll() { + getScroll(): {scrollTop: number; scrollLeft: number} { var {scrollTop, scrollLeft} = this.getDOMNode(); return {scrollTop, scrollLeft}; }, - onScroll(e) { + onScroll(e: any) { this.appendScrollShim(); var {scrollTop, scrollLeft} = e.target; var scroll = {scrollTop, scrollLeft}; diff --git a/src/Cell.js b/src/Cell.js index c8d4035..c8f75d0 100644 --- a/src/Cell.js +++ b/src/Cell.js @@ -1,22 +1,77 @@ +/* @flow */ /** * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 + + */ 'use strict'; var React = require('react/addons'); var cx = React.addons.classSet; var cloneWithProps = React.addons.cloneWithProps; +var EditorContainer = require('./addons/editors/EditorContainer'); +var ExcelColumn = require('./addons/grids/ExcelColumn'); var Cell = React.createClass({ - render() { + propTypes : { + rowIdx : React.PropTypes.number.isRequired, + idx : React.PropTypes.number.isRequired, + selected : React.PropTypes.shape({ + idx : React.PropTypes.number.isRequired, + }), + tabIndex : React.PropTypes.number, + ref : React.PropTypes.string, + column: React.PropTypes.shape(ExcelColumn).isRequired, + value: React.PropTypes.oneOf(React.PropTypes.string,React.PropTypes.number, React.PropTypes.object).isRequired, + isExpanded: React.PropTypes.bool, + cellMetaData: React.PropTypes.shape({selected: React.PropTypes.object.isRequired, onCellClick: React.PropTypes.func}), + handleDragStart: React.PropTypes.func, + className: React.PropTypes.string + }, + + getDefaultProps : function(): {tabIndex: number; ref: string; isExpanded: boolean } { + return { + tabIndex : -1, + ref : "cell", + isExpanded: false + } + }, + + componentDidMount: function() { + this.checkFocus(); + }, + + componentDidUpdate: function(prevProps: any, prevState: any) { + this.checkFocus(); + var dragged = this.props.dragged; + if(dragged && dragged.complete === true){ + this.props.handleTerminateDrag(); + } + }, + + shouldComponentUpdate(nextProps: any, nextState: any): boolean { + return this.props.column.width !== nextProps.column.width + || this.props.value !== nextProps.value + || this.props.height !== nextProps.height + || this.props.rowIdx !== nextProps.rowIdx + || this.isCellSelectionChanging(nextProps); + }, + + getStyle(): {position:string; width: number; height: number; left: number} { + var style = { + position: 'absolute', + width: this.props.column.width, + height: this.props.height, + left: this.props.column.left + }; + return style; + }, + + render(): ?ReactElement { var style = this.getStyle(); - var className = cx( - 'react-grid-Cell', - this.props.className, - this.props.column.locked ? 'react-grid-Cell--locked' : null - ); + + var className = this.getCellClass(); var cellContent = this.renderCellContent({ value : this.props.value, @@ -26,48 +81,154 @@ var Cell = React.createClass({ }); return ( -
- {cellContent} -
-
+
+ {cellContent} +
+
); }, - renderCellContent(props) { - var formatter = React.isValidElement(this.props.formatter) ? cloneWithProps(this.props.formatter, props) : this.props.formatter(props); + renderCellContent(props: any): ReactElement { + var formatter = this.getFormatter(); + var formatterTag = React.isValidElement(formatter) ? cloneWithProps(formatter, props) : formatter(props); return (
{formatter} {this.props.cellControls}
) + className="react-grid-Cell__value">{formatterTag} {this.props.cellControls}
) + }, + + isSelected: function(): boolean { + var meta = this.props.cellMetaData; + if(meta == null || meta.selected == null) { return false; } + return ( + meta.selected + && meta.selected.rowIdx === this.props.rowIdx + && meta.selected.idx === this.props.idx + ); }, - getDefaultProps() { - return { - formatter: simpleCellFormatter - }; + isActive(): boolean{ + var meta = this.props.cellMetaData; + if(meta == null || meta.selected == null) { return false; } + return this.isSelected() && meta.selected.active === true; }, - getStyle() { - var style = { - position: 'absolute', - width: this.props.column.width, - height: this.props.height, - left: this.props.column.left - }; - return style; + isCellSelectionChanging(nextProps: {idx: number; cellMetaData: {selected: {idx: number}}}): boolean { + var meta = this.props.cellMetaData; + if(meta == null || meta.selected == null) { return false; } + var nextSelected = nextProps.cellMetaData.selected; + if(meta.selected && nextSelected){ + return this.props.idx === nextSelected.idx || this.props.idx === meta.selected.idx; + }else{ + return true; + } + }, + + getFormatter(): ReactElement { + var col = this.props.column; + if(this.isActive()){ + return ; + }else{ + return this.props.column.formatter || simpleCellFormatter; + } + }, + + onCellClick(){ + var meta = this.props.cellMetaData; + if(meta != null && meta.onCellClick != null) { + meta.onCellClick({rowIdx : this.props.rowIdx, idx : this.props.idx}); + } }, - setScrollLeft(scrollLeft) { - if (this.isMounted()) { + checkFocus: function() { + if (this.isSelected() && !this.isActive()) { + this.getDOMNode().focus(); + } + }, + + getCellClass : function(): string { + var className = cx( + 'react-grid-Cell', + this.props.className, + this.props.column.locked ? 'react-grid-Cell--locked' : null + ); + + var extraClasses = cx({ + 'selected' : this.isSelected() && !this.isActive() , + 'editing' : this.isActive(), + 'copied' : this.isCopied(), + 'active-drag-cell' : this.isSelected() || this.isDraggedOver(), + // 'active-drag-cell' : this.isSelected() || this.isDraggedOver(), + // 'is-dragged-over-up' : !this.isSelected() && this.isDraggedOver() && this.props.rowIdx < this.props.dragged.rowIdx, + // 'is-dragged-over-down' : !this.isSelected() && this.isDraggedOver() && this.props.rowIdx > this.props.dragged.rowIdx, + // 'was-dragged-over' : this.wasDraggedOver() + }); + return className + ' ' + extraClasses; + }, + + + setScrollLeft(scrollLeft: number) { + var ctrl: any = this; //flow on windows has an outdated react declaration, once that gets updated, we can remove this + if (ctrl.isMounted()) { var node = this.getDOMNode(); var transform = `translate3d(${scrollLeft}px, 0px, 0px)`; node.style.webkitTransform = transform; node.style.transform = transform; } - } + }, + + isCopied : function(): boolean{ + var copied = this.props.cellMetaData.copied + return ( + copied + && copied.rowIdx === this.props.rowIdx + && copied.idx === this.props.idx + ); + }, + + isDraggedOver(): boolean{ + var dragged = this.props.cellMetaData.dragged + return ( + dragged && + dragged.overRowIdx === this.props.rowIdx + && dragged.idx === this.props.idx + ) + }, + // + // wasDraggedOver(){ + // return ( + // this.props.dragged + // && ((this.props.dragged.overRowIdx < this.props.rowIdx && this.props.rowIdx < this.props.dragged.rowIdx) + // || (this.props.dragged.overRowIdx > this.props.rowIdx && this.props.rowIdx > this.props.dragged.rowIdx)) + // && this.props.dragged.idx === this.props.idx + // ); + // }, + // + // handleDragStart(e){ + // var rowIdx = this.props.rowIdx; + // var idx = this.props.idx; + // this.props.handleDragStart({rowIdx : rowIdx, idx : idx, copiedText : this.props.value}); + // }, + // + // handleDragEnter(){ + // this.props.handleDragEnter(this.props.rowIdx); + // }, + // + // handleDragEnd(){ + // this.props.handleDragEnd(); + // }, + // + // isDraggedCellChanging(nextProps){ + // if(this.props.dragged){ + // return (nextProps.dragged && this.props.idx === nextProps.dragged.idx) + // || (this.props.dragged && this.props.idx === this.props.dragged.idx); + // }else{ + // return false; + // } + // } }); -function simpleCellFormatter(props) { +function simpleCellFormatter(props: any): string { return props.value; } diff --git a/src/ColumnComparer.js b/src/ColumnComparer.js new file mode 100644 index 0000000..e270918 --- /dev/null +++ b/src/ColumnComparer.js @@ -0,0 +1,25 @@ +/* TODO@flow objects as a map */ +var isValidElement = require('react/addons').isValidElement; +module.exports = +function sameColumn(a: Column, b: Column): boolean { + var k; + + for (k in a) { + if (a.hasOwnProperty(k)) { + if ((typeof a[k] === 'function' && typeof b[k] === 'function') || (isValidElement(a[k]) && isValidElement(b[k]))) { + continue; + } + if (!b.hasOwnProperty(k) || a[k] !== b[k]) { + return false; + } + } + } + + for (k in b) { + if (b.hasOwnProperty(k) && !a.hasOwnProperty(k)) { + return false; + } + } + + return true; +}; diff --git a/src/ColumnMetrics.js b/src/ColumnMetrics.js index 4da134a..9bc6d78 100644 --- a/src/ColumnMetrics.js +++ b/src/ColumnMetrics.js @@ -1,20 +1,34 @@ +/* @flow */ /** * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 + + */ "use strict"; -var {PropTypes, isValidElement} = require('react/addons'); var shallowCloneObject = require('./shallowCloneObject'); -var DOMMetrics = require('./DOMMetrics'); var merge = require('./merge'); +var isValidElement = require('react/addons').isValidElement; +var sameColumn = require('./ColumnComparer'); + +type ColumnMetricsType = { + columns: Array; + totalWidth: number; + minColumnWidth: number; +}; + +type Column = { + key: string; + left: number; + width: number; +}; /** * Update column metrics calculation. * - * @param {ColumnMetrics} metrics + * @param {ColumnMetricsType} metrics */ -function calculate(metrics) { +function calculate(metrics: ColumnMetricsType): ColumnMetricsType { var width = 0; var unallocatedWidth = metrics.totalWidth; @@ -28,9 +42,9 @@ function calculate(metrics) { column = columns[i]; if (column.width) { - if (/^([0-9]+)%$/.exec(column.width)) { + if (/^([0-9]+)%$/.exec(column.width.toString())) { column.width = Math.floor( - parseInt(column.width, 10) / 100 * metrics.totalWidth); + column.width / 100 * metrics.totalWidth); } unallocatedWidth -= column.width; width += column.width; @@ -71,11 +85,11 @@ function calculate(metrics) { /** * Update column metrics calculation by resizing a column. * - * @param {ColumnMetrics} metrics + * @param {ColumnMetricsType} metrics * @param {Column} column * @param {number} width */ -function resizeColumn(metrics, index, width) { +function resizeColumn(metrics: ColumnMetricsType, index: number, width: number): ColumnMetricsType { var column = metrics.columns[index]; metrics = shallowCloneObject(metrics); metrics.columns = metrics.columns.slice(0); @@ -88,76 +102,10 @@ function resizeColumn(metrics, index, width) { return calculate(metrics); } -var Mixin = { - mixins: [DOMMetrics.MetricsMixin], - - propTypes: { - columns: PropTypes.array, - minColumnWidth: PropTypes.number, - columnEquality: PropTypes.func - }, - - DOMMetrics: { - gridWidth() { - return this.getDOMNode().offsetWidth - 2; - } - }, - - getDefaultProps() { - return { - minColumnWidth: 80, - columnEquality: sameColumn - }; - }, - - getInitialState() { - return this.getColumnMetrics(this.props, true); - }, - - componentWillReceiveProps(nextProps) { - if (nextProps.columns) { - if (!sameColumns(this.props.columns, nextProps.columns, this.props.columnEquality)) { - this.setState(this.getColumnMetrics(nextProps)); - } else { - var index = {}; - this.state.columns.columns.forEach((c) => { - index[c.key] = {width: c.width, left: c.left}; - }); - var nextColumns = merge(this.state.columns, { - columns: nextProps.columns.map((c) => merge(c, index[c.key])) - }); - this.setState({columns: nextColumns}); - } - } - }, - - getColumnMetrics(props, initial) { - var totalWidth = initial ? null : this.DOMMetrics.gridWidth(); - return { - columns: calculate({ - columns: props.columns, - width: null, - totalWidth, - minColumnWidth: props.minColumnWidth - }), - gridWidth: totalWidth - }; - }, - - metricsUpdated() { - this.setState(this.getColumnMetrics(this.props)); - }, - - onColumnResize(index, width) { - var columns = resizeColumn(this.state.columns, index, width); - this.setState({columns}); - } -}; - -function sameColumns(prevColumns, nextColumns, sameColumn) { +function sameColumns(prevColumns: Array, nextColumns: Array, sameColumn: (a: Column, b: Column) => boolean): boolean { var i, len, column; - var prevColumnsByKey = {}; - var nextColumnsByKey = {}; + var prevColumnsByKey: { [key:string]: Column } = {}; + var nextColumnsByKey: { [key:string]: Column } = {}; if(prevColumns.length !== nextColumns.length){ @@ -189,27 +137,4 @@ function sameColumns(prevColumns, nextColumns, sameColumn) { return true; } -function sameColumn(a, b) { - var k; - - for (k in a) { - if (a.hasOwnProperty(k)) { - if ((typeof a[k] === 'function' && typeof b[k] === 'function') || (isValidElement(a[k]) && isValidElement(b[k]))) { - continue; - } - if (!b.hasOwnProperty(k) || a[k] !== b[k]) { - return false; - } - } - } - - for (k in b) { - if (b.hasOwnProperty(k) && !a.hasOwnProperty(k)) { - return false; - } - } - - return true; -} - -module.exports = {Mixin, calculate, resizeColumn, sameColumns, sameColumn}; +module.exports = { calculate, resizeColumn, sameColumn, sameColumns }; diff --git a/src/ColumnMetricsMixin.js b/src/ColumnMetricsMixin.js new file mode 100644 index 0000000..3977a73 --- /dev/null +++ b/src/ColumnMetricsMixin.js @@ -0,0 +1,84 @@ +/* TODO@flow mixins */ + +var ColumnMetrics = require('./ColumnMetrics'); +var DOMMetrics = require('./DOMMetrics'); +Object.assign = require('object-assign'); +var PropTypes = require('react/addons').PropTypes; + + +type ColumnMetricsType = { + columns: Array; + totalWidth: number; + minColumnWidth: number; +}; + +class Column { + key: string; + left: number; + width: number; +}; + +module.exports = { + mixins: [DOMMetrics.MetricsMixin], + + propTypes: { + columns: PropTypes.arrayOf(Column), + minColumnWidth: PropTypes.number, + columnEquality: PropTypes.func + }, + + DOMMetrics: { + gridWidth(): number { + return this.getDOMNode().offsetWidth - 2; + } + }, + + getDefaultProps(): {minColumnWidth: number; columnEquality: (a: Column, b: Column) => boolean} { + return { + minColumnWidth: 80, + columnEquality: ColumnMetrics.sameColumn + }; + }, + + getInitialState(): ColumnMetricsType { + return this.getColumnMetricsType(this.props, true); + }, + + componentWillReceiveProps(nextProps: ColumnMetricsType) { + if (nextProps.columns) { + if (!ColumnMetrics.sameColumns(this.props.columns, nextProps.columns, this.props.columnEquality)) { + this.setState(this.getColumnMetricsType(nextProps)); + } else { + var index = {}; + this.state.columns.columns.forEach((c) => { + index[c.key] = {width: c.width, left: c.left}; + }); + var nextColumns = Object.assign(this.state.columns, { + columns: nextProps.columns.map((c) => Object.assign(c, index[c.key])) + }); + this.setState({columns: nextColumns}); + } + } + }, + + getColumnMetricsType(props: ColumnMetricsType, initial: ?number): { columns: ColumnMetricsType; gridWidth: number } { + var totalWidth = initial ? initial : this.DOMMetrics.gridWidth(); + return { + columns: ColumnMetrics.calculate({ + columns: props.columns, + totalWidth: totalWidth, + minColumnWidth: props.minColumnWidth + }), + gridWidth: totalWidth + }; + }, + + metricsUpdated() { + this.setState(this.getColumnMetricsType(this.props)); + }, + + onColumnResize(index: number, width: number) { + var columns = ColumnMetrics.resizeColumn(this.state.columns, index, width); + this.setState({columns}); + } +}; diff --git a/src/DOMMetrics.js b/src/DOMMetrics.js index d756e13..374adff 100644 --- a/src/DOMMetrics.js +++ b/src/DOMMetrics.js @@ -1,13 +1,14 @@ +/* TODO@flow mixin and invarient splat */ /** * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 + + */ 'use strict'; var React = require('react/addons'); var emptyFunction = require('./emptyFunction'); var shallowCloneObject = require('./shallowCloneObject'); -var invariant = require('./invariant'); var contextTypes = { metricsComputator: React.PropTypes.object @@ -17,23 +18,22 @@ var MetricsComputatorMixin = { childContextTypes: contextTypes, - getChildContext() { + getChildContext(): {metricsComputator: any} { return {metricsComputator: this}; }, - getMetricImpl(name) { + getMetricImpl(name: string): any { return this._DOMMetrics.metrics[name].value; }, - registerMetricsImpl(component, metrics) { + registerMetricsImpl(component: ReactComponent, metrics: any): {[key:string]: any} { var getters = {}; var s = this._DOMMetrics; for (var name in metrics) { - invariant( - s.metrics[name] === undefined, - 'DOM metric ' + name + ' is already defined' - ); + if(s.metrics[name] !== undefined) { + throw new Error('DOM metric ' + name + ' is already defined'); + } s.metrics[name] = {component, computator: metrics[name].bind(component)}; getters[name] = this.getMetricImpl.bind(null, name); } @@ -45,7 +45,7 @@ var MetricsComputatorMixin = { return getters; }, - unregisterMetricsFor(component) { + unregisterMetricsFor(component: ReactComponent) { var s = this._DOMMetrics; var idx = s.components.indexOf(component); @@ -132,7 +132,7 @@ var MetricsMixin = { } }, - componentWillUnmount() { + componentWillUnmount(): any { if (!this.registerMetricsImpl) { return this.context.metricsComputator.unregisterMetricsFor(this); } @@ -141,7 +141,7 @@ var MetricsMixin = { } }, - registerMetrics(metrics) { + registerMetrics(metrics: any): any { if (this.registerMetricsImpl) { return this.registerMetricsImpl(this, metrics); } else { @@ -149,7 +149,7 @@ var MetricsMixin = { } }, - getMetric(name) { + getMetric(name: string): any { if (this.getMetricImpl) { return this.getMetricImpl(name); } else { diff --git a/src/Draggable.js b/src/Draggable.js index 1e945d1..4cd6cb3 100644 --- a/src/Draggable.js +++ b/src/Draggable.js @@ -1,6 +1,8 @@ +/* @flow need */ /** * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 + + */ 'use strict'; @@ -17,7 +19,7 @@ var Draggable = React.createClass({ component: PropTypes.oneOfType([PropTypes.func, PropTypes.constructor]) }, - render() { + render(): ?ReactElement { var Component = this.props.component; return ( @@ -33,13 +35,13 @@ var Draggable = React.createClass({ }; }, - getInitialState() { + getInitialState(): {drag: ?any} { return { drag: null }; }, - onMouseDown(e) { + onMouseDown(e: SyntheticMouseEvent) { var drag = this.props.onDragStart(e); if (drag === null && e.button !== 0) { @@ -52,7 +54,7 @@ var Draggable = React.createClass({ this.setState({drag}); }, - onMouseMove(e) { + onMouseMove(e: SyntheticEvent) { if (this.state.drag === null) { return; } @@ -68,7 +70,7 @@ var Draggable = React.createClass({ this.props.onDrag(e); }, - onMouseUp(e) { + onMouseUp(e: SyntheticEvent) { this.cleanUp(); this.props.onDragEnd(e, this.state.drag); this.setState({drag: null}); diff --git a/src/Grid.js b/src/Grid.js index 67d463e..ebcd5c6 100644 --- a/src/Grid.js +++ b/src/Grid.js @@ -1,6 +1,8 @@ +/* @flow */ /** * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 + + */ "use strict"; @@ -8,57 +10,34 @@ var React = require('react/addons'); var PropTypes = React.PropTypes; var Header = require('./Header'); var Viewport = require('./Viewport'); -var ColumnMetrics = require('./ColumnMetrics'); var DOMMetrics = require('./DOMMetrics'); - - -var GridScrollMixin = { - - componentDidMount() { - this._scrollLeft = this.refs.viewport.getScroll().scrollLeft; - this._onScroll(); - }, - - componentDidUpdate() { - this._onScroll(); - }, - - componentWillMount() { - this._scrollLeft = undefined; - }, - - componentWillUnmount() { - this._scrollLeft = undefined; - }, - - onScroll({scrollLeft}) { - if (this._scrollLeft !== scrollLeft) { - this._scrollLeft = scrollLeft; - this._onScroll(); - } - }, - - _onScroll() { - if (this._scrollLeft !== undefined) { - this.refs.header.setScrollLeft(this._scrollLeft); - this.refs.viewport.setScrollLeft(this._scrollLeft); - } - } -}; +var GridScrollMixin = require('./GridScrollMixin'); +var ColumnMetricsMixin = require('./ColumnMetricsMixin'); +var ExcelColumn = require('./addons/grids/ExcelColumn'); var Grid = React.createClass({ mixins: [ GridScrollMixin, - ColumnMetrics.Mixin, + ColumnMetricsMixin, DOMMetrics.MetricsComputatorMixin ], propTypes: { rows: PropTypes.oneOfType([PropTypes.array, PropTypes.func]).isRequired, - columns: PropTypes.array.isRequired + columns: PropTypes.arrayOf(ExcelColumn).isRequired, + minHeight: PropTypes.number, + headerRows: PropTypes.oneOfType([PropTypes.array, PropTypes.func]), + rowHeight: PropTypes.number, + rowRenderer: PropTypes.func, + expandedRows: PropTypes.oneOfType([PropTypes.array, PropTypes.func]), + selectedRows: PropTypes.oneOfType([PropTypes.array, PropTypes.func]), + totalRows: PropTypes.number, + onRows: PropTypes.func, + rowOffsetHeight: PropTypes.number.isRequired, + onViewportKeydown : PropTypes.func.isRequired }, - getStyle: function(){ + getStyle: function(): { overflow: string; outline: number; position: string; minHeight: number } { return{ overflow: 'hidden', outline: 0, @@ -67,7 +46,7 @@ var Grid = React.createClass({ } }, - render() { + render(): ?ReactElement { var headerRows = this.props.headerRows || [{ref : 'row'}]; return (
@@ -79,22 +58,24 @@ var Grid = React.createClass({ totalWidth={this.DOMMetrics.gridWidth()} headerRows={headerRows} /> - +
+ +
); }, diff --git a/src/GridScrollMixin.js b/src/GridScrollMixin.js new file mode 100644 index 0000000..3719264 --- /dev/null +++ b/src/GridScrollMixin.js @@ -0,0 +1,34 @@ +/* TODO@flow mixins */ +module.exports = { + + componentDidMount() { + this._scrollLeft = this.refs.viewport.getScroll().scrollLeft; + this._onScroll(); + }, + + componentDidUpdate() { + this._onScroll(); + }, + + componentWillMount() { + this._scrollLeft = undefined; + }, + + componentWillUnmount() { + this._scrollLeft = undefined; + }, + + onScroll(props: {scrollLeft: number}) { + if (this._scrollLeft !== props.scrollLeft) { + this._scrollLeft = props.scrollLeft; + this._onScroll(); + } + }, + + _onScroll() { + if (this._scrollLeft !== undefined) { + this.refs.header.setScrollLeft(this._scrollLeft); + this.refs.viewport.setScrollLeft(this._scrollLeft); + } + } +}; diff --git a/src/Header.js b/src/Header.js index bacc6d1..1a43117 100644 --- a/src/Header.js +++ b/src/Header.js @@ -1,6 +1,8 @@ +/* @flow */ /** * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 + + */ "use strict"; @@ -9,18 +11,20 @@ var cx = React.addons.classSet; var shallowCloneObject = require('./shallowCloneObject'); var ColumnMetrics = require('./ColumnMetrics'); var HeaderRow = require('./HeaderRow'); -var ColumnMetrics = require('./ColumnMetrics'); -var Header = React.createClass({ +type Column = { + width: number +} +var Header = React.createClass({ propTypes: { - columns: React.PropTypes.object.isRequired, + columns: React.PropTypes.shape({ width: React.PropTypes.number.isRequired }).isRequired, totalWidth: React.PropTypes.number, height: React.PropTypes.number.isRequired, headerRows : React.PropTypes.array.isRequired }, - render() { + render(): ?ReactElement { var state = this.state.resizing || this.props; var className = cx({ @@ -37,14 +41,16 @@ var Header = React.createClass({ ); }, - shouldComponentUpdate : function(nextProps, nextState){ - return !(ColumnMetrics.sameColumns(this.props.columns.columns, nextProps.columns.columns, ColumnMetrics.sameColumn)) + shouldComponentUpdate : function(nextProps: any, nextState: any): boolean{ + var update = !(ColumnMetrics.sameColumns(this.props.columns.columns, nextProps.columns.columns, ColumnMetrics.sameColumn)) || this.props.totalWidth != nextProps.totalWidth || (this.props.headerRows.length != nextProps.headerRows.length) - || (this.state.resizing != nextState.resizing) + || (this.state.resizing != nextState.resizing); + + return update; }, - getHeaderRows(){ + getHeaderRows(): Array{ var state = this.state.resizing || this.props; var headerRows = []; this.props.headerRows.forEach((function(row, index){ @@ -52,7 +58,8 @@ var Header = React.createClass({ position: 'absolute', top: this.props.height * index, left: 0, - width: this.props.totalWidth + width: this.props.totalWidth, + overflow : 'hidden' }; headerRows.push( ReactElement} { return { renderer: simpleCellRenderer }; }, - getInitialState() { + getInitialState(): {resizing: boolean} { return {resizing: false}; }, - setScrollLeft(scrollLeft) { + setScrollLeft(scrollLeft: number) { var node = this.getDOMNode(); node.style.webkitTransform = `translate3d(${scrollLeft}px, 0px, 0px)`; node.style.transform = `translate3d(${scrollLeft}px, 0px, 0px)`; }, - getStyle() { + getStyle(): {width:number; left: number; display: string; position: string; overflow: string; height: number; margin: number; textOverflow: string; whiteSpace: string } { return { width: this.props.column.width, left: this.props.column.left, @@ -101,28 +103,31 @@ var HeaderCell = React.createClass({ this.setState({resizing: true}); }, - onDrag(e) { - var width = this.getWidthFromMouseEvent(e); - if (width > 0 && this.props.onResize) { - this.props.onResize(this.props.column, width); + onDrag(e: SyntheticMouseEvent) { + var resize = this.props.onResize || null; //for flows sake, doesnt recognise a null check direct + if(resize) { + var width = this.getWidthFromMouseEvent(e); + if (width > 0) { + resize(this.props.column, width); + } } }, - onDragEnd(e) { + onDragEnd(e: SyntheticMouseEvent) { var width = this.getWidthFromMouseEvent(e); this.props.onResizeEnd(this.props.column, width); this.setState({resizing: false}); }, - getWidthFromMouseEvent(e) { + getWidthFromMouseEvent(e: SyntheticMouseEvent): number { var right = e.pageX; var left = this.getDOMNode().getBoundingClientRect().left; return right - left; } }); -function simpleCellRenderer(props) { - return
{props.column.name}
; +function simpleCellRenderer(props: {column: {name: string}}): ReactElement { + return
{props.column.name}
; } module.exports = HeaderCell; diff --git a/src/HeaderRow.js b/src/HeaderRow.js index b2b2493..efedab0 100644 --- a/src/HeaderRow.js +++ b/src/HeaderRow.js @@ -1,6 +1,6 @@ +/* @flow */ /** * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 */ "use strict"; @@ -9,17 +9,27 @@ var PropTypes = React.PropTypes; var shallowEqual = require('./shallowEqual'); var HeaderCell = require('./HeaderCell'); var getScrollbarSize = require('./getScrollbarSize'); +var ExcelColumn = require('./addons/grids/ExcelColumn'); + + +class HeaderRowStyle { + overflow: string; + width: string; + height: number; + position: string; +}; var HeaderRow = React.createClass({ propTypes: { - width: PropTypes.number, + width: PropTypes.oneOf(PropTypes.number, PropTypes.string), height: PropTypes.number.isRequired, - columns: PropTypes.array.isRequired, - onColumnResize: PropTypes.func + columns: PropTypes.arrayOf(ExcelColumn).isRequired, + onColumnResize: PropTypes.func, + style: PropTypes.shape(HeaderRowStyle) }, - render() { + render(): ?ReactElement { var cellsStyle = { width: this.props.width ? (this.props.width + getScrollbarSize()) : '100%', height: this.props.height, @@ -30,7 +40,7 @@ var HeaderRow = React.createClass({ var cells = this.getCells(); return ( -
+
{cells}
@@ -38,7 +48,7 @@ var HeaderRow = React.createClass({ ); }, - getCells() { + getCells(): Array { var cells = []; var lockedCells = []; @@ -66,7 +76,7 @@ var HeaderRow = React.createClass({ return cells.concat(lockedCells); }, - setScrollLeft(scrollLeft) { + setScrollLeft(scrollLeft: number) { for (var i = 0, len = this.props.columns.length; i < len; i++) { if (this.props.columns[i].locked) { this.refs[i].setScrollLeft(scrollLeft); @@ -74,7 +84,8 @@ var HeaderRow = React.createClass({ } }, - shouldComponentUpdate(nextProps) { + + shouldComponentUpdate(nextProps: {width: ?(number | string); height: number; columns: Array; style: ?HeaderRowStyle; onColumnResize: ?any}): boolean { return ( nextProps.width !== this.props.width || nextProps.height !== this.props.height @@ -83,7 +94,7 @@ var HeaderRow = React.createClass({ ); }, - getStyle() { + getStyle(): HeaderRowStyle { return { overflow: 'hidden', width: '100%', diff --git a/src/addons/cells/mixins/KeyboardHandlerMixin.js b/src/KeyboardHandlerMixin.js similarity index 84% rename from src/addons/cells/mixins/KeyboardHandlerMixin.js rename to src/KeyboardHandlerMixin.js index 0617755..d95f49f 100644 --- a/src/addons/cells/mixins/KeyboardHandlerMixin.js +++ b/src/KeyboardHandlerMixin.js @@ -1,6 +1,8 @@ +/* TODO@flow: mixins */ /** * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 + + */ 'use strict'; @@ -12,7 +14,10 @@ var hasPerfStarted = false; var KeyboardHandlerMixin = { - onKeyDown(e){ + propTypes : { + }, + + onKeyDown(e: SyntheticKeyboardEvent){ if(this.isCtrlKeyHeldDown(e)){ this.checkAndCall('onPressKeyWithCtrl', e); } @@ -27,7 +32,7 @@ var KeyboardHandlerMixin = { }, //taken from http://stackoverflow.com/questions/12467240/determine-if-javascript-e-keycode-is-a-printable-non-control-character - isKeyPrintable(keycode){ + isKeyPrintable(keycode: number): boolean{ var valid = (keycode > 47 && keycode < 58) || // number keys keycode == 32 || keycode == 13 || // spacebar & return key(s) (if you want to allow carriage returns) @@ -39,15 +44,15 @@ var KeyboardHandlerMixin = { return valid; }, - isKeyIdentified(key){ + isKeyIdentified(key: string): boolean{ return key !== "Unidentified"; }, - isCtrlKeyHeldDown(e){ + isCtrlKeyHeldDown(e: SyntheticKeyboardEvent): boolean{ return e.ctrlKey === true && e.key !== "Control"; }, - checkAndCall(methodName, args){ + checkAndCall(methodName: string, args: any){ if(typeof this[methodName] === 'function'){ this[methodName](args); } diff --git a/src/Row.js b/src/Row.js index 062e9ea..fc649ee 100644 --- a/src/Row.js +++ b/src/Row.js @@ -1,6 +1,8 @@ +/* @flow */ /** * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 + + */ 'use strict'; @@ -10,16 +12,43 @@ var Cell = require('./Cell'); var cloneWithProps = React.addons.cloneWithProps; var ColumnMetrics = require('./ColumnMetrics'); +type RowPropsType = { + height: number; + idx: number; + columns: any; + row: any; + cellRenderer: ?any; + isSelected: ?boolean; +}; + +type cellProps = { + props: { + selected: {rowIdx: number}; + dragged: {complete: bool; rowIdx: number}; + copied: { rowIdx: number}; + } +}; + var Row = React.createClass({ - render() { + propTypes: { + height: React.PropTypes.number.isRequired, + columns: React.PropTypes.array.isRequired, + row: React.PropTypes.object.isRequired, + cellRenderer: React.PropTypes.func, + isSelected: React.PropTypes.bool, + idx : React.PropTypes.number.isRequired, + expandedRows : React.PropTypes.arrayOf(React.PropTypes.object) + }, + + render(): ?ReactElement { var className = cx( 'react-grid-Row', `react-grid-Row--${this.props.idx % 2 === 0 ? 'even' : 'odd'}` ); var style = { - height: this.getRowHeight(), + height: this.getRowHeight(this.props), overflow: 'hidden' }; @@ -32,7 +61,7 @@ var Row = React.createClass({ ); }, - getCells() { + getCells(): Array { var cells = []; var lockedCells = []; @@ -48,6 +77,8 @@ var Row = React.createClass({ column:column, height:this.getRowHeight(), formatter:column.formatter, + cellMetaData : this.props.cellMetaData, + //TODO passing the row to the cell?? rowData : this.props.row}); if (column.locked) { lockedCells.push(cell); @@ -59,15 +90,18 @@ var Row = React.createClass({ return cells.concat(lockedCells); }, - getRowHeight(){ - if(this.props.expandedRows && this.props.expandedRows[this.props.key]){ - return this.props.expandedRows[this.props.key]; - }else{ - return this.props.height; + getRowHeight(): number { + var rows = this.props.expandedRows || null; + if(rows && this.props.key) { + var row = rows[this.props.key] || null; + if(row) { + return row.height; + } } + return this.props.height; }, - getCellValue(key){ + getCellValue(key: number | string): any { if(key === 'select-row'){ return this.props.isSelected; }else{ @@ -75,7 +109,10 @@ var Row = React.createClass({ } }, - renderCell(props) { + renderCell(props: any): ReactElement { + if(typeof this.props.cellRenderer == 'function') { + this.props.cellRenderer.call(this, props); + } if (React.isValidElement(this.props.cellRenderer)) { return cloneWithProps(this.props.cellRenderer, props); } else { @@ -83,23 +120,16 @@ var Row = React.createClass({ } }, - getDefaultProps() { + getDefaultProps(): {cellRenderer: Cell} { return { - cellRenderer: Cell + cellRenderer: Cell, + isSelected: false, + height : 35 }; }, - shouldComponentUpdate(nextProps) { - return !(ColumnMetrics.sameColumns(this.props.columns, nextProps.columns, ColumnMetrics.sameColumn)) || - this.doesRowContainSelectedCell() || - this.doesRowContainSelectedCell(nextProps) || - this.willRowBeDraggedOver(nextProps) || - this.hasRowBeenCopied() || - nextProps.row !== this.props.row || - nextProps.height !== this.props.height; - }, - setScrollLeft(scrollLeft) { + setScrollLeft(scrollLeft: number) { for (var i = 0, len = this.props.columns.length; i < len; i++) { if (this.props.columns[i].locked) { this.refs[i].setScrollLeft(scrollLeft); @@ -107,26 +137,33 @@ var Row = React.createClass({ } }, - doesRowContainSelectedCell(propsToCheck){ - var props = propsToCheck || this.props; - var cell = cell || props.cellRenderer; - if(cell.props.selected && cell.props.selected.rowIdx === props.idx){ + doesRowContainSelectedCell(props: any): boolean{ + var selected = props.cellMetaData.selected; + if(selected && selected.rowIdx === props.idx){ return true; }else{ return false; } }, - willRowBeDraggedOver(props){ + willRowBeDraggedOver(props: any): boolean{ var dragged = props.cellRenderer.props.dragged; return dragged != null && (dragged.rowIdx || dragged.complete === true); }, - hasRowBeenCopied(){ - var cell = this.props.cellRenderer; - return cell.props.copied != null && cell.props.copied.rowIdx === this.props.idx; - } + hasRowBeenCopied(): boolean{ + var copied = this.props.cellMetaData.copied; + return copied != null && copied.rowIdx === this.props.idx; + }, + shouldComponentUpdate(nextProps: any): boolean { + return !(ColumnMetrics.sameColumns(this.props.columns, nextProps.columns, ColumnMetrics.sameColumn)) || + this.doesRowContainSelectedCell(this.props) || + this.doesRowContainSelectedCell(nextProps) || + nextProps.row !== this.props.row || + this.hasRowBeenCopied() || + nextProps.height !== this.props.height; + } }); diff --git a/src/ScrollShim.js b/src/ScrollShim.js index 66a797b..353b9c6 100644 --- a/src/ScrollShim.js +++ b/src/ScrollShim.js @@ -1,6 +1,8 @@ +/* TODO@flow mixin not compatible and HTMLElement classList */ /** * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 + + */ 'use strict'; @@ -10,7 +12,7 @@ var ScrollShim = { if (!this._scrollShim) { var size = this._scrollShimSize(); var shim = document.createElement('div'); - shim.classList.add('react-grid-ScrollShim'); + shim.classList.add('react-grid-ScrollShim'); //flow - not compatible with HTMLElement shim.style.position = 'absolute'; shim.style.top = 0; shim.style.left = 0; @@ -22,7 +24,7 @@ var ScrollShim = { this._scheduleRemoveScrollShim(); }, - _scrollShimSize() { + _scrollShimSize(): {width: number; height: number } { return { width: this.props.width, height: this.props.length * this.props.rowHeight diff --git a/src/Viewport.js b/src/Viewport.js index d16a935..fc64093 100644 --- a/src/Viewport.js +++ b/src/Viewport.js @@ -1,119 +1,39 @@ +/* @flow */ /** * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 + + */ 'use strict'; var React = require('react/addons'); -var getWindowSize = require('./getWindowSize'); -var DOMMetrics = require('./DOMMetrics'); var Canvas = require('./Canvas'); +var PropTypes = React.PropTypes; -var min = Math.min; -var max = Math.max; -var floor = Math.floor; -var ceil = Math.ceil; - -var ViewportScroll = { - mixins: [DOMMetrics.MetricsMixin], - - DOMMetrics: { - viewportHeight() { - return this.getDOMNode().offsetHeight; - } - }, - - propTypes: { - rowHeight: React.PropTypes.number, - length: React.PropTypes.number.isRequired - }, - - getDefaultProps() { - return { - rowHeight: 30 - }; - }, - - getInitialState() { - return this.getGridState(this.props); - }, - - getGridState(props) { - var height = this.state && this.state.height ? - this.state.height : - getWindowSize().height; - var renderedRowsCount = ceil(height / props.rowHeight); - return { - displayStart: 0, - displayEnd: renderedRowsCount * 2, - height: height, - scrollTop: 0, - scrollLeft: 0 - }; - }, +var ViewportScroll = require('./ViewportScrollMixin'); - updateScroll(scrollTop, scrollLeft, height, rowHeight, length) { - var renderedRowsCount = ceil(height / rowHeight); - var visibleStart = floor(scrollTop / rowHeight); - - var visibleEnd = min( - visibleStart + renderedRowsCount, - length); - - var displayStart = max( - 0, - visibleStart - renderedRowsCount * 2); - - var displayEnd = min( - visibleStart + renderedRowsCount * 2, - length); - - var nextScrollState = { - visibleStart, - visibleEnd, - displayStart, - displayEnd, - height, - scrollTop, - scrollLeft - }; - - this.setState(nextScrollState); - }, - - metricsUpdated() { - var height = this.DOMMetrics.viewportHeight(); - if (height) { - this.updateScroll( - this.state.scrollTop, - this.state.scrollLeft, - height, - this.props.rowHeight, - this.props.length - ); - } - }, - - componentWillReceiveProps(nextProps) { - if (this.props.rowHeight !== nextProps.rowHeight) { - this.setState(this.getGridState(nextProps)); - } else if (this.props.length !== nextProps.length) { - this.updateScroll( - this.state.scrollTop, - this.state.scrollLeft, - this.state.height, - nextProps.rowHeight, - nextProps.length - ); - } - } -}; var Viewport = React.createClass({ mixins: [ViewportScroll], - render() { + propTypes: { + rowOffsetHeight: PropTypes.number.isRequired, + totalWidth: PropTypes.number.isRequired, + columns: PropTypes.shape({ + width: PropTypes.number.isRequired, + columns: PropTypes.array.isRequired, + }), + rows: PropTypes.oneOfType([PropTypes.array, PropTypes.func]).isRequired, + selectedRows: PropTypes.array, + expandedRows: PropTypes.array, + rowRenderer: PropTypes.func, + totalRows: PropTypes.number.isRequired, + rowHeight: PropTypes.number.isRequired, + onRows: PropTypes.func, + onScroll: PropTypes.func + }, + render(): ?ReactElement { var style = { padding: 0, bottom: 0, @@ -135,15 +55,14 @@ var Viewport = React.createClass({ selectedRows={this.props.selectedRows} expandedRows={this.props.expandedRows} columns={this.props.columns.columns} - cellRenderer={this.props.cellRenderer} rowRenderer={this.props.rowRenderer} visibleStart={this.state.visibleStart} visibleEnd={this.state.visibleEnd} displayStart={this.state.displayStart} displayEnd={this.state.displayEnd} - - length={this.props.length} + cellMetaData={this.props.cellMetaData} + totalRows={this.props.totalRows} height={this.state.height} rowHeight={this.props.rowHeight} onScroll={this.onScroll} @@ -153,24 +72,24 @@ var Viewport = React.createClass({ ); }, - getScroll() { + getScroll(): {scrollLeft: number; scrollTop: number} { return this.refs.canvas.getScroll(); }, - onScroll({scrollTop, scrollLeft}) { + onScroll(scroll: {scrollTop: number; scrollLeft: number}) { this.updateScroll( - scrollTop, scrollLeft, + scroll.scrollTop, scroll.scrollLeft, this.state.height, this.props.rowHeight, - this.props.length + this.props.totalRows ); if (this.props.onScroll) { - this.props.onScroll({scrollTop, scrollLeft}); + this.props.onScroll({scrollTop: scroll.scrollTop, scrollLeft: scroll.scrollLeft}); } }, - setScrollLeft(scrollLeft) { + setScrollLeft(scrollLeft: number) { this.refs.canvas.setScrollLeft(scrollLeft); } }); diff --git a/src/ViewportScrollMixin.js b/src/ViewportScrollMixin.js new file mode 100644 index 0000000..2f6e752 --- /dev/null +++ b/src/ViewportScrollMixin.js @@ -0,0 +1,113 @@ +/* TODO@flow mixins */ + +var React = require('react/addons'); +var DOMMetrics = require('./DOMMetrics'); +var getWindowSize = require('./getWindowSize'); + +var PropTypes = React.PropTypes; +var min = Math.min; +var max = Math.max; +var floor = Math.floor; +var ceil = Math.ceil; + +type ViewportScrollState = { + displayStart: number; + displayEnd: number; + height: number; + scrollTop: number; + scrollLeft: number; +}; + +module.exports = { + mixins: [DOMMetrics.MetricsMixin], + + DOMMetrics: { + viewportHeight(): number { + return this.getDOMNode().offsetHeight; + } + }, + + propTypes: { + rowHeight: React.PropTypes.number, + totalRows: React.PropTypes.number.isRequired + }, + + getDefaultProps(): { rowHeight: number } { + return { + rowHeight: 30 + }; + }, + + getInitialState(): ViewportScrollState { + return this.getGridState(this.props); + }, + + getGridState(props: {rowHeight: number}): ViewportScrollState { + var height = this.props.minHeight; + var renderedRowsCount = ceil(height / props.rowHeight); + return { + displayStart: 0, + displayEnd: renderedRowsCount * 2, + height: height, + scrollTop: 0, + scrollLeft: 0 + }; + }, + + updateScroll(scrollTop: number, scrollLeft: number, height: number, rowHeight: number, length: number) { + var renderedRowsCount = ceil(height / rowHeight); + + var visibleStart = floor(scrollTop / rowHeight); + + var visibleEnd = min( + visibleStart + renderedRowsCount, + length); + + var displayStart = max( + 0, + visibleStart - renderedRowsCount * 2); + + var displayEnd = min( + visibleStart + renderedRowsCount * 2, + length); + + var nextScrollState = { + visibleStart, + visibleEnd, + displayStart, + displayEnd, + height, + scrollTop, + scrollLeft + }; + + this.setState(nextScrollState); + }, + + metricsUpdated() { + var height = this.DOMMetrics.viewportHeight(); + if (height) { + this.updateScroll( + this.state.scrollTop, + this.state.scrollLeft, + height, + this.props.rowHeight, + this.props.totalRows + ); + } + }, + + componentWillReceiveProps(nextProps: { rowHeight: number; totalRows: number }) { + if (this.props.rowHeight !== nextProps.rowHeight) { + this.setState(this.getGridState(nextProps)); + } else if (this.props.totalRows !== nextProps.totalRows) { + this.updateScroll( + this.state.scrollTop, + this.state.scrollLeft, + this.state.height, + nextProps.rowHeight, + nextProps.totalRows + ); + } + } +}; diff --git a/src/addons/cells/CopyableCell.js b/src/addons/cells/CopyableCell.js deleted file mode 100644 index 2b05ad7..0000000 --- a/src/addons/cells/CopyableCell.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ -'use strict'; - -var React = require('react/addons'); -var cx = React.addons.classSet; -var cloneWithProps = React.addons.cloneWithProps; -var BaseCell = require('../../Cell'); -var SelectableMixin = require('./mixins/SelectableMixin'); -var EditableMixin = require('./mixins/EditableMixin'); -var CopyableMixin = require('./mixins/CopyableMixin'); -var MixinHelper = require('../utils/MixinHelper'); -var KeyboardHandlerMixin = require('./mixins/KeyboardHandlerMixin'); - - -var CopyableCell = React.createClass({ - - - mixins : [CopyableMixin], - - render: function() { - return () - } - -}); - -module.exports = CopyableCell; diff --git a/src/addons/cells/DraggableCell.js b/src/addons/cells/DraggableCell.js deleted file mode 100644 index 3695f1e..0000000 --- a/src/addons/cells/DraggableCell.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ -'use strict'; - -var React = require('react/addons'); -var cx = React.addons.classSet; -var cloneWithProps = React.addons.cloneWithProps; -var BaseCell = require('../../Cell'); -var SelectableMixin = require('./mixins/SelectableMixin'); -var MixinHelper = require('../utils/MixinHelper'); -var KeyboardHandlerMixin = require('./mixins/KeyboardHandlerMixin'); -var DraggableMixin = require('./mixins/DraggableMixin'); - -var DraggableCell = React.createClass({ - - - mixins : [DraggableMixin], - - render: function() { - return ( - ) - } - -}) - -module.exports = DraggableCell; diff --git a/src/addons/cells/EditableCell.js b/src/addons/cells/EditableCell.js deleted file mode 100644 index 8b8161e..0000000 --- a/src/addons/cells/EditableCell.js +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ -'use strict'; - -var React = require('react/addons'); -var cx = React.addons.classSet; -var cloneWithProps = React.addons.cloneWithProps; -var SelectableMixin = require('./mixins/SelectableMixin'); -var EditableMixin = require('./mixins/EditableMixin'); -var BaseCell = require('../../Cell'); -var MixinHelper = require('../utils/MixinHelper'); -var KeyboardHandlerMixin = require('./mixins/KeyboardHandlerMixin'); -var PropTypes = React.PropTypes; - - - -var EditableCell = React.createClass({ - - mixins : [EditableMixin], - - getCellClass : function(){ - return cx({ - 'editing' : this.isActive(), - 'selected' : this.isSelected() && !this.isActive() - }); - }, - - shouldComponentUpdate(nextProps, nextState) { - return this.props.column.width !== nextProps.column.width - || this.props.value !== nextProps.value - || this.props.height !== nextProps.height - || this.props.rowIdx !== nextProps.rowIdx - || this.isCellSelectionChanging(nextProps); - }, - - render: function() { - return ( - - ) - } - -}) - -module.exports = EditableCell; diff --git a/src/addons/cells/ExcelCell.js b/src/addons/cells/ExcelCell.js index 7d9b62a..a7d2810 100644 --- a/src/addons/cells/ExcelCell.js +++ b/src/addons/cells/ExcelCell.js @@ -1,136 +1,136 @@ -/** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ -'use strict'; - -var React = require('react/addons'); -var BaseCell = require('../../Cell'); -var SelectableMixin = require('./mixins/SelectableMixin'); -var EditableMixin = require('./mixins/EditableMixin'); -var CopyableMixin = require('./mixins/CopyableMixin'); -var DraggableMixin = require('./mixins/DraggableMixin'); -var MixinHelper = require('../utils/MixinHelper'); -var KeyboardHandlerMixin = require('./mixins/KeyboardHandlerMixin'); -var isFunction = require('../utils/isFunction'); -var PropTypes = React.PropTypes; -var cx = React.addons.classSet; -var cloneWithProps = React.addons.cloneWithProps; - - - -var CellControls = React.createClass({ - - onClickEdit : function(e){ - e.stopPropagation(); - e.preventDefault(); - this.props.onClickEdit(); - }, - - onShowMore : function(e){ - e.stopPropagation(); - e.preventDefault(); - var newHeight = this.props.column.getExpandedHeight(this.props.value); - this.props.onShowMore(this.props.rowIdx, newHeight); - }, - - onShowLess : function(e){ - e.stopPropagation(); - e.preventDefault(); - this.props.onShowLess(this.props.rowIdx); - }, - - shouldComponentUpdate(nextProps, nextState){ - return this.props.height != nextProps.height; - }, - - renderShowMoreButton(){ - if(isFunction(this.props.column.getExpandedHeight) && this.props.column.getExpandedHeight(this.props.value) > 0){ - var newHeight = this.props.column.getExpandedHeight(this.props.value); - if(newHeight > this.props.height){ - return - }else{ - return - } - }else{ - return null; - } - }, - - render : function(){ - return (
- {this.renderShowMoreButton()} - -
) - } - -}) - - -var ExcelCell = React.createClass({ - - mixins : [EditableMixin, CopyableMixin, DraggableMixin], - - overrides : { - getCellClass : function(){ - return cx({ - 'selected' : this.isSelected() && !this.isCopied() && !this.isActive(), - 'editing' : this.isActive(), - 'copied' : this.isCopied(), - 'selected-draggable' : this.isSelected() && !this.isActive() && this.canEdit(), - 'active-drag-cell' : this.isActiveDragCell() && this.canEdit(), - 'is-dragged-over-up' : !this.isSelected() && this.isDraggedOver() && this.props.rowIdx < this.props.dragged.rowIdx, - 'is-dragged-over-down' : !this.isSelected() && this.isDraggedOver() && this.props.rowIdx > this.props.dragged.rowIdx, - 'was-dragged-over' : this.wasDraggedOver() && this.canEdit() - }); - } - }, - - isActiveDragCell : function(){ - return (this.isSelected() || this.isDraggedOver()) && !this.isActive(); - }, - - isExpanded : function(){ - var isExpanded = false; - if(isFunction(this.props.column.getExpandedHeight) && this.props.column.getExpandedHeight(this.props.value) > 0){ - var newHeight = this.props.column.getExpandedHeight(this.props.value); - if(this.props.height >= newHeight){ - isExpanded = true; - }else{ - isExpanded = false; - } - } - return isExpanded; - }, - - - shouldComponentUpdate(nextProps, nextState) { - return this.props.column.width !== nextProps.column.width - || this.props.value !== nextProps.value - || this.props.height !== nextProps.height - || this.props.rowIdx !== nextProps.rowIdx - || this.isCellSelectionChanging(nextProps) - || this.isDraggedCellChanging(nextProps); - }, - - - render: function() { - return ( - : null} - isExpanded={this.isExpanded()} - />) - } - -}) - -module.exports = ExcelCell; +// /* @flow */ +// /** +// * @jsx React.DOM +// +// +// */ +// 'use strict'; +// +// var React = require('react/addons'); +// var BaseCell = require('../../Cell'); +// var EditableMixin = require('./mixins/EditableMixin'); +// var CopyableMixin = require('./mixins/CopyableMixin'); +// var DraggableMixin = require('./mixins/DraggableMixin'); +// var MixinHelper = require('../utils/MixinHelper'); +// var KeyboardHandlerMixin = require('./mixins/KeyboardHandlerMixin'); +// var isFunction = require('../utils/isFunction'); +// var PropTypes = React.PropTypes; +// var cx = React.addons.classSet; +// var cloneWithProps = React.addons.cloneWithProps; +// var ExcelColumn = require('../grids/ExcelColumn'); +// +// +// var CellControls = React.createClass({ +// +// propTypes : { +// column : React.PropTypes.shape(ExcelColumn).isRequired, +// onClickEdit : React.PropTypes.func.isRequired, +// onShowMore : React.PropTypes.func.isRequired, +// onShowLess : React.PropTypes.func.isRequired, +// height : React.PropTypes.number.isRequired, +// value : React.PropTypes.any.isRequired, +// rowIdx : React.PropTypes.number.isRequired +// }, +// +// onClickEdit : function(e: Event){ +// e.stopPropagation(); +// e.preventDefault(); +// this.props.onClickEdit(); +// }, +// +// onShowMore : function(e: Event){ +// e.stopPropagation(); +// e.preventDefault(); +// var newHeight = this.props.column.getExpandedHeight(this.props.value); +// this.props.onShowMore(this.props.rowIdx, newHeight); +// }, +// +// onShowLess : function(e: Event){ +// e.stopPropagation(); +// e.preventDefault(); +// this.props.onShowLess(this.props.rowIdx); +// }, +// +// shouldComponentUpdate(nextProps: any, nextState: any){ +// return this.props.height != nextProps.height; +// }, +// +// renderShowMoreButton(): ?ReactElement { +// if(isFunction(this.props.column.getExpandedHeight) && this.props.column.getExpandedHeight(this.props.value) > 0){ +// var newHeight = this.props.column.getExpandedHeight(this.props.value); +// if(newHeight > this.props.height){ +// return +// }else{ +// return +// } +// }else{ +// return null; +// } +// }, +// +// render : function(): ?ReactElement { +// return (
+// {this.renderShowMoreButton()} +// +//
) +// } +// +// }) +// +// +// var ExcelCell = React.createClass({ +// +// mixins : [SelectableMixin], +// +// getCellClass : function(){ +// return cx({ +// 'selected' : this.isSelected() +// }); +// }, +// +// isActiveDragCell : function(): boolean{ +// return (this.isSelected() || this.isDraggedOver()) && !this.isActive(); +// }, +// +// isExpanded : function(): boolean{ +// var isExpanded = false; +// if(isFunction(this.props.column.getExpandedHeight) && this.props.column.getExpandedHeight(this.props.value) > 0){ +// var newHeight = this.props.column.getExpandedHeight(this.props.value); +// if(this.props.height >= newHeight){ +// isExpanded = true; +// }else{ +// isExpanded = false; +// } +// } +// return isExpanded; +// }, +// +// +// shouldComponentUpdate(nextProps: any, nextState: any): boolean { +// return this.props.column.width !== nextProps.column.width +// || this.props.value !== nextProps.value +// || this.props.height !== nextProps.height +// || this.props.rowIdx !== nextProps.rowIdx +// || this.isCellSelectionChanging(nextProps); +// }, +// +// +// render: function(): ?ReactElement { +// return ( +// : null} +// isExpanded={this.isExpanded()} +// />) +// } +// +// }) +// +// module.exports = ExcelCell; diff --git a/src/addons/cells/SelectableCell.js b/src/addons/cells/SelectableCell.js deleted file mode 100644 index 6e7ae55..0000000 --- a/src/addons/cells/SelectableCell.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ -'use strict'; - -var React = require('react/addons'); -var cx = React.addons.classSet; -var cloneWithProps = React.addons.cloneWithProps; -var BaseCell = require('../../Cell'); -var SelectableMixin = require('./mixins/SelectableMixin'); -var MixinHelper = require('../utils/MixinHelper'); - -var SelectableCell = React.createClass({ - - mixins : [SelectableMixin], - - getCellClass : function(){ - return this.isSelected() ? 'selected' : null; - }, - - shouldComponentUpdate(nextProps, nextState) { - return this.props.column.width !== nextProps.column.width - || this.props.value !== nextProps.value - || this.props.height !== nextProps.height - || this.props.rowIdx !== nextProps.rowIdx - || this.isCellSelectionChanging(nextProps); - }, - - render: function() { - return ( - ) - } - -}) - -module.exports = SelectableCell; diff --git a/src/addons/cells/headerCells/FilterableHeaderCell.js b/src/addons/cells/headerCells/FilterableHeaderCell.js index d7fbd8a..29c650a 100644 --- a/src/addons/cells/headerCells/FilterableHeaderCell.js +++ b/src/addons/cells/headerCells/FilterableHeaderCell.js @@ -1,30 +1,41 @@ +/* @flow */ /** * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 + + */ 'use strict'; var React = require('react/addons'); var cx = React.addons.classSet; +var ExcelColumn = require('../../grids/ExcelColumn'); var FilterableHeaderCell = React.createClass({ - getInitialState(){ + propTypes: { + onChange: React.PropTypes.func.isRequired, + column: React.PropTypes.shape(ExcelColumn).isRequired + }, + + getInitialState(): {filterTerm: string}{ return {filterTerm : ''} }, - handleChange(e){ + handleChange(e: Event){ e.preventDefault(); e.stopPropagation(); - this.setState({filterTerm : e.currentTarget.value}); - this.props.onChange({filterTerm : e.currentTarget.value, columnKey : this.props.column.key}); + + var val = e.target.value; + this.setState({filterTerm : val }); + this.props.onChange({filterTerm : val, columnKey : this.props.column.key}); }, - componentDidUpdate(){ - this.getDOMNode().focus(); + componentDidUpdate(nextProps: any) { + var ele = this.getDOMNode(); + if(ele) ele.focus(); }, - render: function() { + render: function(): ?ReactElement { return (
@@ -34,7 +45,7 @@ var FilterableHeaderCell = React.createClass({ ); }, - renderInput : function(){ + renderInput : function(): ?ReactElement { if(this.props.column.filterable === false){ return ; }else{ diff --git a/src/addons/cells/headerCells/SortableHeaderCell.js b/src/addons/cells/headerCells/SortableHeaderCell.js index 28cc238..89eaa0e 100644 --- a/src/addons/cells/headerCells/SortableHeaderCell.js +++ b/src/addons/cells/headerCells/SortableHeaderCell.js @@ -1,14 +1,19 @@ +/* @flow */ /** * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 + + */ 'use strict'; var React = require('react/addons'); var cx = React.addons.classSet; +var ExcelColumn = require('../../grids/ExcelColumn'); var SortableHeaderCell = React.createClass({ - + propTypes: { + column: React.PropTypes.shape(ExcelColumn).isRequired + }, onClick: function() { this.props.column.sortBy( this.props.column, @@ -24,7 +29,7 @@ var SortableHeaderCell = React.createClass({ }); }, - render: function() { + render: function(): ?ReactElement { return (
this.props.dragged.rowIdx, - 'was-dragged-over' : this.wasDraggedOver() - }); -}, - - getDefaultProps : function(){ - return { - handleDragStart: this.handleDragStart, - onDragEnter: this.handleDragEnter, - onDragEnd: this.handleDragEnd - } - }, - - propTypes : { - handleDragEnter : React.PropTypes.func.isRequired, - handleDragStart : React.PropTypes.func.isRequired, - handleDragEnd : React.PropTypes.func.isRequired, - handleTerminateDrag : React.PropTypes.func.isRequired - }, - - isDraggedOver(){ - - return ( - this.props.dragged && - this.props.dragged.overRowIdx === this.props.rowIdx - && this.props.dragged.idx === this.props.idx - ) - }, - - wasDraggedOver(){ - return ( - this.props.dragged - && ((this.props.dragged.overRowIdx < this.props.rowIdx && this.props.rowIdx < this.props.dragged.rowIdx) - || (this.props.dragged.overRowIdx > this.props.rowIdx && this.props.rowIdx > this.props.dragged.rowIdx)) - && this.props.dragged.idx === this.props.idx - ); - }, - - handleDragStart(e){ - var rowIdx = this.props.rowIdx; - var idx = this.props.idx; - this.props.handleDragStart({rowIdx : rowIdx, idx : idx, copiedText : this.props.value}); - }, - - handleDragEnter(){ - this.props.handleDragEnter(this.props.rowIdx); - }, - - handleDragEnd(){ - this.props.handleDragEnd(); - }, - - isDraggedCellChanging(nextProps){ - if(this.props.dragged){ - return (nextProps.dragged && this.props.idx === nextProps.dragged.idx) - || (this.props.dragged && this.props.idx === this.props.dragged.idx); - }else{ - return false; - } - }, - - componentDidUpdate(){ - var dragged = this.props.dragged; - if(dragged && dragged.complete === true){ - this.props.handleTerminateDrag(); - } - } - -}); - - - -module.exports = DraggableMixin; diff --git a/src/addons/cells/mixins/EditableMixin.js b/src/addons/cells/mixins/EditableMixin.js deleted file mode 100644 index e98caa4..0000000 --- a/src/addons/cells/mixins/EditableMixin.js +++ /dev/null @@ -1,139 +0,0 @@ -/** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ -'use strict'; - -var React = require('react/addons'); -var cx = React.addons.classSet; -var cloneWithProps = React.addons.cloneWithProps; -var SimpleTextEditor = require('../../editors/SimpleTextEditor'); -var PropTypes = React.PropTypes; -var MixinHelper = require('../../utils/MixinHelper'); -var SelectableMixin = require('./SelectableMixin'); -var KeyboardHandlerMixin = require('./KeyboardHandlerMixin'); - -var EditableMixin = MixinHelper.createDependency({ - - KeyboardHandlerMixin : KeyboardHandlerMixin, - - SelectableMixin : SelectableMixin - - }).assignTo({ - - propTypes : { - onCommit : PropTypes.func.isRequired - }, - - canEdit(){ - return (this.props.column.editor != null) || this.props.column.editable; - }, - - - getEditor(){ - - var editorProps = {height : this.props.height, onPressEscape : this.onPressEscape, onCommit : this.onCommit, initialKeyCode : this.props.selected.initialKeyCode, editorRowMetaData : this.getEditorRowMetaData()}; - var customEditor = this.props.column.editor; - if(customEditor && React.isValidElement(customEditor)){ - //return custom column editor or SimpleEditor if none specified - return cloneWithProps(customEditor, editorProps); - }else{ - return cloneWithProps(SimpleTextEditor(), editorProps); - } - }, - - getEditorRowMetaData(){ - //clone row data so editor cannot actually change this - var columnName = this.props.column.ItemId; - //convention based method to get corresponding Id or Name of any Name or Id property - if(typeof this.props.column.getEditorRowMetaData === 'function'){ - return this.props.column.getEditorRowMetaData(this.props.rowData); - } - }, - - getFormatter(){ - var col = this.props.column; - if(this.isActive()){ - return this.getEditor(); - }else{ - return this.props.column.formatter; - } - }, - - onCommit(commit){ - var rowIdx = this.props.rowIdx; - var idx = this.props.idx; - var cellKey = this.props.column.key; - this.props.onCommit({cellKey: cellKey, rowIdx: this.props.filterRowIdx || rowIdx, updated : commit.updated, keyCode : commit.key}); - }, - - checkFocus: function() { - if (this.isSelected() && !this.isActive()) { - this.getDOMNode().focus(); - } - }, - - onClick() { - if(!this.isActive()){ - var rowIdx = this.props.rowIdx; - var idx = this.props.idx; - this.props.onClick({rowIdx: rowIdx, idx: idx}); - } - - }, - - onDoubleClick() { - var rowIdx = this.props.rowIdx; - var idx = this.props.idx; - this.props.onClick({rowIdx: rowIdx, idx: idx, active : this.canEdit()}); - }, - - setActive(keyPressed){ - var rowIdx = this.props.rowIdx; - var idx = this.props.idx; - if(this.props.column.key === 'select-row' && this.props.column.onRowSelect){ - this.props.column.onRowSelect(rowIdx); - } - else if(this.canEdit() && !this.isActive()){ - this.props.onSetActive({idx: idx, rowIdx: rowIdx, active : true, initialKeyCode : keyPressed}); - } - }, - - setInactive(){ - if(this.canEdit() && this.isActive()){ - var rowIdx = this.props.rowIdx; - var idx = this.props.idx; - this.props.onSetActive({idx: idx, rowIdx: rowIdx, active : false}); - } - }, - - isActive(){ - return this.isSelected() && this.props.selected.active === true; - }, - - onPressEnter(e){ - this.setActive(e.key); - }, - - onPressDelete(e){ - this.setActive(e.key); - }, - - onPressEscape(e){ - this.setInactive(e.key); - }, - - onPressBackspace(e){ - this.setActive(e.key); - }, - - onPressChar(e){ - if(this.isKeyPrintable(e.keyCode)){ - this.setActive(e.keyCode); - } - } -}); - - - -module.exports = EditableMixin; diff --git a/src/addons/cells/mixins/SelectableMixin.js b/src/addons/cells/mixins/SelectableMixin.js deleted file mode 100644 index c01f732..0000000 --- a/src/addons/cells/mixins/SelectableMixin.js +++ /dev/null @@ -1,93 +0,0 @@ -/** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ -'use strict'; - -var React = require('react/addons'); -var cx = React.addons.classSet; -var cloneWithProps = React.addons.cloneWithProps; -var KeyboardHandlerMixin = require('./KeyboardHandlerMixin'); -var MixinHelper = require('../../utils/MixinHelper'); - -var SelectableMixin = MixinHelper.createDependency({KeyboardHandlerMixin : KeyboardHandlerMixin}).assignTo({ - - getDefaultProps : function(){ - return { - tabIndex : -1, - ref : "cell" - } - }, - - isSelected: function() { - return ( - this.props.selected - && this.props.selected.rowIdx === this.props.rowIdx - && this.props.selected.idx === this.props.idx - ); - }, - - onClick: function() { - var rowIdx = this.props.rowIdx; - var idx = this.props.idx; - this.props.onClick({rowIdx: rowIdx, idx: idx}); - }, - - onPressArrowUp(e){ - this.moveSelectedCell(e, -1, 0); - }, - - onPressArrowDown(e){ - this.moveSelectedCell(e, 1, 0); - }, - - onPressArrowLeft(e){ - this.moveSelectedCell(e, 0, -1); - }, - - onPressArrowRight(e){ - this.moveSelectedCell(e, 0, 1); - }, - - onPressTab(e){ - this.moveSelectedCell(e, 0, 1); - }, - - moveSelectedCell(e, rowDelta, cellDelta){ - e.stopPropagation(); - e.preventDefault(); - var rowIdx = this.props.rowIdx + rowDelta; - var idx = this.props.idx + cellDelta; - this.props.onSelect({idx: idx, rowIdx: rowIdx}); - }, - - setScrollLeft: function(scrollLeft) { - this.refs.row.setScrollLeft(scrollLeft); - }, - - componentDidMount: function() { - this.checkFocus(); - }, - - componentDidUpdate: function() { - this.checkFocus(); - }, - - isCellSelectionChanging(nextProps){ - if(this.props.selected && nextProps.selected){ - return this.props.idx === nextProps.selected.idx || this.props.idx === this.props.selected.idx; - }else{ - return true; - } - }, - - checkFocus: function() { - if (this.isSelected()) { - this.getDOMNode().focus(); - } - } -}) - - - -module.exports = SelectableMixin; diff --git a/src/addons/cells/mixins/index.js b/src/addons/cells/mixins/index.js deleted file mode 100644 index e0ebbe1..0000000 --- a/src/addons/cells/mixins/index.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - KeyboardHandlerMixin : require('./KeyboardHandlerMixin'), - SelectableMixin : require('./SelectableMixin') - -} diff --git a/src/addons/editors/AutoCompleteEditor.js b/src/addons/editors/AutoCompleteEditor.js index 9e29618..b6ba45e 100644 --- a/src/addons/editors/AutoCompleteEditor.js +++ b/src/addons/editors/AutoCompleteEditor.js @@ -1,16 +1,17 @@ +/* @flow */ +/* Flow issues: +overrides? getDefaultValue, getStyle, onKeyDown +*/ /** * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 */ 'use strict'; var React = require('react/addons'); var cx = React.addons.classSet; -var MixinHelper = require('../utils/MixinHelper'); -var EditorMixin = require('./mixins/EditorMixin'); -var TextInputMixin = require('./mixins/TextInputMixin'); var ReactAutocomplete = require('ron-react-autocomplete'); -var keyboardHandlerMixin = require('../cells/mixins/KeyboardHandlerMixin'); +var KeyboardHandlerMixin = require('../../KeyboardHandlerMixin'); +var ExcelColumn = require('../grids/ExcelColumn'); var optionPropType = React.PropTypes.shape({ id : React.PropTypes.required, @@ -20,109 +21,75 @@ var optionPropType = React.PropTypes.shape({ var AutoCompleteEditor = React.createClass({ propTypes : { - options : React.PropTypes.arrayOf(optionPropType) + onCommit : React.PropTypes.func.isRequired, + options : React.PropTypes.arrayOf(optionPropType).isRequired, + label : React.PropTypes.string, + value : React.PropTypes.any.isRequired, + valueParams: React.PropTypes.arrayOf(React.PropTypes.string), + column: React.PropTypes.shape(ExcelColumn).isRequired, + resultIdentifier : React.PropTypes.string, + search : React.PropTypes.string }, - mixins : MixinHelper.mix([keyboardHandlerMixin, EditorMixin, TextInputMixin]), - - overrides : { - checkFocus : function(){ - this.setTextInputFocus(); - }, - getInputNode(){ - return this.getSearchComponent().getDOMNode(); - }, - onPressEnter(args){ - var e = args[0]; - this.handleEnter(e); - }, - onPressTab(args){ - var e = args[0]; - this.handleTab(e); - } - }, - - handleTab(e){ - e.stopPropagation(); - e.preventDefault(); - if(!this.isFocusedOnSuggestion()){ - this.handleChange(null, 'Tab'); - }else{ - this.handleChange(this.getFocusedSuggestion(), 'Tab'); + getDefaultProps(): {resultIdentifier: string}{ + return { + resultIdentifier : 'id' } }, - handleEnter(e){ - e.stopPropagation(); - e.preventDefault(); - if(!this.isFocusedOnSuggestion()){ - this.props.onCommit({value : this.refs.autoComplete.state.searchTerm, key : 'Enter'}); + getValue(): any{ + var value, updated = {}; + if(this.hasResults() && this.isFocusedOnSuggestion()){ + value = this.getLabel(this.refs.autoComplete.state.focusedValue); + if(this.props.valueParams){ + value = this.constuctValueFromParams(this.refs.autoComplete.state.focusedValue, this.props.valueParams); + } + }else{ + value = this.refs.autoComplete.state.searchTerm; } + updated[this.props.column.key] = value; + return updated; }, - getSearchComponent(){ - return this.refs.autoComplete.refs.search; - }, - - isFocusedOnSuggestion(){ - var autoComplete = this.refs.autoComplete; - return autoComplete.state.focusedValue != null; + getInputNode(): HTMLInputElement{ + return this.getDOMNode().getElementsByTagName("input")[0]; }, - getFocusedSuggestion(){ - return this.refs.autoComplete.state.focusedValue; + render(): ?ReactElement { + var label = this.props.label != null ? this.props.label : 'title'; + return (
+ +
); }, - onPressArrowDown(e){ - //prevent event propogation. this disables downwards cell navigation - e.stopPropagation(); - e.preventDefault(); + hasResults(): boolean{ + return this.refs.autoComplete.state.results.length > 0; }, - onPressArrowUp(e){ - //prevent event propogation. this disables upwards cell navigation - e.stopPropagation(); + isFocusedOnSuggestion(): boolean{ + var autoComplete = this.refs.autoComplete; + return autoComplete.state.focusedValue != null; }, - getLabel(result) { + getLabel(item: any): string { var label = this.props.label != null ? this.props.label : 'title'; if (typeof label === "function") { - return label(result); + return label(item); } else if (typeof label === "string") { - return result[label]; + return item[label]; } }, - handleChange(item, key){ - var rowDataChanged = {}; - var value = this.props.value; - if(item!=null){ - value = this.getLabel(item); - if(this.props.valueParams){ - value = this.constuctValueFromParams(item, this.props.valueParams); - } - rowDataChanged[this.props.column.key] = value; + constuctValueFromParams(obj: any, props: ?Array): string { + if(!props){ + return ''; } - key = key ? key : 'Enter'; - this.props.onCommit({value : value, key : key, updated : rowDataChanged}); - }, - - constuctValueFromParams(obj, props) { var ret = []; for (var i = 0, ii = props.length; i < ii; i++) { ret.push(obj[props[i]]); } return ret.join('|'); - }, - - renderEditorNode(){ - var val = {title : this.getDefaultValue()}; - var label = this.props.label != null ? this.props.label : 'title'; - return (
- -
); } - }); module.exports = AutoCompleteEditor; diff --git a/src/addons/editors/CheckboxEditor.js b/src/addons/editors/CheckboxEditor.js index c647968..0400f3f 100644 --- a/src/addons/editors/CheckboxEditor.js +++ b/src/addons/editors/CheckboxEditor.js @@ -1,6 +1,6 @@ +/* @flow */ /** * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 */ 'use strict'; @@ -11,18 +11,19 @@ var CheckBoxEditor = React.createClass({ PropTypes : { - value : React.PropTypes.bool.isRequired + value : React.PropTypes.bool.isRequired, + rowIdx : React.PropTypes.number.isRequired }, - render(){ + render(): ?ReactElement{ return (); }, - handleChange(e){ + handleChange(e: Event){ this.props.column.onRowSelect(this.props.rowIdx) }, - shouldComponentUpdate(nextProps, nextState){ + shouldComponentUpdate(nextProps: any, nextState: any): boolean{ return this.props.value != nextProps.value; } diff --git a/src/addons/editors/DateRangeEditor.js b/src/addons/editors/DateRangeEditor.js index 9b02dfa..cf40580 100644 --- a/src/addons/editors/DateRangeEditor.js +++ b/src/addons/editors/DateRangeEditor.js @@ -1,22 +1,30 @@ + /** * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 + + */ 'use strict'; var React = require('react/addons'); var cx = React.addons.classSet; -var MixinHelper = require('../utils/MixinHelper'); -var EditorMixin = require('./mixins/EditorMixin'); -var TextInputMixin = require('./mixins/TextInputMixin'); -var keyboardHandlerMixin = require('../cells/mixins/KeyboardHandlerMixin'); var DateRangeFilter = require('./widgets/DateRangeFilter'); +var Moment = require('moment'); + +type DateRangeValue = { startDate: Date; endDate: Date}; var DateRangeEditor = React.createClass({ - mixins : [keyboardHandlerMixin, EditorMixin, TextInputMixin], + PropTypes : { + format : React.PropTypes.string, + ranges : React.PropTypes.arrayOf(React.PropTypes.string), + value : React.PropTypes.shape({ + startDate: React.PropTypes.Date.isRequired, + endDate: React.PropTypes.Date.isRequired + }).isRequired + }, - getDefaultProps(){ + getDefaultProps(): {format: string; ranges: Array}{ return { format : "YYYY-MM-DD", ranges : [] @@ -29,10 +37,10 @@ var DateRangeEditor = React.createClass({ checkFocus : function(){ this.setTextInputFocus(); }, - getInputNode(){ + getInputNode(): HTMLElement{ return this.refs.datepicker.getDOMNode(); }, - getValue(){ + getValue(): DateRangeValue{ var dateToParse = this.getInputNode().value; var dateRanges = dateToParse.split(this.rangeSeparatorChar); if(dateRanges.length !== 2){ @@ -42,22 +50,22 @@ var DateRangeEditor = React.createClass({ } }, - isDateValid(date){ - return moment(date, this.props.format, true).isValid(); + isDateValid(date: Date): boolean{ + return Moment(date, this.props.format, true).isValid(); }, - validate(value){ + validate(value: DateRangeValue): boolean{ return this.isDateValid(value.startDate) && this.isDateValid(value.endDate) - && (moment(value.startDate, this.props.format).isBefore(value.endDate) - || moment(value.startDate, this.props.format).isSame(value.endDate)); + && (Moment(value.startDate, this.props.format).isBefore(value.endDate) + || Moment(value.startDate, this.props.format).isSame(value.endDate)); }, - handleDateFilterApply(startDate, endDate){ + handleDateFilterApply(startDate: string, endDate: string){ this.commit({value : {startDate : startDate, endDate : endDate}}); }, - renderEditorNode(){ + render(): ?ReactElement{ return (
diff --git a/src/addons/editors/DropDownEditor.js b/src/addons/editors/DropDownEditor.js index eadbfb6..91d8a02 100644 --- a/src/addons/editors/DropDownEditor.js +++ b/src/addons/editors/DropDownEditor.js @@ -1,38 +1,36 @@ +/* @flow */ /** * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 + + */ 'use strict'; var React = require('react/addons'); var cx = React.addons.classSet; -var MixinHelper = require('../utils/MixinHelper'); -var keyboardHandlerMixin = require('../cells/mixins/KeyboardHandlerMixin'); -var EditorMixin = require('./mixins/EditorMixin'); -var cloneWithProps = React.addons.cloneWithProps; var DropDownEditor = React.createClass({ - mixins : [keyboardHandlerMixin, EditorMixin], - - overrides : { - getInputNode : function(){ - return this.refs.select.getDOMNode(); - } + propTypes : { + options : React.PropTypes.arrayOf(React.PropTypes.string).isRequired, + value : React.PropTypes.string.isRequired, + commit : React.PropTypes.func.isRequired }, - propTypes : { - options : React.PropTypes.array.isRequired + getStyle(): {width: string}{ + return { + width : '100%' + } }, - renderEditorNode(){ + render(): ?ReactElement{ return ( ); }, - renderOptions(){ + renderOptions(): Array{ var options = []; this.props.options.forEach(function(name){ options.push(); @@ -40,12 +38,21 @@ var DropDownEditor = React.createClass({ return options; }, + getValue(): string{ + var updated = {}; + updated[this.props.column.key] = this.refs.select.getDOMNode().value; + return updated; + }, + + getInputNode(): HTMLInputElement{ + return this.refs.select.getDOMNode(); + }, - onChange(e){ - this.commit({key : 'Enter'}); + onChange(){ + this.props.onCommit({key : 'Enter'}); }, - onClick(e){ + onClick(e: Event){ e.stopPropagation(); e.preventDefault(); } diff --git a/src/addons/editors/EditorContainer.js b/src/addons/editors/EditorContainer.js new file mode 100644 index 0000000..1a02096 --- /dev/null +++ b/src/addons/editors/EditorContainer.js @@ -0,0 +1,218 @@ +/* @flow */ +/** +* @jsx React.DOM + + +*/ +'use strict'; + +var React = require('react/addons'); +var cx = React.addons.classSet; +var keyboardHandlerMixin = require('../../KeyboardHandlerMixin'); +var SimpleTextEditor = require('./SimpleTextEditor'); +var isFunction = require('../utils/isFunction'); +var cloneWithProps = React.addons.cloneWithProps; + + +var EditorContainer = React.createClass({ + + mixins : [keyboardHandlerMixin], + + propTypes : { + cellMetaData : React.PropTypes.func.isRequired, + column : React.PropTypes.object.isRequired + }, + + getInitialState(){ + return {isInvalid : false} + }, + + componentWillMount(){ + this.validateEditor(); + }, + + componentDidMount: function() { + var inputNode = this.getInputNode(); + if(inputNode !== undefined){ + this.setTextInputFocus(); + inputNode.className += ' editor-main'; + inputNode.style.height = this.props.height - 1 + 'px'; + } + }, + + validateEditor(){ + var editor = this.props.column.editor; + if(editor){ + + } + }, + + createEditor(): ReactElement{ + var editorProps = {ref: 'editor', column : this.props.column, onKeyDown : this.onKeyDown, value : this.getInitialValue(), onCommit : this.commit, editorRowMetaData : this.getEditorRowMetaData(), height : this.props.height}; + var customEditor = this.props.column.editor; + if(customEditor && React.isValidElement(customEditor)){ + //return custom column editor or SimpleEditor if none specified + return React.addons.cloneWithProps(customEditor, editorProps); + }else{ + return ; + } + }, + + getEditorRowMetaData(): ?any { + //clone row data so editor cannot actually change this + var columnName = this.props.column.ItemId; + //convention based method to get corresponding Id or Name of any Name or Id property + if(typeof this.props.column.getEditorRowMetaData === 'function'){ + return this.props.column.getEditorRowMetaData(this.props.rowData); + } + }, + + onPressEnter(e: SyntheticKeyboardEvent){ + e.stopPropagation(); + e.preventDefault(); + this.commit({key : 'Enter'}); + }, + + onPressTab(e: SyntheticKeyboardEvent){ + e.stopPropagation(); + e.preventDefault(); + this.commit({key : 'Tab'}); + }, + + onPressArrowDown(e: SyntheticKeyboardEvent){ + if(this.editorHasResults()){ + e.stopPropagation(); + e.preventDefault(); + } + }, + + onPressArrowUp(e: SyntheticKeyboardEvent){ + if(this.editorHasResults()){ + e.stopPropagation(); + e.preventDefault(); + } + }, + + onPressArrowLeft(e: SyntheticKeyboardEvent){ + //prevent event propogation. this disables left cell navigation + if(!this.isCaretAtBeginningOfInput()){ + e.stopPropagation(); + } + }, + + onPressArrowRight(e: SyntheticKeyboardEvent){ + //prevent event propogation. this disables right cell navigation + if(!this.isCaretAtEndOfInput()){ + e.stopPropagation(); + } + }, + + editorHasResults(): boolean{ + if(isFunction(this.getEditor().hasResults)){ + return this.getEditor().hasResults(); + }else{ + return false; + } + }, + + getEditor(): Editor { + //TODO need to check that this.refs.editor conforms to the type + //this function is basically just a type cast for the sake of flow + return this.refs.editor; + }, + + commit(args: {key : string}){ + var updated = this.getEditor().getValue(); + if(this.isNewValueValid(updated)){ + var cellKey = this.props.column.key; + this.props.cellMetaData.onCommit({cellKey: cellKey, rowIdx: this.props.rowIdx, updated : updated, key : args.key}); + } + }, + + isNewValueValid(value: string): boolean{ + if(isFunction(this.validate)){ + var isValid = this.validate(value); + this.setState({isInvalid : !isValid}); + return isValid; + }else{ + return true; + } + }, + + getInputNode(): HTMLInputElement{ + return this.getEditor().getInputNode(); + }, + + getInitialValue(): string{ + var selected = this.props.cellMetaData.selected; + var keyCode = selected.initialKeyCode; + if(keyCode === 'Delete' || keyCode === 'Backspace'){ + return ''; + }else if(keyCode === 'Enter'){ + return this.props.value; + }else{ + var text = keyCode ? String.fromCharCode(keyCode) : this.props.value; + return text; + } + + }, + + getContainerClass(){ + return cx({ + 'has-error' : this.state.isInvalid === true + }) + }, + + renderStatusIcon(): ?ReactElement{ + if(this.state.isInvalid === true){ + return + } + }, + + render(): ?ReactElement{ + return ( +
+ {this.createEditor()} + {this.renderStatusIcon()} +
+ ) + }, + + setCaretAtEndOfInput(){ + var input = this.getInputNode(); + //taken from http://stackoverflow.com/questions/511088/use-javascript-to-place-cursor-at-end-of-text-in-text-input-element + var txtLength = input.value.length; + if(input.setSelectionRange){ + input.setSelectionRange(txtLength, txtLength); + }else if(input.createTextRange){ + var fieldRange = input.createTextRange(); + fieldRange.moveStart('character', txtLength); + fieldRange.collapse(); + fieldRange.select(); + } + }, + + isCaretAtBeginningOfInput(): boolean{ + var inputNode = this.getInputNode(); + return inputNode.selectionStart === 0; + }, + + isCaretAtEndOfInput(): boolean{ + var inputNode = this.getInputNode(); + return inputNode.selectionStart === inputNode.value.length; + }, + + setTextInputFocus(){ + var selected = this.props.cellMetaData.selected; + var keyCode = selected.initialKeyCode; + if(!this.isKeyPrintable(keyCode)){ + this.getInputNode().focus(); + this.setCaretAtEndOfInput(); + }else{ + this.getInputNode().select(); + } + } + +}); + +module.exports = EditorContainer; diff --git a/src/addons/editors/SimpleTextEditor.js b/src/addons/editors/SimpleTextEditor.js index 7560c4a..aed407c 100644 --- a/src/addons/editors/SimpleTextEditor.js +++ b/src/addons/editors/SimpleTextEditor.js @@ -1,31 +1,39 @@ +/* @flow */ /** * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 + + */ 'use strict'; var React = require('react/addons'); var cx = React.addons.classSet; -var MixinHelper = require('../utils/MixinHelper'); -var EditorMixin = require('./mixins/EditorMixin'); -var TextInputMixin = require('./mixins/TextInputMixin'); -var keyboardHandlerMixin = require('../cells/mixins/KeyboardHandlerMixin'); +var keyboardHandlerMixin = require('../../KeyboardHandlerMixin'); +var ExcelColumn = require('../grids/ExcelColumn'); var SimpleTextEditor = React.createClass({ - mixins : [keyboardHandlerMixin, EditorMixin, TextInputMixin], + propTypes : { + onKeyDown : React.PropTypes.func.isRequired, + value : React.PropTypes.any.isRequired, + onBlur : React.PropTypes.func.isRequired, + column : React.PropTypes.shape(ExcelColumn).isRequired + }, + + getValue(): any{ + var updated = {}; + updated[this.props.column.key] = this.refs.input.getDOMNode().value; + return updated; + }, - overrides : { - checkFocus : function(){ - this.setTextInputFocus(); - } + getInputNode(): HTMLInputElement{ + return this.getDOMNode(); }, - renderEditorNode(){ - return (); + render(): ?ReactElement { + return (); } - }); module.exports = SimpleTextEditor; diff --git a/src/addons/editors/index.js b/src/addons/editors/index.js index 642d233..8b9861c 100644 --- a/src/addons/editors/index.js +++ b/src/addons/editors/index.js @@ -1,3 +1,4 @@ +/* @flow */ var Editors = { AutoComplete : require('./AutoCompleteEditor'), DropDownEditor : require('./DropDownEditor'), diff --git a/src/addons/editors/mixins/EditorMixin.js b/src/addons/editors/mixins/EditorMixin.js deleted file mode 100644 index 7b27e9b..0000000 --- a/src/addons/editors/mixins/EditorMixin.js +++ /dev/null @@ -1,106 +0,0 @@ -/** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ -'use strict'; -var React = require('react/addons'); -var cx = React.addons.classSet; -var isFunction = require('../../utils/isFunction'); - -var EditorMixin = { - - propTypes : { - onCommit : React.PropTypes.func.isRequired - }, - - getStyle(){ - return { - height : this.props.height - 1 - } - }, - - getInitialState(){ - return {isInvalid : false} - }, - - onPressEnter(e){ - e.stopPropagation(); - e.preventDefault(); - this.commit({key : 'Enter'}); - }, - - onPressTab(e){ - e.stopPropagation(); - e.preventDefault(); - this.commit({key : 'Tab'}); - }, - - commit(args){ - var value = this.getValue(); - var rowDataChanged = {}; - rowDataChanged[this.props.column.key] = value; - if(this.isNewValueValid(value)){ - this.props.onCommit({updated : rowDataChanged, key : args.key}); - } - }, - - isNewValueValid(value){ - if(isFunction(this.validate)){ - var isValid = this.validate(value); - this.setState({isInvalid : !isValid}); - return isValid; - }else{ - return true; - } - }, - - getValue(){ - return this.getInputNode().value; - }, - - setValue(value){ - this.getInputNode().value = value; - }, - - componentDidMount: function() { - if(this.getInputNode() !== undefined){ - this.checkFocus(); - this.getInputNode().className += ' editor-main'; - } - }, - - checkFocus(){ - this.getInputNode().focus(); - }, - - getInputNode(){ - return this.getDOMNode().getElementsByTagName("input")[0]; - }, - - getContainerClass(){ - return cx({ - 'has-error' : this.state.isInvalid === true - }) - }, - - renderStatusIcon(){ - if(this.state.isInvalid === true){ - return - } - }, - - render(){ - if(!isFunction(this.renderEditorNode)){ - throw "Editor Mixin Error : " + this.displayName + " component must implement method renderEditorNode"; - } - var editorNode = this.renderEditorNode(); - return ( -
- {editorNode} - {this.renderStatusIcon()} -
- ) - } -}; - -module.exports = EditorMixin; diff --git a/src/addons/editors/mixins/TextInputMixin.js b/src/addons/editors/mixins/TextInputMixin.js deleted file mode 100644 index f9f7267..0000000 --- a/src/addons/editors/mixins/TextInputMixin.js +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ -'use strict'; - -var TextInputMixin = { - - onPressArrowLeft(e){ - //prevent event propogation. this disables left cell navigation - e.stopPropagation(); - }, - - onPressArrowRight(e){ - //prevent event propogation. this disables right cell navigation - e.stopPropagation(); - }, - - getDefaultValue(){ - var keyCode = this.props.initialKeyCode; - if(keyCode === 'Delete' || keyCode === 'Backspace'){ - return ''; - }else if(keyCode === 'Enter'){ - return this.props.value; - }else{ - var text = keyCode ? String.fromCharCode(keyCode) : this.props.value; - return text; - } - - }, - - setCaretAtEndOfInput(){ - var input = this.getInputNode(); - //taken from http://stackoverflow.com/questions/511088/use-javascript-to-place-cursor-at-end-of-text-in-text-input-element - var txtLength = input.value.length; - if(input.setSelectionRange){ - input.setSelectionRange(txtLength, txtLength); - }else if(input.createTextRange){ - var fieldRange = input.createTextRange(); - fieldRange.moveStart('character', txt.value.length); - fieldRange.collapse(); - fieldRange.select(); - } - }, - - setTextInputFocus(){ - if(!this.isKeyPrintable(this.props.initialKeyCode)){ - this.getInputNode().focus(); - this.setCaretAtEndOfInput(); - }else{ - this.getInputNode().select(); - } - } - - -}; - -module.exports = TextInputMixin; diff --git a/src/addons/editors/mixins/index.js b/src/addons/editors/mixins/index.js deleted file mode 100644 index 7fff5f0..0000000 --- a/src/addons/editors/mixins/index.js +++ /dev/null @@ -1,7 +0,0 @@ -var Editors = { - EditorMixin : require('./EditorMixin'), - TextInputMixin : require('./TextInputMixin') - -} - -module.exports = Editors; diff --git a/src/addons/editors/widgets/DateRangeFilter.js b/src/addons/editors/widgets/DateRangeFilter.js index 07d2af3..d681455 100644 --- a/src/addons/editors/widgets/DateRangeFilter.js +++ b/src/addons/editors/widgets/DateRangeFilter.js @@ -1,11 +1,14 @@ +/* TODO@flow jquery.... */ /** * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 */ 'use strict'; -var React = require('react/addons'); -var cx = React.addons.classSet; +var React = require('react/addons'); +var cx = React.addons.classSet; +var Moment = require('moment'); +var $ = require('jquery'); + var DateRangePicker = function (element, options, cb) { // by default, the daterangepicker element is placed at the bottom of HTML body @@ -100,8 +103,8 @@ DateRangePicker.prototype = { setOptions: function(options, callback) { - this.startDate = moment().startOf('day'); - this.endDate = moment().endOf('day'); + this.startDate = Moment().startOf('day'); + this.endDate = Moment().endOf('day'); this.minDate = false; this.maxDate = false; this.dateLimit = false; @@ -132,9 +135,9 @@ DateRangePicker.prototype = { toLabel: 'To', weekLabel: 'W', customRangeLabel: 'Custom Range', - daysOfWeek: moment.weekdaysMin(), - monthNames: moment.monthsShort(), - firstDay: moment.localeData()._week.dow + daysOfWeek: Moment.weekdaysMin(), + monthNames: Moment.monthsShort(), + firstDay: Moment.localeData()._week.dow }; this.cb = function () { }; @@ -149,25 +152,25 @@ DateRangePicker.prototype = { this.startDate = moment(options.startDate, this.format); if (typeof options.endDate === 'string') - this.endDate = moment(options.endDate, this.format); + this.endDate = Moment(options.endDate, this.format); if (typeof options.minDate === 'string') - this.minDate = moment(options.minDate, this.format); + this.minDate = Moment(options.minDate, this.format); if (typeof options.maxDate === 'string') - this.maxDate = moment(options.maxDate, this.format); + this.maxDate = Moment(options.maxDate, this.format); if (typeof options.startDate === 'object') - this.startDate = moment(options.startDate); + this.startDate = Moment(options.startDate); if (typeof options.endDate === 'object') - this.endDate = moment(options.endDate); + this.endDate = Moment(options.endDate); if (typeof options.minDate === 'object') - this.minDate = moment(options.minDate); + this.minDate = Moment(options.minDate); if (typeof options.maxDate === 'object') - this.maxDate = moment(options.maxDate); + this.maxDate = Moment(options.maxDate); if (typeof options.applyClass === 'string') this.applyClass = options.applyClass; @@ -1096,9 +1099,11 @@ var DateRangeFilter = React.createClass({ }, propTypes : { - format : React.PropTypes.string, - ranges : React.PropTypes.object, + format : React.PropTypes.string.isRequired, + ranges : React.PropTypes.object.isRequired, onApply : React.PropTypes.func, + title : React.PropTypes.string.isRequired, + onblur : React.PropTypes.func, startDate : validateDate, endDate : validateDate }, diff --git a/src/addons/formatters/DateRangeFormatter.js b/src/addons/formatters/DateRangeFormatter.js index 34f102b..4e7069f 100644 --- a/src/addons/formatters/DateRangeFormatter.js +++ b/src/addons/formatters/DateRangeFormatter.js @@ -1,6 +1,9 @@ +/* @flow */ /** + * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 + + */ 'use strict'; @@ -12,13 +15,15 @@ var PropTypes = React.PropTypes; var DateRangeFormatter = React.createClass({ propTypes : { - value : PropTypes.shape({ + value : PropTypes.shape({ startDate : PropTypes.oneOfType([PropTypes.string, PropTypes.object]), endDate : PropTypes.oneOfType([PropTypes.string, PropTypes.object]) - }).isRequired + }).isRequired, + inputFormat : PropTypes.string, + displayFormat : PropTypes.string }, - getDefaultProps(){ + getDefaultProps() : {inputFormat: string; displayFormat: string; value: {startDate: ?Date; endDate: ?Date }}{ return { inputFormat : 'YYYY-MM-DD', displayFormat : 'YYYY-MM-DD', @@ -26,15 +31,15 @@ var DateRangeFormatter = React.createClass({ } }, - formatDate(date){ + formatDate(date: Date | moment): string{ if(moment.isMoment(date)){ - return date.format(this.props.displayFormat); + return moment(date).format(this.props.displayFormat); }else{ return moment(date, this.props.inputFormat).format(this.props.displayFormat); } }, - render(){ + render(): ?ReactElement{ var startDate = this.props.value.startDate; var endDate = this.props.value.endDate; return ({startDate} to {endDate}); diff --git a/src/addons/formatters/ImageFormatter.js b/src/addons/formatters/ImageFormatter.js new file mode 100644 index 0000000..cae0490 --- /dev/null +++ b/src/addons/formatters/ImageFormatter.js @@ -0,0 +1,71 @@ +var React = require('react/addons'); + +var PendingPool = {}; +var ReadyPool = {}; + +var ImageFormatter = React.createClass({ + propTypes: { + src: React.PropTypes.string.isRequired, + }, + + getInitialState() { + return { + ready: false, + }; + }, + + componentWillMount() { + this._load(this.props.src); + }, + + componentWillReceiveProps(nextProps) { + if (nextProps.src !== this.props.src) { + this.setState({src: null}); + this._load(nextProps.src); + } + }, + + render() { + var style = this.state.src ? + { backgroundImage : 'url(' + this.state.src + ')'} : + undefined; + + return
; + }, + + _load(/*string*/ src) { + if (ReadyPool[src]) { + this.setState({src: src}); + return; + } + + if (PendingPool[src]) { + PendingPool[src].push(this._onLoad); + return; + } + + PendingPool[src] = [this._onLoad]; + + var img = new Image(); + img.onload = () => { + PendingPool[src].forEach(/*function*/ callback => { + callback(src); + }); + delete PendingPool[src]; + img.onload = null; + src = undefined; + }; + img.src = src; + }, + + _onLoad(/*string*/ src) { + if (this.isMounted() && src === this.props.src) { + this.setState({ + src: src, + }); + } + }, +}); + + +module.exports = ImageFormatter; diff --git a/src/addons/formatters/index.js b/src/addons/formatters/index.js index 8c7dfcc..de761f6 100644 --- a/src/addons/formatters/index.js +++ b/src/addons/formatters/index.js @@ -1,5 +1,10 @@ -var formatters = { +/* @flow */ +//not including this +//it currently requires the whole of moment, which we dont want to take as a dependency +var ImageFormatter = require('./ImageFormatter'); +var Formatters = { + ImageFormatter : ImageFormatter } -module.exports = formatters; +module.exports = Formatters; diff --git a/src/addons/grids/ExcelColumn.js b/src/addons/grids/ExcelColumn.js new file mode 100644 index 0000000..8292452 --- /dev/null +++ b/src/addons/grids/ExcelColumn.js @@ -0,0 +1,11 @@ +/* @flow */ + +class ExcelColumn { + name: string; + key: string; + width: number; + cellRenderer: (cellData: any, cellDataKey: string, rowData: any, rowIndex: number, columnData: any, width: number ) => ReactElement; + editor: ?Editor; + +} +module.exports = ExcelColumn; diff --git a/src/addons/grids/ExcelGrid.js b/src/addons/grids/ExcelGrid.js index 4fd03df..b744c39 100644 --- a/src/addons/grids/ExcelGrid.js +++ b/src/addons/grids/ExcelGrid.js @@ -1,7 +1,7 @@ /* @flow */ /** * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 + */ "use strict"; @@ -9,69 +9,298 @@ var React = require('react/addons'); var PropTypes = React.PropTypes; var BaseGrid = require('../../Grid'); var ExcelCell = require('../cells/ExcelCell'); -var ExcelRow = require('../rows/ExcelRow'); +var Row = require('../../Row'); +var ExcelColumn = require('./ExcelColumn'); var merge = require('../../merge'); -var SelectableGridMixin = require('./mixins/SelectableGridMixin'); -var DraggableGridMixin = require('./mixins/DraggableGridMixin'); -var CopyPasteGridMixin = require('./mixins/CopyPasteGridMixin'); -var EditableGridMixin = require('./mixins/EditableGridMixin'); -var SortableGridMixin = require('./mixins/SortableGridMixin'); -var FilterableGridMixin = require('./mixins/FilterableGridMixin'); +var KeyboardHandlerMixin = require('../../KeyboardHandlerMixin'); var CheckboxEditor = require('../editors/CheckboxEditor'); -var MixinHelper = require('../utils/MixinHelper'); +var SortableHeaderCell = require('../cells/headerCells/SortableHeaderCell'); +var FilterableHeaderCell = require('../cells/headerCells/FilterableHeaderCell'); var cloneWithProps = React.addons.cloneWithProps; -var ExcelGrid = React.createClass({ +type SelectedType = { + rowIdx: number; + idx: number; +}; - mixins : [SelectableGridMixin, EditableGridMixin, DraggableGridMixin, CopyPasteGridMixin, SortableGridMixin, FilterableGridMixin], +type DraggedType = { + idx: number; + rowIdx: number; +}; - getInitialState(){ - return {selectedRows : [], expandedRows : []}; - }, +type ExcelGridProps = { + rowHeight: number; + minHeight: number; + enableRowSelect: ?boolean; + onRowUpdated: ?() => void; + columns: Array; + rows: Array; + toolbar: ?any; +}; - overrides : { - onCellCommit(commit: RowUpdateEvent){ - var committed = commit[0]; - var selected = Object.assign({}, this.state.selected); - selected.active = false; - if (committed.keyCode === 'Tab') { - selected.idx += 1; - } - var expandedRows = this.state.expandedRows; - if(committed.changed && committed.changed.expandedHeight){ - expandedRows = this.expandRow(committed.rowIdx, committed.changed.expandedHeight); - } - this.setState({selected : selected, expandedRows : expandedRows}); - this.props.onRowUpdated(committed); - }, - getColumns : function(){ - var cols = this.getDecoratedColumns(this.props.columns) - if(this.props.enableRowSelect){ - cols.unshift({ - key: 'select-row', - name: '', - formatter : , - onRowSelect :this.handleRowSelect, - filterable : false, - headerRenderer : , - width : 60 - }); - } - return cols; - } +type SortType = {ASC: string; DESC: string}; +var DEFINE_SORT = { + ASC : 'ASC', + DESC : 'DESC' +} + +type RowUpdateEvent = { + keyCode: string; + changed: {expandedHeight: number}; + rowIdx: number; +}; + +var ExcelGrid = React.createClass({ + + propTypes: { + rowHeight: React.PropTypes.number.isRequired, + minHeight: React.PropTypes.number.isRequired, + enableRowSelect: React.PropTypes.bool, + onRowUpdated:React.PropTypes.func, + rows:React.PropTypes.arrayOf(Row).isRequired, + toolbar:React.PropTypes.element, + enableCellSelect : React.PropTypes.bool, + columns : React.PropTypes.arrayOf(React.PropTypes.shape(ExcelColumn)).isRequired, + onFilter : React.PropTypes.func, + onCellCopyPaste : React.PropTypes.func, + onCellsDragged : React.PropTypes.func }, - getDefaultProps() { + mixins : [KeyboardHandlerMixin], + + getDefaultProps(): {enableCellSelect: boolean} { return { + enableCellSelect : false, + tabIndex : -1, + ref : "cell", rowHeight: 35, enableRowSelect : false, minHeight : 350 }; }, - handleCheckboxChange : function(e){ - if(e.currentTarget.checked === true){ + getInitialState: function(): {selected: SelectedType; copied: ?{idx: number; rowIdx: number}; selectedRows: Array; expandedRows: Array; canFilter: boolean; columnFilters: any; sortDirection: SortType; sortColumn: ExcelColumn; dragged: ?DraggedType } { + var initialState = {selectedRows : [], copied : null, expandedRows : [], canFilter : false, columnFilters : {}, sortDirection: null, sortColumn: null, dragged : null} + if(this.props.enableCellSelect){ + initialState.selected = {rowIdx: 0, idx: 0}; + }else{ + initialState.selected = {rowIdx: -1, idx: -1}; + } + return initialState; + }, + + componentWillReceiveProps:function(nextProps: ExcelGridProps){ + if(nextProps.rows.length === this.props.rows.length + 1){ + this.onAfterAddRow(nextProps.rows.length + 1); + } + }, + + render: function(): ?ReactElement { + var cellMetaData = { + selected : this.state.selected, + onCellClick : this.onCellClick, + onCommit : this.onCellCommit, + copied : this.state.copied + } + + var rows = this.filterRows(); + var toolbar = this.renderToolbar(); + return( +
+ {toolbar} +
+ {()} +
+
+ ) + }, + + renderToolbar(): ReactElement { + var Toolbar = this.props.toolbar; + if(React.isValidElement(Toolbar)){ + return( React.addons.cloneWithProps(Toolbar, {onToggleFilter : this.onToggleFilter, numberOfRows : this.props.rows.length})); + } + + }, + + onSelect: function(selected: SelectedType) { + if(this.props.enableCellSelect){ + var idx = selected.idx; + var rowIdx = selected.rowIdx; + if ( + idx >= 0 + && rowIdx >= 0 + && idx < this.getColumns().length + && rowIdx < this.props.rows.length + ) { + this.setState({selected: selected}); + } + } + }, + + isSelected: function(): boolean { + return ( + this.props.selected + && this.props.selected.rowIdx === this.props.rowIdx + && this.props.selected.idx === this.props.idx + ); + }, + + onCellClick: function(cell: SelectedType) { + this.onSelect({rowIdx: cell.rowIdx, idx: cell.idx}); + }, + + onPressArrowUp(e: SyntheticEvent){ + this.moveSelectedCell(e, -1, 0); + }, + + onPressArrowDown(e: SyntheticEvent){ + this.moveSelectedCell(e, 1, 0); + }, + + onPressArrowLeft(e: SyntheticEvent){ + this.moveSelectedCell(e, 0, -1); + }, + + onPressArrowRight(e: SyntheticEvent){ + this.moveSelectedCell(e, 0, 1); + }, + + onPressTab(e: SyntheticEvent){ + this.moveSelectedCell(e, 0, 1); + }, + + onPressEnter(e: SyntheticKeyboardEvent){ + this.setActive(e.key); + }, + + onPressDelete(e: SyntheticKeyboardEvent){ + this.setActive(e.key); + }, + + onPressEscape(e: SyntheticKeyboardEvent){ + this.setInactive(e.key); + }, + + onPressBackspace(e: SyntheticKeyboardEvent){ + this.setActive(e.key); + }, + + onPressChar(e: SyntheticKeyboardEvent){ + if(this.isKeyPrintable(e.keyCode)){ + this.setActive(e.keyCode); + } + }, + + onPressKeyWithCtrl(e){ + var keys = { + KeyCode_c : '99', + KeyCode_C : '67', + KeyCode_V : '86', + KeyCode_v : '118', + } + + var idx = this.state.selected.idx + if(this.canEdit(idx)){ + var value = this.getSelectedValue(); + if(e.keyCode == keys.KeyCode_c || e.keyCode == keys.KeyCode_C){ + this.handleCopy({value : value}); + }else if(e.keyCode == keys.KeyCode_v || e.keyCode == keys.KeyCode_V){ + this.handlePaste({value : value}); + } + } + }, + + moveSelectedCell(e: SyntheticEvent, rowDelta: number, cellDelta: number){ + e.stopPropagation(); + e.preventDefault(); + var rowIdx = this.state.selected.rowIdx + rowDelta; + var idx = this.state.selected.idx + cellDelta; + this.onSelect({idx: idx, rowIdx: rowIdx}); + }, + + getSelectedValue(): string{ + var rowIdx = this.state.selected.rowIdx; + var idx = this.state.selected.idx; + var cellOffset = this.props.enableRowSelect ? 1 : 0; + var cellKey = this.props.columns[idx - cellOffset].key; + return this.props.rows[rowIdx][cellKey]; + }, + + setActive(keyPressed: string){ + var rowIdx = this.state.selected.rowIdx; + var idx = this.state.selected.idx; + if(this.props.columns[idx].key === 'select-row' && this.props.columns[idx].onRowSelect){ + this.props.column.onRowSelect(rowIdx); + } + else if(this.canEdit(idx) && !this.isActive()){ + var selected = Object.assign(this.state.selected, {idx: idx, rowIdx: rowIdx, active : true, initialKeyCode : keyPressed}); + this.setState({selected: selected}); + } + }, + + setInactive(){ + var rowIdx = this.state.selected.rowIdx; + var idx =this.state.selected.idx; + if(this.canEdit(idx) && this.isActive()){ + var selected = Object.assign(this.state.selected, {idx: idx, rowIdx: rowIdx, active : false}); + this.setState({selected: selected}); + } + }, + + canEdit(idx: number): boolean{ + return (this.props.columns[idx].editor != null) || this.props.columns[idx].editable; + }, + + isActive(): boolean{ + return this.state.selected.active === true; + }, + + onCellCommit(commit: RowUpdateEvent){ + var selected = Object.assign({}, this.state.selected); + selected.active = false; + if (commit.keyCode === 'Tab') { + selected.idx += 1; + } + var expandedRows = this.state.expandedRows; + if(commit.changed && commit.changed.expandedHeight){ + expandedRows = this.expandRow(commit.rowIdx, commit.changed.expandedHeight); + } + this.setState({selected : selected, expandedRows : expandedRows}); + this.props.onRowUpdated(commit); + + }, + getColumns : function(): Array{ + var cols = this.getDecoratedColumns(this.props.columns) + if(this.props.enableRowSelect){ + cols.unshift({ + key: 'select-row', + name: '', + formatter : , + onRowSelect :this.handleRowSelect, + filterable : false, + headerRenderer : , + width : 60 + }); + } + return cols; + }, + + handleCheckboxChange : function(e: SyntheticEvent){ + if(e.currentTarget instanceof HTMLInputElement && e.currentTarget.checked === true){ var selectedRows = this.props.rows.map(() => true); this.setState({selectedRows : selectedRows}); }else{ @@ -80,7 +309,7 @@ var ExcelGrid = React.createClass({ } }, - handleRowSelect(row){ + handleRowSelect(row: Row){ var selectedRows = this.state.selectedRows; if(selectedRows[row] == null || selectedRows[row] == false){ selectedRows[row] = true; @@ -90,7 +319,7 @@ var ExcelGrid = React.createClass({ this.setState({selectedRows : selectedRows}); }, - expandRow(row, newHeight){ + expandRow(row: Row, newHeight: number): Array{ var expandedRows = this.state.expandedRows; if(expandedRows[row]){ if(expandedRows[row]== null || expandedRows[row] < newHeight){ @@ -106,12 +335,12 @@ var ExcelGrid = React.createClass({ }, - handleShowMore(row, newHeight){ + handleShowMore(row: Row, newHeight: number) { var expandedRows = this.expandRow(row, newHeight); this.setState({expandedRows : expandedRows}); }, - handleShowLess(row){ + handleShowLess(row: Row){ var expandedRows = this.state.expandedRows; if(expandedRows[row]){ expandedRows[row] = false; @@ -127,74 +356,201 @@ var ExcelGrid = React.createClass({ }, - onAfterAddRow:function(numberOfRows){ + onAfterAddRow:function(numberOfRows: number){ this.setState({selected : {idx : 1, rowIdx : numberOfRows - 2}}); - //cheeky - this.refs.base.refs.viewport.refs.canvas.getDOMNode().scrollTop = numberOfRows * this.props.rowHeight; }, - componentWillReceiveProps:function(nextProps){ - if(nextProps.rows.length === this.props.rows.length + 1){ - this.onAfterAddRow(nextProps.rows.length + 1); + filterRows(): Array{ + var rows = this.props.rows; + if(this.state.sortColumn){ + rows = this.sortRows(rows); + } + + if(this.hasFilters()){ + rows = rows.map((r, i) => {r.key = i;return r;}).filter(this.isRowDisplayed); + if(this.props.onFilter){ + this.props.onFilter(rows); + } } + return rows; }, - render: function() { - var cellRenderer = ( - - ); + hasFilters(): boolean{ + var hasFilters = false; + Object.keys(this.state.columnFilters).every(function(key){ + var filter = this.state.columnFilters[key]; + if(filter != null && filter != undefined && filter != ''){ + hasFilters = true; + return false; + } + return true; + }, this); + return hasFilters; + }, - var rows = this.filterRows(); - var toolbar = this.renderToolbar(); - return( -
- {toolbar} -
- {(} - selectedRows={this.state.selectedRows} - expandedRows={this.state.expandedRows} - rowOffsetHeight={this.getRowOffsetHeight()} - minHeight={this.props.minHeight} />)} -
-
- ) + isRowDisplayed(row: Row): boolean{ + var isRowDisplayed = null; + Object.keys(this.state.columnFilters).every(function(key){ + var filter = this.state.columnFilters[key].toLowerCase(); + var cellValue = row[key].toString().toLowerCase(); + if(filter != null && filter != undefined && filter != '' && typeof cellValue === 'string'){ + if(cellValue.indexOf(filter) > -1){ + isRowDisplayed = true; + }else{ + isRowDisplayed = false; + return false; + } + } + return true; + }, this); + return isRowDisplayed == null ? false : isRowDisplayed; }, - renderToolbar(){ - var Toolbar = this.props.toolbar; - if(React.isValidElement(Toolbar)){ - return( React.addons.cloneWithProps(Toolbar, {onToggleFilter : this.onToggleFilter, rows : this.props.rows})); + onToggleFilter(){ + this.setState({canFilter : !this.state.canFilter}); + }, + + handleAddFilter(filter: {columnKey: string; filterTerm: string }){ + var columnFilters = this.state.columnFilters; + columnFilters[filter.columnKey] = filter.filterTerm; + this.setState({columnFilters : columnFilters, selected : null}); + }, + + getHeaderRows(): Array { + var rows = [{ref:"row", height: this.props.rowHeight}]; + if(this.state.canFilter === true){ + rows.push({ + ref:"filterRow", + headerCellRenderer : , + height : 45 + }); } + return rows; + }, - } + getRowOffsetHeight(): number{ + var offsetHeight = 0; + this.getHeaderRows().forEach((row) => offsetHeight += row.height ); + return offsetHeight; + }, + getDecoratedColumns: function(columns: Array): Array { + return this.props.columns.map(function(column) { + column = Object.assign({}, column); + if (column.sortable) { + column.headerRenderer = ; + column.sortBy = this.sortBy; + if (this.state.sortColumn === column.key) { + column.sorted = this.state.sortDirection; + }else{ + column.sorted = DEFINE_SORT.NONE; + } + } + return column + }, this); + }, + + sortBy: function(column: ExcelColumn, direction: SortType) { + switch(direction){ + case null: + case undefined: + direction = DEFINE_SORT.ASC; + break; + case DEFINE_SORT.ASC: + direction = DEFINE_SORT.DESC; + break; + case DEFINE_SORT.DESC: + direction = null; + break; + } + this.setState({sortDirection: direction, sortColumn: column.key}); + }, + + sortRows: function(rows: Array): Array { + //feels naughty + rows = [].concat(rows); + var sortColumn = this.state.sortColumn; + var sortDirection = this.state.sortDirection; + if(sortColumn != null && sortDirection !== null){ + return rows.sort(function(row1, row2){ + var k1 = row1[sortColumn], k2 = row2[sortColumn]; + if(sortDirection === DEFINE_SORT.ASC){ + return (k1 > k2) ? 1 : ( (k2 > k1) ? -1 : 0 ); + }else if(sortDirection === DEFINE_SORT.DESC){ + return (k1 > k2) ? -1 : ( (k2 > k1) ? 1 : 0 ); + } + }); + }else{ + return rows; + } + }, + + copyPasteEnabled: function(): boolean { + return this.props.onCellCopyPaste !== null; + }, + + handleCopy(args: {value: string}){ + if(!this.copyPasteEnabled()) { return; } + var textToCopy = args.value; + var selected = this.state.selected; + var copied = {idx : selected.idx, rowIdx : selected.rowIdx}; + this.setState({textToCopy:textToCopy, copied : copied}); + }, + + handlePaste(){ + if(!this.copyPasteEnabled()) { return; } + var selected = this.state.selected; + var cellKey = this.getColumns()[selected.idx].key; + if(this.props.onCellCopyPaste) { + this.props.onCellCopyPaste({cellKey: cellKey , rowIdx: selected.rowIdx, value : this.state.textToCopy, fromRow : this.state.copied.rowIdx, toRow : selected.rowIdx}); + } + this.setState({copied : null}); + }, + + dragEnabled: function(): boolean { + return this.props.onCellsDragged !== null; + }, + + handleDragStart(dragged: DraggedType){ + if(!this.dragEnabled()) { return; } + var idx = dragged.idx; + var rowIdx = dragged.rowIdx; + if ( + idx >= 0 + && rowIdx >= 0 + && idx < this.getColumns().length + && rowIdx < this.props.rows.length + ) { + this.setState({dragged: dragged}); + } + }, + + handleDragEnter(row: any){ + if(!this.dragEnabled()) { return; } + var selected = this.state.selected; + var dragged = this.state.dragged; + dragged.overRowIdx = row; + this.setState({dragged : dragged}); + }, + + handleDragEnd(){ + if(!this.dragEnabled()) { return; } + var fromRow, toRow; + var selected = this.state.selected; + var dragged = this.state.dragged; + var cellKey = this.getColumns()[this.state.selected.idx].key; + fromRow = selected.rowIdx < dragged.overRowIdx ? selected.rowIdx : dragged.overRowIdx; + toRow = selected.rowIdx > dragged.overRowIdx ? selected.rowIdx : dragged.overRowIdx; + if(this.props.onCellsDragged) { this.props.onCellsDragged({cellKey: cellKey , fromRow: fromRow, toRow : toRow, value : dragged.copiedText}); } + this.setState({dragged : {complete : true}}); + }, + + handleTerminateDrag(){ + if(!this.dragEnabled()) { return; } + this.setState({dragged: null}); + } -}) +}); module.exports = ExcelGrid; diff --git a/src/addons/grids/mixins/CopyPasteGridMixin.js b/src/addons/grids/mixins/CopyPasteGridMixin.js deleted file mode 100644 index f1417a4..0000000 --- a/src/addons/grids/mixins/CopyPasteGridMixin.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ -"use strict"; - -var React = require('react/addons'); -var PropTypes = React.PropTypes; - -var CopyPasteGridMixin = { - - propTypes : { - onCellCopyPaste : React.PropTypes.func - }, - - getInitialState: function() { - return {copied : null}; - }, - - - handleCopy(args){ - var textToCopy = args.value; - var selected = this.state.selected; - var copied = {idx : selected.idx, rowIdx : selected.rowIdx}; - this.setState({textToCopy:textToCopy, copied : copied}); - }, - - handlePaste(){ - var selected = this.state.selected; - var cellKey = this.getColumns()[selected.idx].key; - this.props.onCellCopyPaste({cellKey: cellKey , rowIdx: selected.rowIdx, value : this.state.textToCopy, fromRow : this.state.copied.rowIdx, toRow : selected.rowIdx}); - this.setState({copied : null}); - } -} - -module.exports = CopyPasteGridMixin; diff --git a/src/addons/grids/mixins/DraggableGridMixin.js b/src/addons/grids/mixins/DraggableGridMixin.js deleted file mode 100644 index 5b91490..0000000 --- a/src/addons/grids/mixins/DraggableGridMixin.js +++ /dev/null @@ -1,63 +0,0 @@ -/** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ -"use strict"; - -var React = require('react/addons'); -var PropTypes = React.PropTypes; -var MixinHelper = require('../../utils/MixinHelper'); -var SelectableGridMixin = require('./SelectableGridMixin'); - -MixinHelper.addAlias('SelectableGridMixin'); - -var DraggableGridMixin = { - - mixinDependencies : ['SelectableGridMixin'], - - propTypes : { - onCellsDragged : React.PropTypes.func - }, - - getInitialState: function() { - return {dragged : null}; - }, - - handleDragStart(dragged){ - var idx = dragged.idx; - var rowIdx = dragged.rowIdx; - if ( - idx >= 0 - && rowIdx >= 0 - && idx < this.getColumns().length - && rowIdx < this.props.rows.length - ) { - this.setState({dragged: dragged}); - } - }, - - handleDragEnter(row){ - var selected = this.state.selected; - var dragged = this.state.dragged; - dragged.overRowIdx = row; - this.setState({dragged : dragged}); - }, - - handleDragEnd(){ - var fromRow, toRow; - var selected = this.state.selected; - var dragged = this.state.dragged; - var cellKey = this.getColumns()[this.state.selected.idx].key; - fromRow = selected.rowIdx < dragged.overRowIdx ? selected.rowIdx : dragged.overRowIdx; - toRow = selected.rowIdx > dragged.overRowIdx ? selected.rowIdx : dragged.overRowIdx; - this.props.onCellsDragged({cellKey: cellKey , fromRow: fromRow, toRow : toRow, value : dragged.copiedText}); - this.setState({dragged : {complete : true}}); - }, - - handleTerminateDrag(){ - this.setState({dragged: null}); - } -} - - -module.exports = DraggableGridMixin; diff --git a/src/addons/grids/mixins/EditableGridMixin.js b/src/addons/grids/mixins/EditableGridMixin.js deleted file mode 100644 index 6aca4b8..0000000 --- a/src/addons/grids/mixins/EditableGridMixin.js +++ /dev/null @@ -1,35 +0,0 @@ -/** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ -"use strict"; - -var React = require('react/addons'); -var PropTypes = React.PropTypes; -var merge = require('../../../merge'); - -var EditableGridMixin = { - - propTypes : { - onRowUpdated : React.PropTypes.func - }, - - onCellCommit(commit){ - var selected = this.state.selected; - selected.active = false; - if(commit.keyCode === 'Tab'){ - selected.idx += 1; - } - this.setState({selected : selected}); - this.props.onRowUpdate(commit); - }, - - onSetActive(activeCell) { - var selected = merge(this.state.selected, activeCell); - this.setState({selected: selected}); - } - -}; - - -module.exports = EditableGridMixin; diff --git a/src/addons/grids/mixins/FilterableGridMixin.js b/src/addons/grids/mixins/FilterableGridMixin.js deleted file mode 100644 index 4c4dfb1..0000000 --- a/src/addons/grids/mixins/FilterableGridMixin.js +++ /dev/null @@ -1,89 +0,0 @@ -/** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ -"use strict"; - -var React = require('react/addons'); -var PropTypes = React.PropTypes; -var FilterableHeaderCell = require('../../cells/headerCells/FilterableHeaderCell'); - -var FilterableGridMixin = { - - getInitialState : function(){ - return {canFilter : false, columnFilters : {}}; - }, - - filterRows(){ - var rows = this.props.rows; - if(this.state.sortColumn){ - rows = this.sortRows(rows); - } - - if(this.hasFilters()){ - rows = rows.map((r, i) => {r.key = i;return r;}).filter(this.isRowDisplayed); - if(this.props.onFilter){ - this.props.onFilter(rows); - } - } - return rows; - }, - - hasFilters(){ - var hasFilters = false; - Object.keys(this.state.columnFilters).every(function(key){ - var filter = this.state.columnFilters[key]; - if(filter != null && filter != undefined && filter != ''){ - hasFilters = true; - return false; - } - return true; - }, this); - return hasFilters; - }, - - isRowDisplayed(row){ - var isRowDisplayed = null; - Object.keys(this.state.columnFilters).every(function(key){ - var filter = this.state.columnFilters[key].toLowerCase(); - var cellValue = row[key].toString().toLowerCase(); - if(filter != null && filter != undefined && filter != '' && typeof cellValue === 'string'){ - if(cellValue.indexOf(filter) > -1){ - isRowDisplayed = true; - }else{ - isRowDisplayed = false; - return false; - } - } - return true; - }, this); - return isRowDisplayed == null ? false : isRowDisplayed; - }, - - onToggleFilter(){ - this.setState({canFilter : !this.state.canFilter}); - }, - - handleAddFilter(filter){ - var columnFilters = this.state.columnFilters; - columnFilters[filter.columnKey] = filter.filterTerm; - this.setState({columnFilters : columnFilters, selected : null}); - }, - - getHeaderRows(){ - var rows = [{ref:"row", height: this.props.rowHeight}]; - if(this.state.canFilter === true){ - rows.push({ref:"filterRow", headerCellRenderer : , height : 45}); - } - return rows; - }, - - getRowOffsetHeight(){ - var offsetHeight = 0; - this.getHeaderRows().forEach((row) => offsetHeight += row.height ); - return offsetHeight; - } - -} - -module.exports = FilterableGridMixin; diff --git a/src/addons/grids/mixins/SelectableGridMixin.js b/src/addons/grids/mixins/SelectableGridMixin.js deleted file mode 100644 index 6bb3562..0000000 --- a/src/addons/grids/mixins/SelectableGridMixin.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ -"use strict"; - -var SelectableGridMixin = { - - getDefaultProps() { - return { - enableCellSelect : false, - }; - }, - - getColumns : function(){ - return this.props.columns - }, - - getInitialState: function() { - if(this.props.enableCellSelect){ - return {selected: {rowIdx: 0, idx: 0}}; - }else{ - return {selected: {rowIdx: -1, idx: -1}}; - } - }, - - onSelect: function(selected) { - if(this.props.enableCellSelect){ - var idx = selected.idx; - var rowIdx = selected.rowIdx; - if ( - idx >= 0 - && rowIdx >= 0 - && idx < this.getColumns().length - && rowIdx < this.props.rows.length - ) { - if(this.props.onSelect){ - this.props.onSelect({selected: selected}); - } - this.setState({selected: selected}); - } - } - } -} - -module.exports = SelectableGridMixin; diff --git a/src/addons/grids/mixins/SortableGridMixin.js b/src/addons/grids/mixins/SortableGridMixin.js deleted file mode 100644 index 54c916f..0000000 --- a/src/addons/grids/mixins/SortableGridMixin.js +++ /dev/null @@ -1,78 +0,0 @@ -/** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ -"use strict"; - -var React = require('react/addons'); -var PropTypes = React.PropTypes; -var SortableHeaderCell = require('../../cells/headerCells/SortableHeaderCell'); -var shallowCloneObject = require('../../../shallowCloneObject'); - -var DEFINE_SORT = { - ASC : 'ASC', - DESC : 'DESC' -} -Object.freeze(DEFINE_SORT); - -var SortableGridMixin = { - - getInitialState: function() { - return {sortDirection: null, sortColumn: null}; - }, - - getDecoratedColumns: function(columns) { - return this.props.columns.map(function(column) { - column = shallowCloneObject(column); - if (column.sortable) { - column.headerRenderer = ; - column.sortBy = this.sortBy; - if (this.state.sortColumn === column.key) { - column.sorted = this.state.sortDirection; - }else{ - column.sorted = DEFINE_SORT.NONE; - } - } - return column - }, this); - }, - - sortBy: function(column, direction) { - switch(direction){ - case null: - case undefined: - direction = DEFINE_SORT.ASC; - break; - case DEFINE_SORT.ASC: - direction = DEFINE_SORT.DESC; - break; - case DEFINE_SORT.DESC: - direction = null; - break; - } - this.setState({sortDirection: direction, sortColumn: column.key}); - }, - - sortRows: function(rows) { - //feels naughty - rows = [].concat(rows); - var sortColumn = this.state.sortColumn; - var sortDirection = this.state.sortDirection; - if(sortColumn != null && sortDirection !== null){ - return rows.sort(function(row1, row2){ - var k1 = row1[sortColumn], k2 = row2[sortColumn]; - if(sortDirection === DEFINE_SORT.ASC){ - return (k1 > k2) ? 1 : ( (k2 > k1) ? -1 : 0 ); - }else if(sortDirection === DEFINE_SORT.DESC){ - return (k1 > k2) ? -1 : ( (k2 > k1) ? 1 : 0 ); - } - }); - }else{ - return rows; - } - - } - -} - -module.exports = SortableGridMixin; diff --git a/src/addons/index.js b/src/addons/index.js index 6566bf0..9dc8246 100644 --- a/src/addons/index.js +++ b/src/addons/index.js @@ -1,11 +1,7 @@ +/* @flow */ module.exports = { Grid : require('./grids/ExcelGrid'), Editors : require('./editors'), Formatters : require('./formatters'), - Toolbar : require('./toolbars/Toolbar'), - Mixins : { - EditorMixin : require('./editors/mixins/EditorMixin'), - TextInputMixin : require('./editors/mixins/TextInputMixin'), - KeyboardHandlerMixin : require('./cells/mixins/KeyboardHandlerMixin') - } + Toolbar : require('./toolbars/Toolbar') } diff --git a/src/addons/rows/ExcelRow.js b/src/addons/rows/ExcelRow.js deleted file mode 100644 index eb7c82c..0000000 --- a/src/addons/rows/ExcelRow.js +++ /dev/null @@ -1,96 +0,0 @@ -/** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ -'use strict'; - -var React = require('react/addons'); -var cx = React.addons.classSet; -var BaseRow = require('../../Row'); -var ColumnMetrics = require('../../ColumnMetrics'); -var ExcelRow = React.createClass({ - - render() { - var row = React.addons.update(this.props.row, {$merge : {'select-row' : this.props.isSelected}}); - - return ( - - ); - }, - - getRowHeight(props){ - if(props.expandedRows && props.expandedRows[props.idx]){ - return props.expandedRows[props.idx]; - }else{ - return props.height; - } - }, - - hasRowHeightChanged(props){ - if(props.expandedRows){ - if(typeof props.expandedRows[props.idx] !== 'undefined'){ - return this.props.height !== props.expandedRows[props.idx] - }else{ - return false; - } - }else{ - return false; - } - }, - - shouldComponentUpdate(nextProps) { - return !(ColumnMetrics.sameColumns(this.props.columns, nextProps.columns, ColumnMetrics.sameColumn)) || - this.doesRowContainSelectedCell() || - this.doesRowContainSelectedCell(nextProps) || - this.willRowBeDraggedOver(nextProps) || - this.hasRowBeenCopied() || - nextProps.row !== this.props.row || - this.props.isSelected !== nextProps.isSelected || - this.hasRowHeightChanged(nextProps); - }, - - doesRowContainSelectedCell(propsToCheck){ - var props = propsToCheck || this.props; - var cell = cell || props.cellRenderer; - if(cell.props && cell.props.selected && cell.props.selected.rowIdx === props.idx){ - return true; - }else{ - return false; - } - }, - - willRowBeDraggedOver(props){ - if(props.cellRenderer.props){ - var dragged = props.cellRenderer.props.dragged; - return dragged != null && (dragged.rowIdx || dragged.complete === true); - }else{ - return false; - } - - }, - - hasRowBeenCopied(){ - if(this.props.cellRenderer.props){ - var cell = this.props.cellRenderer; - return cell.props.copied != null && cell.props.copied.rowIdx === this.props.idx; - }else{ - return false; - } - - }, - - setScrollLeft(scrollLeft) { - for (var i = 0, len = this.props.columns.length; i < len; i++) { - if (this.props.columns[i].locked) { - this.refs[i].setScrollLeft(scrollLeft); - } - } - } - - -}); - -module.exports = ExcelRow; diff --git a/src/addons/toolbars/Toolbar.js b/src/addons/toolbars/Toolbar.js index 23f213e..59ebfbd 100644 --- a/src/addons/toolbars/Toolbar.js +++ b/src/addons/toolbars/Toolbar.js @@ -1,40 +1,54 @@ +/* @flow */ /** * @jsx React.DOM -* @copyright Prometheus Research, LLC 2014 + */ 'use strict'; -var React = require('react/addons'); -var Toolbar = React.createClass({ +var React = require('react/addons'); +var Row = require('../../Row'); +var Toolbar = React.createClass({ + propTypes: { + onAddRow : React.PropTypes.func, + onToggleFilter : React.PropTypes.func.isRequired, + enableFilter : React.PropTypes.bool, + numberOfRows : React.PropTypes.number.isRequired + }, onAddRow(){ if(this.props.onAddRow){ - this.props.onAddRow({newRowIndex : this.props.rows.length}); + this.props.onAddRow({newRowIndex : this.props.numberOfRows}); } }, - getDefaultProps(){ + getDefaultProps(): {enableAddRow: boolean}{ return { enableAddRow : true } }, - getAddRowButton(){ - if(this.props.enableAddRow){ + renderAddRowButton(): ReactElement{ + if(this.props.onAddRow){ return() } }, - render(){ + renderToggleFilterButton(): ReactElement{ + if(this.props.enableFilter){ + return( ) + } + }, + + render(): ?ReactElement{ return (
- {this.getAddRowButton()} - + {this.renderAddRowButton()} + {this.renderToggleFilterButton()}
) } diff --git a/src/addons/utils/MixinHelper.js b/src/addons/utils/MixinHelper.js deleted file mode 100644 index 398a04f..0000000 --- a/src/addons/utils/MixinHelper.js +++ /dev/null @@ -1,229 +0,0 @@ - -"use strict"; - -var keyMirror = require('react/lib/keyMirror'); -var isFunction = require('./isFunction') -var React = require('react/addons'); -if (!Object.assign) { - Object.assign = require('object-assign'); -} - -/** - * Policies that describe methods in Adazzle React Mixins - * Any methods that do not confirm to one of these policies will be treated as a custom method - * All custom methods will be wrapped to potentially allow override/extension as defined on a component - */ -var SpecPolicy = keyMirror({ - /** - * These methods are React Lifecycle methods and should be mixed into any components - * according to their default behviour as specified in React srcrary - */ - DEFINE_LIFE_CYCLE_METHOD : null, - /** - * These methods may be defined only once by the class specification or mixin. - */ - DEFINE_ONCE: null, - /** - * These methods may be defined by both the class specification and mixins. - * Subsequent definitions will be chained. These methods must return void. - */ - DEFINE_MANY: null, - /** - * These methods are overriding the base ReactCompositeComponent class. - */ - OVERRIDE_BASE: null, - /** - * These methods are similar to DEFINE_MANY, except we assume they return - * objects. We try to merge the keys of the return values of all the mixed in - * functions. If there is a key conflict we throw. - */ - DEFINE_MANY_MERGED: null - -}); - -var MixinInterface = { - - - getDefaultProps : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD, - propTypes : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD, - getInitialState : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD, - statics : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD, - displayName : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD, - componentWillMount : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD, - componentWillReceiveProps : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD, - shouldComponentUpdate : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD, - componentWillUpdate : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD, - componentDidUpdate : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD, - componentWillUnmount : SpecPolicy.DEFINE_LIFE_CYCLE_METHOD -} - -var MixinAliasCache = {}; - - -var Mixin = function(base, dependsOn){ - this.base = base; - this.dependsOn = dependsOn; -}; - -var Dependency = function(dependsOn){ - this.assignTo = function(base){ - return new Mixin(base, dependsOn); - } -}; - - -var wrapEachMethodInObject = function(clone, results){ - //loop over each property and mix according to its spec policy - Object.keys(clone).forEach(function(key){ - if(mixinUtils.isCustomProperty(key)){ - //overwrite each function of object with custom functionlity - if(isFunction(clone[key])){ - clone[key] = mixinUtils.wrapCustomMethod(key, clone[key]); - } - }else{ - - switch(MixinInterface[key]){ - case SpecPolicy.DEFINE_LIFE_CYCLE_METHOD: - var lifeCycleObj = {}; - lifeCycleObj[key] = clone[key]; - //add this to mixin result - will be treated as standard - results.push(lifeCycleObj); - break; - case SpecPolicy.DEFINE_MANY_MERGED: - //TODO imlplement handlers for other spec policies - break; - } - - delete clone[key]; - } - - }, this); -} - - -var MixinHelper = { - - /** - * Mix properties and methods from multiple objects, without mutating any of them - * - * @param {array} array of all mixins to be merged - * @return {array} A new array of mixins, the first object being an object of containing all custom methods wrapped - * Subsequent object in array will be any extracted lifecycle methods which should be treated as standard - */ - mix : function(mixins){ - - var results = []; - var primary = {}; - - var dependencies = mixinUtils.getUniqueDependencies(mixins); - for (var d in dependencies){ - Object.assign(primary, MixinAliasCache[dependencies[d]]); - } - wrapEachMethodInObject(primary, results); - - mixins.forEach(function(obj){ - //clone the object so that original methods are not overwritten - var clone = {}; - //check if mixin was created using Mixin Helper - //If it is then merge the properties object - if(obj instanceof Mixin){ - Object.assign(clone, obj.base); - }else{ - Object.assign(clone, obj); - } - - wrapEachMethodInObject(clone, results); - - Object.assign(primary, clone); - }, this); - - results.push(primary); - - - return results; - }, - - - createDependency : function(deps){ - var dependencyList = []; - for (var d in deps){ - if(deps[d] instanceof Mixin){ - this.addAlias(d, deps[d].base) - }else{ - this.addAlias(d, deps[d]) - } - dependencyList.push(d); - } - var uniqueDependencyList = dependencyList.filter(function(value, index, self) { - return self.indexOf(value) === index; - }); - return new Dependency(uniqueDependencyList); - }, - - addAlias : function(key, object){ - MixinAliasCache[key] = object; - } - -}; - -// idea borrowed from https://github.com/jhudson8/react-mixin-manager/blob/master/react-mixin-manager.js -var _createClass = React.createClass; -React.createClass = function(spec) { - if (spec.mixins) { - spec.mixins = MixinHelper.mix(spec.mixins); - } - return _createClass.apply(React, arguments); -}; - - -var mixinUtils = { - - isCustomProperty : function(key){ - return (!MixinInterface[key]); - }, - - wrapCustomMethod : function(methodName, old){ - return function(){ - //call overridden method if exists - if(mixinUtils.isMethodOverridden.call(this, methodName)){ - return mixinUtils.callOverriddenMethod.call(this, methodName, arguments); - }else{ - //call the original mixin method - return old.apply(this, arguments); - } - } - }, - - checkMethodExtendedAndCall : function(methodName, args){ - if(this.extended && (typeof this.extended[methodName] === 'function')){ - return this.extended[methodName].call(this, args); - } - }, - - checkMethodImplementedAndCall: function(methodName, args){ - if(this.implemented && (typeof this.implemented[methodName] === 'function')){ - return this.implemented[methodName].call(this, args); - } - }, - - isMethodOverridden: function(methodName){ - return this.overrides && (typeof this.overrides[methodName] === 'function'); - }, - - callOverriddenMethod: function(methodName, args){ - return this.overrides[methodName].call(this, args); - }, - - getUniqueDependencies : function(mixins){ - var deps = []; - mixins.forEach(function(m){ - if(m instanceof Mixin){ - deps = deps.concat(m.dependsOn); - } - }, this); - return deps.filter(function(value, index, self) { - return self.indexOf(value) === index; - });; - } -} -module.exports = MixinHelper; diff --git a/src/addons/utils/isFunction.js b/src/addons/utils/isFunction.js index 00ada42..a58f701 100644 --- a/src/addons/utils/isFunction.js +++ b/src/addons/utils/isFunction.js @@ -1,7 +1,7 @@ - +/* @flow */ "use strict"; -var isFunction = function(functionToCheck){ +var isFunction = function(functionToCheck: any): boolean{ var getType = {}; return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]'; } diff --git a/src/copyProperties.js b/src/copyProperties.js index ca7ab58..481d95e 100644 --- a/src/copyProperties.js +++ b/src/copyProperties.js @@ -14,6 +14,7 @@ * limitations under the License. * * @providesModule copyProperties + */ 'use strict'; diff --git a/src/emptyFunction.js b/src/emptyFunction.js index ca82a36..77c792d 100644 --- a/src/emptyFunction.js +++ b/src/emptyFunction.js @@ -1,3 +1,4 @@ +/* @flow */ /** * Copyright 2013-2014 Facebook, Inc. * @@ -14,6 +15,7 @@ * limitations under the License. * * @providesModule emptyFunction + */ 'use strict'; diff --git a/src/flowInterfaces/interfaces.js b/src/flowInterfaces/interfaces.js deleted file mode 100644 index 0874699..0000000 --- a/src/flowInterfaces/interfaces.js +++ /dev/null @@ -1,4 +0,0 @@ -/* @flow */ -type RowUpdateEvent = {rowIdx: number; updated: object; cellKey: string; keyCode: string}; -type CellDragEvent = {rowIdx: number; fromRow: number; toRow: number; value: any}; -type CellCopyPasteEvent = {rowIdx: number; value : any; fromRow: number; toRow: number; cellKey: string}; diff --git a/src/getScrollbarSize.js b/src/getScrollbarSize.js index 79b8589..83855d9 100644 --- a/src/getScrollbarSize.js +++ b/src/getScrollbarSize.js @@ -1,3 +1,4 @@ +/* @flow offsetWidth in HTMLElement */ "use strict"; var size; @@ -20,8 +21,8 @@ function getScrollbarSize() { outer.appendChild(inner); document.body.appendChild(outer); - var outerWidth = outer.offsetWidth; - var innerWidth = inner.offsetWidth; + var outerWidth = outer.clientWidth; + var innerWidth = inner.clientWidth; document.body.removeChild(outer); diff --git a/src/getWindowSize.js b/src/getWindowSize.js index e7c10bb..18b702c 100644 --- a/src/getWindowSize.js +++ b/src/getWindowSize.js @@ -1,6 +1,9 @@ +/* @flow */ /** * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 + + + */ 'use strict'; @@ -9,7 +12,7 @@ * * @return {Object} height and width of the window */ -function getWindowSize() { +function getWindowSize(): {width: number; height: number} { var width = window.innerWidth; var height = window.innerHeight; diff --git a/src/index.js b/src/index.js index 4207feb..cf2f2c6 100644 --- a/src/index.js +++ b/src/index.js @@ -1,7 +1,4 @@ -/** - * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 - */ +/* @flow */ 'use strict'; var Grid = require('./addons/grids/ExcelGrid'); diff --git a/src/invariant.js b/src/invariant.js deleted file mode 100644 index 6310bfa..0000000 --- a/src/invariant.js +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright 2013-2014 Facebook, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @providesModule invariant - */ - -"use strict"; - -/** - * Use invariant() to assert state which your program assumes to be true. - * - * Provide sprintf-style format (only %s is supported) and arguments - * to provide information about what broke and what you were - * expecting. - * - * The invariant message will be stripped in production, but the invariant - * will remain to ensure logic does not differ in production. - */ - -var invariant = function(condition, format, a, b, c, d, e, f) { - if (process.env.NODE_ENV) { - if (format === undefined) { - throw new Error('invariant requires an error message argument'); - } - } - - if (!condition) { - var error; - if (format === undefined) { - error = new Error( - 'Minified exception occurred; use the non-minified dev environment ' + - 'for the full error message and additional helpful warnings.' - ); - } else { - var args = [a, b, c, d, e, f]; - var argIndex = 0; - error = new Error( - 'Invariant Violation: ' + - format.replace(/%s/g, function() { return args[argIndex++]; }) - ); - } - - error.framesToPop = 1; // we don't care about invariant's own frame - throw error; - } -}; - -module.exports = invariant; diff --git a/src/merge.js b/src/merge.js index ccefb07..f38429f 100644 --- a/src/merge.js +++ b/src/merge.js @@ -1,3 +1,4 @@ +/* @flow */ /** * Copyright 2013-2014 Facebook, Inc. * @@ -14,6 +15,7 @@ * limitations under the License. * * @providesModule merge + */ "use strict"; @@ -25,7 +27,7 @@ * @param {?object} two Optional object with properties to merge from. * @return {object} The shallow extension of one by two. */ -var merge = function(one, two) { +var merge = function(one: any, two: any): any { var result = {}; if (one != null) { Object.assign(result, one); @@ -36,7 +38,7 @@ var merge = function(one, two) { return result; }; -function mergeFallback(obj1,obj2){ +function mergeFallback(obj1: any,obj2: any): any{ var obj3 = {}; for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; } for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; } diff --git a/src/mergeInto.js b/src/mergeInto.js index de5e435..9896632 100644 --- a/src/mergeInto.js +++ b/src/mergeInto.js @@ -1,3 +1,4 @@ +/* @flow */ /** * Copyright 2013-2014 Facebook, Inc. * @@ -15,6 +16,7 @@ * * @providesModule mergeInto * @typechecks static-only + */ "use strict"; @@ -26,7 +28,7 @@ * @param {?object} two Optional object with properties to merge from. * @return {object|function} The first argument coerced into an object. */ -function mergeInto(one, two) { +function mergeInto(one: any, two: any): any { if (two != null) { return Object.assign(one, two); } else { diff --git a/src/shallowCloneObject.js b/src/shallowCloneObject.js index d89ed18..9dff1e6 100644 --- a/src/shallowCloneObject.js +++ b/src/shallowCloneObject.js @@ -1,10 +1,12 @@ +/* @flow */ /** * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 + + */ 'use strict'; -function shallowCloneObject(obj) { +function shallowCloneObject(obj: any): any { var result = {}; for (var k in obj) { if (obj.hasOwnProperty(k)) { diff --git a/src/shallowEqual.js b/src/shallowEqual.js index 11eca4d..fd2b7b9 100644 --- a/src/shallowEqual.js +++ b/src/shallowEqual.js @@ -1,10 +1,12 @@ +/* @flow */ /** * @jsx React.DOM - * @copyright Prometheus Research, LLC 2014 + + */ 'use strict'; -function shallowEqual(a, b) { +function shallowEqual(a: any, b: any): boolean { if (a === b) { return true; } diff --git a/themes/reactGrid.css b/themes/reactGrid.css index 69e1a1b..e31a415 100644 --- a/themes/reactGrid.css +++ b/themes/reactGrid.css @@ -287,6 +287,14 @@ input.react-grid-CheckBox { outline: none; } +.react-grid-image { + background: #efefef; + background-size: 100%; + display: inline-block; + height: 40px; + width: 40px; +} + .react-autocomplete-Autocomplete__search { display: block; width: 100%; diff --git a/webpack.config.js b/webpack.config.js deleted file mode 100644 index 19eaf2c..0000000 --- a/webpack.config.js +++ /dev/null @@ -1,31 +0,0 @@ -var path = require("path"); -var webpack = require('webpack'); -var release = false; -var path = require("path"); - -module.exports = { - entry: { - 'ReactGrid' : './src/index', - 'ReactGridWithAddons' : './src/addons/index' - }, - output: { - path: path.join(__dirname, "./dist"), - filename: "[name].js", - library: ["ReactGrid"], - libraryTarget: "umd" - }, - externals: { - "react/addons": { - root : 'React', - commonjs : 'react/addons', - commonjs2 : 'react/addons', - amd : 'react/addons' - }, - "moment" : "moment" - }, - module: { - loaders: [ - { test: /\.js$/, loader: 'jsx-loader?stripTypes&harmony' } // loaders can take parameters as a querystring - ] - } -}