react-calendar-timeline
Advanced tools
Comparing version
@@ -10,2 +10,22 @@ # Change Log | ||
## [0.13.0] | ||
### Added | ||
- An option to add another sidebar to the right of the Timeline. @goooseman #80 | ||
- `itemRenderer` prop to allow specifying a custom component to render the items @nicocrm #103 | ||
- `groupRenderer` prop to allow specifying a custom component to render the groups @nicocrm #103 | ||
- `showCursorLine` prop to show a vertical line at the snap position @meikoudras | ||
- You can now select multiple items if you take control of the `selected` prop and the `onItemSelect` handler. @meengit #71 | ||
- Canvas context menu handler `onCanvasContextMenu` @meikoudras | ||
### Fixed | ||
- Calculate width when we receive sidebar width property @jmerriweather #75 | ||
- Avoid updating updateDimensions right after updateScrollCanvas @nicocrm #87 | ||
- Fix typo collision detection in stack() @nicocrm #96 | ||
- Remove dead code @signalwerk #101 | ||
- Disable cursor style by interactjs @bkniffler #89 | ||
- Fixed header width and Header label weekday support @meikoudras #66 | ||
### Changed | ||
- [Deprecated] To have content above the left sidebar, pass it in a `sidebarContent={<div />}` prop, not as children to the component. | ||
## [0.11.1] | ||
@@ -46,1 +66,2 @@ ### Fixed | ||
[0.11.1]: https://github.com/namespace-ee/react-calendar-timeline/compare/v0.11.0...v0.11.1 | ||
[0.13.0]: https://github.com/namespace-ee/react-calendar-timeline/compare/v0.11.1...v0.13.0 |
@@ -475,2 +475,12 @@ 'use strict'; | ||
}, { | ||
key: 'renderContent', | ||
value: function renderContent() { | ||
var Comp = this.props.itemRenderer; | ||
if (Comp) { | ||
return _react2.default.createElement(Comp, { item: this.props.item }); | ||
} else { | ||
return this.itemTitle; | ||
} | ||
} | ||
}, { | ||
key: 'render', | ||
@@ -514,3 +524,3 @@ value: function render() { | ||
{ className: 'rct-item-content' }, | ||
this.itemTitle | ||
this.renderContent() | ||
) | ||
@@ -550,3 +560,4 @@ ), | ||
// onResized: React.PropTypes.func, | ||
// onContextMenu: React.PropTypes.func | ||
// onContextMenu: React.PropTypes.func, | ||
// itemRenderer: React.PropTypes.func | ||
}; | ||
@@ -553,0 +564,0 @@ Item.defaultProps = { |
@@ -7,2 +7,4 @@ 'use strict'; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
@@ -51,3 +53,3 @@ | ||
value: function shouldComponentUpdate(nextProps, nextState) { | ||
return !((0, _utils.arraysEqual)(nextProps.groups, this.props.groups) && (0, _utils.arraysEqual)(nextProps.items, this.props.items) && nextProps.keys === this.props.keys && nextProps.canvasTimeStart === this.props.canvasTimeStart && nextProps.canvasTimeEnd === this.props.canvasTimeEnd && nextProps.canvasWidth === this.props.canvasWidth && nextProps.selectedItem === this.props.selectedItem && nextProps.lineHeight === this.props.lineHeight && nextProps.dragSnap === this.props.dragSnap && nextProps.minResizeWidth === this.props.minResizeWidth && nextProps.canChangeGroup === this.props.canChangeGroup && nextProps.canMove === this.props.canMove && nextProps.canResize === this.props.canResize && nextProps.canSelect === this.props.canSelect && nextProps.dimensionItems === this.props.dimensionItems && nextProps.topOffset === this.props.topOffset); | ||
return !((0, _utils.arraysEqual)(nextProps.groups, this.props.groups) && (0, _utils.arraysEqual)(nextProps.items, this.props.items) && nextProps.keys === this.props.keys && nextProps.canvasTimeStart === this.props.canvasTimeStart && nextProps.canvasTimeEnd === this.props.canvasTimeEnd && nextProps.canvasWidth === this.props.canvasWidth && nextProps.selectedItem === this.props.selectedItem && nextProps.selected === this.props.selected && nextProps.lineHeight === this.props.lineHeight && nextProps.dragSnap === this.props.dragSnap && nextProps.minResizeWidth === this.props.minResizeWidth && nextProps.canChangeGroup === this.props.canChangeGroup && nextProps.canMove === this.props.canMove && nextProps.canResize === this.props.canResize && nextProps.canSelect === this.props.canSelect && nextProps.dimensionItems === this.props.dimensionItems && nextProps.topOffset === this.props.topOffset); | ||
} | ||
@@ -69,2 +71,22 @@ }, { | ||
}, { | ||
key: 'isSelected', | ||
value: function isSelected(item, itemIdKey) { | ||
var _this2 = this; | ||
if (!this.props.selected) { | ||
return this.props.selectedItem === (0, _utils._get)(item, itemIdKey); | ||
} else { | ||
var _ret = function () { | ||
var target = (0, _utils._get)(item, itemIdKey); | ||
return { | ||
v: _this2.props.selected.find(function (value) { | ||
return value === target; | ||
}) | ||
}; | ||
}(); | ||
if ((typeof _ret === 'undefined' ? 'undefined' : _typeof(_ret)) === "object") return _ret.v; | ||
} | ||
} | ||
}, { | ||
key: 'getVisibleItems', | ||
@@ -84,3 +106,3 @@ value: function getVisibleItems(canvasTimeStart, canvasTimeEnd, groupOrders) { | ||
value: function render() { | ||
var _this2 = this; | ||
var _this3 = this; | ||
@@ -108,29 +130,30 @@ var _props = this.props, | ||
item: item, | ||
keys: _this2.props.keys, | ||
keys: _this3.props.keys, | ||
order: groupOrders[(0, _utils._get)(item, itemGroupKey)], | ||
dimensions: sortedDimensionItems[(0, _utils._get)(item, itemIdKey)].dimensions, | ||
selected: _this2.props.selectedItem === (0, _utils._get)(item, itemIdKey), | ||
canChangeGroup: (0, _utils._get)(item, 'canChangeGroup') !== undefined ? (0, _utils._get)(item, 'canChangeGroup') : _this2.props.canChangeGroup, | ||
canMove: (0, _utils._get)(item, 'canMove') !== undefined ? (0, _utils._get)(item, 'canMove') : _this2.props.canMove, | ||
canResizeLeft: canResizeLeft(item, _this2.props.canResize), | ||
canResizeRight: canResizeRight(item, _this2.props.canResize), | ||
canSelect: (0, _utils._get)(item, 'canSelect') !== undefined ? (0, _utils._get)(item, 'canSelect') : _this2.props.canSelect, | ||
useResizeHandle: _this2.props.useResizeHandle, | ||
topOffset: _this2.props.topOffset, | ||
groupHeights: _this2.props.groupHeights, | ||
groupTops: _this2.props.groupTops, | ||
canvasTimeStart: _this2.props.canvasTimeStart, | ||
canvasTimeEnd: _this2.props.canvasTimeEnd, | ||
canvasWidth: _this2.props.canvasWidth, | ||
lineHeight: _this2.props.lineHeight, | ||
dragSnap: _this2.props.dragSnap, | ||
minResizeWidth: _this2.props.minResizeWidth, | ||
onResizing: _this2.props.itemResizing, | ||
onResized: _this2.props.itemResized, | ||
moveResizeValidator: _this2.props.moveResizeValidator, | ||
onDrag: _this2.props.itemDrag, | ||
onDrop: _this2.props.itemDrop, | ||
onItemDoubleClick: _this2.props.onItemDoubleClick, | ||
onContextMenu: _this2.props.onItemContextMenu, | ||
onSelect: _this2.props.itemSelect }); | ||
selected: _this3.isSelected(item, itemIdKey), | ||
canChangeGroup: (0, _utils._get)(item, 'canChangeGroup') !== undefined ? (0, _utils._get)(item, 'canChangeGroup') : _this3.props.canChangeGroup, | ||
canMove: (0, _utils._get)(item, 'canMove') !== undefined ? (0, _utils._get)(item, 'canMove') : _this3.props.canMove, | ||
canResizeLeft: canResizeLeft(item, _this3.props.canResize), | ||
canResizeRight: canResizeRight(item, _this3.props.canResize), | ||
canSelect: (0, _utils._get)(item, 'canSelect') !== undefined ? (0, _utils._get)(item, 'canSelect') : _this3.props.canSelect, | ||
useResizeHandle: _this3.props.useResizeHandle, | ||
topOffset: _this3.props.topOffset, | ||
groupHeights: _this3.props.groupHeights, | ||
groupTops: _this3.props.groupTops, | ||
canvasTimeStart: _this3.props.canvasTimeStart, | ||
canvasTimeEnd: _this3.props.canvasTimeEnd, | ||
canvasWidth: _this3.props.canvasWidth, | ||
lineHeight: _this3.props.lineHeight, | ||
dragSnap: _this3.props.dragSnap, | ||
minResizeWidth: _this3.props.minResizeWidth, | ||
onResizing: _this3.props.itemResizing, | ||
onResized: _this3.props.itemResized, | ||
moveResizeValidator: _this3.props.moveResizeValidator, | ||
onDrag: _this3.props.itemDrag, | ||
onDrop: _this3.props.itemDrop, | ||
onItemDoubleClick: _this3.props.onItemDoubleClick, | ||
onContextMenu: _this3.props.onItemContextMenu, | ||
onSelect: _this3.props.itemSelect, | ||
itemRenderer: _this3.props.itemRenderer }); | ||
}) | ||
@@ -172,5 +195,10 @@ ); | ||
onItemDoubleClick: _react.PropTypes.func, | ||
onItemContextMenu: _react.PropTypes.func | ||
onItemContextMenu: _react.PropTypes.func, | ||
itemRenderer: _react.PropTypes.func, | ||
selected: _react.PropTypes.array | ||
}; | ||
Items.defaultProps = {}; | ||
Items.defaultProps = { | ||
selected: [] | ||
}; | ||
var _default = Items; | ||
@@ -177,0 +205,0 @@ exports.default = _default; |
@@ -196,3 +196,5 @@ 'use strict'; | ||
headerLabelGroupHeight = _props.headerLabelGroupHeight, | ||
headerLabelHeight = _props.headerLabelHeight; | ||
headerLabelHeight = _props.headerLabelHeight, | ||
hasRightSidebar = _props.hasRightSidebar, | ||
width = _props.width; | ||
var scrollTop = this.state.scrollTop; | ||
@@ -220,3 +222,3 @@ | ||
href: '#', | ||
className: 'rct-label-group', | ||
className: 'rct-label-group' + (hasRightSidebar ? ' rct-has-right-sidebar' : ''), | ||
'data-time': time, | ||
@@ -249,3 +251,3 @@ 'data-unit': nextUnit, | ||
href: '#', | ||
className: 'rct-label ' + (twoHeaders ? '' : 'rct-label-only') + ' ' + (firstOfType ? 'rct-first-of-type' : '') + ' ', | ||
className: 'rct-label ' + (twoHeaders ? '' : 'rct-label-only') + ' ' + (firstOfType ? 'rct-first-of-type' : '') + ' ' + (minUnit !== 'month' ? 'rct-day-' + time.day() : '') + ' ', | ||
'data-time': time, | ||
@@ -276,3 +278,3 @@ 'data-unit': minUnit, | ||
headerStyle.position = 'fixed'; | ||
headerStyle.width = '100%'; | ||
headerStyle.width = width + 'px'; | ||
headerStyle.zIndex = zIndex; | ||
@@ -309,2 +311,3 @@ } else if (fixedHeader === 'absolute') { | ||
// headerBackgroundColor: React.PropTypes.string.isRequired, | ||
hasRightSidebar: _react2.default.PropTypes.bool.isRequired, | ||
showPeriod: _react2.default.PropTypes.func.isRequired, | ||
@@ -311,0 +314,0 @@ canvasTimeStart: _react2.default.PropTypes.number.isRequired, |
@@ -92,4 +92,15 @@ 'use strict'; | ||
}, { | ||
key: 'renderGroupContent', | ||
value: function renderGroupContent(group, isRightSidebar, groupTitleKey, groupRightTitleKey) { | ||
if (this.props.groupRenderer) { | ||
return _react2.default.createElement(this.props.groupRenderer, { group: group, isRightSidebar: isRightSidebar }); | ||
} else { | ||
return (0, _utils._get)(group, isRightSidebar ? groupRightTitleKey : groupTitleKey); | ||
} | ||
} | ||
}, { | ||
key: 'render', | ||
value: function render() { | ||
var _this3 = this; | ||
var _props = this.props, | ||
@@ -102,6 +113,8 @@ fixedHeader = _props.fixedHeader, | ||
height = _props.height, | ||
headerHeight = _props.headerHeight; | ||
headerHeight = _props.headerHeight, | ||
isRightSidebar = _props.isRightSidebar; | ||
var _props$keys = this.props.keys, | ||
groupIdKey = _props$keys.groupIdKey, | ||
groupTitleKey = _props$keys.groupTitleKey; | ||
groupTitleKey = _props$keys.groupTitleKey, | ||
groupRightTitleKey = _props$keys.groupRightTitleKey; | ||
var scrollTop = this.state.scrollTop; | ||
@@ -157,3 +170,3 @@ | ||
{ key: (0, _utils._get)(group, groupIdKey), className: 'rct-sidebar-row' + (i % 2 === 0 ? ' rct-sidebar-row-even' : ' rct-sidebar-row-odd'), style: elementStyle }, | ||
(0, _utils._get)(group, groupTitleKey) | ||
_this3.renderGroupContent(group, isRightSidebar, groupTitleKey, groupRightTitleKey) | ||
)); | ||
@@ -165,3 +178,3 @@ i += 1; | ||
'div', | ||
{ ref: 'sidebar', className: 'rct-sidebar', style: sidebarStyle }, | ||
{ ref: 'sidebar', className: 'rct-sidebar' + (isRightSidebar ? ' rct-sidebar-right' : ''), style: sidebarStyle }, | ||
header, | ||
@@ -191,3 +204,5 @@ _react2.default.createElement( | ||
keys: _react2.default.PropTypes.object.isRequired, | ||
children: _react2.default.PropTypes.node | ||
groupRenderer: _react2.default.PropTypes.func, | ||
children: _react2.default.PropTypes.node, | ||
isRightSidebar: _react2.default.PropTypes.bool | ||
}; | ||
@@ -197,3 +212,4 @@ Sidebar.defaultProps = { | ||
zIndex: 12, | ||
children: null | ||
children: null, | ||
isRightSidebar: false | ||
}; | ||
@@ -200,0 +216,0 @@ ; |
@@ -49,2 +49,6 @@ 'use strict'; | ||
var _CursorLine = require('./lines/CursorLine'); | ||
var _CursorLine2 = _interopRequireDefault(_CursorLine); | ||
var _utils = require('./utils.js'); | ||
@@ -65,2 +69,3 @@ | ||
groupTitleKey: 'title', | ||
groupRightTitleKey: 'rightTitle', | ||
itemIdKey: 'id', | ||
@@ -155,7 +160,7 @@ itemTitleKey: 'title', | ||
this.resize(); | ||
this.resize(this.props); | ||
this.resizeEventListener = { | ||
handleEvent: function handleEvent(event) { | ||
_this2.resize(); | ||
_this2.resize(_this2.props); | ||
} | ||
@@ -261,4 +266,3 @@ }; | ||
key: 'resize', | ||
value: function resize() { | ||
// FIXME currently when the component creates a scroll the scrollbar is not used in the initial width calculation, resizing fixes this | ||
value: function resize(props) { | ||
var _refs$container$getBo = this.refs.container.getBoundingClientRect(), | ||
@@ -268,5 +272,5 @@ containerWidth = _refs$container$getBo.width, | ||
var width = containerWidth - this.props.sidebarWidth; | ||
var width = containerWidth - props.sidebarWidth - props.rightSidebarWidth; | ||
var _stackItems = this.stackItems(this.props.items, this.props.groups, this.state.canvasTimeStart, this.state.visibleTimeStart, this.state.visibleTimeEnd, width), | ||
var _stackItems = this.stackItems(props.items, props.groups, this.state.canvasTimeStart, this.state.visibleTimeStart, this.state.visibleTimeEnd, width), | ||
dimensionItems = _stackItems.dimensionItems, | ||
@@ -321,3 +325,4 @@ height = _stackItems.height, | ||
items = nextProps.items, | ||
groups = nextProps.groups; | ||
groups = nextProps.groups, | ||
sidebarWidth = nextProps.sidebarWidth; | ||
@@ -327,6 +332,8 @@ | ||
this.updateScrollCanvas(visibleTimeStart, visibleTimeEnd, items !== this.props.items || groups !== this.props.groups, items, groups); | ||
} else if (items !== this.props.items || groups !== this.props.groups) { | ||
this.updateDimensions(items, groups); | ||
} | ||
if (items !== this.props.items || groups !== this.props.groups) { | ||
this.updateDimensions(items, groups); | ||
if (sidebarWidth && items && groups) { | ||
this.resize(nextProps); | ||
} | ||
@@ -511,2 +518,4 @@ } | ||
this.props.onItemSelect(item, e); | ||
} else if (item === null && this.props.onItemDeselect) { | ||
this.props.onItemDeselect(e); | ||
} | ||
@@ -607,3 +616,3 @@ } | ||
if (pageY - topOffset > headerHeight) { | ||
if (pageY - topOffset > headerHeight && e.button === 0) { | ||
this.setState({ isDragging: true, dragStartPosition: e.pageX, dragLastPosition: e.pageX }); | ||
@@ -633,2 +642,60 @@ } | ||
}, { | ||
key: '__handleCanvasMouseEnter__REACT_HOT_LOADER__', | ||
value: function __handleCanvasMouseEnter__REACT_HOT_LOADER__(e) { | ||
var showCursorLine = this.props.showCursorLine; | ||
if (showCursorLine) { | ||
this.setState({ mouseOverCanvas: true }); | ||
} | ||
if (this.props.onCanvasMouseEnter) { | ||
this.props.onCanvasMouseEnter(e); | ||
} | ||
} | ||
}, { | ||
key: '__handleCanvasMouseLeave__REACT_HOT_LOADER__', | ||
value: function __handleCanvasMouseLeave__REACT_HOT_LOADER__(e) { | ||
var showCursorLine = this.props.showCursorLine; | ||
if (showCursorLine) { | ||
this.setState({ mouseOverCanvas: false }); | ||
} | ||
if (this.props.onCanvasMouseLeave) { | ||
this.props.onCanvasMouseLeave(e); | ||
} | ||
} | ||
}, { | ||
key: '__handleCanvasMouseMove__REACT_HOT_LOADER__', | ||
value: function __handleCanvasMouseMove__REACT_HOT_LOADER__(e) { | ||
var showCursorLine = this.props.showCursorLine; | ||
var _state3 = this.state, | ||
canvasTimeStart = _state3.canvasTimeStart, | ||
width = _state3.width, | ||
visibleTimeStart = _state3.visibleTimeStart, | ||
visibleTimeEnd = _state3.visibleTimeEnd, | ||
cursorTime = _state3.cursorTime; | ||
var zoom = visibleTimeEnd - visibleTimeStart; | ||
var canvasTimeEnd = canvasTimeStart + zoom * 3; | ||
var canvasWidth = width * 3; | ||
var pageX = e.pageX; | ||
var ratio = (canvasTimeEnd - canvasTimeStart) / canvasWidth; | ||
var boundingRect = this.refs.scrollComponent.getBoundingClientRect(); | ||
var timePosition = visibleTimeStart + ratio * (pageX - boundingRect.left); | ||
if (this.props.dragSnap) { | ||
timePosition = Math.round(timePosition / this.props.dragSnap) * this.props.dragSnap; | ||
} | ||
if (this.props.onCanvasMouseMove) { | ||
this.props.onCanvasMouseMove(e); | ||
} | ||
if (cursorTime !== timePosition && showCursorLine) { | ||
this.setState({ cursorTime: timePosition, mouseOverCanvas: true }); | ||
} | ||
} | ||
}, { | ||
key: 'todayLine', | ||
@@ -646,2 +713,15 @@ value: function todayLine(canvasTimeStart, zoom, canvasTimeEnd, canvasWidth, minUnit, height, headerHeight) { | ||
}, { | ||
key: 'cursorLine', | ||
value: function cursorLine(cursorTime, canvasTimeStart, zoom, canvasTimeEnd, canvasWidth, minUnit, height, headerHeight) { | ||
return _react2.default.createElement(_CursorLine2.default, { cursorTime: cursorTime, | ||
canvasTimeStart: canvasTimeStart, | ||
canvasTimeEnd: canvasTimeEnd, | ||
canvasWidth: canvasWidth, | ||
lineHeight: this.props.lineHeight, | ||
lineCount: (0, _utils._length)(this.props.groups), | ||
height: height, | ||
headerHeight: headerHeight | ||
}); | ||
} | ||
}, { | ||
key: 'verticalLines', | ||
@@ -703,3 +783,5 @@ value: function verticalLines(canvasTimeStart, zoom, canvasTimeEnd, canvasWidth, minUnit, timeSteps, height, headerHeight) { | ||
itemResizing: this.resizingItem, | ||
itemResized: this.resizedItem }); | ||
itemResized: this.resizedItem, | ||
itemRenderer: this.props.itemRenderer, | ||
selected: this.props.selected }); | ||
} | ||
@@ -723,2 +805,3 @@ }, { | ||
return _react2.default.createElement(_Header2.default, { canvasTimeStart: canvasTimeStart, | ||
hasRightSidebar: this.props.rightSidebarWidth > 0, | ||
canvasTimeEnd: canvasTimeEnd, | ||
@@ -745,2 +828,3 @@ canvasWidth: canvasWidth, | ||
{ groups: this.props.groups, | ||
groupRenderer: this.props.groupRenderer, | ||
keys: this.props.keys, | ||
@@ -756,6 +840,26 @@ | ||
zIndex: this.props.zIndexStart + 2 }, | ||
this.props.children | ||
this.props.sidebarContent || this.props.children | ||
); | ||
} | ||
}, { | ||
key: 'rightSidebar', | ||
value: function rightSidebar(height, groupHeights, headerHeight) { | ||
return _react2.default.createElement( | ||
_Sidebar2.default, | ||
{ groups: this.props.groups, | ||
keys: this.props.keys, | ||
isRightSidebar: true, | ||
width: this.props.rightSidebarWidth, | ||
lineHeight: this.props.lineHeight, | ||
groupHeights: groupHeights, | ||
height: height, | ||
headerHeight: headerHeight, | ||
fixedHeader: this.props.fixedHeader, | ||
zIndex: this.props.zIndexStart + 2 }, | ||
this.props.rightSidebarContent | ||
); | ||
} | ||
}, { | ||
key: 'stackItems', | ||
@@ -772,9 +876,9 @@ value: function stackItems(items, groups, canvasTimeStart, visibleTimeStart, visibleTimeEnd, width) { | ||
itemHeightRatio = _props4.itemHeightRatio; | ||
var _state3 = this.state, | ||
draggingItem = _state3.draggingItem, | ||
dragTime = _state3.dragTime, | ||
resizingItem = _state3.resizingItem, | ||
resizingEdge = _state3.resizingEdge, | ||
resizeTime = _state3.resizeTime, | ||
newGroupOrder = _state3.newGroupOrder; | ||
var _state4 = this.state, | ||
draggingItem = _state4.draggingItem, | ||
dragTime = _state4.dragTime, | ||
resizingItem = _state4.resizingItem, | ||
resizingEdge = _state4.resizingEdge, | ||
resizeTime = _state4.resizeTime, | ||
newGroupOrder = _state4.newGroupOrder; | ||
@@ -829,9 +933,9 @@ var zoom = visibleTimeEnd - visibleTimeStart; | ||
value: function __handleDoubleClick__REACT_HOT_LOADER__(e) { | ||
var _state4 = this.state, | ||
canvasTimeStart = _state4.canvasTimeStart, | ||
width = _state4.width, | ||
visibleTimeStart = _state4.visibleTimeStart, | ||
visibleTimeEnd = _state4.visibleTimeEnd, | ||
groupTops = _state4.groupTops, | ||
topOffset = _state4.topOffset; | ||
var _state5 = this.state, | ||
canvasTimeStart = _state5.canvasTimeStart, | ||
width = _state5.width, | ||
visibleTimeStart = _state5.visibleTimeStart, | ||
visibleTimeEnd = _state5.visibleTimeEnd, | ||
groupTops = _state5.groupTops, | ||
topOffset = _state5.topOffset; | ||
@@ -887,2 +991,62 @@ var zoom = visibleTimeEnd - visibleTimeStart; | ||
}, { | ||
key: '__handleCanvasContextMenu__REACT_HOT_LOADER__', | ||
value: function __handleCanvasContextMenu__REACT_HOT_LOADER__(e) { | ||
var _state6 = this.state, | ||
canvasTimeStart = _state6.canvasTimeStart, | ||
width = _state6.width, | ||
visibleTimeStart = _state6.visibleTimeStart, | ||
visibleTimeEnd = _state6.visibleTimeEnd, | ||
groupTops = _state6.groupTops, | ||
topOffset = _state6.topOffset; | ||
var zoom = visibleTimeEnd - visibleTimeStart; | ||
var canvasTimeEnd = canvasTimeStart + zoom * 3; | ||
var canvasWidth = width * 3; | ||
var pageX = e.pageX, | ||
pageY = e.pageY; | ||
var ratio = (canvasTimeEnd - canvasTimeStart) / canvasWidth; | ||
var boundingRect = this.refs.scrollComponent.getBoundingClientRect(); | ||
var timePosition = visibleTimeStart + ratio * (pageX - boundingRect.left); | ||
if (this.props.dragSnap) { | ||
timePosition = Math.round(timePosition / this.props.dragSnap) * this.props.dragSnap; | ||
} | ||
var groupIndex = 0; | ||
var _iteratorNormalCompletion2 = true; | ||
var _didIteratorError2 = false; | ||
var _iteratorError2 = undefined; | ||
try { | ||
for (var _iterator2 = Object.keys(groupTops)[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { | ||
var key = _step2.value; | ||
var item = groupTops[key]; | ||
if (pageY - topOffset > item) { | ||
groupIndex = parseInt(key, 10); | ||
} else { | ||
break; | ||
} | ||
} | ||
} catch (err) { | ||
_didIteratorError2 = true; | ||
_iteratorError2 = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion2 && _iterator2.return) { | ||
_iterator2.return(); | ||
} | ||
} finally { | ||
if (_didIteratorError2) { | ||
throw _iteratorError2; | ||
} | ||
} | ||
} | ||
if (this.props.onCanvasContextMenu) { | ||
e.preventDefault(); | ||
this.props.onCanvasContextMenu(this.props.groups[groupIndex], timePosition, e); | ||
} | ||
} | ||
}, { | ||
key: 'render', | ||
@@ -896,17 +1060,22 @@ value: function render() { | ||
sidebarWidth = _props5.sidebarWidth, | ||
timeSteps = _props5.timeSteps; | ||
var _state5 = this.state, | ||
draggingItem = _state5.draggingItem, | ||
resizingItem = _state5.resizingItem, | ||
isDragging = _state5.isDragging, | ||
width = _state5.width, | ||
visibleTimeStart = _state5.visibleTimeStart, | ||
visibleTimeEnd = _state5.visibleTimeEnd, | ||
canvasTimeStart = _state5.canvasTimeStart; | ||
var _state6 = this.state, | ||
dimensionItems = _state6.dimensionItems, | ||
height = _state6.height, | ||
groupHeights = _state6.groupHeights, | ||
groupTops = _state6.groupTops; | ||
rightSidebarWidth = _props5.rightSidebarWidth, | ||
timeSteps = _props5.timeSteps, | ||
showCursorLine = _props5.showCursorLine; | ||
var _state7 = this.state, | ||
draggingItem = _state7.draggingItem, | ||
resizingItem = _state7.resizingItem, | ||
isDragging = _state7.isDragging, | ||
width = _state7.width, | ||
visibleTimeStart = _state7.visibleTimeStart, | ||
visibleTimeEnd = _state7.visibleTimeEnd, | ||
canvasTimeStart = _state7.canvasTimeStart, | ||
mouseOverCanvas = _state7.mouseOverCanvas, | ||
cursorTime = _state7.cursorTime; | ||
var _state8 = this.state, | ||
dimensionItems = _state8.dimensionItems, | ||
height = _state8.height, | ||
groupHeights = _state8.groupHeights, | ||
groupTops = _state8.groupTops; | ||
var zoom = visibleTimeEnd - visibleTimeStart; | ||
@@ -964,3 +1133,7 @@ var canvasTimeEnd = canvasTimeStart + zoom * 3; | ||
style: canvasComponentStyle, | ||
onDoubleClick: this.handleDoubleClick | ||
onDoubleClick: this.handleDoubleClick, | ||
onMouseEnter: this.handleCanvasMouseEnter, | ||
onMouseLeave: this.handleCanvasMouseLeave, | ||
onMouseMove: this.handleCanvasMouseMove, | ||
onContextMenu: this.handleCanvasContextMenu | ||
}, | ||
@@ -971,6 +1144,8 @@ this.items(canvasTimeStart, zoom, canvasTimeEnd, canvasWidth, minUnit, dimensionItems, groupHeights, groupTops), | ||
this.todayLine(canvasTimeStart, zoom, canvasTimeEnd, canvasWidth, minUnit, height, headerHeight), | ||
mouseOverCanvas && showCursorLine ? this.cursorLine(cursorTime, canvasTimeStart, zoom, canvasTimeEnd, canvasWidth, minUnit, height, headerHeight) : null, | ||
this.infoLabel(), | ||
this.header(canvasTimeStart, zoom, canvasTimeEnd, canvasWidth, minUnit, timeSteps, headerLabelGroupHeight, headerLabelHeight) | ||
) | ||
) | ||
), | ||
rightSidebarWidth > 0 ? this.rightSidebar(height, groupHeights, headerHeight) : null | ||
) | ||
@@ -988,2 +1163,5 @@ ); | ||
sidebarWidth: _react.PropTypes.number, | ||
sidebarContent: _react.PropTypes.node, | ||
rightSidebarWidth: _react.PropTypes.number, | ||
rightSidebarContent: _react.PropTypes.node, | ||
dragSnap: _react.PropTypes.number, | ||
@@ -1013,2 +1191,3 @@ minResizeWidth: _react.PropTypes.number, | ||
traditionalZoom: _react.PropTypes.bool, | ||
showCursorLine: _react.PropTypes.bool, | ||
@@ -1021,2 +1200,3 @@ itemTouchSendsClick: _react.PropTypes.bool, | ||
onItemSelect: _react.PropTypes.func, | ||
onItemDeselect: _react.PropTypes.func, | ||
onCanvasClick: _react.PropTypes.func, | ||
@@ -1026,4 +1206,10 @@ onItemDoubleClick: _react.PropTypes.func, | ||
onCanvasDoubleClick: _react.PropTypes.func, | ||
onCanvasContextMenu: _react.PropTypes.func, | ||
onCanvasMouseEnter: _react.PropTypes.func, | ||
onCanvasMouseLeave: _react.PropTypes.func, | ||
onCanvasMouseMove: _react.PropTypes.func, | ||
moveResizeValidator: _react.PropTypes.func, | ||
itemRenderer: _react.PropTypes.func, | ||
groupRenderer: _react.PropTypes.func, | ||
@@ -1046,6 +1232,9 @@ dayBackground: _react.PropTypes.func, | ||
children: _react.PropTypes.node | ||
children: _react.PropTypes.node, | ||
selected: _react.PropTypes.array | ||
}; | ||
ReactCalendarTimeline.defaultProps = { | ||
sidebarWidth: 150, | ||
rightSidebarWidth: 0, | ||
dragSnap: 1000 * 60 * 15, // 15min | ||
@@ -1075,2 +1264,3 @@ minResizeWidth: 20, | ||
traditionalZoom: false, | ||
showCursorLine: false, | ||
@@ -1081,5 +1271,9 @@ onItemMove: null, | ||
onItemSelect: null, | ||
onItemDeselect: null, | ||
onCanvasClick: null, | ||
onItemDoubleClick: null, | ||
onItemContextMenu: null, | ||
onCanvasMouseEnter: null, | ||
onCanvasMouseLeave: null, | ||
onCanvasMouseMove: null, | ||
@@ -1110,3 +1304,5 @@ moveResizeValidator: null, | ||
onBoundsChange: null, | ||
children: null | ||
children: null, | ||
selected: null | ||
}; | ||
@@ -1181,5 +1377,21 @@ | ||
this.handleCanvasMouseEnter = function () { | ||
return _this3.__handleCanvasMouseEnter__REACT_HOT_LOADER__.apply(_this3, arguments); | ||
}; | ||
this.handleCanvasMouseLeave = function () { | ||
return _this3.__handleCanvasMouseLeave__REACT_HOT_LOADER__.apply(_this3, arguments); | ||
}; | ||
this.handleCanvasMouseMove = function () { | ||
return _this3.__handleCanvasMouseMove__REACT_HOT_LOADER__.apply(_this3, arguments); | ||
}; | ||
this.handleDoubleClick = function () { | ||
return _this3.__handleDoubleClick__REACT_HOT_LOADER__.apply(_this3, arguments); | ||
}; | ||
this.handleCanvasContextMenu = function () { | ||
return _this3.__handleCanvasContextMenu__REACT_HOT_LOADER__.apply(_this3, arguments); | ||
}; | ||
}; | ||
@@ -1186,0 +1398,0 @@ |
@@ -202,3 +202,3 @@ 'use strict'; | ||
order: isDragging ? newGroupOrder : order, | ||
stack: true, | ||
stack: !item.isOverlay, | ||
collisionLeft: collisionX, | ||
@@ -205,0 +205,0 @@ originalLeft: itemTimeStart, |
{ | ||
"name": "react-calendar-timeline", | ||
"version": "0.12.0", | ||
"version": "0.13.0", | ||
"description": "react calendar timeline", | ||
@@ -8,3 +8,3 @@ "main": "lib/index.js", | ||
"scripts": { | ||
"build": "npm run build:lib && npm run build:demo", | ||
"build": "npm run build:lib", | ||
"build:demo": "echo '!!! Building Demo' && BABEL_ENV=react node build.js production", | ||
@@ -18,3 +18,3 @@ "build:lib": "echo '!!! Building Library' && ./node_modules/.bin/babel src --out-dir lib && ./node_modules/.bin/node-sass src/lib/Timeline.scss lib/lib/Timeline.css && sed -i'.bak' 's/Timeline\\.scss/Timeline\\.css/g' lib/lib/Timeline.js && rm lib/lib/Timeline.js.bak", | ||
"start": "./node_modules/.bin/webpack-dev-server --hot --host 0.0.0.0 --port 8080 --display-modules", | ||
"test": "npm run module && npm run jest && npm run lint" | ||
"test": "npm run build:lib && npm run jest && npm run lint" | ||
}, | ||
@@ -21,0 +21,0 @@ "files": [ |
@@ -75,6 +75,9 @@ # React Calendar Timeline | ||
id: 1, | ||
title: 'group 1' | ||
title: 'group 1', | ||
rightTitle: 'title in the right sidebar' | ||
} | ||
``` | ||
If you use right sidebar, you can pass optional `rightTitle` property here. | ||
### items | ||
@@ -101,2 +104,5 @@ Expects either a vanilla JS array or an immutableJS array, consisting of objects with the following attributes: | ||
### selected | ||
An array with id's corresponding to id's in items (`item.id`). If this prop is set you have to manage the selected items yourself within the `onItemSelect` handler to update the property with new id's. This overwrites the default behaviour of selecting one item on click. | ||
### keys | ||
@@ -108,2 +114,3 @@ An array specifying keys in the `items` and `groups` objects. Defaults to | ||
groupTitleKey: 'title', | ||
groupRightTitleKey: 'rightTitle', | ||
itemIdKey: 'id', | ||
@@ -119,4 +126,13 @@ itemTitleKey: 'title', // key for item div content | ||
### sidebarWidth | ||
Width of the sidebar in pixels. Defaults to `150`. | ||
Width of the sidebar in pixels. If set to `0`, the sidebar is not rendered. Defaults to `150`. | ||
### sidebarContent | ||
Everything passed here will be displayed above the left sidebar. Use this to display small filters or so. Defaults to `null`. | ||
### rightSidebarWidth | ||
Width of the right sidebar in pixels. If set to `0`, the right sidebar is not rendered. Defaults to `0`. | ||
### rightSidebarContent | ||
Everything passed here will be displayed above the right sidebar. Use this to display small filters or so. Defaults to `null`. | ||
### dragSnap | ||
@@ -180,2 +196,5 @@ Snapping unit when dragging items. Defaults to `15 * 60 * 1000` or 15min. When so, the items will snap to 15min intervals when dragging. | ||
### showCursorLine | ||
Show a vertical line at the snap point when you mouse over the calendar | ||
### stackItems | ||
@@ -217,14 +236,17 @@ Stack items under each other, so there is no visual overlap when times collide. Defaults to `false`. | ||
### onItemDoubleClick(itemId, e) | ||
Called when an item was double clicked | ||
### onItemContextMenu(itemId, e) | ||
Called when the item is clicked by the right button of the mouse. Note: If this property is set the default context menu doesn't appear | ||
### onCanvasClick(groupId, time, e) | ||
Called when an empty spot on the canvas was clicked. Get the group ID and the time as arguments. For example open a "new item" window after this. | ||
### onCanvasDoubleClick(groupId, time,e ) | ||
### onCanvasDoubleClick(groupId, time, e) | ||
Called when an empty spot on the canvas was double clicked. Get the group ID and the time as arguments. | ||
### onItemDoubleClick(itemId, e) | ||
Called when an item was double clicked | ||
### onCanvasContextMenu(group, time, e) | ||
Called when the canvas is clicked by the right button of the mouse. Note: If this property is set the default context menu doesn't appear | ||
### onItemContextMenu(itemId, e) | ||
Called when the item is clicked by the right button of the mouse. Note: If this property is set the default context menu doesn't appear | ||
### moveResizeValidator(action, itemId, time, resizeEdge) | ||
@@ -289,4 +311,13 @@ This function is called when an item is being moved or resized. It's up to this function to return a new version of `change`, when the proposed move would violate business logic. | ||
### itemRenderer | ||
React component that will be used to render the item content. Will be | ||
passed the `item` as a prop. Using complex components may result in | ||
performance problems. | ||
### groupRenderer | ||
React component that will be used to render the content of groups in the | ||
sidebar. Will be passed the `group` and `isRightSidebar` as props. | ||
### children | ||
All children of the Timeline component will be displayed above the sidebar. Use this to display small filters or so. | ||
**DEPRECATED. User the sidebarContent prop instead.** All children of the Timeline component will be displayed above the sidebar. Use this to display small filters or so. | ||
@@ -307,3 +338,23 @@ ## FAQ | ||
### How can I add one more sidebar on the right? | ||
The library supports right sidebar. | ||
 | ||
To use it, you need to add two props to the `<Timeline />` component: | ||
``` | ||
rightSidebarWidth={150} | ||
rightSidebarContent={<p>Second filter</p>} | ||
``` | ||
And add `right_sidebar` prop to the groups objects: | ||
``` | ||
{ | ||
id: 1, | ||
title: 'group 1', | ||
right_sidebar: 'additional info about group 1' | ||
} | ||
``` | ||
## Behind the scenes | ||
@@ -310,0 +361,0 @@ The timeline is built with speed, usability and extensibility in mind. |
@@ -35,3 +35,4 @@ import React, { Component } from 'react' | ||
// onResized: React.PropTypes.func, | ||
// onContextMenu: React.PropTypes.func | ||
// onContextMenu: React.PropTypes.func, | ||
// itemRenderer: React.PropTypes.func | ||
} | ||
@@ -426,2 +427,11 @@ static defaultProps = { | ||
renderContent () { | ||
const Comp = this.props.itemRenderer | ||
if (Comp) { | ||
return <Comp item={this.props.item} /> | ||
} else { | ||
return this.itemTitle | ||
} | ||
} | ||
render () { | ||
@@ -467,3 +477,3 @@ const dimensions = this.props.dimensions | ||
<div className='rct-item-content'> | ||
{this.itemTitle} | ||
{this.renderContent()} | ||
</div> | ||
@@ -470,0 +480,0 @@ </div> |
@@ -46,6 +46,10 @@ import React, { Component, PropTypes } from 'react' | ||
onItemDoubleClick: PropTypes.func, | ||
onItemContextMenu: PropTypes.func | ||
onItemContextMenu: PropTypes.func, | ||
itemRenderer: PropTypes.func, | ||
selected: PropTypes.array | ||
} | ||
static defaultProps = { | ||
selected: [] | ||
} | ||
@@ -61,2 +65,3 @@ | ||
nextProps.selectedItem === this.props.selectedItem && | ||
nextProps.selected === this.props.selected && | ||
nextProps.lineHeight === this.props.lineHeight && | ||
@@ -86,2 +91,11 @@ nextProps.dragSnap === this.props.dragSnap && | ||
isSelected (item, itemIdKey) { | ||
if (!this.props.selected) { | ||
return this.props.selectedItem === _get(item, itemIdKey) | ||
} else { | ||
let target = _get(item, itemIdKey) | ||
return this.props.selected.find((value) => value === target) | ||
} | ||
} | ||
getVisibleItems (canvasTimeStart, canvasTimeEnd, groupOrders) { | ||
@@ -111,3 +125,3 @@ const { itemTimeStartKey, itemTimeEndKey } = this.props.keys | ||
dimensions={sortedDimensionItems[_get(item, itemIdKey)].dimensions} | ||
selected={this.props.selectedItem === _get(item, itemIdKey)} | ||
selected={this.isSelected(item, itemIdKey)} | ||
canChangeGroup={_get(item, 'canChangeGroup') !== undefined ? _get(item, 'canChangeGroup') : this.props.canChangeGroup} | ||
@@ -135,3 +149,4 @@ canMove={_get(item, 'canMove') !== undefined ? _get(item, 'canMove') : this.props.canMove} | ||
onContextMenu={this.props.onItemContextMenu} | ||
onSelect={this.props.itemSelect}/>)} | ||
onSelect={this.props.itemSelect} | ||
itemRenderer={this.props.itemRenderer} />)} | ||
</div> | ||
@@ -138,0 +153,0 @@ ) |
@@ -129,3 +129,3 @@ import React, { Component } from 'react' | ||
visibleTimeStart, visibleTimeEnd, minUnit, timeSteps, fixedHeader, | ||
headerLabelGroupHeight, headerLabelHeight | ||
headerLabelGroupHeight, headerLabelHeight, hasRightSidebar, width | ||
} = this.props | ||
@@ -153,3 +153,3 @@ const { | ||
href='#' | ||
className='rct-label-group' | ||
className={`rct-label-group${hasRightSidebar ? ' rct-has-right-sidebar' : ''}`} | ||
data-time={time} | ||
@@ -181,3 +181,3 @@ data-unit={nextUnit} | ||
href='#' | ||
className={`rct-label ${twoHeaders ? '' : 'rct-label-only'} ${firstOfType ? 'rct-first-of-type' : ''} `} | ||
className={`rct-label ${twoHeaders ? '' : 'rct-label-only'} ${firstOfType ? 'rct-first-of-type' : ''} ${(minUnit !== 'month' ? `rct-day-${time.day()}` : '')} `} | ||
data-time={time} | ||
@@ -208,3 +208,3 @@ data-unit={minUnit} | ||
headerStyle.position = 'fixed' | ||
headerStyle.width = '100%' | ||
headerStyle.width = `${width}px` | ||
headerStyle.zIndex = zIndex | ||
@@ -234,2 +234,3 @@ } else if (fixedHeader === 'absolute') { | ||
// headerBackgroundColor: React.PropTypes.string.isRequired, | ||
hasRightSidebar: React.PropTypes.bool.isRequired, | ||
showPeriod: React.PropTypes.func.isRequired, | ||
@@ -236,0 +237,0 @@ canvasTimeStart: React.PropTypes.number.isRequired, |
@@ -66,8 +66,16 @@ import React, { Component } from 'react' | ||
renderGroupContent (group, isRightSidebar, groupTitleKey, groupRightTitleKey) { | ||
if (this.props.groupRenderer) { | ||
return React.createElement(this.props.groupRenderer, { group, isRightSidebar }) | ||
} else { | ||
return _get(group, isRightSidebar ? groupRightTitleKey : groupTitleKey) | ||
} | ||
} | ||
render () { | ||
const { | ||
fixedHeader, width, lineHeight, zIndex, groupHeights, height, headerHeight | ||
fixedHeader, width, lineHeight, zIndex, groupHeights, height, headerHeight, isRightSidebar | ||
} = this.props | ||
const {groupIdKey, groupTitleKey} = this.props.keys | ||
const {groupIdKey, groupTitleKey, groupRightTitleKey} = this.props.keys | ||
@@ -122,3 +130,3 @@ const { | ||
<div key={_get(group, groupIdKey)} className={'rct-sidebar-row' + (i % 2 === 0 ? ' rct-sidebar-row-even' : ' rct-sidebar-row-odd')} style={elementStyle}> | ||
{_get(group, groupTitleKey)} | ||
{this.renderGroupContent(group, isRightSidebar, groupTitleKey, groupRightTitleKey)} | ||
</div> | ||
@@ -130,3 +138,3 @@ ) | ||
return ( | ||
<div ref='sidebar' className='rct-sidebar' style={sidebarStyle}> | ||
<div ref='sidebar' className={'rct-sidebar' + (isRightSidebar ? ' rct-sidebar-right' : '')} style={sidebarStyle}> | ||
{header} | ||
@@ -148,3 +156,5 @@ <div style={groupsStyle}> | ||
keys: React.PropTypes.object.isRequired, | ||
children: React.PropTypes.node | ||
groupRenderer: React.PropTypes.func, | ||
children: React.PropTypes.node, | ||
isRightSidebar: React.PropTypes.bool | ||
} | ||
@@ -154,3 +164,4 @@ Sidebar.defaultProps = { | ||
zIndex: 12, | ||
children: null | ||
children: null, | ||
isRightSidebar: false | ||
} |
@@ -12,2 +12,3 @@ import React, { Component, PropTypes } from 'react' | ||
import TodayLine from './lines/TodayLine' | ||
import CursorLine from './lines/CursorLine' | ||
@@ -19,2 +20,3 @@ import { getMinUnit, getNextUnit, getParentPosition, _get, _length, stack, nostack, calculateDimensions, getGroupOrders, getVisibleItems, hasSomeParentTheClass } from './utils.js' | ||
groupTitleKey: 'title', | ||
groupRightTitleKey: 'rightTitle', | ||
itemIdKey: 'id', | ||
@@ -42,2 +44,5 @@ itemTitleKey: 'title', | ||
sidebarWidth: PropTypes.number, | ||
sidebarContent: PropTypes.node, | ||
rightSidebarWidth: PropTypes.number, | ||
rightSidebarContent: PropTypes.node, | ||
dragSnap: PropTypes.number, | ||
@@ -67,2 +72,3 @@ minResizeWidth: PropTypes.number, | ||
traditionalZoom: PropTypes.bool, | ||
showCursorLine: PropTypes.bool, | ||
@@ -75,2 +81,3 @@ itemTouchSendsClick: PropTypes.bool, | ||
onItemSelect: PropTypes.func, | ||
onItemDeselect: PropTypes.func, | ||
onCanvasClick: PropTypes.func, | ||
@@ -80,4 +87,10 @@ onItemDoubleClick: PropTypes.func, | ||
onCanvasDoubleClick: PropTypes.func, | ||
onCanvasContextMenu: PropTypes.func, | ||
onCanvasMouseEnter: PropTypes.func, | ||
onCanvasMouseLeave: PropTypes.func, | ||
onCanvasMouseMove: PropTypes.func, | ||
moveResizeValidator: PropTypes.func, | ||
itemRenderer: PropTypes.func, | ||
groupRenderer: PropTypes.func, | ||
@@ -100,3 +113,5 @@ dayBackground: PropTypes.func, | ||
children: PropTypes.node | ||
children: PropTypes.node, | ||
selected: PropTypes.array | ||
} | ||
@@ -106,2 +121,3 @@ | ||
sidebarWidth: 150, | ||
rightSidebarWidth: 0, | ||
dragSnap: 1000 * 60 * 15, // 15min | ||
@@ -131,2 +147,3 @@ minResizeWidth: 20, | ||
traditionalZoom: false, | ||
showCursorLine: false, | ||
@@ -137,5 +154,9 @@ onItemMove: null, | ||
onItemSelect: null, | ||
onItemDeselect: null, | ||
onCanvasClick: null, | ||
onItemDoubleClick: null, | ||
onItemContextMenu: null, | ||
onCanvasMouseEnter: null, | ||
onCanvasMouseLeave: null, | ||
onCanvasMouseMove: null, | ||
@@ -166,3 +187,5 @@ moveResizeValidator: null, | ||
onBoundsChange: null, | ||
children: null | ||
children: null, | ||
selected: null | ||
} | ||
@@ -224,7 +247,7 @@ | ||
componentDidMount () { | ||
this.resize() | ||
this.resize(this.props) | ||
this.resizeEventListener = { | ||
handleEvent: (event) => { | ||
this.resize() | ||
this.resize(this.props) | ||
} | ||
@@ -325,10 +348,9 @@ } | ||
resize () { | ||
// FIXME currently when the component creates a scroll the scrollbar is not used in the initial width calculation, resizing fixes this | ||
resize (props) { | ||
const {width: containerWidth, top: containerTop} = this.refs.container.getBoundingClientRect() | ||
let width = containerWidth - this.props.sidebarWidth | ||
let width = containerWidth - props.sidebarWidth - props.rightSidebarWidth | ||
const { | ||
dimensionItems, height, groupHeights, groupTops | ||
} = this.stackItems(this.props.items, this.props.groups, this.state.canvasTimeStart, this.state.visibleTimeStart, this.state.visibleTimeEnd, width) | ||
} = this.stackItems(props.items, props.groups, this.state.canvasTimeStart, this.state.visibleTimeStart, this.state.visibleTimeEnd, width) | ||
@@ -374,10 +396,12 @@ this.setState({ | ||
componentWillReceiveProps (nextProps) { | ||
const { visibleTimeStart, visibleTimeEnd, items, groups } = nextProps | ||
const { visibleTimeStart, visibleTimeEnd, items, groups, sidebarWidth } = nextProps | ||
if (visibleTimeStart && visibleTimeEnd) { | ||
this.updateScrollCanvas(visibleTimeStart, visibleTimeEnd, items !== this.props.items || groups !== this.props.groups, items, groups) | ||
} else if (items !== this.props.items || groups !== this.props.groups) { | ||
this.updateDimensions(items, groups) | ||
} | ||
if (items !== this.props.items || groups !== this.props.groups) { | ||
this.updateDimensions(items, groups) | ||
if (sidebarWidth && items && groups) { | ||
this.resize(nextProps) | ||
} | ||
@@ -538,2 +562,4 @@ } | ||
this.props.onItemSelect(item, e) | ||
} else if (item === null && this.props.onItemDeselect) { | ||
this.props.onItemDeselect(e) | ||
} | ||
@@ -614,3 +640,3 @@ } | ||
if (pageY - topOffset > headerHeight) { | ||
if (pageY - topOffset > headerHeight && e.button === 0) { | ||
this.setState({isDragging: true, dragStartPosition: e.pageX, dragLastPosition: e.pageX}) | ||
@@ -637,2 +663,48 @@ } | ||
handleCanvasMouseEnter = (e) => { | ||
const { showCursorLine } = this.props | ||
if (showCursorLine) { | ||
this.setState({mouseOverCanvas: true}) | ||
} | ||
if (this.props.onCanvasMouseEnter) { | ||
this.props.onCanvasMouseEnter(e) | ||
} | ||
} | ||
handleCanvasMouseLeave = (e) => { | ||
const { showCursorLine } = this.props | ||
if (showCursorLine) { | ||
this.setState({mouseOverCanvas: false}) | ||
} | ||
if (this.props.onCanvasMouseLeave) { | ||
this.props.onCanvasMouseLeave(e) | ||
} | ||
} | ||
handleCanvasMouseMove = (e) => { | ||
const { showCursorLine } = this.props | ||
const { canvasTimeStart, width, visibleTimeStart, visibleTimeEnd, cursorTime } = this.state | ||
const zoom = visibleTimeEnd - visibleTimeStart | ||
const canvasTimeEnd = canvasTimeStart + zoom * 3 | ||
const canvasWidth = width * 3 | ||
const { pageX } = e | ||
const ratio = (canvasTimeEnd - canvasTimeStart) / canvasWidth | ||
const boundingRect = this.refs.scrollComponent.getBoundingClientRect() | ||
let timePosition = visibleTimeStart + ratio * (pageX - boundingRect.left) | ||
if (this.props.dragSnap) { | ||
timePosition = Math.round(timePosition / this.props.dragSnap) * this.props.dragSnap | ||
} | ||
if (this.props.onCanvasMouseMove) { | ||
this.props.onCanvasMouseMove(e) | ||
} | ||
if (cursorTime !== timePosition && showCursorLine) { | ||
this.setState({cursorTime: timePosition, mouseOverCanvas: true}) | ||
} | ||
} | ||
todayLine (canvasTimeStart, zoom, canvasTimeEnd, canvasWidth, minUnit, height, headerHeight) { | ||
@@ -651,2 +723,16 @@ return ( | ||
cursorLine (cursorTime, canvasTimeStart, zoom, canvasTimeEnd, canvasWidth, minUnit, height, headerHeight) { | ||
return ( | ||
<CursorLine cursorTime={ cursorTime } | ||
canvasTimeStart={canvasTimeStart} | ||
canvasTimeEnd={canvasTimeEnd} | ||
canvasWidth={canvasWidth} | ||
lineHeight={this.props.lineHeight} | ||
lineCount={_length(this.props.groups)} | ||
height={height} | ||
headerHeight={headerHeight} | ||
/> | ||
) | ||
} | ||
verticalLines (canvasTimeStart, zoom, canvasTimeEnd, canvasWidth, minUnit, timeSteps, height, headerHeight) { | ||
@@ -710,3 +796,5 @@ return ( | ||
itemResizing={this.resizingItem} | ||
itemResized={this.resizedItem} /> | ||
itemResized={this.resizedItem} | ||
itemRenderer={this.props.itemRenderer} | ||
selected={this.props.selected} /> | ||
) | ||
@@ -730,2 +818,3 @@ } | ||
<Header canvasTimeStart={canvasTimeStart} | ||
hasRightSidebar={this.props.rightSidebarWidth > 0} | ||
canvasTimeEnd={canvasTimeEnd} | ||
@@ -751,2 +840,3 @@ canvasWidth={canvasWidth} | ||
<Sidebar groups={this.props.groups} | ||
groupRenderer={this.props.groupRenderer} | ||
keys={this.props.keys} | ||
@@ -762,3 +852,3 @@ | ||
zIndex={this.props.zIndexStart + 2}> | ||
{this.props.children} | ||
{this.props.sidebarContent || this.props.children} | ||
</Sidebar> | ||
@@ -768,2 +858,21 @@ ) | ||
rightSidebar (height, groupHeights, headerHeight) { | ||
return ( | ||
<Sidebar groups={this.props.groups} | ||
keys={this.props.keys} | ||
isRightSidebar | ||
width={this.props.rightSidebarWidth} | ||
lineHeight={this.props.lineHeight} | ||
groupHeights={groupHeights} | ||
height={height} | ||
headerHeight={headerHeight} | ||
fixedHeader={this.props.fixedHeader} | ||
zIndex={this.props.zIndexStart + 2}> | ||
{this.props.rightSidebarContent} | ||
</Sidebar> | ||
) | ||
} | ||
stackItems (items, groups, canvasTimeStart, visibleTimeStart, visibleTimeEnd, width) { | ||
@@ -846,6 +955,36 @@ const { keys, dragSnap, lineHeight, headerLabelGroupHeight, headerLabelHeight, stackItems, fullUpdate, itemHeightRatio } = this.props | ||
handleCanvasContextMenu = (e) => { | ||
const { canvasTimeStart, width, visibleTimeStart, visibleTimeEnd, groupTops, topOffset } = this.state | ||
const zoom = visibleTimeEnd - visibleTimeStart | ||
const canvasTimeEnd = canvasTimeStart + zoom * 3 | ||
const canvasWidth = width * 3 | ||
const { pageX, pageY } = e | ||
const ratio = (canvasTimeEnd - canvasTimeStart) / canvasWidth | ||
const boundingRect = this.refs.scrollComponent.getBoundingClientRect() | ||
let timePosition = visibleTimeStart + ratio * (pageX - boundingRect.left) | ||
if (this.props.dragSnap) { | ||
timePosition = Math.round(timePosition / this.props.dragSnap) * this.props.dragSnap | ||
} | ||
let groupIndex = 0 | ||
for (var key of Object.keys(groupTops)) { | ||
var item = groupTops[key] | ||
if (pageY - topOffset > item) { | ||
groupIndex = parseInt(key, 10) | ||
} else { | ||
break | ||
} | ||
} | ||
if (this.props.onCanvasContextMenu) { | ||
e.preventDefault() | ||
this.props.onCanvasContextMenu(this.props.groups[groupIndex], timePosition, e) | ||
} | ||
} | ||
render () { | ||
const { items, groups, headerLabelGroupHeight, headerLabelHeight, sidebarWidth, timeSteps } = this.props | ||
const { draggingItem, resizingItem, isDragging, width, visibleTimeStart, visibleTimeEnd, canvasTimeStart } = this.state | ||
const { items, groups, headerLabelGroupHeight, headerLabelHeight, sidebarWidth, rightSidebarWidth, timeSteps, showCursorLine } = this.props | ||
const { draggingItem, resizingItem, isDragging, width, visibleTimeStart, visibleTimeEnd, canvasTimeStart, mouseOverCanvas, cursorTime } = this.state | ||
let { dimensionItems, height, groupHeights, groupTops } = this.state | ||
const zoom = visibleTimeEnd - visibleTimeStart | ||
@@ -897,2 +1036,6 @@ const canvasTimeEnd = canvasTimeStart + zoom * 3 | ||
onDoubleClick={ this.handleDoubleClick } | ||
onMouseEnter={ this.handleCanvasMouseEnter } | ||
onMouseLeave={ this.handleCanvasMouseLeave } | ||
onMouseMove={ this.handleCanvasMouseMove } | ||
onContextMenu={ this.handleCanvasContextMenu } | ||
> | ||
@@ -903,2 +1046,5 @@ {this.items(canvasTimeStart, zoom, canvasTimeEnd, canvasWidth, minUnit, dimensionItems, groupHeights, groupTops)} | ||
{this.todayLine(canvasTimeStart, zoom, canvasTimeEnd, canvasWidth, minUnit, height, headerHeight)} | ||
{mouseOverCanvas && showCursorLine | ||
? this.cursorLine(cursorTime, canvasTimeStart, zoom, canvasTimeEnd, canvasWidth, minUnit, height, headerHeight) | ||
: null} | ||
{this.infoLabel()} | ||
@@ -918,2 +1064,3 @@ {this.header( | ||
</div> | ||
{rightSidebarWidth > 0 ? this.rightSidebar(height, groupHeights, headerHeight) : null} | ||
</div> | ||
@@ -920,0 +1067,0 @@ </div> |
@@ -152,3 +152,3 @@ import moment from 'moment' | ||
order: isDragging ? newGroupOrder : order, | ||
stack: true, | ||
stack: !item.isOverlay, | ||
collisionLeft: collisionX, | ||
@@ -155,0 +155,0 @@ originalLeft: itemTimeStart, |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
264042
10.59%34
6.25%5576
9.76%386
15.22%