Sfoglia il codice sorgente

implement by using TS

方正 7 anni fa
parent
commit
e1d2721a9d

+ 3 - 0
.vscode/settings.json

@@ -0,0 +1,3 @@
+{
+    "typescript.tsdk": "node_modules/typescript/lib"
+}

+ 0 - 89
app/src/index.js

@@ -1,89 +0,0 @@
-'use strict'
-import React from 'react';
-import ReactDOM from 'react-dom';
-import { LayoutDemo } from './NormalLayout';
-import { SortedTable } from './SortedTable';
-import { SortedTableWithStatic } from './StaticHeader';
-
-
-
-ReactDOM.render(
-    <div>
-        <LayoutDemo />
-        {/* <SortedTable /> */}
-        {/* <SortedTableWithStatic /> */}
-    </div>,
-    document.getElementById('root')
-);
-
-document.body.addEventListener('touchmove', function (event) {
-    event.preventDefault();
-}, false);
-
-// const ThemeContext = React.createContext();
-
-// class ThemeProvider extends React.Component {
-//     state = {
-//         theme: "dark",
-//         color: "blue"
-//     };
-
-//     changeTheme = theme => {
-//         this.setState({
-//             theme
-//         });
-//     };
-
-//     changeColor = color => {
-//         this.setState({
-//             color
-//         });
-//     };
-
-//     render() {
-//         return (
-//             <ThemeContext.Provider
-//                 value={{
-//                     theme: this.state.theme,
-//                     color: this.state.color,
-//                     changeColor: this.changeColor
-//                 }}
-//             >
-//                 <button onClick={() => this.changeTheme("light")}>change theme</button>
-//                 {this.props.children}
-//             </ThemeContext.Provider>
-//         );
-//     }
-// }
-// const SubComponent = props => (
-//     <div>
-//         <div>{props.theme}</div>
-//         <button onClick={() => props.changeColor("red")}>change color</button>
-//         <div>{props.color}</div>
-//         <ThemeContext.Consumer>
-//             {context => (
-//                 <div>{context.theme}{context.color}{context.changeColor}
-//                 </div>
-//             )}
-//         </ThemeContext.Consumer>
-//     </div>
-// );
-// class App extends React.Component {
-//     render() {
-//         return (
-//             <ThemeProvider>
-//                 <ThemeContext.Consumer>
-//                     {context => (
-//                         <SubComponent
-//                             theme={context.theme}
-//                             color={context.color}
-//                             changeColor={context.changeColor}
-//                         />
-//                     )}
-//                 </ThemeContext.Consumer>
-//             </ThemeProvider>
-//         );
-//     }
-// }
-
-// ReactDOM.render(<App />, document.getElementById("root"));

+ 0 - 532
build/App.js

@@ -1,532 +0,0 @@
-import _Object$getPrototypeOf from 'babel-runtime/core-js/object/get-prototype-of';
-import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
-import _createClass from 'babel-runtime/helpers/createClass';
-import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
-import _inherits from 'babel-runtime/helpers/inherits';
-import _extends from 'babel-runtime/helpers/extends';
-import _toConsumableArray from 'babel-runtime/helpers/toConsumableArray';
-import React from 'react';
-import PropTypes from 'prop-types';
-import GridItem, { checkInContainer } from './GridItem';
-
-import './style.css';
-
-/**
- * 这个函数会有副作用,不是纯函数,会改变item的Gridx和GridY
- * @param {*} item 
- */
-var correctItem = function correctItem(item, col) {
-    var _checkInContainer = checkInContainer(item.GridX, item.GridY, col, item.w),
-        GridX = _checkInContainer.GridX,
-        GridY = _checkInContainer.GridY;
-
-    item.GridX = GridX;
-    item.GridY = GridY;
-};
-var correctLayout = function correctLayout(layout, col) {
-    var copy = [].concat(_toConsumableArray(layout));
-    for (var i = 0; i < layout.length - 1; i++) {
-        correctItem(copy[i], col);
-        correctItem(copy[i + 1], col);
-
-        if (collision(copy[i], copy[i + 1])) {
-            copy = layoutCheck(copy, copy[i], copy[i].key, copy[i].key, undefined);
-        }
-    }
-
-    return copy;
-};
-
-/**
- * 用key从layout中拿出item
- * @param {*} layout 输入进来的布局
- * @param {*} key 
- */
-var layoutItemForkey = function layoutItemForkey(layout, key) {
-    for (var i = 0, length = layout.length; i < length; i++) {
-        if (key === layout[i].key) {
-            return layout[i];
-        }
-    }
-};
-
-/**
- * 初始化的时候调用
- * 会把isUserMove和key一起映射到layout中
- * 不用用户设置
- * @param {*} layout 
- * @param {*} children 
- */
-
-var MapLayoutTostate = function MapLayoutTostate(layout, children) {
-    return layout.map(function (child, index) {
-        var newChild = _extends({}, child, { isUserMove: true, key: children[index].key, static: children[index].static });
-        return newChild;
-    });
-};
-
-/**
- * 把用户移动的块,标记为true
- * @param {*} layout 
- * @param {*} key 
- * @param {*} GridX 
- * @param {*} GridY 
- * @param {*} isUserMove 
- */
-var syncLayout = function syncLayout(layout, key, GridX, GridY, isUserMove) {
-    var newlayout = layout.map(function (item) {
-        if (item.key === key) {
-            item.GridX = GridX;
-            item.GridY = GridY;
-            item.isUserMove = isUserMove;
-            return item;
-        }
-        return item;
-    });
-    return newlayout;
-};
-
-var collision = function collision(a, b) {
-    if (a.GridX === b.GridX && a.GridY === b.GridY && a.w === b.w && a.h === b.h) {
-        return true;
-    }
-    if (a.GridX + a.w <= b.GridX) return false;
-    if (a.GridX >= b.GridX + b.w) return false;
-    if (a.GridY + a.h <= b.GridY) return false;
-    if (a.GridY >= b.GridY + b.h) return false;
-    return true;
-};
-
-var sortLayout = function sortLayout(layout) {
-    return [].concat(layout).sort(function (a, b) {
-        if (a.GridY > b.GridY || a.GridY === b.GridY && a.GridX > b.GridX) {
-            if (a.static) return 0; //为了静态,排序的时候尽量把静态的放在前面
-            return 1;
-        } else if (a.GridY === b.GridY && a.GridX === b.GridX) {
-            return 0;
-        }
-        return -1;
-    });
-};
-
-/**获取layout中,item第一个碰撞到的物体 */
-var getFirstCollison = function getFirstCollison(layout, item) {
-    for (var i = 0, length = layout.length; i < length; i++) {
-        if (collision(layout[i], item)) {
-            return layout[i];
-        }
-    }
-    return null;
-};
-
-/**
- * 压缩单个元素,使得每一个元素都会紧挨着边界或者相邻的元素
- * @param {*} finishedLayout 压缩完的元素会放进这里来,用来对比之后的每一个元素是否需要压缩
- * @param {*} item 
- */
-var compactItem = function compactItem(finishedLayout, item) {
-    if (item.static) return item;
-    var newItem = _extends({}, item);
-    if (finishedLayout.length === 0) {
-        return _extends({}, newItem, { GridY: 0 });
-    }
-    /**
-     * 类似一个递归调用
-     */
-    while (true) {
-        var FirstCollison = getFirstCollison(finishedLayout, newItem);
-        if (FirstCollison) {
-            /**第一次发生碰撞时,就可以返回了 */
-            newItem.GridY = FirstCollison.GridY + FirstCollison.h;
-            return newItem;
-        }
-        newItem.GridY--;
-
-        if (newItem.GridY < 0) return _extends({}, newItem, { GridY: 0 /**碰到边界的时候,返回 */
-        });
-    }
-    return newItem;
-};
-
-/**
- * 压缩layout,使得每一个元素都会紧挨着边界或者相邻的元素
- * @param {*} layout 
- */
-var compactLayout = function compactLayout(layout) {
-    var sorted = sortLayout(layout);
-    var needCompact = Array(layout.length);
-    var compareList = [];
-    for (var i = 0, length = sorted.length; i < length; i++) {
-        var finished = compactItem(compareList, sorted[i]);
-        finished.isUserMove = false;
-        compareList.push(finished);
-        needCompact[i] = finished;
-    }
-    return needCompact;
-};
-
-var layoutCheck = function layoutCheck(layout, layoutItem, key, fristItemkey, moving) {
-    var i = [],
-        movedItem = []; /**收集所有移动过的物体 */
-    var newlayout = layout.map(function (item, idx) {
-
-        if (item.key !== key) {
-            if (item.static) {
-                return item;
-            }
-            if (collision(item, layoutItem)) {
-                i.push(item.key);
-                /**
-                 * 这里就是奇迹发生的地方,如果向上移动,那么必须注意的是
-                 * 一格一格的移动,而不是一次性移动
-                 */
-                var offsetY = item.GridY + 1;
-
-                /**这一行也非常关键,当向上移动的时候,碰撞的元素必须固定 */
-                // if (moving < 0 && layoutItem.GridY > 0) offsetY = item.GridY
-
-                if (layoutItem.GridY > item.GridY && layoutItem.GridY < item.GridY + item.h) {
-                    /**
-                     * 元素向上移动时,元素的上面空间不足,则不移动这个元素
-                     * 当元素移动到GridY>所要向上交换的元素时,就不会进入这里,直接交换元素
-                     */
-                    offsetY = item.GridY;
-                }
-                /**
-                 * 物体向下移动的时候
-                 */
-
-                if (moving > 0) {
-                    if (layoutItem.GridY + layoutItem.h < item.GridY) {
-                        (function () {
-                            var collision = void 0;
-                            var copy = _extends({}, item);
-                            while (true) {
-                                var newLayout = layout.filter(function (item) {
-                                    if (item.key !== key && item.key !== copy.key) {
-                                        return item;
-                                    }
-                                });
-                                collision = getFirstCollison(newLayout, copy);
-                                if (collision) {
-                                    offsetY = collision.GridY + collision.h;
-                                    break;
-                                } else {
-                                    copy.GridY--;
-                                }
-                                if (copy.GridY < 0) {
-                                    offsetY = 0;
-                                    break;
-                                }
-                            }
-                        })();
-                    }
-                }
-
-                movedItem.push(_extends({}, item, { GridY: offsetY, isUserMove: false }));
-                return _extends({}, item, { GridY: offsetY, isUserMove: false });
-            }
-        } else if (fristItemkey === key) {
-
-            /**永远保持用户移动的块是 isUserMove === true */
-            return _extends({}, item, { GridX: layoutItem.GridX, GridY: layoutItem.GridY, isUserMove: true });
-        }
-
-        return item;
-    });
-    /** 递归调用,将layout中的所有重叠元素全部移动 */
-    var length = movedItem.length;
-    for (var c = 0; c < length; c++) {
-        newlayout = layoutCheck(newlayout, movedItem[c], i[c], fristItemkey, undefined);
-    }
-    return newlayout;
-};
-
-function quickSort(a) {
-    return a.length <= 1 ? a : quickSort(a.slice(1).filter(function (item) {
-        return item <= a[0];
-    })).concat(a[0], quickSort(a.slice(1).filter(function (item) {
-        return item > a[0];
-    })));
-}
-
-var getMaxContainerHeight = function getMaxContainerHeight(layout) {
-    var elementHeight = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 30;
-    var elementMarginBottom = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 10;
-
-    var ar = layout.map(function (item) {
-        return item.GridY + item.h;
-    });
-    var h = quickSort(ar)[ar.length - 1];
-    var height = h * (elementHeight + elementMarginBottom) + elementMarginBottom;
-    return height;
-};
-
-var getDataSet = function getDataSet(children) {
-    return children.map(function (child) {
-        return _extends({}, child.props['data-set'], { isUserMove: true, key: child.key });
-    });
-};
-
-var stringJoin = function stringJoin(source, join) {
-    return source + (join ? ' ' + join : '');
-};
-
-export var DraggerLayout = function (_React$Component) {
-    _inherits(DraggerLayout, _React$Component);
-
-    function DraggerLayout(props) {
-        _classCallCheck(this, DraggerLayout);
-
-        var _this = _possibleConstructorReturn(this, (DraggerLayout.__proto__ || _Object$getPrototypeOf(DraggerLayout)).call(this, props));
-
-        _this.onDrag = _this.onDrag.bind(_this);
-        _this.onDragStart = _this.onDragStart.bind(_this);
-        _this.onDragEnd = _this.onDragEnd.bind(_this);
-
-        var layout = props.layout ? MapLayoutTostate(props.layout, props.children) : getDataSet(props.children);
-
-        _this.state = {
-            GridXMoving: 0,
-            GridYMoving: 0,
-            wMoving: 0,
-            hMoving: 0,
-            placeholderShow: false,
-            placeholderMoving: false,
-            layout: layout,
-            containerHeight: 500
-        };
-        return _this;
-    }
-
-    _createClass(DraggerLayout, [{
-        key: 'onDragStart',
-        value: function onDragStart(bundles) {
-            var GridX = bundles.GridX,
-                GridY = bundles.GridY,
-                w = bundles.w,
-                h = bundles.h,
-                UniqueKey = bundles.UniqueKey;
-
-
-            var newlayout = syncLayout(this.state.layout, UniqueKey, GridX, GridY, true);
-
-            this.setState({
-                GridXMoving: GridX,
-                GridYMoving: GridY,
-                wMoving: w,
-                hMoving: h,
-                placeholderShow: true,
-                placeholderMoving: true,
-                layout: newlayout
-            });
-            this.props.onDragStart && this.props.onDragStart({ GridX: GridX, GridY: GridY });
-        }
-    }, {
-        key: 'onDrag',
-        value: function onDrag(layoutItem, key) {
-            var GridX = layoutItem.GridX,
-                GridY = layoutItem.GridY;
-
-            var moving = GridY - this.state.GridYMoving;
-
-            var newLayout = layoutCheck(this.state.layout, layoutItem, key, key /*用户移动方块的key */, moving);
-            var compactedLayout = compactLayout(newLayout);
-            for (var i = 0; i < compactedLayout.length; i++) {
-                var compactedItem = compactedLayout[i];
-                if (key === compactedItem.key) {
-                    /**
-                     * 特殊点:当我们移动元素的时候,元素在layout中的位置不断改变
-                     * 但是当isUserMove=true的时候,鼠标拖拽的元素不会随着位图变化而变化
-                     * 但是实际layout中的位置还是会改变
-                     * (isUserMove=true用于解除placeholder和元素的绑定)
-                     */
-                    compactedItem.isUserMove = true;
-                    layoutItem.GridX = compactedItem.GridX;
-                    layoutItem.GridY = compactedItem.GridY;
-                    break;
-                }
-            }
-            this.setState({
-                GridXMoving: layoutItem.GridX,
-                GridYMoving: layoutItem.GridY,
-                layout: compactedLayout,
-                containerHeight: getMaxContainerHeight(compactedLayout, this.props.rowHeight, this.props.margin[1])
-            });
-            this.props.onDrag && this.props.onDrag({ GridX: GridX, GridY: GridY });
-        }
-    }, {
-        key: 'onDragEnd',
-        value: function onDragEnd(key) {
-            var compactedLayout = compactLayout(this.state.layout);
-            this.setState({
-                placeholderShow: false,
-                layout: compactedLayout,
-                containerHeight: getMaxContainerHeight(compactedLayout, this.props.rowHeight, this.props.margin[1])
-            });
-
-            this.props.onDragEnd && this.props.onDragEnd();
-        }
-    }, {
-        key: 'renderPlaceholder',
-        value: function renderPlaceholder() {
-            if (!this.state.placeholderShow) return null;
-            var _props = this.props,
-                col = _props.col,
-                width = _props.width,
-                padding = _props.padding,
-                rowHeight = _props.rowHeight,
-                margin = _props.margin;
-            var _state = this.state,
-                GridXMoving = _state.GridXMoving,
-                GridYMoving = _state.GridYMoving,
-                wMoving = _state.wMoving,
-                hMoving = _state.hMoving,
-                placeholderMoving = _state.placeholderMoving;
-
-
-            return React.createElement(GridItem, {
-                margin: margin,
-                col: col,
-                containerWidth: width,
-                containerPadding: padding,
-                rowHeight: rowHeight,
-                GridX: GridXMoving,
-                GridY: GridYMoving,
-                w: wMoving,
-                h: hMoving,
-                style: { background: '#d6e4ff', zIndex: 1, transition: ' all .15s' },
-                isUserMove: !placeholderMoving
-            });
-        }
-    }, {
-        key: 'componentDidMount',
-        value: function componentDidMount() {
-            var _this2 = this;
-
-            setTimeout(function () {
-                var layout = correctLayout(_this2.state.layout, _this2.props.col);
-                var compacted = compactLayout(layout);
-                _this2.setState({
-                    layout: compacted,
-                    containerHeight: getMaxContainerHeight(compacted, _this2.props.rowHeight, _this2.props.margin[1])
-                });
-            }, 1);
-        }
-    }, {
-        key: 'getGridItem',
-        value: function getGridItem(child, index) {
-            var layout = this.state.layout;
-            var _props2 = this.props,
-                col = _props2.col,
-                width = _props2.width,
-                padding = _props2.padding,
-                rowHeight = _props2.rowHeight,
-                margin = _props2.margin;
-
-            var renderItem = layoutItemForkey(layout, child.key); //TODO:可以优化速度,这一步不是必须;
-            return React.createElement(
-                GridItem,
-                {
-                    margin: margin,
-                    col: col,
-                    containerWidth: width,
-                    containerPadding: padding,
-                    rowHeight: rowHeight,
-                    GridX: renderItem.GridX,
-                    GridY: renderItem.GridY,
-                    w: renderItem.w,
-                    h: renderItem.h,
-                    onDrag: this.onDrag,
-                    onDragStart: this.onDragStart,
-                    onDragEnd: this.onDragEnd,
-                    index: index,
-                    isUserMove: renderItem.isUserMove,
-                    UniqueKey: child.key,
-                    style: { zIndex: 2 },
-                    'static': renderItem.static
-                },
-                child
-            );
-        }
-    }, {
-        key: 'render',
-        value: function render() {
-            var _this3 = this;
-
-            var _props3 = this.props,
-                layout = _props3.layout,
-                col = _props3.col,
-                width = _props3.width,
-                padding = _props3.padding,
-                rowHeight = _props3.rowHeight,
-                className = _props3.className;
-            var containerHeight = this.state.containerHeight;
-
-
-            return React.createElement(
-                'div',
-                {
-                    className: stringJoin('DraggerLayout', className),
-                    style: { left: 100, width: width, height: containerHeight, zIndex: 1 }
-                },
-                React.Children.map(this.props.children, function (child, index) {
-                    return _this3.getGridItem(child, index);
-                }),
-                this.renderPlaceholder()
-            );
-        }
-    }]);
-
-    return DraggerLayout;
-}(React.Component);
-DraggerLayout.propTypes = {
-    /**外部属性 */
-    layout: PropTypes.array,
-    col: PropTypes.number,
-    width: PropTypes.number,
-    /**每个元素的最小高度 */
-    rowHeight: PropTypes.number,
-    padding: PropTypes.number
-};
-;
-
-var _temp = function () {
-    if (typeof __REACT_HOT_LOADER__ === 'undefined') {
-        return;
-    }
-
-    __REACT_HOT_LOADER__.register(correctItem, 'correctItem', 'app/src/App.js');
-
-    __REACT_HOT_LOADER__.register(correctLayout, 'correctLayout', 'app/src/App.js');
-
-    __REACT_HOT_LOADER__.register(layoutItemForkey, 'layoutItemForkey', 'app/src/App.js');
-
-    __REACT_HOT_LOADER__.register(MapLayoutTostate, 'MapLayoutTostate', 'app/src/App.js');
-
-    __REACT_HOT_LOADER__.register(syncLayout, 'syncLayout', 'app/src/App.js');
-
-    __REACT_HOT_LOADER__.register(collision, 'collision', 'app/src/App.js');
-
-    __REACT_HOT_LOADER__.register(sortLayout, 'sortLayout', 'app/src/App.js');
-
-    __REACT_HOT_LOADER__.register(getFirstCollison, 'getFirstCollison', 'app/src/App.js');
-
-    __REACT_HOT_LOADER__.register(compactItem, 'compactItem', 'app/src/App.js');
-
-    __REACT_HOT_LOADER__.register(compactLayout, 'compactLayout', 'app/src/App.js');
-
-    __REACT_HOT_LOADER__.register(layoutCheck, 'layoutCheck', 'app/src/App.js');
-
-    __REACT_HOT_LOADER__.register(quickSort, 'quickSort', 'app/src/App.js');
-
-    __REACT_HOT_LOADER__.register(getMaxContainerHeight, 'getMaxContainerHeight', 'app/src/App.js');
-
-    __REACT_HOT_LOADER__.register(getDataSet, 'getDataSet', 'app/src/App.js');
-
-    __REACT_HOT_LOADER__.register(stringJoin, 'stringJoin', 'app/src/App.js');
-
-    __REACT_HOT_LOADER__.register(DraggerLayout, 'DraggerLayout', 'app/src/App.js');
-}();
-
-;

+ 0 - 359
build/Dragger.js

@@ -1,359 +0,0 @@
-import _extends from 'babel-runtime/helpers/extends';
-import _Object$getPrototypeOf from 'babel-runtime/core-js/object/get-prototype-of';
-import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
-import _createClass from 'babel-runtime/helpers/createClass';
-import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
-import _inherits from 'babel-runtime/helpers/inherits';
-import React from 'react';
-import PropTypes from 'prop-types';
-import { int, innerHeight, innerWidth, outerHeight, outerWidth, parseBounds, isNumber } from './utils';
-
-var doc = document;
-
-var Dragger = function (_React$Component) {
-    _inherits(Dragger, _React$Component);
-
-    function Dragger() {
-        var _ref;
-
-        _classCallCheck(this, Dragger);
-
-        for (var _len = arguments.length, props = Array(_len), _key = 0; _key < _len; _key++) {
-            props[_key] = arguments[_key];
-        }
-
-        var _this = _possibleConstructorReturn(this, (_ref = Dragger.__proto__ || _Object$getPrototypeOf(Dragger)).call.apply(_ref, [this].concat(props)));
-
-        _this.state = {
-            /** x轴位移,单位是px */
-            x: null,
-
-            /** y轴位移,单位是px */
-            y: null,
-
-            /**鼠标点击元素的原始位置,单位是px */
-            originX: 0,
-            originY: 0,
-
-            isUserMove: true,
-
-            /**已经移动的位移,单位是px */
-            lastX: 0,
-            lastY: 0,
-
-            /**堆叠的层级 */
-            zIndex: 1
-        };
-
-        _this.move = _this.move.bind(_this);
-        _this.onDragEnd = _this.onDragEnd.bind(_this);
-        return _this;
-    }
-    /** props end */
-
-    /**
-     * 初始变量设置
-     */
-
-
-    _createClass(Dragger, [{
-        key: 'move',
-        value: function move(event) {
-            var _state = this.state,
-                lastX = _state.lastX,
-                lastY = _state.lastY;
-            /*  event.client - this.state.origin 表示的是移动的距离,
-            *   elX表示的是原来已经有的位移
-            */
-
-            var deltaX = void 0,
-                deltaY = void 0;
-            if (event.clientX) {
-                deltaX = event.clientX - this.state.originX + lastX;
-                deltaY = event.clientY - this.state.originY + lastY;
-            } else {
-                deltaX = event.touches[0].clientX - this.state.originX + lastX;
-                deltaY = event.touches[0].clientY - this.state.originY + lastY;
-            }
-
-            var bounds = this.props.bounds;
-
-            if (bounds) {
-                /**
-                * 如果用户指定一个边界,那么在这里处理
-                */
-                var NewBounds = typeof bounds !== 'string' ? bounds : parseBounds(bounds);
-
-                /**
-                 * 网格式移动范围设定,永远移动 n 的倍数
-                 * 注意:设定移动范围的时候,一定要在判断bounds之前,否则会造成bounds不对齐
-                 */
-                var grid = this.props.grid;
-
-                if (Array.isArray(grid) && grid.length === 2) {
-                    deltaX = Math.round(deltaX / grid[0]) * grid[0];
-                    deltaY = Math.round(deltaY / grid[1]) * grid[1];
-                }
-
-                if (this.props.bounds === 'parent') {
-                    NewBounds = {
-                        left: int(this.parent.style.paddingLeft) + int(this.self.style.marginLeft) - this.self.offsetLeft,
-                        top: int(this.parent.style.paddingTop) + int(this.self.style.marginTop) - this.self.offsetTop,
-                        right: innerWidth(this.parent) - outerWidth(this.self) - this.self.offsetLeft + int(this.parent.style.paddingRight) - int(this.self.style.marginRight),
-                        bottom: innerHeight(this.parent) - outerHeight(this.self) - this.self.offsetTop + int(this.parent.style.paddingBottom) - int(this.self.style.marginBottom)
-                    };
-                }
-
-                /**
-                 * 保证不超出右边界和底部
-                 * keep element right and bot can not cross the bounds
-                 */
-                if (isNumber(NewBounds.right)) deltaX = Math.min(deltaX, NewBounds.right);
-                if (isNumber(NewBounds.bottom)) deltaY = Math.min(deltaY, NewBounds.bottom);
-
-                /**
-                 * 保证不超出左边和上边
-                 * keep element left and top can not cross the bounds
-                 */
-                if (isNumber(NewBounds.left)) deltaX = Math.max(deltaX, NewBounds.left);
-                if (isNumber(NewBounds.top)) deltaY = Math.max(deltaY, NewBounds.top);
-            }
-
-            /**如果设置了x,y限制 */
-            deltaX = this.props.allowX ? deltaX : 0;
-            deltaY = this.props.allowY ? deltaY : 0;
-
-            /**移动时回调,用于外部控制 */
-            if (this.props.onMove) this.props.onMove(event, deltaX, deltaY);
-
-            this.setState({
-                x: deltaX,
-                y: deltaY
-            });
-        }
-    }, {
-        key: 'onDragStart',
-        value: function onDragStart(event) {
-            /** 保证用户在移动元素的时候不会选择到元素内部的东西 */
-            doc.body.style.userSelect = 'none';
-
-            if (this.props.hasDraggerHandle) {
-                if (event.target.className !== 'handle') return;
-            }
-
-            /**
-             * 把监听事件的回掉函数,绑定在document上
-             * 当设置边界的时候,用户鼠标会离开元素的范围
-             * 绑定在document上可以使得其依旧能够监听
-             * 如果绑定在元素上,则鼠标离开元素,就不会再被监听了
-             */
-            doc.addEventListener('mousemove', this.move);
-            doc.addEventListener('touchmove', this.move);
-
-            doc.addEventListener('mouseup', this.onDragEnd);
-            doc.addEventListener('touchend', this.onDragEnd);
-
-            if (this.props.bounds === 'parent' && (
-            /**为了让 这段代码不会重复执行 */
-            typeof this.parent === 'undefined' || this.parent === null)) {
-                /**
-                 * 在这里我们将父节点缓存下来,保证当用户鼠标离开拖拽区域时,我们仍然能获取到父节点
-                 * what we do here is 
-                 * making sure that we still can retrieve our parent when user's mouse left this node.
-                 */
-                this.parent = event.currentTarget.offsetParent;
-                /**
-                 * 我们自己
-                 * ourself
-                 */
-                this.self = event.currentTarget;
-            }
-
-            this.props.onDragStart(this.state.x, this.state.y);
-
-            var originX = void 0,
-                originY = void 0;
-            if (event.clientX) {
-                originX = event.clientX;
-                originY = event.clientY;
-            } else {
-                originX = event.touches[0].clientX;
-                originY = event.touches[0].clientY;
-            }
-
-            this.setState({
-                originX: originX,
-                originY: originY,
-                lastX: this.state.x,
-                lastY: this.state.y,
-                zIndex: 10
-            });
-        }
-    }, {
-        key: 'onDragEnd',
-        value: function onDragEnd(event) {
-            /** 取消用户选择限制,用户可以重新选择 */
-            doc.body.style.userSelect = '';
-            this.parent = null;
-            this.self = null;
-            doc.removeEventListener('mousemove', this.move);
-            doc.removeEventListener('touchmove', this.move);
-
-            doc.removeEventListener('touchend', this.onDragEnd);
-            doc.removeEventListener('mouseup', this.onDragEnd);
-
-            this.setState({
-                zIndex: 1
-            });
-
-            this.props.onDragEnd(event);
-        }
-    }, {
-        key: 'componentDidMount',
-        value: function componentDidMount() {
-            /** 
-             * 这个函数只会调用一次 
-             * 这个只是一个临时的解决方案,因为这样会使得元素进行两次刷新
-            */
-            if (typeof this.props.x === 'number' && typeof this.props.y === 'number') {
-                this.setState({
-                    x: this.props.x,
-                    y: this.props.y
-                });
-            }
-        }
-    }, {
-        key: 'componentWillReceiveProps',
-        value: function componentWillReceiveProps(nextProps) {
-            /**
-             * 外部props 改变的时候更新元素的内部位置
-             * 这个api设计其实很不好
-             * 以后可能会修改掉
-             */
-            var isUserMove = nextProps.isUserMove;
-
-            if (!isUserMove) {
-                if (typeof nextProps.x === 'number' && typeof nextProps.y === 'number') {
-                    this.setState({
-                        x: nextProps.x,
-                        y: nextProps.y,
-                        lastX: nextProps.x,
-                        lastY: nextProps.y
-                    });
-                }
-            }
-        }
-    }, {
-        key: 'render',
-        value: function render() {
-            var _state2 = this.state,
-                x = _state2.x,
-                y = _state2.y,
-                zIndex = _state2.zIndex;
-            var _props = this.props,
-                bounds = _props.bounds,
-                style = _props.style,
-                className = _props.className,
-                others = _props.others;
-
-
-            if (!this.props.isUserMove) {
-                /**当外部设置其props的x,y初始属性的时候,我们在这里设置元素的初始位移 */
-                x = this.props.x;
-                y = this.props.y;
-            }
-
-            /**主要是为了让用户定义自己的className去修改css */
-            var fixedClassName = typeof className === 'undefined' ? '' : className + ' ';
-            return React.createElement(
-                'div',
-                _extends({ className: fixedClassName + 'WrapDragger',
-                    style: _extends({}, style, { zIndex: zIndex, touchAction: 'none!important', transform: 'translate(' + x + 'px,' + y + 'px)' }),
-                    onMouseDown: this.onDragStart.bind(this),
-                    onTouchStart: this.onDragStart.bind(this),
-                    onTouchEnd: this.onDragEnd.bind(this),
-                    onMouseUp: this.onDragEnd.bind(this)
-                }, others),
-                React.Children.only(this.props.children)
-            );
-        }
-    }]);
-
-    return Dragger;
-}(React.Component);
-
-Dragger.propTypes = {
-    /**
-     * 给予元素一个x,y的初始位置,单位是px
-     */
-    x: PropTypes.number,
-    y: PropTypes.number,
-
-    /**
-     * 拖动范围限制
-     * 如果不规定范围,那么子元素就可以随意拖动不受限制
-     * 1.可以提供自定义的范围限制
-     * 2.也可以提供父类为边框的范围限制(string === parent)
-     */
-    bounds: PropTypes.oneOfType([PropTypes.shape({
-        left: PropTypes.number,
-        right: PropTypes.number,
-        top: PropTypes.number,
-        bottom: PropTypes.number
-    }), PropTypes.string]),
-    /**
-     * 以网格的方式移动,每次移动并不是平滑的移动
-     * [20,30],鼠标x轴方向移动了20 px ,y方向移动了30 px,整个子元素才会移动
-     */
-    grid: PropTypes.arrayOf(PropTypes.number),
-
-    /**只允许移动x轴 */
-    allowX: PropTypes.bool,
-
-    /**只允许移动y轴 */
-    allowY: PropTypes.bool,
-
-    /**
-     * 内部的移动拖拽把手
-     * 拖拽把手className一定要设置成handle并且这个属性设置成true
-     * <Dragger hasDraggerHandle={true}>
-     *      <div className={handle} >点击我拖动</div>
-     * </Dragger>
-     */
-    hasDraggerHandle: PropTypes.bool,
-
-    /**
-     * 是否由用户移动
-     * 可能是通过外部props改变
-     */
-    isUserMove: PropTypes.bool,
-
-    /**
-     * 生命周期回调
-     */
-    onDragStart: PropTypes.func,
-    onMove: PropTypes.func,
-    onDragEnd: PropTypes.func };
-Dragger.defaultProps = {
-    allowX: true,
-    allowY: true,
-    hasDraggerHandle: false,
-    isUserMove: true
-};
-var _default = Dragger;
-export default _default;
-;
-
-var _temp = function () {
-    if (typeof __REACT_HOT_LOADER__ === 'undefined') {
-        return;
-    }
-
-    __REACT_HOT_LOADER__.register(doc, 'doc', 'app/src/Dragger.js');
-
-    __REACT_HOT_LOADER__.register(Dragger, 'Dragger', 'app/src/Dragger.js');
-
-    __REACT_HOT_LOADER__.register(_default, 'default', 'app/src/Dragger.js');
-}();
-
-;

+ 0 - 242
build/GridItem.js

@@ -1,242 +0,0 @@
-import _extends from 'babel-runtime/helpers/extends';
-import _Object$getPrototypeOf from 'babel-runtime/core-js/object/get-prototype-of';
-import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
-import _createClass from 'babel-runtime/helpers/createClass';
-import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn';
-import _inherits from 'babel-runtime/helpers/inherits';
-import React from 'react';
-
-import PropTypes from 'prop-types';
-import Dragger from './Dragger';
-
-export var checkInContainer = function checkInContainer(GridX, GridY, col, w) {
-    /**防止元素出container */
-    if (GridX + w > col - 1) GridX = col - w; //右边界
-    if (GridX < 0) GridX = 0; //左边界
-    if (GridY < 0) GridY = 0; //上边界
-    return { GridX: GridX, GridY: GridY };
-};
-
-var GridItem = function (_React$Component) {
-    _inherits(GridItem, _React$Component);
-
-    function GridItem(props) {
-        _classCallCheck(this, GridItem);
-
-        var _this = _possibleConstructorReturn(this, (GridItem.__proto__ || _Object$getPrototypeOf(GridItem)).call(this, props));
-
-        _this.onDrag = _this.onDrag.bind(_this);
-        _this.onDragStart = _this.onDragStart.bind(_this);
-        _this.onDragEnd = _this.onDragEnd.bind(_this);
-        _this.calGridXY = _this.calGridXY.bind(_this);
-        _this.calColWidth = _this.calColWidth.bind(_this);
-        return _this;
-    }
-
-    _createClass(GridItem, [{
-        key: 'calColWidth',
-
-
-        /** 计算容器的每一个格子多大 */
-        value: function calColWidth() {
-            var _props = this.props,
-                containerWidth = _props.containerWidth,
-                col = _props.col,
-                containerPadding = _props.containerPadding,
-                margin = _props.margin;
-
-
-            return (containerWidth - containerPadding[0] * 2 - margin[0] * (col + 1)) / col;
-        }
-
-        /**转化,计算网格的GridX,GridY值 */
-
-    }, {
-        key: 'calGridXY',
-        value: function calGridXY(x, y) {
-            var _props2 = this.props,
-                margin = _props2.margin,
-                containerWidth = _props2.containerWidth,
-                col = _props2.col,
-                w = _props2.w;
-
-            /**坐标转换成格子的时候,无须计算margin */
-
-            var GridX = Math.round(x / containerWidth * col);
-            var GridY = Math.round(y / (this.props.rowHeight + margin[1]));
-
-            // /**防止元素出container */
-            return checkInContainer(GridX, GridY, col, w);
-        }
-
-        /**给予一个grid的位置,算出元素具体的在容器中位置在哪里,单位是px */
-
-    }, {
-        key: 'calGridItemPosition',
-        value: function calGridItemPosition(GridX, GridY) {
-            var _props3 = this.props,
-                w = _props3.w,
-                margin = _props3.margin,
-                col = _props3.col,
-                containerWidth = _props3.containerWidth;
-
-            var x = Math.round(GridX * this.calColWidth() + (GridX + 1) * margin[0]);
-            var y = Math.round(GridY * this.props.rowHeight + margin[1] * (GridY + 1));
-
-            return {
-                x: x,
-                y: y
-            };
-        }
-
-        /**宽和高计算成为px */
-
-    }, {
-        key: 'calWHtoPx',
-        value: function calWHtoPx(w, h) {
-            var _props4 = this.props,
-                margin = _props4.margin,
-                containerPadding = _props4.containerPadding,
-                containerWidth = _props4.containerWidth,
-                col = _props4.col;
-
-
-            var wPx = Math.round(w * this.calColWidth() + (w - 1) * margin[0]);
-            var hPx = Math.round(h * this.props.rowHeight + (h - 1) * margin[1]);
-
-            return { wPx: wPx, hPx: hPx };
-        }
-    }, {
-        key: 'onDragStart',
-        value: function onDragStart(x, y) {
-            var _props5 = this.props,
-                w = _props5.w,
-                h = _props5.h,
-                UniqueKey = _props5.UniqueKey;
-
-            if (this.props.static) return;
-
-            var _calGridXY = this.calGridXY(x, y),
-                GridX = _calGridXY.GridX,
-                GridY = _calGridXY.GridY;
-
-            this.props.onDragStart({
-                event: event, GridX: GridX, GridY: GridY, w: w, h: h, UniqueKey: UniqueKey
-            });
-        }
-    }, {
-        key: 'onDrag',
-        value: function onDrag(event, x, y) {
-            if (this.props.static) return;
-
-            var _calGridXY2 = this.calGridXY(x, y),
-                GridX = _calGridXY2.GridX,
-                GridY = _calGridXY2.GridY;
-
-            var _props6 = this.props,
-                w = _props6.w,
-                h = _props6.h,
-                col = _props6.col,
-                UniqueKey = _props6.UniqueKey;
-
-            this.props.onDrag({ GridX: GridX, GridY: GridY, w: w, h: h }, UniqueKey);
-        }
-    }, {
-        key: 'onDragEnd',
-        value: function onDragEnd() {
-            if (this.props.static) return;
-            if (this.props.onDragEnd) this.props.onDragEnd(this.props.UniqueKey);
-        }
-    }, {
-        key: 'render',
-        value: function render() {
-            var _props7 = this.props,
-                w = _props7.w,
-                h = _props7.h,
-                margin = _props7.margin,
-                style = _props7.style,
-                bounds = _props7.bounds,
-                GridX = _props7.GridX,
-                GridY = _props7.GridY;
-
-            var _calGridItemPosition = this.calGridItemPosition(this.props.GridX, this.props.GridY),
-                x = _calGridItemPosition.x,
-                y = _calGridItemPosition.y;
-
-            var _calWHtoPx = this.calWHtoPx(w, h),
-                wPx = _calWHtoPx.wPx,
-                hPx = _calWHtoPx.hPx;
-
-            return React.createElement(
-                Dragger,
-                {
-                    style: _extends({}, style, { width: wPx, height: hPx, position: 'absolute',
-                        transition: this.props.isUserMove ? '' : 'all .2s'
-                    }),
-                    onDragStart: this.onDragStart,
-                    onMove: this.onDrag,
-                    onDragEnd: this.onDragEnd,
-                    x: x,
-                    y: y,
-                    isUserMove: this.props.isUserMove
-                },
-                React.createElement(
-                    'div',
-                    { style: { width: wPx, height: hPx } },
-                    React.Children.map(this.props.children, function (child) {
-                        return child;
-                    })
-                )
-            );
-        }
-    }]);
-
-    return GridItem;
-}(React.Component);
-
-GridItem.propTypes = {
-    /**外部容器属性 */
-    col: PropTypes.number,
-    containerWidth: PropTypes.number,
-    containerPadding: PropTypes.array,
-
-    /**子元素的属性 */
-    margin: PropTypes.array,
-    GridX: PropTypes.number,
-    GridY: PropTypes.number,
-    rowHeight: PropTypes.number,
-
-    /**子元素的宽高 */
-    w: PropTypes.number,
-    h: PropTypes.number,
-
-    /**生命周期回掉函数 */
-    onDragStart: PropTypes.func,
-    onDragEnd: PropTypes.func
-
-};
-GridItem.defaultProps = {
-    col: 12,
-    containerWidth: 500,
-    containerPadding: [0, 0],
-    margin: [10, 10],
-    rowHeight: 30,
-    w: 1,
-    h: 1 };
-var _default = GridItem;
-export default _default;
-;
-
-var _temp = function () {
-    if (typeof __REACT_HOT_LOADER__ === 'undefined') {
-        return;
-    }
-
-    __REACT_HOT_LOADER__.register(checkInContainer, 'checkInContainer', 'app/src/GridItem.js');
-
-    __REACT_HOT_LOADER__.register(GridItem, 'GridItem', 'app/src/GridItem.js');
-
-    __REACT_HOT_LOADER__.register(_default, 'default', 'app/src/GridItem.js');
-}();
-
-;

+ 0 - 62
build/NormalLayout/index.js

@@ -1,62 +0,0 @@
-import React from 'react';
-import { DraggerLayout } from '../App';
-
-var Words = [{ content: 'You can do anything, but not everything.', img: 'http://pic.sc.chinaz.com/files/pic/pic9/201303/xpic10472.jpg' }, { content: 'Those who dare to fail miserably can achieve greatly.', img: 'https://img00.deviantart.net/1163/i/2013/059/d/7/irish_views_by_ssquared_photography-d5wjnsk.jpg' }, { content: 'You miss 100 percent of the shots you never take.', img: 'http://www.landsendhotel.co.uk/uploads/gallery/gallery/coastal_scenery_seascapes_6.jpg' }, { content: 'Those who believe in telekinetics, raise my hand.', img: 'https://tctechcrunch2011.files.wordpress.com/2017/10/26099344353_18cd6fabb8_k.jpg?w=738' }, { content: 'I’d rather live with a good question than a bad answer.', img: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQVa26cLzh6PYUwY4LMpwbHyDHFmWi_w2JuqDzeOdm1IIEbBZO0Vg' }];
-
-var Card = function Card(_ref) {
-    var item = _ref.item;
-
-    return React.createElement(
-        'div',
-        null,
-        React.createElement(
-            'div',
-            { className: 'layout-item' },
-            React.createElement('img', { src: item.img, style: { width: '100%' }, draggable: false, alt: 'card' }),
-            React.createElement(
-                'div',
-                { style: { padding: 5, textAlign: 'center', color: '#595959' } },
-                item.content
-            )
-        )
-    );
-};
-
-export var LayoutDemo = function LayoutDemo() {
-
-    return React.createElement(
-        'div',
-        { style: { display: 'flex', justifyContent: 'center' } },
-        React.createElement(
-            'div',
-            null,
-            React.createElement(
-                'h1',
-                { style: { textAlign: 'center' } },
-                'Normal Layout Demo'
-            ),
-            React.createElement(
-                DraggerLayout,
-                { width: 800, col: 12, rowHeight: 800 / 12, margin: [5, 5], className: 'normal-layout' },
-                Words.map(function (el, index) {
-                    return React.createElement(Card, { item: el, key: index, 'data-set': { GridX: index * 3 % 12, GridY: index * 2, w: 3, h: 3 } });
-                })
-            )
-        )
-    );
-};
-;
-
-var _temp = function () {
-    if (typeof __REACT_HOT_LOADER__ === 'undefined') {
-        return;
-    }
-
-    __REACT_HOT_LOADER__.register(Words, 'Words', 'app/src/NormalLayout/index.js');
-
-    __REACT_HOT_LOADER__.register(Card, 'Card', 'app/src/NormalLayout/index.js');
-
-    __REACT_HOT_LOADER__.register(LayoutDemo, 'LayoutDemo', 'app/src/NormalLayout/index.js');
-}();
-
-;

+ 0 - 59
build/SortedTable/index.js

@@ -1,59 +0,0 @@
-import React from 'react';
-import { DraggerLayout } from '../App';
-import './index.css';
-
-var Words = [{ content: 'You can do anything, but not everything.', img: 'http://pic.sc.chinaz.com/files/pic/pic9/201303/xpic10472.jpg' }, { content: 'Those who dare to fail miserably can achieve greatly.', img: 'https://img00.deviantart.net/1163/i/2013/059/d/7/irish_views_by_ssquared_photography-d5wjnsk.jpg' }, { content: 'You miss 100 percent of the shots you never take.', img: 'http://www.landsendhotel.co.uk/uploads/gallery/gallery/coastal_scenery_seascapes_6.jpg' }, { content: 'Those who believe in telekinetics, raise my hand.', img: 'https://tctechcrunch2011.files.wordpress.com/2017/10/26099344353_18cd6fabb8_k.jpg?w=738' }, { content: 'I’d rather live with a good question than a bad answer.', img: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQVa26cLzh6PYUwY4LMpwbHyDHFmWi_w2JuqDzeOdm1IIEbBZO0Vg' }];
-
-var Cell = function Cell(_ref) {
-    var item = _ref.item;
-
-    return React.createElement(
-        'div',
-        { className: 'layout-Cell' },
-        React.createElement('img', { src: item.img, style: { width: 45, height: 45 }, draggable: false, alt: 'card' }),
-        React.createElement(
-            'div',
-            { style: { paddingLeft: 12, color: '#595959' } },
-            item.content
-        )
-    );
-};
-
-export var SortedTable = function SortedTable() {
-
-    return React.createElement(
-        'div',
-        { style: { display: 'flex', justifyContent: 'center' } },
-        React.createElement(
-            'div',
-            null,
-            React.createElement(
-                'h1',
-                { style: { textAlign: 'center' } },
-                'Sorted Table Demo'
-            ),
-            React.createElement(
-                DraggerLayout,
-                { width: 800, col: 1, rowHeight: 60, margin: [2, 2], className: 'normal-layout' },
-                Words.map(function (el, index) {
-                    return React.createElement(Cell, { item: el, key: index, 'data-set': { GridX: 0, GridY: 0, w: 1, h: 1 } });
-                })
-            )
-        )
-    );
-};
-;
-
-var _temp = function () {
-    if (typeof __REACT_HOT_LOADER__ === 'undefined') {
-        return;
-    }
-
-    __REACT_HOT_LOADER__.register(Words, 'Words', 'app/src/SortedTable/index.js');
-
-    __REACT_HOT_LOADER__.register(Cell, 'Cell', 'app/src/SortedTable/index.js');
-
-    __REACT_HOT_LOADER__.register(SortedTable, 'SortedTable', 'app/src/SortedTable/index.js');
-}();
-
-;

+ 0 - 58
build/StaticHeader/index.js

@@ -1,58 +0,0 @@
-import React from 'react';
-import { DraggerLayout } from '../App';
-import './index.css';
-
-var Words = [{ content: 'Sorry I just can not move in any circumstances', img: 'http://pic.sc.chinaz.com/files/pic/pic9/201303/xpic10472.jpg', static: true }, { content: 'Those who dare to fail miserably can achieve greatly.', img: 'https://img00.deviantart.net/1163/i/2013/059/d/7/irish_views_by_ssquared_photography-d5wjnsk.jpg' }, { content: 'You miss 100 percent of the shots you never take.', img: 'http://www.landsendhotel.co.uk/uploads/gallery/gallery/coastal_scenery_seascapes_6.jpg' }, { content: 'Those who believe in telekinetics, raise my hand.', img: 'https://tctechcrunch2011.files.wordpress.com/2017/10/26099344353_18cd6fabb8_k.jpg?w=738' }, { content: 'I’d rather live with a good question than a bad answer.', img: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQVa26cLzh6PYUwY4LMpwbHyDHFmWi_w2JuqDzeOdm1IIEbBZO0Vg' }];
-
-var Cell = function Cell(_ref) {
-    var item = _ref.item;
-
-    return React.createElement(
-        'div',
-        { className: 'layout-Cell ' + (item.static ? "static" : ""), style: { background: item.static ? "#e8e8e8" : "" } },
-        React.createElement('img', { src: item.img, style: { width: 45, height: 45 }, draggable: false, alt: 'card' }),
-        React.createElement(
-            'div',
-            { style: { paddingLeft: 12, color: '#595959' } },
-            item.content
-        )
-    );
-};
-
-export var SortedTableWithStatic = function SortedTableWithStatic() {
-    return React.createElement(
-        'div',
-        { style: { display: 'flex', justifyContent: 'center' } },
-        React.createElement(
-            'div',
-            null,
-            React.createElement(
-                'h1',
-                { style: { textAlign: 'center' } },
-                'Static Header Table Demo'
-            ),
-            React.createElement(
-                DraggerLayout,
-                { width: 800, col: 1, rowHeight: 60, margin: [2, 2], className: 'normal-layout' },
-                Words.map(function (el, index) {
-                    return React.createElement(Cell, { item: el, key: index, 'data-set': { GridX: 0, GridY: 0, w: 1, h: 1, static: index === 0 ? true : false } });
-                })
-            )
-        )
-    );
-};
-;
-
-var _temp = function () {
-    if (typeof __REACT_HOT_LOADER__ === 'undefined') {
-        return;
-    }
-
-    __REACT_HOT_LOADER__.register(Words, 'Words', 'app/src/StaticHeader/index.js');
-
-    __REACT_HOT_LOADER__.register(Cell, 'Cell', 'app/src/StaticHeader/index.js');
-
-    __REACT_HOT_LOADER__.register(SortedTableWithStatic, 'SortedTableWithStatic', 'app/src/StaticHeader/index.js');
-}();
-
-;

+ 0 - 97
build/index.js

@@ -1,97 +0,0 @@
-'use strict';
-
-import React from 'react';
-import ReactDOM from 'react-dom';
-import { LayoutDemo } from './NormalLayout';
-import { SortedTable } from './SortedTable';
-import { SortedTableWithStatic } from './StaticHeader';
-
-ReactDOM.render(React.createElement(
-    'div',
-    null,
-    React.createElement(LayoutDemo, null),
-    React.createElement(SortedTable, null),
-    React.createElement(SortedTableWithStatic, null)
-), document.getElementById('root'));
-
-document.body.addEventListener('touchmove', function (event) {
-    event.preventDefault();
-}, false);
-
-// const ThemeContext = React.createContext();
-
-// class ThemeProvider extends React.Component {
-//     state = {
-//         theme: "dark",
-//         color: "blue"
-//     };
-
-//     changeTheme = theme => {
-//         this.setState({
-//             theme
-//         });
-//     };
-
-//     changeColor = color => {
-//         this.setState({
-//             color
-//         });
-//     };
-
-//     render() {
-//         return (
-//             <ThemeContext.Provider
-//                 value={{
-//                     theme: this.state.theme,
-//                     color: this.state.color,
-//                     changeColor: this.changeColor
-//                 }}
-//             >
-//                 <button onClick={() => this.changeTheme("light")}>change theme</button>
-//                 {this.props.children}
-//             </ThemeContext.Provider>
-//         );
-//     }
-// }
-// const SubComponent = props => (
-//     <div>
-//         <div>{props.theme}</div>
-//         <button onClick={() => props.changeColor("red")}>change color</button>
-//         <div>{props.color}</div>
-//         <ThemeContext.Consumer>
-//             {context => (
-//                 <div>{context.theme}{context.color}{context.changeColor}
-//                 </div>
-//             )}
-//         </ThemeContext.Consumer>
-//     </div>
-// );
-// class App extends React.Component {
-//     render() {
-//         return (
-//             <ThemeProvider>
-//                 <ThemeContext.Consumer>
-//                     {context => (
-//                         <SubComponent
-//                             theme={context.theme}
-//                             color={context.color}
-//                             changeColor={context.changeColor}
-//                         />
-//                     )}
-//                 </ThemeContext.Consumer>
-//             </ThemeProvider>
-//         );
-//     }
-// }
-
-// ReactDOM.render(<App />, document.getElementById("root"));
-
-;
-
-var _temp = function () {
-    if (typeof __REACT_HOT_LOADER__ === 'undefined') {
-        return;
-    }
-}();
-
-;

File diff suppressed because it is too large
+ 0 - 5
build/react-dragger-layout.js


+ 0 - 11
build/style.css

@@ -1,11 +0,0 @@
-/* .shit:hover{
-    width: 100px;
-    height: 100px;
-} */
-
-.WrapDragger{
-    display: flex;
-    align-items: center;
-    justify-content: center;
-
-}

+ 0 - 72
build/utils.js

@@ -1,72 +0,0 @@
-export var int = function int(number) {
-    if (number === '') {
-        return 0;
-    }
-    return parseInt(number, 10);
-};
-export var innerWidth = function innerWidth(node) {
-    var width = node.clientWidth;
-    var computedStyle = node.style;
-    width -= int(computedStyle.paddingLeft);
-    width -= int(computedStyle.paddingRight);
-    return width;
-};
-
-export var outerWidth = function outerWidth(node) {
-    var width = node.clientWidth;
-    var computedStyle = node.style;
-    width += int(computedStyle.borderLeftWidth);
-    width += int(computedStyle.borderRightWidth);
-    return width;
-};
-
-export var innerHeight = function innerHeight(node) {
-    var height = node.clientHeight;
-    var computedStyle = node.style;
-    height -= int(computedStyle.paddingTop);
-    height -= int(computedStyle.paddingBottom);
-    return height;
-};
-
-export var outerHeight = function outerHeight(node) {
-    var height = node.clientHeight;
-    var computedStyle = node.style;
-    height += int(computedStyle.borderTopWidth);
-    height += int(computedStyle.borderBottomWidth);
-    return height;
-};
-export var parseBounds = function parseBounds(bounds) {
-    return {
-        left: bounds.left,
-        top: bounds.top,
-        right: bounds.right,
-        bottom: bounds.bottom
-    };
-};
-
-export var isNumber = function isNumber(things) {
-    return typeof things === 'number' ? true : false;
-};
-;
-
-var _temp = function () {
-    if (typeof __REACT_HOT_LOADER__ === 'undefined') {
-        return;
-    }
-
-    __REACT_HOT_LOADER__.register(int, 'int', 'app/src/utils.js');
-
-    __REACT_HOT_LOADER__.register(innerWidth, 'innerWidth', 'app/src/utils.js');
-
-    __REACT_HOT_LOADER__.register(outerWidth, 'outerWidth', 'app/src/utils.js');
-
-    __REACT_HOT_LOADER__.register(innerHeight, 'innerHeight', 'app/src/utils.js');
-
-    __REACT_HOT_LOADER__.register(outerHeight, 'outerHeight', 'app/src/utils.js');
-
-    __REACT_HOT_LOADER__.register(parseBounds, 'parseBounds', 'app/src/utils.js');
-
-    __REACT_HOT_LOADER__.register(isNumber, 'isNumber', 'app/src/utils.js');
-}();
-
-;

+ 0 - 0
app/src/App.js → deprecated/App.js


+ 0 - 0
app/src/Dragger.js → deprecated/Dragger.js


+ 0 - 0
app/src/GridItem.js → deprecated/GridItem.js


+ 0 - 0
app/src/util/collison.js → deprecated/collison.js


+ 1 - 1
app/src/util/correction.js → deprecated/correction.js

@@ -1,4 +1,4 @@
-import { collision } from "./collison";
+import { collision, layoutCheck } from "./collison";
 
 
 export const checkInContainer = (GridX, GridY, col, w) => {

+ 21 - 0
deprecated/index.js

@@ -0,0 +1,21 @@
+'use strict'
+import React from 'react';
+import ReactDOM from 'react-dom';
+import { LayoutDemo } from './NormalLayout';
+import { SortedTable } from './SortedTable';
+import { SortedTableWithStatic } from './StaticHeader';
+
+
+
+ReactDOM.render(
+    <div>
+        <LayoutDemo />
+        <SortedTable />
+        <SortedTableWithStatic />
+    </div>,
+    document.getElementById('root')
+);
+
+document.body.addEventListener('touchmove', function (event) {
+    event.preventDefault();
+}, false);

+ 0 - 0
app/src/util/initiate.js → deprecated/initiate.js


+ 0 - 0
app/src/util/compact.js → deprecated/r-compact.js


+ 0 - 0
app/src/util/sort.js → deprecated/sort.js


+ 0 - 0
app/src/utils.js → deprecated/utils.js


File diff suppressed because it is too large
+ 815 - 5
package-lock.json


+ 5 - 0
package.json

@@ -12,6 +12,7 @@
   "author": "Fangzheng",
   "license": "MIT",
   "devDependencies": {
+    "awesome-typescript-loader": "^3.4.1",
     "babel-core": "^6.25.0",
     "babel-loader": "^7.0.0",
     "babel-preset-es2015": "^6.24.1",
@@ -20,11 +21,15 @@
     "css-loader": "^0.28.4",
     "extract-text-webpack-plugin": "^3.0.0",
     "react-hot-loader": "^3.0.0-beta.6",
+    "source-map-loader": "^0.2.3",
     "style-loader": "^0.18.2",
+    "typescript": "^2.7.2",
     "webpack": "^3.0.0",
     "webpack-dev-server": "^2.4.5"
   },
   "dependencies": {
+    "@types/react": "^16.0.38",
+    "@types/react-dom": "^16.0.4",
     "babel-plugin-transform-object-rest-spread": "^6.26.0",
     "babel-plugin-transform-react-jsx": "^6.24.1",
     "babel-plugin-transform-runtime": "^6.23.0",

+ 12 - 0
src/NormalLayout/index.css

@@ -0,0 +1,12 @@
+.layout-Item {
+    background: white;
+    height: 100%;
+}
+
+.layout-item:hover {
+    cursor: -webkit-grab;
+}
+
+.normal-layout {
+    background: #d9d9d9;
+}

+ 14 - 8
app/src/NormalLayout/index.js → src/NormalLayout/index.tsx

@@ -1,5 +1,12 @@
-import React from 'react';
-import { DraggerLayout } from '../App'
+import *as React from 'react';
+import { DraggerLayout } from '../lib/dragact'
+import './index.css';
+
+
+interface CardItem {
+    content: string,
+    img: string
+}
 
 const Words = [
     { content: 'You can do anything, but not everything.', img: 'http://pic.sc.chinaz.com/files/pic/pic9/201303/xpic10472.jpg' },
@@ -10,13 +17,12 @@ const Words = [
 ]
 
 
-const Card = ({ item }) => {
+const Card = (props: any) => {
+    const item: CardItem = props.item;
     return (
-        <div>
-            <div className='layout-item'>
-                <img src={item.img} style={{ width: '100%' }} draggable={false} alt='card'></img>
-                <div style={{ padding: 5, textAlign: 'center', color: '#595959' }}>{item.content}</div>
-            </div>
+        <div className='layout-Item'>
+            <img src={item.img} style={{ width: '100%', height: '60%' }} draggable={false} alt='card'></img>
+            <div style={{ padding: 5, textAlign: 'center', color: '#595959' }}>{item.content}</div>
         </div>
     )
 }

+ 0 - 0
app/src/SortedTable/index.css → src/SortedTable/index.css


+ 4 - 3
app/src/SortedTable/index.js → src/SortedTable/index.tsx

@@ -1,5 +1,5 @@
-import React from 'react';
-import { DraggerLayout } from '../App'
+import * as React from 'react';
+import { DraggerLayout } from '../lib/dragact'
 import './index.css'
 
 const Words = [
@@ -11,7 +11,8 @@ const Words = [
 ]
 
 
-const Cell = ({ item }) => {
+const Cell = (props: any) => {
+    const item = props.item;
     return (
         <div className='layout-Cell'>
             <img src={item.img} style={{ width: 45, height: 45 }} draggable={false} alt='card'></img>

+ 0 - 0
app/src/StaticHeader/index.css → src/StaticHeader/index.css


+ 5 - 4
app/src/StaticHeader/index.js → src/StaticHeader/index.tsx

@@ -1,5 +1,5 @@
-import React from 'react';
-import { DraggerLayout } from '../App'
+import * as React from 'react';
+import { DraggerLayout } from '../lib/dragact'
 import './index.css'
 
 const Words = [
@@ -11,7 +11,8 @@ const Words = [
 ]
 
 
-const Cell = ({ item }) => {
+const Cell = (props: any) => {
+    const { item } = props;
     return (
         <div className={`layout-Cell ${item.static ? "static" : ""}`} style={{ background: item.static ? "#e8e8e8" : "" }}>
             <img src={item.img} style={{ width: 45, height: 45 }} draggable={false} alt='card'></img>
@@ -27,7 +28,7 @@ export const SortedTableWithStatic = () => {
                 <h1 style={{ textAlign: 'center' }}>Static Header Table Demo</h1>
                 <DraggerLayout width={800} col={1} rowHeight={60} margin={[2, 2]} className='normal-layout'>
                     {Words.map((el, index) => {
-                        return <Cell item={el} key={index} data-set={{ GridX: 0, GridY: 0, w: 1, h: 1, static: index === 0 ? true : false }} />
+                        return <Cell item={el} key={index} data-set={{ GridX: 0, GridY: index, w: 1, h: 1, static: el.static }} />
                     })}
                 </DraggerLayout>
             </div>

+ 14 - 0
src/index.css

@@ -0,0 +1,14 @@
+.demo-button-layout {
+    display: flex;
+    flex-direction: column;
+    width: 120px;
+    position: fixed;
+}
+
+.demo-button-layout>button {
+    padding: 12px;
+    background-color: white;
+    margin-top: 2px;
+    border-radius: 5px;
+    border: 1pt solid #1890ff;
+}

+ 47 - 0
src/index.tsx

@@ -0,0 +1,47 @@
+import * as React from "react";
+import * as ReactDOM from "react-dom";
+import { LayoutDemo } from './NormalLayout/index';
+import { SortedTable } from "./SortedTable";
+import { SortedTableWithStatic } from "./StaticHeader";
+
+import './index.css'
+
+
+const DemoMap: any = {
+    normalLayout: <LayoutDemo />,
+    SortedTable: <SortedTable />,
+    StaticHeader: <SortedTableWithStatic />
+}
+
+class DemoDispatcher extends React.Component<{}, {}> {
+
+    state = {
+        demo: <LayoutDemo />
+    }
+
+    handleLayoutChange = (demoName: string) => {
+        this.setState({
+            demo: DemoMap[demoName]
+        })
+    }
+
+    render() {
+        return (
+            <div>
+                <div className='demo-button-layout'>
+                    <div>Switch Demos</div>
+                    <button onClick={() => this.handleLayoutChange('normalLayout')}>normalLayout</button>
+                    <button onClick={() => this.handleLayoutChange('SortedTable')}>SortedTable</button>
+                    <button onClick={() => this.handleLayoutChange('StaticHeader')}>StaticHeader</button>
+                </div>
+                {this.state.demo}
+            </div>
+        )
+    }
+}
+
+
+ReactDOM.render(
+    <DemoDispatcher />,
+    document.getElementById('root')
+);

+ 218 - 0
src/lib/dragact.tsx

@@ -0,0 +1,218 @@
+import * as React from "react";
+import GridItem, { GridItemEvent } from './GridItem'
+import { compactLayout } from './util/compact';
+import { getMaxContainerHeight } from './util/sort';
+import { layoutCheck } from './util/collison';
+import { correctLayout } from './util/correction';
+import { getDataSet, stringJoin } from './utils';
+import { layoutItemForkey, syncLayout, MapLayoutTostate } from './util/initiate';
+
+import './style.css';
+
+
+export interface DragactLayout {
+    GridX: number
+    GridY: number
+    static?: Boolean
+    w: number
+    h: number
+    isUserMove?: Boolean
+    key?: number | string
+}
+
+interface DragactProps {
+    layout?: DragactLayout[]
+    /**外部属性 */
+    col: number,
+    width: number,
+    /**每个元素的最小高度 */
+    rowHeight: number,
+    padding?: number,
+
+    children: any[]
+
+    onDragStart?: (event: GridItemEvent) => void
+    onDrag?: (event: GridItemEvent) => void
+    onDragEnd?: (key: number | string) => void
+
+    margin: [number, number]
+
+    className: number | string
+}
+
+interface DragactState {
+    GridXMoving: number
+    GridYMoving: number
+    wMoving: number
+    hMoving: number
+    placeholderShow: Boolean,
+    placeholderMoving: Boolean,
+    layout: DragactLayout[],
+    containerHeight: number
+}
+
+export class DraggerLayout extends React.Component<DragactProps, DragactState> {
+    constructor(props: DragactProps) {
+        super(props)
+        this.onDrag = this.onDrag.bind(this)
+        this.onDragStart = this.onDragStart.bind(this)
+        this.onDragEnd = this.onDragEnd.bind(this)
+
+
+        const layout = props.layout ?
+            MapLayoutTostate(props.layout, props.children)
+            :
+            getDataSet(props.children);
+
+        this.state = {
+            GridXMoving: 0,
+            GridYMoving: 0,
+            wMoving: 0,
+            hMoving: 0,
+            placeholderShow: false,
+            placeholderMoving: false,
+            layout: layout,
+            containerHeight: 500
+        }
+    }
+
+
+    onDragStart(bundles: GridItemEvent) {
+        const { GridX, GridY, w, h, UniqueKey } = bundles
+
+        const newlayout = syncLayout(this.state.layout, UniqueKey, GridX, GridY, true)
+
+        this.setState({
+            GridXMoving: GridX,
+            GridYMoving: GridY,
+            wMoving: w,
+            hMoving: h,
+            placeholderShow: true,
+            placeholderMoving: true,
+            layout: newlayout,
+        })
+        this.props.onDragStart && this.props.onDragStart(bundles)
+    }
+
+    onDrag(layoutItem: GridItemEvent) {
+
+        const { GridY, UniqueKey } = layoutItem
+        const moving = GridY - this.state.GridYMoving
+
+        const newLayout = layoutCheck(this.state.layout, layoutItem, UniqueKey, UniqueKey/*用户移动方块的key */, moving)
+        const compactedLayout = compactLayout(newLayout)
+        for (let i = 0; i < compactedLayout.length; i++) {
+            const compactedItem = compactedLayout[i];
+            if (UniqueKey === compactedItem.key) {
+                /**
+                 * 特殊点:当我们移动元素的时候,元素在layout中的位置不断改变
+                 * 但是当isUserMove=true的时候,鼠标拖拽的元素不会随着位图变化而变化
+                 * 但是实际layout中的位置还是会改变
+                 * (isUserMove=true用于解除placeholder和元素的绑定)
+                 */
+                compactedItem.isUserMove = true
+                layoutItem.GridX = compactedItem.GridX
+                layoutItem.GridY = compactedItem.GridY
+                break
+            }
+        }
+        this.setState({
+            GridXMoving: layoutItem.GridX,
+            GridYMoving: layoutItem.GridY,
+            layout: compactedLayout,
+            containerHeight: getMaxContainerHeight(compactedLayout, this.props.rowHeight, this.props.margin[1])
+        })
+        this.props.onDrag && this.props.onDrag(layoutItem);
+    }
+
+    onDragEnd(key: number | string) {
+        const compactedLayout = compactLayout(this.state.layout)
+        this.setState({
+            placeholderShow: false,
+            layout: compactedLayout,
+            containerHeight: getMaxContainerHeight(compactedLayout, this.props.rowHeight, this.props.margin[1])
+        })
+
+        this.props.onDragEnd && this.props.onDragEnd(key);
+    }
+    renderPlaceholder() {
+        if (!this.state.placeholderShow) return null
+        var { col, width, padding, rowHeight, margin } = this.props
+        const { GridXMoving, GridYMoving, wMoving, hMoving, placeholderMoving } = this.state
+
+        if (!padding) padding = 0;
+        return (
+            <GridItem
+                margin={margin}
+                col={col}
+                containerWidth={width}
+                containerPadding={[padding, padding]}
+                rowHeight={rowHeight}
+                GridX={GridXMoving}
+                GridY={GridYMoving}
+                w={wMoving}
+                h={hMoving}
+                style={{ background: '#d6e4ff', zIndex: 1, transition: ' all .15s' }}
+                isUserMove={!placeholderMoving}
+            />
+        )
+    }
+    componentDidMount() {
+        setTimeout(() => {
+            let layout = correctLayout(this.state.layout, this.props.col)
+            const compacted = compactLayout(layout);
+            this.setState({
+                layout: compacted,
+                containerHeight: getMaxContainerHeight(compacted, this.props.rowHeight, this.props.margin[1])
+            })
+        }, 1);
+    }
+
+    getGridItem(child: any, index: number) {
+        const { layout } = this.state
+        var { col, width, padding, rowHeight, margin } = this.props;
+        const renderItem = layoutItemForkey(layout, child.key);//TODO:可以优化速度,这一步不是必须;
+        if (renderItem) {
+            if (!padding) padding = 0;
+            return (
+                <GridItem
+                    margin={margin}
+                    col={col}
+                    containerWidth={width}
+                    containerPadding={[padding, padding]}
+                    rowHeight={rowHeight}
+                    GridX={renderItem.GridX}
+                    GridY={renderItem.GridY}
+                    w={renderItem.w}
+                    h={renderItem.h}
+                    onDrag={this.onDrag}
+                    onDragStart={this.onDragStart}
+                    onDragEnd={this.onDragEnd}
+                    isUserMove={renderItem.isUserMove !== void 666 ? renderItem.isUserMove : false}
+                    UniqueKey={child.key}
+                    style={{ zIndex: 2 }}
+                    static={renderItem.static}
+                >
+                    {child}
+                </GridItem >
+            )
+        }
+    }
+
+    render() {
+        const { width, className } = this.props;
+        const { containerHeight } = this.state;
+
+        return (
+            <div
+                className={stringJoin('DraggerLayout', className + '')}
+                style={{ left: 100, width: width, height: containerHeight, zIndex: 1 }}
+            >
+                {React.Children.map(this.props.children,
+                    (child, index) => this.getGridItem(child, index)
+                )}
+                {this.renderPlaceholder()}
+            </div>
+        )
+    }
+}

+ 318 - 0
src/lib/dragger/index.tsx

@@ -0,0 +1,318 @@
+import * as React from "react";
+import { int, innerHeight, innerWidth, outerHeight, outerWidth, parseBounds, Bound } from '../utils'
+/// <reference path="react.d.ts" />
+
+const doc = document
+
+
+
+interface DraggerProps {
+
+    className?: string;
+
+    /**
+    * 给予元素一个x,y的初始位置,单位是px
+    */
+    x?: number,
+    y?: number,
+
+    /** 
+     * 拖动范围限制
+     * 如果不规定范围,那么子元素就可以随意拖动不受限制
+     * 1.可以提供自定义的范围限制
+     * 2.也可以提供父类为边框的范围限制(string === parent)
+     */
+    bounds?: Bound | 'parent',
+
+    /**
+         * 以网格的方式移动,每次移动并不是平滑的移动
+         * [20,30],鼠标x轴方向移动了20 px ,y方向移动了30 px,整个子元素才会移动
+         */
+    grid?: [number, number],
+
+
+    /**只允许移动x轴 */
+    /**只允许移动y轴 */
+    allowX?: Boolean,
+    allowY?: Boolean,
+
+
+    /**
+    * 是否由用户移动
+    * 可能是通过外部props改变
+    */
+    isUserMove?: Boolean,
+
+    /**
+     * 生命周期回调
+     */
+    onDragStart?: (x: number, y: number) => void,
+    onMove?: (event: MouseEvent | TouchEvent, x: number, y: number) => void,
+    onDragEnd?: (event: MouseEvent | TouchEvent) => void,
+
+    style?: React.CSSProperties
+}
+
+export class Dragger extends React.Component<DraggerProps, {}> {
+    parent: any;
+    self: any;
+
+    constructor(props: DraggerProps) {
+        super(props)
+        this.move = this.move.bind(this)
+        this.onDragEnd = this.onDragEnd.bind(this)
+        this.parent = null;
+        this.self = null;
+    }
+    /**
+     * 初始变量设置
+     */
+    static defaultProps = {
+        allowX: true,
+        allowY: true,
+        isUserMove: true
+    }
+
+    state = {
+        /** x轴位移,单位是px */
+        x: 0,
+
+        /** y轴位移,单位是px */
+        y: 0,
+
+        /**鼠标点击元素的原始位置,单位是px */
+        originX: 0,
+        originY: 0,
+
+        isUserMove: true,
+
+        /**已经移动的位移,单位是px */
+        lastX: 0,
+        lastY: 0,
+
+        /**堆叠的层级 */
+        zIndex: 1
+    }
+
+
+
+    move(event: MouseEvent | TouchEvent) {
+
+        let { lastX, lastY } = this.state
+        /*  event.client - this.state.origin 表示的是移动的距离,
+        *   elX表示的是原来已经有的位移
+        */
+
+
+        let deltaX, deltaY;
+        if (event.type.indexOf('mouse') >= 0) {
+            deltaX = (event as MouseEvent).clientX - this.state.originX + lastX
+            deltaY = (event as MouseEvent).clientY - this.state.originY + lastY
+        } else {
+            deltaX = (event as TouchEvent).touches[0].clientX - this.state.originX + lastX
+            deltaY = (event as TouchEvent).touches[0].clientY - this.state.originY + lastY
+        }
+
+        const { bounds } = this.props
+        if (bounds) {
+            /**
+            * 如果用户指定一个边界,那么在这里处理
+            */
+            let NewBounds = typeof bounds !== 'string' ? parseBounds(bounds) : bounds;
+
+            /**
+             * 网格式移动范围设定,永远移动 n 的倍数
+             * 注意:设定移动范围的时候,一定要在判断bounds之前,否则会造成bounds不对齐
+             */
+            const { grid } = this.props
+            if (Array.isArray(grid) && grid.length === 2) {
+                deltaX = Math.round(deltaX / grid[0]) * grid[0]
+                deltaY = Math.round(deltaY / grid[1]) * grid[1]
+            }
+
+            if (this.props.bounds === 'parent') {
+                NewBounds = {
+                    left: int(this.parent.style.paddingLeft) + int(this.self.style.marginLeft) - this.self.offsetLeft,
+                    top: int(this.parent.style.paddingTop) + int(this.self.style.marginTop) - this.self.offsetTop,
+                    right: innerWidth(this.parent) - outerWidth(this.self) - this.self.offsetLeft +
+                        int(this.parent.style.paddingRight) - int(this.self.style.marginRight),
+                    bottom: innerHeight(this.parent) - outerHeight(this.self) - this.self.offsetTop +
+                        int(this.parent.style.paddingBottom) - int(this.self.style.marginBottom)
+                }
+            }
+
+            /**
+             * 保证不超出右边界和底部
+             * keep element right and bot can not cross the bounds
+             */
+            if (NewBounds !== 'parent') deltaX = Math.min(deltaX, NewBounds.right)
+            if (NewBounds !== 'parent') deltaY = Math.min(deltaY, NewBounds.bottom)
+
+
+            /**
+             * 保证不超出左边和上边
+             * keep element left and top can not cross the bounds
+             */
+            if (NewBounds !== 'parent') deltaX = Math.max(deltaX, NewBounds.left)
+            if (NewBounds !== 'parent') deltaY = Math.max(deltaY, NewBounds.top)
+        }
+
+
+        /**如果设置了x,y限制 */
+        deltaX = this.props.allowX ? deltaX : 0
+        deltaY = this.props.allowY ? deltaY : 0
+
+        /**移动时回调,用于外部控制 */
+        if (this.props.onMove) this.props.onMove(event, deltaX, deltaY)
+
+        this.setState({
+            x: deltaX,
+            y: deltaY
+        })
+    }
+
+    onDragStart(event: MouseEvent | TouchEvent) {
+        /** 保证用户在移动元素的时候不会选择到元素内部的东西 */
+        doc.body.style.userSelect = 'none'
+
+        // if (this.props.hasDraggerHandle) {
+        //     if (event.target.className !== 'handle') return
+        // }
+
+        /**
+         * 把监听事件的回掉函数,绑定在document上
+         * 当设置边界的时候,用户鼠标会离开元素的范围
+         * 绑定在document上可以使得其依旧能够监听
+         * 如果绑定在元素上,则鼠标离开元素,就不会再被监听了
+         */
+        if (event.type.indexOf('mouse') >= 0) {
+            doc.addEventListener('mousemove', this.move);
+            doc.addEventListener('mouseup', this.onDragEnd);
+        } else {
+            doc.addEventListener('touchmove', this.move)
+            doc.addEventListener('touchend', this.onDragEnd)
+        }
+
+        if (this.props.bounds === 'parent' &&
+            /**为了让 这段代码不会重复执行 */
+            (typeof this.parent === 'undefined' || this.parent === null)) {
+            /**
+             * 在这里我们将父节点缓存下来,保证当用户鼠标离开拖拽区域时,我们仍然能获取到父节点
+             * what we do here is 
+             * making sure that we still can retrieve our parent when user's mouse left this node.
+             */
+
+            this.parent = (event as any).currentTarget.offsetParent //todo
+
+            /**
+             * 我们自己
+             * ourself
+             */
+            this.self = event.currentTarget
+        }
+
+        this.props.onDragStart && this.props.onDragStart(this.state.x, this.state.y)
+
+
+        let originX, originY;
+        if (event.type.indexOf('mouse') >= 0) {
+            originX = (event as MouseEvent).clientX
+            originY = (event as MouseEvent).clientY
+        } else {
+            originX = (event as TouchEvent).touches[0].clientX
+            originY = (event as TouchEvent).touches[0].clientY
+        }
+
+        this.setState({
+            originX: originX,
+            originY: originY,
+            lastX: this.state.x,
+            lastY: this.state.y,
+            zIndex: 10
+        })
+    }
+
+    onDragEnd(event: MouseEvent | TouchEvent) {
+        /** 取消用户选择限制,用户可以重新选择 */
+        doc.body.style.userSelect = ''
+        this.parent = null
+        this.self = null
+
+        if (event.type.indexOf('mouse') >= 0) {
+            doc.removeEventListener('mousemove', this.move)
+            doc.removeEventListener('mouseup', this.onDragEnd)
+        } else {
+            doc.removeEventListener('touchmove', this.move)
+            doc.removeEventListener('touchend', this.onDragEnd)
+        }
+
+        this.setState({
+            zIndex: 1
+        })
+
+        this.props.onDragEnd && this.props.onDragEnd(event)
+    }
+
+    componentDidMount() {
+        /** 
+         * 这个函数只会调用一次 
+         * 这个只是一个临时的解决方案,因为这样会使得元素进行两次刷新
+        */
+        if (typeof this.props.x === 'number' &&
+            typeof this.props.y === 'number') {
+            this.setState({
+                x: this.props.x,
+                y: this.props.y
+            })
+        }
+    }
+
+    componentWillReceiveProps(nextProps: DraggerProps) {
+        /**
+         * 外部props 改变的时候更新元素的内部位置
+         * 这个api设计其实很不好
+         * 以后可能会修改掉
+         */
+        const { isUserMove } = nextProps
+        if (!isUserMove) {
+            if (typeof nextProps.x === 'number' &&
+                typeof nextProps.y === 'number') {
+                this.setState({
+                    x: nextProps.x,
+                    y: nextProps.y,
+                    lastX: nextProps.x,
+                    lastY: nextProps.y
+                })
+            }
+        }
+    }
+
+    render() {
+        let { x, y, zIndex } = this.state
+        const { style, className } = this.props
+
+        if (!this.props.isUserMove) {
+            /**当外部设置其props的x,y初始属性的时候,我们在这里设置元素的初始位移 */
+            x = this.props.x ? this.props.x : 0
+            y = this.props.y ? this.props.y : 0
+        }
+
+        /**主要是为了让用户定义自己的className去修改css */
+        const fixedClassName = typeof className === 'undefined' ? '' : className + ' '
+        return (
+            <div className={`${fixedClassName}WrapDragger`}
+                style={{ ...style, zIndex: zIndex, touchAction: 'none!important', transform: `translate(${x}px,${y}px)` }}
+                onMouseDown={this.onDragStart.bind(this)}
+                onTouchStart={this.onDragStart.bind(this)}
+                onTouchEnd={this.onDragEnd.bind(this)}
+                onMouseUp={this.onDragEnd.bind(this)}
+            >
+                {/**
+             *
+             *  React.Children.only 只允许子元素有一个根节点
+             */}
+                {React.Children.only(this.props.children)}
+            </div>
+        )
+    }
+}

+ 178 - 0
src/lib/gridItem.tsx

@@ -0,0 +1,178 @@
+import * as React from "react";
+import { Dragger } from './dragger/index'
+import { checkInContainer } from './util/correction';
+import { Bound } from './utils'
+
+
+export interface GridItemProps {
+    /**外部容器属性 */
+    col: number,
+    containerWidth: number,
+    containerPadding: [number, number],
+
+    /**子元素的属性 */
+    margin?: [number, number],
+    GridX: number,
+    GridY: number,
+    rowHeight: number,
+
+    /**子元素的宽高 */
+    w: number,
+    h: number,
+
+    /**生命周期回掉函数 */
+    onDragStart?: (event: GridItemEvent) => void,
+    onDragEnd?: (key: string | number) => void,
+    onDrag?: (event: GridItemEvent) => void
+
+    isUserMove: Boolean
+
+    UniqueKey?: string | number
+
+    static?: Boolean
+
+    style?: React.CSSProperties
+
+    bounds?: Bound | 'parent'
+}
+
+export interface GridItemEvent {
+    event: any
+    GridX: number
+    GridY: number
+    w: number
+    h: number
+    UniqueKey: string | number
+}
+
+
+export default class GridItem extends React.Component<GridItemProps, {}> {
+    constructor(props: GridItemProps) {
+        super(props)
+        this.onDrag = this.onDrag.bind(this)
+        this.onDragStart = this.onDragStart.bind(this)
+        this.onDragEnd = this.onDragEnd.bind(this)
+        this.calGridXY = this.calGridXY.bind(this)
+        this.calColWidth = this.calColWidth.bind(this)
+    }
+
+
+    static defaultProps = {
+        col: 12,
+        containerWidth: 500,
+        containerPadding: [0, 0],
+        margin: [10, 10],
+        rowHeight: 30,
+        w: 1,
+        h: 1
+    }
+
+    /** 计算容器的每一个格子多大 */
+    calColWidth() {
+        const { containerWidth, col, containerPadding, margin } = this.props;
+
+        if (margin) {
+            return (containerWidth - containerPadding[0] * 2 - margin[0] * (col + 1)) / col
+        }
+        return (containerWidth - containerPadding[0] * 2 - 0 * (col + 1)) / col
+    }
+
+    /**转化,计算网格的GridX,GridY值 */
+    calGridXY(x: number, y: number) {
+        const { margin, containerWidth, col, w, rowHeight } = this.props
+
+        /**坐标转换成格子的时候,无须计算margin */
+        let GridX = Math.round(x / containerWidth * col)
+        let GridY = Math.round(y / (rowHeight + (margin ? margin[1] : 0)))
+
+        // /**防止元素出container */
+        return checkInContainer(GridX, GridY, col, w)
+    }
+
+
+    /**给予一个grid的位置,算出元素具体的在容器中位置在哪里,单位是px */
+    calGridItemPosition(GridX: number, GridY: number) {
+        var { margin, rowHeight } = this.props
+
+        if (!margin) margin = [0, 0];
+
+        let x = Math.round(GridX * this.calColWidth() + (GridX + 1) * margin[0])
+        let y = Math.round(GridY * rowHeight + margin[1] * (GridY + 1))
+
+
+        return {
+            x: x,
+            y: y
+        }
+    }
+
+
+    shouldComponentUpdate(props: GridItemProps, state: any) {
+
+        return this.props.GridX !== props.GridX ||
+            this.props.GridY !== props.GridY ||
+            this.props.isUserMove !== props.isUserMove
+    }
+
+    /**宽和高计算成为px */
+    calWHtoPx(w: number, h: number) {
+        var { margin } = this.props
+
+        if (!margin) margin = [0, 0];
+        const wPx = Math.round(w * this.calColWidth() + (w - 1) * margin[0])
+        const hPx = Math.round(h * this.props.rowHeight + (h - 1) * margin[1])
+
+        return { wPx, hPx }
+    }
+
+    onDragStart(x: number, y: number) {
+        const { w, h, UniqueKey } = this.props;
+        if (this.props.static) return;
+
+        const { GridX, GridY } = this.calGridXY(x, y)
+
+        this.props.onDragStart && this.props.onDragStart({
+            event, GridX, GridY, w, h, UniqueKey: UniqueKey + ''
+        })
+    }
+    onDrag(event: any, x: number, y: number) {
+        if (this.props.static) return;
+        const { GridX, GridY } = this.calGridXY(x, y)
+        const { w, h, UniqueKey } = this.props
+        this.props.onDrag && this.props.onDrag({ GridX, GridY, w, h, UniqueKey: UniqueKey + '', event })
+    }
+
+    onDragEnd() {
+        if (this.props.static) return;
+        if (this.props.onDragEnd) this.props.onDragEnd(this.props.UniqueKey + '')
+    }
+
+    render() {
+
+        const { w, h, style, bounds, GridX, GridY } = this.props
+        const { x, y } = this.calGridItemPosition(GridX, GridY)
+        const { wPx, hPx } = this.calWHtoPx(w, h);
+
+
+        return (
+            <Dragger
+                style={{
+                    ...style, width: wPx, height: hPx, position: 'absolute',
+                    transition: this.props.isUserMove ? '' : 'all .2s'
+                }}
+
+                onDragStart={this.onDragStart}
+                onMove={this.onDrag}
+                onDragEnd={this.onDragEnd}
+                x={x}
+                y={y}
+                isUserMove={this.props.isUserMove}
+                bounds={bounds}
+            >
+                <div style={{ width: wPx, height: hPx }}>
+                    {React.Children.map(this.props.children, (child) => child)}
+                </div>
+            </Dragger>
+        )
+    }
+}

+ 0 - 12
app/src/style.css → src/lib/style.css

@@ -18,15 +18,3 @@ body {
     background: white;
 }
 
-.normal-layout {
-    background: #d9d9d9;
-}
-
-.layout-item {
-    background: white;
-    height: 100%;
-}
-
-.layout-item:hover {
-    cursor: -webkit-grab;
-}

+ 102 - 0
src/lib/util/collison.ts

@@ -0,0 +1,102 @@
+import { DragactLayout } from "../dragact";
+import { GridItemEvent } from "../gridItem";
+
+export const collision = (a: DragactLayout, b: DragactLayout) => {
+    if (a.GridX === b.GridX && a.GridY === b.GridY &&
+        a.w === b.w && a.h === b.h) {
+        return true
+    }
+    if (a.GridX + a.w <= b.GridX) return false
+    if (a.GridX >= b.GridX + b.w) return false
+    if (a.GridY + a.h <= b.GridY) return false
+    if (a.GridY >= b.GridY + b.h) return false
+    return true
+}
+
+
+/**获取layout中,item第一个碰撞到的物体 */
+export const getFirstCollison = (layout: DragactLayout[], item: DragactLayout) => {
+    for (let i = 0, length = layout.length; i < length; i++) {
+        if (collision(layout[i], item)) {
+            return layout[i]
+        }
+    }
+    return null
+}
+
+export const layoutCheck = (layout: DragactLayout[], layoutItem: GridItemEvent,
+    key: string | number, fristItemkey: string | number, moving: number) => {
+
+    let i: any = [], movedItem: any = []/**收集所有移动过的物体 */
+    let newlayout = layout.map((item, idx) => {
+
+        if (item.key !== key) {
+            if (item.static) {
+                return item
+            }
+            if (collision(item, layoutItem)) {
+                i.push(item.key)
+                /**
+                 * 这里就是奇迹发生的地方,如果向上移动,那么必须注意的是
+                 * 一格一格的移动,而不是一次性移动
+                 */
+                let offsetY = item.GridY + 1
+
+                /**这一行也非常关键,当向上移动的时候,碰撞的元素必须固定 */
+                // if (moving < 0 && layoutItem.GridY > 0) offsetY = item.GridY
+
+                if (layoutItem.GridY > item.GridY && layoutItem.GridY < item.GridY + item.h) {
+                    /**
+                     * 元素向上移动时,元素的上面空间不足,则不移动这个元素
+                     * 当元素移动到GridY>所要向上交换的元素时,就不会进入这里,直接交换元素
+                     */
+                    offsetY = item.GridY
+                }
+                /**
+                 * 物体向下移动的时候
+                 */
+
+                if (moving > 0) {
+                    if (layoutItem.GridY + layoutItem.h < item.GridY) {
+                        let collision;
+                        let copy = { ...item }
+                        while (true) {
+                            let newLayout = layout.filter((item) => {
+                                if (item.key !== key && (item.key !== copy.key)) {
+                                    return item
+                                }
+                            })
+                            collision = getFirstCollison(newLayout, copy)
+                            if (collision) {
+                                offsetY = collision.GridY + collision.h
+                                break
+                            } else {
+                                copy.GridY--
+                            }
+                            if (copy.GridY < 0) {
+                                offsetY = 0
+                                break
+                            }
+                        }
+                    }
+                }
+
+                movedItem.push({ ...item, GridY: offsetY, isUserMove: false })
+                return { ...item, GridY: offsetY, isUserMove: false }
+            }
+        } else if (fristItemkey === key) {
+
+            /**永远保持用户移动的块是 isUserMove === true */
+            return { ...item, GridX: layoutItem.GridX, GridY: layoutItem.GridY, isUserMove: true }
+        }
+
+        return item
+    })
+    /** 递归调用,将layout中的所有重叠元素全部移动 */
+    const length = movedItem.length;
+    for (let c = 0; c < length; c++) {
+        newlayout = layoutCheck(newlayout, movedItem[c], i[c], fristItemkey, 0)
+    }
+    return newlayout
+}
+

+ 48 - 0
src/lib/util/compact.ts

@@ -0,0 +1,48 @@
+import { sortLayout } from "./sort";
+import { getFirstCollison } from "./collison";
+import { DragactLayout } from "../dragact";
+
+/**
+ * 压缩单个元素,使得每一个元素都会紧挨着边界或者相邻的元素
+ * @param {*} finishedLayout 压缩完的元素会放进这里来,用来对比之后的每一个元素是否需要压缩
+ * @param {*} item 
+ */
+export const compactItem = (finishedLayout: DragactLayout[], item: DragactLayout) => {
+    if (item.static) return item;
+    const newItem = { ...item }
+    if (finishedLayout.length === 0) {
+        return { ...newItem, GridY: 0 }
+    }
+    /**
+     * 类似一个递归调用
+     */
+    while (true) {
+        let FirstCollison = getFirstCollison(finishedLayout, newItem)
+        if (FirstCollison) {
+            /**第一次发生碰撞时,就可以返回了 */
+            newItem.GridY = FirstCollison.GridY + FirstCollison.h
+            return newItem
+        }
+        newItem.GridY--
+
+        if (newItem.GridY < 0) return { ...newItem, GridY: 0 }/**碰到边界的时候,返回 */
+    }
+
+}
+
+/**
+ * 压缩layout,使得每一个元素都会紧挨着边界或者相邻的元素
+ * @param {*} layout 
+ */
+export const compactLayout = (layout: DragactLayout[]) => {
+    let sorted = sortLayout(layout)
+    const needCompact = Array(layout.length)
+    const compareList = []
+    for (let i = 0, length = sorted.length; i < length; i++) {
+        let finished = compactItem(compareList, sorted[i])
+        finished.isUserMove = false
+        compareList.push(finished)
+        needCompact[i] = finished
+    }
+    return needCompact
+}

+ 35 - 0
src/lib/util/correction.ts

@@ -0,0 +1,35 @@
+import { collision, layoutCheck } from "./collison";
+import { DragactLayout } from "../dragact";
+import { GridItemEvent } from "../gridItem";
+
+
+export const checkInContainer = (GridX: number, GridY: number, col: number, w: number) => {
+    /**防止元素出container */
+    if (GridX + w > col - 1) GridX = col - w //右边界
+    if (GridX < 0) GridX = 0//左边界
+    if (GridY < 0) GridY = 0//上边界
+    return { GridX, GridY }
+}
+
+/**
+ * 这个函数会有副作用,不是纯函数,会改变item的Gridx和GridY
+ * @param {*} item 
+ */
+export const correctItem = (item: DragactLayout, col: number) => {
+    const { GridX, GridY } = checkInContainer(item.GridX, item.GridY, col, item.w)
+    item.GridX = GridX;
+    item.GridY = GridY;
+}
+export const correctLayout = (layout: DragactLayout[], col: number) => {
+    var copy = [...layout];
+    for (let i = 0; i < layout.length - 1; i++) {
+        correctItem(copy[i], col)
+        correctItem(copy[i + 1], col);
+
+        if (collision(copy[i], copy[i + 1])) {
+            copy = layoutCheck(copy, <GridItemEvent>copy[i], (<GridItemEvent>copy[i]).UniqueKey, (<GridItemEvent>copy[i]).UniqueKey, 0)
+        }
+    }
+
+    return copy;
+}

+ 53 - 0
src/lib/util/initiate.ts

@@ -0,0 +1,53 @@
+import { DragactLayout } from "../dragact";
+
+/**
+ * 把用户移动的块,标记为true
+ * @param {*} layout 
+ * @param {*} key 
+ * @param {*} GridX 
+ * @param {*} GridY 
+ * @param {*} isUserMove 
+ */
+export const syncLayout = (layout: DragactLayout[], key: number | string, GridX: number, GridY: number, isUserMove: Boolean) => {
+    const newlayout = layout.map((item) => {
+        if (item.key === key) {
+            item.GridX = GridX
+            item.GridY = GridY
+            item.isUserMove = isUserMove
+            return item
+        }
+        return item
+    })
+    return newlayout
+}
+
+
+/**
+ * 初始化的时候调用
+ * 会把isUserMove和key一起映射到layout中
+ * 不用用户设置
+ * @param {*} layout 
+ * @param {*} children 
+ */
+
+export const MapLayoutTostate = (layout: DragactLayout[], children: any[]) => {
+    return layout.map((child, index) => {
+        let newChild = { ...child, isUserMove: true, key: children[index].key, static: children[index].static }
+        return newChild
+    })
+}
+
+/**
+ * 用key从layout中拿出item
+ * @param {*} layout 输入进来的布局
+ * @param {*} key 
+ */
+export const layoutItemForkey = (layout: DragactLayout[], key: number) => {
+    for (let i = 0, length = layout.length; i < length; i++) {
+        if (key === layout[i].key) {
+            return layout[i]
+        }
+    }
+}
+
+

+ 27 - 0
src/lib/util/sort.ts

@@ -0,0 +1,27 @@
+import { DragactLayout } from "../dragact";
+
+export function quickSort(a: number[]): any {
+    return a.length <= 1 ? a : quickSort(a.slice(1).filter(item => item <= a[0])).concat(a[0], quickSort(a.slice(1).filter(item => item > a[0])));
+}
+
+export const sortLayout = (layout: any) => {
+    return [].concat(layout).sort((a: any, b: any) => {
+        if (a.GridY > b.GridY || (a.GridY === b.GridY && a.GridX > b.GridX)) {
+            if (a.static) return 0//为了静态,排序的时候尽量把静态的放在前面
+            return 1
+        } else if (a.GridY === b.GridY && a.GridX === b.GridX) {
+            return 0
+        }
+        return -1
+    })
+}
+
+export const getMaxContainerHeight = (layout: DragactLayout[], elementHeight = 30, elementMarginBottom = 10) => {
+    const ar = layout.map((item) => {
+        return item.GridY + item.h
+    })
+    const h = quickSort(ar)[ar.length - 1];
+    const height = h * (elementHeight + elementMarginBottom) + elementMarginBottom
+    return height
+}
+

+ 67 - 0
src/lib/utils.ts

@@ -0,0 +1,67 @@
+export const int = (number: string | null) => {
+    if (number === '' || number === null) {
+        return 0
+    }
+    return parseInt(number, 10)
+}
+export const innerWidth = (node: HTMLElement) => {
+    let width = node.clientWidth;
+    const computedStyle = node.style;
+
+    width -= int(computedStyle.paddingLeft);
+    width -= int(computedStyle.paddingRight);
+    return width;
+}
+
+export const outerWidth = (node: HTMLElement) => {
+    let width = node.clientWidth;
+    const computedStyle = node.style
+    width += int(computedStyle.borderLeftWidth);
+    width += int(computedStyle.borderRightWidth);
+    return width;
+}
+
+export const innerHeight = (node: HTMLElement) => {
+    let height = node.clientHeight;
+    const computedStyle = node.style
+    height -= int(computedStyle.paddingTop);
+    height -= int(computedStyle.paddingBottom);
+    return height;
+}
+
+export const outerHeight = (node: HTMLElement) => {
+    let height = node.clientHeight;
+    const computedStyle = node.style
+    height += int(computedStyle.borderTopWidth);
+    height += int(computedStyle.borderBottomWidth);
+    return height;
+}
+
+export interface Bound {
+    left: number,
+    top: number,
+    right: number,
+    bottom: number
+}
+export const parseBounds = (bounds: Bound) => {
+    return {
+        left: bounds.left,
+        top: bounds.top,
+        right: bounds.right,
+        bottom: bounds.bottom
+    }
+}
+
+export const isNumber = (things: any) => {
+    return typeof things === 'number' ? true : false
+}
+
+export const getDataSet = (children: any[]) => {
+    return children.map((child) => {
+        return { ...child.props['data-set'], isUserMove: true, key: child.key, }
+    })
+}
+
+export const stringJoin = (source: string, join: string) => {
+    return source + (join ? ` ${join}` : '')
+}

+ 19 - 0
tsconfig.json

@@ -0,0 +1,19 @@
+{
+    "compilerOptions": {
+        "module": "commonjs",
+        "target": "es5",
+        "noImplicitAny": true,
+        "sourceMap": false,
+        "outDir": "./dist",
+        "watch": false,
+        "noUnusedLocals": true,
+        "strict": true,
+        "experimentalDecorators": true,
+        "strictFunctionTypes": true,
+        "strictPropertyInitialization": false,
+        "jsx": "react"
+    },
+    "include": [
+        "src/**/*"
+    ]
+}

+ 12 - 3
webpack.config.js

@@ -6,7 +6,7 @@ module.exports = {
     entry: [
         'react-hot-loader/patch',
         'webpack/hot/only-dev-server',
-        './app/src/index.js'
+        './src/index.tsx'
     ],
     output: {
         path: resolve(__dirname, 'build'),//打包后的文件存放的地方
@@ -18,7 +18,10 @@ module.exports = {
         hot: true,
         publicPath: '/',
     },
-
+    resolve: {
+        // Add '.ts' and '.tsx' as resolvable extensions.
+        extensions: [".ts", ".tsx", ".js", ".json"]
+    },
     module: {
         rules: [
             {
@@ -32,6 +35,11 @@ module.exports = {
                 test: /\.css$/,
                 loader: 'style-loader!css-loader'//在webpack-dev中不能使用--hot
             },
+            // All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
+            { test: /\.tsx?$/, loader: "awesome-typescript-loader" },
+
+            // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
+            { enforce: "pre", test: /\.js$/, loader: "source-map-loader" }
 
         ]
     },
@@ -41,7 +49,8 @@ module.exports = {
         new webpack.optimize.UglifyJsPlugin({
             compress: {
                 warnings: false
-            }
+            },
+            
         }),
         new webpack.DefinePlugin({
             'process.env': {

+ 19 - 3
webpack.pro.config.js

@@ -5,7 +5,7 @@ module.exports = {
     entry: [
         // 'react-hot-loader/patch',
         // 'webpack/hot/only-dev-server',
-        './app/src/index.js'
+        './src/index.tsx'
     ],
     output: {
         path: resolve(__dirname, 'build'),//打包后的文件存放的地方
@@ -17,6 +17,10 @@ module.exports = {
         hot: true,
         publicPath: '/',
     },
+    resolve: {
+        // Add '.ts' and '.tsx' as resolvable extensions.
+        extensions: [".ts", ".tsx", ".js", ".json"]
+    },
     module: {
         rules: [
             {
@@ -33,6 +37,11 @@ module.exports = {
                 ],
                 exclude: /node_modules/
             },
+            // All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
+            { test: /\.tsx?$/, loader: "awesome-typescript-loader" },
+
+            // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
+            { enforce: "pre", test: /\.js$/, loader: "source-map-loader" }
         ],
     },
     plugins: [
@@ -40,8 +49,15 @@ module.exports = {
         // new webpack.NamedModulesPlugin(),
         new webpack.optimize.UglifyJsPlugin({
             compress: {
-                warnings: false
-            }
+                warnings: false,
+                comparisons: false,
+            },
+            output: {
+                comments: false,
+                // Turned on because emoji and regex is not minified properly using default
+                // https://github.com/facebookincubator/create-react-app/issues/2488
+                ascii_only: true,
+            },
         }),
         new webpack.DefinePlugin({
             'process.env': {

Some files were not shown because too many files changed in this diff