diff --git a/.gitignore b/.gitignore index b53b607..b8b1c4a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ node_modules npm-debug.log .DS_Store -lib yarn.lock demo/dist \ No newline at end of file diff --git a/lib/ActionList.js b/lib/ActionList.js new file mode 100644 index 0000000..193eea7 --- /dev/null +++ b/lib/ActionList.js @@ -0,0 +1,166 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _extends2 = require('babel-runtime/helpers/extends'); + +var _extends3 = _interopRequireDefault(_extends2); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactDom = require('react-dom'); + +var _reactDom2 = _interopRequireDefault(_reactDom); + +var _ActionListRow = require('./ActionListRow'); + +var _ActionListRow2 = _interopRequireDefault(_ActionListRow); + +var _ActionListHeader = require('./ActionListHeader'); + +var _ActionListHeader2 = _interopRequireDefault(_ActionListHeader); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function getTimestamps(actions, actionIds, actionId) { + var idx = actionIds.indexOf(actionId); + var prevActionId = actionIds[idx - 1]; + + return { + current: actions[actionId].timestamp, + previous: idx ? actions[prevActionId].timestamp : 0 + }; +} + +var ActionList = function (_PureComponent) { + (0, _inherits3.default)(ActionList, _PureComponent); + + function ActionList() { + (0, _classCallCheck3.default)(this, ActionList); + return (0, _possibleConstructorReturn3.default)(this, (ActionList.__proto__ || (0, _getPrototypeOf2.default)(ActionList)).apply(this, arguments)); + } + + (0, _createClass3.default)(ActionList, [{ + key: 'componentDidMount', + value: function componentDidMount() { + this.scrollToBottom(true); + } + }, { + key: 'componentDidUpdate', + value: function componentDidUpdate(prevProps) { + if (this.props.lastActionId !== prevProps.lastActionId) { + this.scrollToBottom(); + } + } + }, { + key: 'scrollToBottom', + value: function scrollToBottom(force) { + var el = _reactDom2.default.findDOMNode(this.refs.rows); + var scrollHeight = el.scrollHeight; + if (force || Math.abs(scrollHeight - (el.scrollTop + el.offsetHeight)) < 50) { + el.scrollTop = scrollHeight; + } + } + }, { + key: 'render', + value: function render() { + var _props = this.props, + styling = _props.styling, + actions = _props.actions, + actionIds = _props.actionIds, + isWideLayout = _props.isWideLayout, + onToggleAction = _props.onToggleAction, + skippedActionIds = _props.skippedActionIds, + selectedActionId = _props.selectedActionId, + startActionId = _props.startActionId, + onSelect = _props.onSelect, + onSearch = _props.onSearch, + searchValue = _props.searchValue, + currentActionId = _props.currentActionId, + onCommit = _props.onCommit, + onSweep = _props.onSweep, + onJumpToState = _props.onJumpToState; + + var lowerSearchValue = searchValue && searchValue.toLowerCase(); + var filteredActionIds = searchValue ? actionIds.filter(function (id) { + return actions[id].action.type.toLowerCase().indexOf(lowerSearchValue) !== -1; + }) : actionIds; + + return _react2.default.createElement( + 'div', + (0, _extends3.default)({ + key: 'actionList' + }, styling(['actionList', isWideLayout ? 'actionListWide' : null], isWideLayout)), + _react2.default.createElement(_ActionListHeader2.default, { styling: styling, + onSearch: onSearch, + onCommit: onCommit, + onSweep: onSweep, + hasSkippedActions: skippedActionIds.length > 0, + hasStagedActions: actionIds.length > 1 }), + _react2.default.createElement( + 'div', + (0, _extends3.default)({}, styling('actionListRows'), { ref: 'rows' }), + filteredActionIds.map(function (actionId) { + return _react2.default.createElement(_ActionListRow2.default, { key: actionId, + styling: styling, + isInitAction: !actionId, + isSelected: startActionId !== null && actionId >= startActionId && actionId <= selectedActionId || actionId === selectedActionId, + isInFuture: actionId > currentActionId, + onSelect: function (_onSelect) { + function onSelect(_x) { + return _onSelect.apply(this, arguments); + } + + onSelect.toString = function () { + return _onSelect.toString(); + }; + + return onSelect; + }(function (e) { + return onSelect(e, actionId); + }), + timestamps: getTimestamps(actions, actionIds, actionId), + action: actions[actionId].action, + onToggleClick: function onToggleClick() { + return onToggleAction(actionId); + }, + onJumpClick: function onJumpClick() { + return onJumpToState(actionId); + }, + onCommitClick: function onCommitClick() { + return onCommit(actionId); + }, + isSkipped: skippedActionIds.indexOf(actionId) !== -1 }); + }) + ) + ); + } + }]); + return ActionList; +}(_react.PureComponent); + +exports.default = ActionList; \ No newline at end of file diff --git a/lib/ActionListHeader.js b/lib/ActionListHeader.js new file mode 100644 index 0000000..75e1c8e --- /dev/null +++ b/lib/ActionListHeader.js @@ -0,0 +1,71 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _extends2 = require('babel-runtime/helpers/extends'); + +var _extends3 = _interopRequireDefault(_extends2); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _RightSlider = require('./RightSlider'); + +var _RightSlider2 = _interopRequireDefault(_RightSlider); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var getActiveButtons = function getActiveButtons(hasSkippedActions) { + return [hasSkippedActions ? 'Sweep' : null, 'Commit'].filter(Boolean); +}; + +var ActionListHeader = function ActionListHeader(_ref) { + var styling = _ref.styling, + onSearch = _ref.onSearch, + hasSkippedActions = _ref.hasSkippedActions, + hasStagedActions = _ref.hasStagedActions, + onCommit = _ref.onCommit, + onSweep = _ref.onSweep; + return _react2.default.createElement( + 'div', + styling('actionListHeader'), + _react2.default.createElement('input', (0, _extends3.default)({}, styling('actionListHeaderSearch'), { + onChange: function onChange(e) { + return onSearch(e.target.value); + }, + placeholder: 'filter...' + })), + _react2.default.createElement( + 'div', + styling('actionListHeaderWrapper'), + _react2.default.createElement( + _RightSlider2.default, + { shown: hasStagedActions, styling: styling }, + _react2.default.createElement( + 'div', + styling('actionListHeaderSelector'), + getActiveButtons(hasSkippedActions).map(function (btn) { + return _react2.default.createElement( + 'div', + (0, _extends3.default)({ + key: btn, + onClick: function onClick() { + return { + Commit: onCommit, + Sweep: onSweep + }[btn](); + } + }, styling(['selectorButton', 'selectorButtonSmall'], false, true)), + btn + ); + }) + ) + ) + ) + ); +}; + +exports.default = ActionListHeader; \ No newline at end of file diff --git a/lib/ActionListRow.js b/lib/ActionListRow.js new file mode 100644 index 0000000..4db0777 --- /dev/null +++ b/lib/ActionListRow.js @@ -0,0 +1,172 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _extends2 = require('babel-runtime/helpers/extends'); + +var _extends3 = _interopRequireDefault(_extends2); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _dateformat = require('dateformat'); + +var _dateformat2 = _interopRequireDefault(_dateformat); + +var _lodash = require('lodash.debounce'); + +var _lodash2 = _interopRequireDefault(_lodash); + +var _RightSlider = require('./RightSlider'); + +var _RightSlider2 = _interopRequireDefault(_RightSlider); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var BUTTON_SKIP = 'Skip'; +var BUTTON_JUMP = 'Jump'; + +var ActionListRow = function (_PureComponent) { + (0, _inherits3.default)(ActionListRow, _PureComponent); + + function ActionListRow() { + var _ref; + + var _temp, _this, _ret; + + (0, _classCallCheck3.default)(this, ActionListRow); + + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + return _ret = (_temp = (_this = (0, _possibleConstructorReturn3.default)(this, (_ref = ActionListRow.__proto__ || (0, _getPrototypeOf2.default)(ActionListRow)).call.apply(_ref, [this].concat(args))), _this), _this.state = { hover: false }, _this.handleMouseEnter = function (e) { + if (_this.hover) return; + _this.handleMouseEnterDebounced(e.buttons); + }, _this.handleMouseEnterDebounced = (0, _lodash2.default)(function (buttons) { + if (buttons) return; + _this.setState({ hover: true }); + }, 300), _this.handleMouseLeave = function () { + _this.handleMouseEnterDebounced.cancel(); + if (_this.state.hover) _this.setState({ hover: false }); + }, _this.handleMouseDown = function (e) { + if (e.target instanceof Element && e.target.className.indexOf('selectorButton') === 0) return; + if (_this.handleMouseEnterDebounced) _this.handleMouseEnterDebounced.cancel(); + if (_this.state.hover) _this.setState({ hover: false }); + }, _temp), (0, _possibleConstructorReturn3.default)(_this, _ret); + } + + (0, _createClass3.default)(ActionListRow, [{ + key: 'render', + value: function render() { + var _this2 = this; + + var _props = this.props, + styling = _props.styling, + isSelected = _props.isSelected, + action = _props.action, + isInitAction = _props.isInitAction, + onSelect = _props.onSelect, + timestamps = _props.timestamps, + isSkipped = _props.isSkipped, + isInFuture = _props.isInFuture; + var hover = this.state.hover; + + var timeDelta = timestamps.current - timestamps.previous; + var showButtons = hover && !isInitAction || isSkipped; + + var isButtonSelected = function isButtonSelected(btn) { + return btn === BUTTON_SKIP && isSkipped; + }; + + var actionType = action.type; + if (typeof actionType === 'undefined') actionType = '';else if (actionType === null) actionType = '';else actionType = actionType.toString() || ''; + + return _react2.default.createElement( + 'div', + (0, _extends3.default)({ + onClick: onSelect, + onMouseEnter: this.handleMouseEnter, + onMouseLeave: this.handleMouseLeave, + onMouseDown: this.handleMouseDown + }, styling(['actionListItem', isSelected ? 'actionListItemSelected' : null, isSkipped ? 'actionListItemSkipped' : null, isInFuture ? 'actionListFromFuture' : null], isSelected, action)), + _react2.default.createElement( + 'div', + styling(['actionListItemName', isSkipped ? 'actionListItemNameSkipped' : null]), + actionType + ), + _react2.default.createElement( + 'div', + styling('actionListItemButtons'), + _react2.default.createElement( + _RightSlider2.default, + { styling: styling, shown: !showButtons, rotate: true }, + _react2.default.createElement( + 'div', + styling('actionListItemTime'), + timeDelta === 0 ? '+00:00:00' : (0, _dateformat2.default)(timeDelta, timestamps.previous ? '+MM:ss.L' : 'h:MM:ss.L') + ) + ), + _react2.default.createElement( + _RightSlider2.default, + { styling: styling, shown: showButtons, rotate: true }, + _react2.default.createElement( + 'div', + styling('actionListItemSelector'), + [BUTTON_JUMP, BUTTON_SKIP].map(function (btn) { + return (!isInitAction || btn !== BUTTON_SKIP) && _react2.default.createElement( + 'div', + (0, _extends3.default)({ + key: btn, + onClick: _this2.handleButtonClick.bind(_this2, btn) + }, styling(['selectorButton', isButtonSelected(btn) ? 'selectorButtonSelected' : null, 'selectorButtonSmall'], isButtonSelected(btn), true)), + btn + ); + }) + ) + ) + ) + ); + } + }, { + key: 'handleButtonClick', + value: function handleButtonClick(btn, e) { + e.stopPropagation(); + + switch (btn) { + case BUTTON_SKIP: + this.props.onToggleClick(); + break; + case BUTTON_JUMP: + this.props.onJumpClick(); + break; + } + } + }]); + return ActionListRow; +}(_react.PureComponent); + +exports.default = ActionListRow; \ No newline at end of file diff --git a/lib/ActionPreview.js b/lib/ActionPreview.js new file mode 100644 index 0000000..beb73c8 --- /dev/null +++ b/lib/ActionPreview.js @@ -0,0 +1,191 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _extends2 = require('babel-runtime/helpers/extends'); + +var _extends3 = _interopRequireDefault(_extends2); + +var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray'); + +var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2); + +var _toArray2 = require('babel-runtime/helpers/toArray'); + +var _toArray3 = _interopRequireDefault(_toArray2); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _ActionPreviewHeader = require('./ActionPreviewHeader'); + +var _ActionPreviewHeader2 = _interopRequireDefault(_ActionPreviewHeader); + +var _DiffTab = require('./tabs/DiffTab'); + +var _DiffTab2 = _interopRequireDefault(_DiffTab); + +var _StateTab = require('./tabs/StateTab'); + +var _StateTab2 = _interopRequireDefault(_StateTab); + +var _ActionTab = require('./tabs/ActionTab'); + +var _ActionTab2 = _interopRequireDefault(_ActionTab); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var DEFAULT_TABS = [{ + name: 'Action', + component: _ActionTab2.default +}, { + name: 'Diff', + component: _DiffTab2.default +}, { + name: 'State', + component: _StateTab2.default +}]; + +var ActionPreview = function (_Component) { + (0, _inherits3.default)(ActionPreview, _Component); + + function ActionPreview() { + var _ref; + + var _temp, _this, _ret; + + (0, _classCallCheck3.default)(this, ActionPreview); + + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + return _ret = (_temp = (_this = (0, _possibleConstructorReturn3.default)(this, (_ref = ActionPreview.__proto__ || (0, _getPrototypeOf2.default)(ActionPreview)).call.apply(_ref, [this].concat(args))), _this), _this.labelRenderer = function (_ref2, nodeType, expanded) { + var _ref3 = (0, _toArray3.default)(_ref2), + key = _ref3[0], + rest = _ref3.slice(1); + + var _this$props = _this.props, + styling = _this$props.styling, + onInspectPath = _this$props.onInspectPath, + inspectedPath = _this$props.inspectedPath; + + + return _react2.default.createElement( + 'span', + null, + _react2.default.createElement( + 'span', + styling('treeItemKey'), + key + ), + _react2.default.createElement( + 'span', + (0, _extends3.default)({}, styling('treeItemPin'), { + onClick: function onClick() { + return onInspectPath([].concat((0, _toConsumableArray3.default)(inspectedPath.slice(0, inspectedPath.length - 1)), (0, _toConsumableArray3.default)([key].concat((0, _toConsumableArray3.default)(rest)).reverse()))); + } }), + '(pin)' + ), + !expanded && ': ' + ); + }, _temp), (0, _possibleConstructorReturn3.default)(_this, _ret); + } + + (0, _createClass3.default)(ActionPreview, [{ + key: 'render', + value: function render() { + var _props = this.props, + styling = _props.styling, + delta = _props.delta, + error = _props.error, + nextState = _props.nextState, + onInspectPath = _props.onInspectPath, + inspectedPath = _props.inspectedPath, + tabName = _props.tabName, + isWideLayout = _props.isWideLayout, + onSelectTab = _props.onSelectTab, + action = _props.action, + actions = _props.actions, + selectedActionId = _props.selectedActionId, + startActionId = _props.startActionId, + computedStates = _props.computedStates, + base16Theme = _props.base16Theme, + invertTheme = _props.invertTheme, + tabs = _props.tabs; + + + var renderedTabs = typeof tabs === 'function' ? tabs(DEFAULT_TABS) : tabs ? tabs : DEFAULT_TABS; + + var tab = renderedTabs.find(function (tab) { + return tab.name === tabName; + }); + + var TabComponent = void 0; + if (tab) { + TabComponent = tab.component; + } + + return _react2.default.createElement( + 'div', + (0, _extends3.default)({ key: 'actionPreview' }, styling('actionPreview')), + _react2.default.createElement(_ActionPreviewHeader2.default, (0, _extends3.default)({ + tabs: renderedTabs + }, { styling: styling, inspectedPath: inspectedPath, onInspectPath: onInspectPath, tabName: tabName, onSelectTab: onSelectTab })), + !error && _react2.default.createElement( + 'div', + (0, _extends3.default)({ key: 'actionPreviewContent' }, styling('actionPreviewContent')), + TabComponent && _react2.default.createElement(TabComponent, (0, _extends3.default)({ + labelRenderer: this.labelRenderer + }, { + styling: styling, + computedStates: computedStates, + actions: actions, + selectedActionId: selectedActionId, + startActionId: startActionId, + base16Theme: base16Theme, + invertTheme: invertTheme, + isWideLayout: isWideLayout, + delta: delta, + action: action, + nextState: nextState + })) + ), + error && _react2.default.createElement( + 'div', + styling('stateError'), + error + ) + ); + } + }]); + return ActionPreview; +}(_react.Component); + +ActionPreview.defaultProps = { + tabName: 'Diff' +}; +exports.default = ActionPreview; \ No newline at end of file diff --git a/lib/ActionPreviewHeader.js b/lib/ActionPreviewHeader.js new file mode 100644 index 0000000..6b25c4c --- /dev/null +++ b/lib/ActionPreviewHeader.js @@ -0,0 +1,79 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _extends2 = require('babel-runtime/helpers/extends'); + +var _extends3 = _interopRequireDefault(_extends2); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var ActionPreviewHeader = function ActionPreviewHeader(_ref) { + var styling = _ref.styling, + inspectedPath = _ref.inspectedPath, + onInspectPath = _ref.onInspectPath, + tabName = _ref.tabName, + onSelectTab = _ref.onSelectTab, + tabs = _ref.tabs; + return _react2.default.createElement( + 'div', + (0, _extends3.default)({ key: 'previewHeader' }, styling('previewHeader')), + _react2.default.createElement( + 'div', + styling('tabSelector'), + tabs.map(function (tab) { + return _react2.default.createElement( + 'div', + (0, _extends3.default)({ onClick: function onClick() { + return onSelectTab(tab.name); + }, + key: tab.name + }, styling(['selectorButton', tab.name === tabName ? 'selectorButtonSelected' : null], tab.name === tabName)), + tab.name + ); + }) + ), + _react2.default.createElement( + 'div', + styling('inspectedPath'), + inspectedPath.length ? _react2.default.createElement( + 'span', + styling('inspectedPathKey'), + _react2.default.createElement( + 'a', + (0, _extends3.default)({ onClick: function onClick() { + return onInspectPath([]); + } + }, styling('inspectedPathKeyLink')), + tabName + ) + ) : tabName, + inspectedPath.map(function (key, idx) { + return idx === inspectedPath.length - 1 ? _react2.default.createElement( + 'span', + { key: key }, + key + ) : _react2.default.createElement( + 'span', + (0, _extends3.default)({ key: key + }, styling('inspectedPathKey')), + _react2.default.createElement( + 'a', + (0, _extends3.default)({ onClick: function onClick() { + return onInspectPath(inspectedPath.slice(0, idx + 1)); + } + }, styling('inspectedPathKeyLink')), + key + ) + ); + }) + ) + ); +}; +exports.default = ActionPreviewHeader; \ No newline at end of file diff --git a/lib/DevtoolsInspector.js b/lib/DevtoolsInspector.js new file mode 100644 index 0000000..6455aec --- /dev/null +++ b/lib/DevtoolsInspector.js @@ -0,0 +1,317 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _extends2 = require('babel-runtime/helpers/extends'); + +var _extends3 = _interopRequireDefault(_extends2); + +var _defineProperty2 = require('babel-runtime/helpers/defineProperty'); + +var _defineProperty3 = _interopRequireDefault(_defineProperty2); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _createStylingFromTheme = require('./utils/createStylingFromTheme'); + +var _ActionList = require('./ActionList'); + +var _ActionList2 = _interopRequireDefault(_ActionList); + +var _ActionPreview = require('./ActionPreview'); + +var _ActionPreview2 = _interopRequireDefault(_ActionPreview); + +var _getInspectedState = require('./utils/getInspectedState'); + +var _getInspectedState2 = _interopRequireDefault(_getInspectedState); + +var _createDiffPatcher = require('./createDiffPatcher'); + +var _createDiffPatcher2 = _interopRequireDefault(_createDiffPatcher); + +var _reactBase16Styling = require('react-base16-styling'); + +var _redux = require('./redux'); + +var _reduxDevtools = require('redux-devtools'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var commit = _reduxDevtools.ActionCreators.commit, + sweep = _reduxDevtools.ActionCreators.sweep, + toggleAction = _reduxDevtools.ActionCreators.toggleAction, + jumpToAction = _reduxDevtools.ActionCreators.jumpToAction, + jumpToState = _reduxDevtools.ActionCreators.jumpToState; + + +function getLastActionId(props) { + return props.stagedActionIds[props.stagedActionIds.length - 1]; +} + +function getCurrentActionId(props, monitorState) { + return monitorState.selectedActionId === null ? props.stagedActionIds[props.currentStateIndex] : monitorState.selectedActionId; +} + +function getFromState(actionIndex, stagedActionIds, computedStates, monitorState) { + var startActionId = monitorState.startActionId; + + if (startActionId === null) { + return actionIndex > 0 ? computedStates[actionIndex - 1] : null; + } + var fromStateIdx = stagedActionIds.indexOf(startActionId - 1); + if (fromStateIdx === -1) fromStateIdx = 0; + return computedStates[fromStateIdx]; +} + +function createIntermediateState(props, monitorState) { + var supportImmutable = props.supportImmutable, + computedStates = props.computedStates, + stagedActionIds = props.stagedActionIds, + actions = props.actionsById, + diffObjectHash = props.diffObjectHash, + diffPropertyFilter = props.diffPropertyFilter; + var inspectedStatePath = monitorState.inspectedStatePath, + inspectedActionPath = monitorState.inspectedActionPath; + + var currentActionId = getCurrentActionId(props, monitorState); + var currentAction = actions[currentActionId] && actions[currentActionId].action; + + var actionIndex = stagedActionIds.indexOf(currentActionId); + var fromState = getFromState(actionIndex, stagedActionIds, computedStates, monitorState); + var toState = computedStates[actionIndex]; + var error = toState ? toState.error : null; + + var fromInspectedState = !error && fromState ? (0, _getInspectedState2.default)(fromState.state, inspectedStatePath, supportImmutable) : null; + var toInspectedState = !error && toState ? (0, _getInspectedState2.default)(toState.state, inspectedStatePath, supportImmutable) : null; + var delta = fromInspectedState && toInspectedState ? (0, _createDiffPatcher2.default)(diffObjectHash, diffPropertyFilter).diff(fromInspectedState, toInspectedState) : null; + + return { + delta: delta, + nextState: toState && (0, _getInspectedState2.default)(toState.state, inspectedStatePath, false), + action: (0, _getInspectedState2.default)(currentAction, inspectedActionPath, false), + error: error + }; +} + +function createThemeState(props) { + var base16Theme = (0, _reactBase16Styling.getBase16Theme)(props.theme, _createStylingFromTheme.base16Themes); + var styling = (0, _createStylingFromTheme.createStylingFromTheme)(props.theme, props.invertTheme); + + return { base16Theme: base16Theme, styling: styling }; +} + +var DevtoolsInspector = function (_PureComponent) { + (0, _inherits3.default)(DevtoolsInspector, _PureComponent); + + function DevtoolsInspector(props) { + (0, _classCallCheck3.default)(this, DevtoolsInspector); + + var _this = (0, _possibleConstructorReturn3.default)(this, (DevtoolsInspector.__proto__ || (0, _getPrototypeOf2.default)(DevtoolsInspector)).call(this, props)); + + _this.handleToggleAction = function (actionId) { + _this.props.dispatch(toggleAction(actionId)); + }; + + _this.handleJumpToState = function (actionId) { + if (jumpToAction) { + _this.props.dispatch(jumpToAction(actionId)); + } else { + // Fallback for redux-devtools-instrument < 1.5 + var index = _this.props.stagedActionIds.indexOf(actionId); + if (index !== -1) _this.props.dispatch(jumpToState(index)); + } + }; + + _this.handleCommit = function () { + _this.props.dispatch(commit()); + }; + + _this.handleSweep = function () { + _this.props.dispatch(sweep()); + }; + + _this.handleSearch = function (val) { + _this.updateMonitorState({ searchValue: val }); + }; + + _this.handleSelectAction = function (e, actionId) { + var monitorState = _this.props.monitorState; + + var startActionId = void 0; + var selectedActionId = void 0; + + if (e.shiftKey && monitorState.selectedActionId !== null) { + if (monitorState.startActionId !== null) { + if (actionId >= monitorState.startActionId) { + startActionId = Math.min(monitorState.startActionId, monitorState.selectedActionId); + selectedActionId = actionId; + } else { + selectedActionId = Math.max(monitorState.startActionId, monitorState.selectedActionId); + startActionId = actionId; + } + } else { + startActionId = Math.min(actionId, monitorState.selectedActionId); + selectedActionId = Math.max(actionId, monitorState.selectedActionId); + } + } else { + startActionId = null; + if (actionId === monitorState.selectedActionId || monitorState.startActionId !== null) { + selectedActionId = null; + } else { + selectedActionId = actionId; + } + } + + _this.updateMonitorState({ startActionId: startActionId, selectedActionId: selectedActionId }); + }; + + _this.handleInspectPath = function (pathType, path) { + _this.updateMonitorState((0, _defineProperty3.default)({}, pathType, path)); + }; + + _this.handleSelectTab = function (tabName) { + _this.updateMonitorState({ tabName: tabName }); + }; + + _this.state = (0, _extends3.default)({}, createIntermediateState(props, props.monitorState), { + isWideLayout: false, + themeState: createThemeState(props) + }); + return _this; + } + + (0, _createClass3.default)(DevtoolsInspector, [{ + key: 'componentDidMount', + value: function componentDidMount() { + this.updateSizeMode(); + this.updateSizeTimeout = setInterval(this.updateSizeMode.bind(this), 150); + } + }, { + key: 'componentWillUnmount', + value: function componentWillUnmount() { + clearTimeout(this.updateSizeTimeout); + } + }, { + key: 'updateMonitorState', + value: function updateMonitorState(monitorState) { + this.props.dispatch((0, _redux.updateMonitorState)(monitorState)); + } + }, { + key: 'updateSizeMode', + value: function updateSizeMode() { + var isWideLayout = this.refs.inspector.offsetWidth > 500; + + if (isWideLayout !== this.state.isWideLayout) { + this.setState({ isWideLayout: isWideLayout }); + } + } + }, { + key: 'componentWillReceiveProps', + value: function componentWillReceiveProps(nextProps) { + var nextMonitorState = nextProps.monitorState; + var monitorState = this.props.monitorState; + + if (getCurrentActionId(this.props, monitorState) !== getCurrentActionId(nextProps, nextMonitorState) || monitorState.startActionId !== nextMonitorState.startActionId || monitorState.inspectedStatePath !== nextMonitorState.inspectedStatePath || monitorState.inspectedActionPath !== nextMonitorState.inspectedActionPath) { + this.setState(createIntermediateState(nextProps, nextMonitorState)); + } + + if (this.props.theme !== nextProps.theme || this.props.invertTheme !== nextProps.invertTheme) { + this.setState({ themeState: createThemeState(nextProps) }); + } + } + }, { + key: 'render', + value: function render() { + var _props = this.props, + actionIds = _props.stagedActionIds, + actions = _props.actionsById, + computedStates = _props.computedStates, + tabs = _props.tabs, + invertTheme = _props.invertTheme, + skippedActionIds = _props.skippedActionIds, + currentStateIndex = _props.currentStateIndex, + monitorState = _props.monitorState; + var selectedActionId = monitorState.selectedActionId, + startActionId = monitorState.startActionId, + searchValue = monitorState.searchValue, + tabName = monitorState.tabName; + + var inspectedPathType = tabName === 'Action' ? 'inspectedActionPath' : 'inspectedStatePath'; + var _state = this.state, + themeState = _state.themeState, + isWideLayout = _state.isWideLayout, + action = _state.action, + nextState = _state.nextState, + delta = _state.delta, + error = _state.error; + var base16Theme = themeState.base16Theme, + styling = themeState.styling; + + + return _react2.default.createElement( + 'div', + (0, _extends3.default)({ key: 'inspector', + ref: 'inspector' + }, styling(['inspector', isWideLayout ? 'inspectorWide' : null], isWideLayout)), + _react2.default.createElement(_ActionList2.default, (0, _extends3.default)({ + actions: actions, actionIds: actionIds, isWideLayout: isWideLayout, searchValue: searchValue, selectedActionId: selectedActionId, startActionId: startActionId + }, { + styling: styling, + onSearch: this.handleSearch, + onSelect: this.handleSelectAction, + onToggleAction: this.handleToggleAction, + onJumpToState: this.handleJumpToState, + onCommit: this.handleCommit, + onSweep: this.handleSweep, + skippedActionIds: skippedActionIds, + currentActionId: actionIds[currentStateIndex], + lastActionId: getLastActionId(this.props) })), + _react2.default.createElement(_ActionPreview2.default, (0, _extends3.default)({ + base16Theme: base16Theme, invertTheme: invertTheme, isWideLayout: isWideLayout, tabs: tabs, tabName: tabName, delta: delta, error: error, nextState: nextState, + computedStates: computedStates, action: action, actions: actions, selectedActionId: selectedActionId, startActionId: startActionId + }, { + styling: styling, + onInspectPath: this.handleInspectPath.bind(this, inspectedPathType), + inspectedPath: monitorState[inspectedPathType], + onSelectTab: this.handleSelectTab })) + ); + } + }]); + return DevtoolsInspector; +}(_react.PureComponent); + +DevtoolsInspector.update = _redux.reducer; +DevtoolsInspector.defaultProps = { + select: function select(state) { + return state; + }, + supportImmutable: false, + theme: 'inspector', + invertTheme: true +}; +exports.default = DevtoolsInspector; \ No newline at end of file diff --git a/lib/RightSlider.js b/lib/RightSlider.js new file mode 100644 index 0000000..041560e --- /dev/null +++ b/lib/RightSlider.js @@ -0,0 +1,24 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var RightSlider = function RightSlider(_ref) { + var styling = _ref.styling, + shown = _ref.shown, + children = _ref.children, + rotate = _ref.rotate; + return _react2.default.createElement( + 'div', + styling(['rightSlider', shown ? 'rightSliderShown' : null, rotate ? 'rightSliderRotate' : null, rotate && shown ? 'rightSliderRotateShown' : null]), + children + ); +}; +exports.default = RightSlider; \ No newline at end of file diff --git a/lib/createDiffPatcher.js b/lib/createDiffPatcher.js new file mode 100644 index 0000000..61437bb --- /dev/null +++ b/lib/createDiffPatcher.js @@ -0,0 +1,44 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _stringify = require('babel-runtime/core-js/json/stringify'); + +var _stringify2 = _interopRequireDefault(_stringify); + +exports.default = createDiffPatcher; + +var _jsondiffpatch = require('jsondiffpatch'); + +var _jsondiffpatch2 = _interopRequireDefault(_jsondiffpatch); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var defaultObjectHash = function defaultObjectHash(o, idx) { + return o === null && '$$null' || o && (o.id || o.id === 0) && '$$id:' + (0, _stringify2.default)(o.id) || o && (o._id || o._id === 0) && '$$_id:' + (0, _stringify2.default)(o._id) || '$$index:' + idx.toString(); +}; + + +var defaultPropertyFilter = function defaultPropertyFilter(name, context) { + return typeof context.left[name] !== 'function' && typeof context.right[name] !== 'function'; +}; + +var defaultDiffPatcher = _jsondiffpatch2.default.create({ + arrays: { detectMove: false }, + objectHash: defaultObjectHash, + propertyFilter: defaultPropertyFilter +}); + +function createDiffPatcher(objectHash, propertyFilter) { + if (!objectHash && !propertyFilter) { + return defaultDiffPatcher; + } + + return _jsondiffpatch2.default.create({ + arrays: { detectMove: false }, + objectHash: objectHash || defaultObjectHash, + propertyFilter: propertyFilter || defaultPropertyFilter + }); +} \ No newline at end of file diff --git a/lib/index.js b/lib/index.js new file mode 100644 index 0000000..2fe0dbd --- /dev/null +++ b/lib/index.js @@ -0,0 +1,16 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _DevtoolsInspector = require('./DevtoolsInspector'); + +Object.defineProperty(exports, 'default', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_DevtoolsInspector).default; + } +}); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/lib/redux.js b/lib/redux.js new file mode 100644 index 0000000..b1237f1 --- /dev/null +++ b/lib/redux.js @@ -0,0 +1,42 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _extends2 = require('babel-runtime/helpers/extends'); + +var _extends3 = _interopRequireDefault(_extends2); + +exports.updateMonitorState = updateMonitorState; +exports.reducer = reducer; + +var _types = require('./types'); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var UPDATE_MONITOR_STATE = '@@redux-devtools-inspector/UPDATE_MONITOR_STATE'; + + +var DEFAULT_STATE = { + selectedActionId: null, + startActionId: null, + inspectedActionPath: [], + inspectedStatePath: [], + tabName: 'Diff' +}; + +function updateMonitorState(monitorState) { + return { type: UPDATE_MONITOR_STATE, monitorState: monitorState }; +} + +function reduceUpdateState(state, action) { + return action.type === UPDATE_MONITOR_STATE ? (0, _extends3.default)({}, state, action.monitorState) : state; +} + +function reducer(props) { + var state = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_STATE; + var action = arguments[2]; + + return (0, _extends3.default)({}, reduceUpdateState(state, action)); +} \ No newline at end of file diff --git a/lib/tabs/ActionTab.js b/lib/tabs/ActionTab.js new file mode 100644 index 0000000..6f681b5 --- /dev/null +++ b/lib/tabs/ActionTab.js @@ -0,0 +1,95 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactJsonTree = require('react-json-tree'); + +var _reactJsonTree2 = _interopRequireDefault(_reactJsonTree); + +var _getItemString = require('./getItemString'); + +var _getItemString2 = _interopRequireDefault(_getItemString); + +var _getJsonTreeTheme = require('./getJsonTreeTheme'); + +var _getJsonTreeTheme2 = _interopRequireDefault(_getJsonTreeTheme); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var getStateFromProps = function getStateFromProps(props) { + return { + theme: (0, _getJsonTreeTheme2.default)(props.base16Theme) + }; +}; + +var ActionTab = function (_PureComponent) { + (0, _inherits3.default)(ActionTab, _PureComponent); + + function ActionTab(props) { + (0, _classCallCheck3.default)(this, ActionTab); + + var _this = (0, _possibleConstructorReturn3.default)(this, (ActionTab.__proto__ || (0, _getPrototypeOf2.default)(ActionTab)).call(this, props)); + + _this.getItemString = function (type, data) { + return (0, _getItemString2.default)(_this.props.styling, type, data, _this.props.isWideLayout); + }; + + _this.state = getStateFromProps(props); + return _this; + } + + (0, _createClass3.default)(ActionTab, [{ + key: 'componentWillReceiveProps', + value: function componentWillReceiveProps(nextProps) { + if (nextProps.base16Theme !== this.props.base16Theme) { + this.setState(getStateFromProps(nextProps)); + } + } + }, { + key: 'render', + value: function render() { + var _props = this.props, + labelRenderer = _props.labelRenderer, + action = _props.action, + invertTheme = _props.invertTheme; + + return _react2.default.createElement(_reactJsonTree2.default, { + labelRenderer: labelRenderer, + theme: this.state.theme, + data: action, + getItemString: this.getItemString, + invertTheme: invertTheme, + hideRoot: true + }); + } + }]); + return ActionTab; +}(_react.PureComponent); + +exports.default = ActionTab; \ No newline at end of file diff --git a/lib/tabs/DiffTab.js b/lib/tabs/DiffTab.js new file mode 100644 index 0000000..ef06589 --- /dev/null +++ b/lib/tabs/DiffTab.js @@ -0,0 +1,27 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _JSONDiff = require('./JSONDiff'); + +var _JSONDiff2 = _interopRequireDefault(_JSONDiff); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var DiffTab = function DiffTab(_ref) { + var delta = _ref.delta, + styling = _ref.styling, + base16Theme = _ref.base16Theme, + invertTheme = _ref.invertTheme, + labelRenderer = _ref.labelRenderer, + isWideLayout = _ref.isWideLayout; + return _react2.default.createElement(_JSONDiff2.default, { delta: delta, styling: styling, base16Theme: base16Theme, invertTheme: invertTheme, labelRenderer: labelRenderer, isWideLayout: isWideLayout }); +}; + +exports.default = DiffTab; \ No newline at end of file diff --git a/lib/tabs/JSONDiff.js b/lib/tabs/JSONDiff.js new file mode 100644 index 0000000..906edaf --- /dev/null +++ b/lib/tabs/JSONDiff.js @@ -0,0 +1,199 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _extends2 = require('babel-runtime/helpers/extends'); + +var _extends3 = _interopRequireDefault(_extends2); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactJsonTree = require('react-json-tree'); + +var _reactJsonTree2 = _interopRequireDefault(_reactJsonTree); + +var _javascriptStringify = require('javascript-stringify'); + +var _javascriptStringify2 = _interopRequireDefault(_javascriptStringify); + +var _getItemString = require('./getItemString'); + +var _getItemString2 = _interopRequireDefault(_getItemString); + +var _getJsonTreeTheme = require('./getJsonTreeTheme'); + +var _getJsonTreeTheme2 = _interopRequireDefault(_getJsonTreeTheme); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function stringifyAndShrink(val, isWideLayout) { + if (val === null) { + return 'null'; + } + + var str = (0, _javascriptStringify2.default)(val); + if (typeof str === 'undefined') { + return 'undefined'; + } + + if (isWideLayout) return str.length > 42 ? str.substr(0, 30) + '…' + str.substr(-10) : str; + return str.length > 22 ? str.substr(0, 15) + '\u2026' + str.substr(-5) : str; +} + + +var expandFirstLevel = function expandFirstLevel(keyName, data, level) { + return level <= 1; +}; + +function prepareDelta(value) { + if (value && value._t === 'a') { + var arrayDelta = value; + var res = {}; + for (var key in arrayDelta) { + if (key !== '_t') { + if (key[0] === '_' && !arrayDelta[key.substr(1)]) { + res[key.substr(1)] = arrayDelta[key]; + } else if (arrayDelta['_' + key]) { + res[key] = [arrayDelta['_' + key][0], arrayDelta[key][0]]; + } else if (!arrayDelta['_' + key] && key[0] !== '_') { + res[key] = arrayDelta[key]; + } + } + } + return res; + } + + return value; +} + +var getStateFromProps = function getStateFromProps(props) { + return { + theme: (0, _getJsonTreeTheme2.default)(props.base16Theme) + }; +}; + +var JSONDiff = function (_PureComponent) { + (0, _inherits3.default)(JSONDiff, _PureComponent); + + function JSONDiff(props) { + (0, _classCallCheck3.default)(this, JSONDiff); + + var _this = (0, _possibleConstructorReturn3.default)(this, (JSONDiff.__proto__ || (0, _getPrototypeOf2.default)(JSONDiff)).call(this, props)); + + _this.valueRenderer = function (raw, value) { + var _this$props = _this.props, + styling = _this$props.styling, + isWideLayout = _this$props.isWideLayout; + + + function renderSpan(name, body) { + return _react2.default.createElement( + 'span', + (0, _extends3.default)({ key: name }, styling(['diff', name])), + body + ); + } + + if (Array.isArray(value)) { + switch (value.length) { + case 1: + return _react2.default.createElement( + 'span', + styling('diffWrap'), + renderSpan('diffAdd', stringifyAndShrink(value[0], isWideLayout)) + ); + case 2: + return _react2.default.createElement( + 'span', + styling('diffWrap'), + renderSpan('diffUpdateFrom', stringifyAndShrink(value[0], isWideLayout)), + renderSpan('diffUpdateArrow', ' => '), + renderSpan('diffUpdateTo', stringifyAndShrink(value[1], isWideLayout)) + ); + case 3: + return _react2.default.createElement( + 'span', + styling('diffWrap'), + renderSpan('diffRemove', stringifyAndShrink(value[0], isWideLayout)) + ); + } + } + + return raw; + }; + + _this.getItemString = function (type, data) { + return (0, _getItemString2.default)(_this.props.styling, type, data, _this.props.isWideLayout, true); + }; + + _this.state = getStateFromProps(props); + return _this; + } + + (0, _createClass3.default)(JSONDiff, [{ + key: 'componentWillReceiveProps', + value: function componentWillReceiveProps(nextProps) { + if (nextProps.base16Theme !== this.props.base16Theme) { + this.setState(getStateFromProps(nextProps)); + } + } + }, { + key: 'render', + value: function render() { + var _props = this.props, + styling = _props.styling, + labelRenderer = _props.labelRenderer, + invertTheme = _props.invertTheme, + delta = _props.delta; + + + if (!delta) { + return _react2.default.createElement( + 'div', + styling('stateDiffEmpty'), + '(states are equal)' + ); + } + + return _react2.default.createElement(_reactJsonTree2.default, { + labelRenderer: labelRenderer, + invertTheme: invertTheme, + theme: this.state.theme, + data: delta, + getItemString: this.getItemString, + valueRenderer: this.valueRenderer, + postprocessValue: prepareDelta, + isCustomNode: Array.isArray, + shouldExpandNode: expandFirstLevel, + hideRoot: true + }); + } + }]); + return JSONDiff; +}(_react.PureComponent); + +exports.default = JSONDiff; \ No newline at end of file diff --git a/lib/tabs/StateTab.js b/lib/tabs/StateTab.js new file mode 100644 index 0000000..8e2092e --- /dev/null +++ b/lib/tabs/StateTab.js @@ -0,0 +1,95 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); + +var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); + +var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _createClass2 = require('babel-runtime/helpers/createClass'); + +var _createClass3 = _interopRequireDefault(_createClass2); + +var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); + +var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); + +var _inherits2 = require('babel-runtime/helpers/inherits'); + +var _inherits3 = _interopRequireDefault(_inherits2); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _reactJsonTree = require('react-json-tree'); + +var _reactJsonTree2 = _interopRequireDefault(_reactJsonTree); + +var _getItemString = require('./getItemString'); + +var _getItemString2 = _interopRequireDefault(_getItemString); + +var _getJsonTreeTheme = require('./getJsonTreeTheme'); + +var _getJsonTreeTheme2 = _interopRequireDefault(_getJsonTreeTheme); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var getStateFromProps = function getStateFromProps(props) { + return { + theme: (0, _getJsonTreeTheme2.default)(props.base16Theme) + }; +}; + +var StateTab = function (_PureComponent) { + (0, _inherits3.default)(StateTab, _PureComponent); + + function StateTab(props) { + (0, _classCallCheck3.default)(this, StateTab); + + var _this = (0, _possibleConstructorReturn3.default)(this, (StateTab.__proto__ || (0, _getPrototypeOf2.default)(StateTab)).call(this, props)); + + _this.getItemString = function (type, data) { + return (0, _getItemString2.default)(_this.props.styling, type, data, _this.props.isWideLayout); + }; + + _this.state = getStateFromProps(props); + return _this; + } + + (0, _createClass3.default)(StateTab, [{ + key: 'componentWillReceiveProps', + value: function componentWillReceiveProps(nextProps) { + if (nextProps.base16Theme !== this.props.base16Theme) { + this.setState(getStateFromProps(nextProps)); + } + } + }, { + key: 'render', + value: function render() { + var _props = this.props, + labelRenderer = _props.labelRenderer, + nextState = _props.nextState, + invertTheme = _props.invertTheme; + + return _react2.default.createElement(_reactJsonTree2.default, { + labelRenderer: labelRenderer, + theme: this.state.theme, + data: nextState, + getItemString: this.getItemString, + invertTheme: invertTheme, + hideRoot: true + }); + } + }]); + return StateTab; +}(_react.PureComponent); + +exports.default = StateTab; \ No newline at end of file diff --git a/lib/tabs/getItemString.js b/lib/tabs/getItemString.js new file mode 100644 index 0000000..cedd806 --- /dev/null +++ b/lib/tabs/getItemString.js @@ -0,0 +1,181 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _getIterator2 = require('babel-runtime/core-js/get-iterator'); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +var _keys = require('babel-runtime/core-js/object/keys'); + +var _keys2 = _interopRequireDefault(_keys); + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +var _getType = require('../utils/getType'); + +var _getType2 = _interopRequireDefault(_getType); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function getShortTypeString(val, diff) { + + if (diff && Array.isArray(val)) { + val = val[val.length === 2 ? 1 : 0]; + } + + var type = (0, _getType2.default)(val); + + switch (type) { + case 'Immutable List': + case 'Immutable Stack': + case 'Immutable Seq': + return '' + val.size ? '[…]' : '[]'; + case 'Map': + return val.size ? '{…}' : '{}'; + case 'WeakMap': + return '{…}'; + case 'Set': + return val.size ? '(…)' : '()'; + case 'WeakSet': + return '(…)'; + case 'Immutable Map': + case 'Immutable OrderedMap': + return '' + val.size ? '{…}' : '{}'; + case 'Immutable Set': + case 'Immutable OrderedSet': + return '' + val.size ? '(…)' : '()'; + case 'Iterable': + return '(…)'; + case 'Array': + return val.length > 0 ? '[…]' : '[]'; + case 'Null': + return 'null'; + case 'Undefined': + return 'undef'; + case 'Error': + return 'Error(' + getShortTypeString(val.message); + case 'Object': + return (0, _keys2.default)(val).length > 0 ? '{…}' : '{}'; + case 'Function': + return 'fn'; + case 'String': + return '"' + (val.substr(0, 10) + (val.length > 10 ? '…' : '')) + '"'; + case 'Symbol': + return 'symbol'; + default: + return val.toString(); + } +} + +function getFirstEntries(data, limit, getEntryString) { + var idx = 0, + arr = []; + + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = (0, _getIterator3.default)(data), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var entry = _step.value; + + if (idx === 3) { + arr.push('…'); + break; + }; + arr.push(getEntryString(entry)); + idx++; + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + + return arr.join(', '); +} + +function getText(type, data, isWideLayout, isDiff) { + var str = void 0; + type = (0, _getType2.default)(data); + + switch (type) { + case 'Immutable List': + case 'Immutable Stack': + case 'Immutable Seq': + str = getFirstEntries(data, 3, function (entry) { + return getShortTypeString(entry); + }); + return '[ ' + str + ' ]'; + case 'Map': + str = getFirstEntries(data, 3, function (entry) { + return getShortTypeString(entry[0]) + ' => ' + getShortTypeString(entry[1]); + }); + return '{ ' + str + ' }'; + case 'WeakMap': + return '{…}'; + case 'Set': + str = getFirstEntries(data, 3, function (entry) { + return getShortTypeString(entry); + }); + return '( ' + str + ' )'; + case 'WeakSet': + return '(…)'; + case 'Immutable Map': + case 'Immutable OrderedMap': + str = getFirstEntries(data, 3, function (entry) { + return getShortTypeString(entry[0]) + ' => ' + getShortTypeString(entry[1]); + }); + return '{ ' + str + ' }'; + case 'Immutable Set': + case 'Immutable OrderedSet': + str = getFirstEntries(data, 3, function (entry) { + return getShortTypeString(entry); + }); + return '( ' + str + ' )'; + case 'Object': + var keys = (0, _keys2.default)(data); + if (!isWideLayout) return keys.length ? '{…}' : '{}'; + + str = keys.slice(0, 3).map(function (key) { + return key + ': ' + getShortTypeString(data[key], isDiff); + }).concat(keys.length > 3 ? ['…'] : []).join(', '); + + return '{ ' + str + ' }'; + case 'Array': + if (!isWideLayout) return data.length ? '[…]' : '[]'; + + str = data.slice(0, 4).map(function (val) { + return getShortTypeString(val, isDiff); + }).concat(data.length > 4 ? ['…'] : []).join(', '); + + return '[' + str + ']'; + default: + return type; + } +} + +var getItemString = function getItemString(styling, type, data, isWideLayout) { + var isDiff = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; + return _react2.default.createElement( + 'span', + styling('treeItemHint'), + getText(type, data, isWideLayout, isDiff) + ); +}; + +exports.default = getItemString; \ No newline at end of file diff --git a/lib/tabs/getJsonTreeTheme.js b/lib/tabs/getJsonTreeTheme.js new file mode 100644 index 0000000..0963a82 --- /dev/null +++ b/lib/tabs/getJsonTreeTheme.js @@ -0,0 +1,35 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _extends2 = require('babel-runtime/helpers/extends'); + +var _extends3 = _interopRequireDefault(_extends2); + +exports.default = getJsonTreeTheme; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function getJsonTreeTheme(base16Theme) { + return { + extend: base16Theme, + nestedNode: function nestedNode(_ref, keyPath, nodeType, expanded) { + var style = _ref.style; + return { + style: (0, _extends3.default)({}, style, { + whiteSpace: expanded ? 'inherit' : 'nowrap' + }) + }; + }, + nestedNodeItemString: function nestedNodeItemString(_ref2, keyPath, nodeType, expanded) { + var style = _ref2.style; + return { + style: (0, _extends3.default)({}, style, { + display: expanded ? 'none' : 'inline' + }) + }; + } + }; +} \ No newline at end of file diff --git a/lib/themes/index.js b/lib/themes/index.js new file mode 100644 index 0000000..2d14fc0 --- /dev/null +++ b/lib/themes/index.js @@ -0,0 +1,16 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _inspector = require('./inspector'); + +Object.defineProperty(exports, 'inspector', { + enumerable: true, + get: function get() { + return _interopRequireDefault(_inspector).default; + } +}); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/lib/themes/inspector.js b/lib/themes/inspector.js new file mode 100644 index 0000000..5f8dc37 --- /dev/null +++ b/lib/themes/inspector.js @@ -0,0 +1,25 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = { + scheme: 'inspector', + author: 'Alexander Kuznetsov (alexkuz@gmail.com)', + base00: '#181818', + base01: '#282828', + base02: '#383838', + base03: '#585858', + base04: '#b8b8b8', + base05: '#d8d8d8', + base06: '#e8e8e8', + base07: '#FFFFFF', + base08: '#E92F28', + base09: '#dc9656', + base0A: '#f7ca88', + base0B: '#65AD00', + base0C: '#86c1b9', + base0D: '#347BD9', + base0E: '#EC31C0', + base0F: '#a16946' +}; \ No newline at end of file diff --git a/lib/types.js b/lib/types.js new file mode 100644 index 0000000..a726efc --- /dev/null +++ b/lib/types.js @@ -0,0 +1 @@ +'use strict'; \ No newline at end of file diff --git a/lib/utils/createStylingFromTheme.js b/lib/utils/createStylingFromTheme.js new file mode 100644 index 0000000..45240fb --- /dev/null +++ b/lib/utils/createStylingFromTheme.js @@ -0,0 +1,435 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.createStylingFromTheme = exports.base16Themes = undefined; + +var _extends2 = require('babel-runtime/helpers/extends'); + +var _extends3 = _interopRequireDefault(_extends2); + +var _defineProperty2 = require('babel-runtime/helpers/defineProperty'); + +var _defineProperty3 = _interopRequireDefault(_defineProperty2); + +var _jss = require('jss'); + +var _jss2 = _interopRequireDefault(_jss); + +var _jssVendorPrefixer = require('jss-vendor-prefixer'); + +var _jssVendorPrefixer2 = _interopRequireDefault(_jssVendorPrefixer); + +var _jssNested = require('jss-nested'); + +var _jssNested2 = _interopRequireDefault(_jssNested); + +var _reactBase16Styling = require('react-base16-styling'); + +var _hexRgba = require('hex-rgba'); + +var _hexRgba2 = _interopRequireDefault(_hexRgba); + +var _inspector = require('../themes/inspector'); + +var _inspector2 = _interopRequireDefault(_inspector); + +var _reduxDevtoolsThemes = require('redux-devtools-themes'); + +var reduxThemes = _interopRequireWildcard(_reduxDevtoolsThemes); + +var _themes = require('../themes'); + +var inspectorThemes = _interopRequireWildcard(_themes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +_jss2.default.use((0, _jssVendorPrefixer2.default)()); +_jss2.default.use((0, _jssNested2.default)()); + +var colorMap = function colorMap(theme) { + return { + TEXT_COLOR: theme.base06, + TEXT_PLACEHOLDER_COLOR: (0, _hexRgba2.default)(theme.base06, 60), + BACKGROUND_COLOR: theme.base00, + SELECTED_BACKGROUND_COLOR: (0, _hexRgba2.default)(theme.base03, 20), + SKIPPED_BACKGROUND_COLOR: (0, _hexRgba2.default)(theme.base03, 10), + HEADER_BACKGROUND_COLOR: (0, _hexRgba2.default)(theme.base03, 30), + HEADER_BORDER_COLOR: (0, _hexRgba2.default)(theme.base03, 20), + BORDER_COLOR: (0, _hexRgba2.default)(theme.base03, 50), + LIST_BORDER_COLOR: (0, _hexRgba2.default)(theme.base03, 50), + ACTION_TIME_BACK_COLOR: (0, _hexRgba2.default)(theme.base03, 20), + ACTION_TIME_COLOR: theme.base04, + PIN_COLOR: theme.base04, + ITEM_HINT_COLOR: (0, _hexRgba2.default)(theme.base0F, 90), + TAB_BACK_SELECTED_COLOR: (0, _hexRgba2.default)(theme.base03, 20), + TAB_BACK_COLOR: (0, _hexRgba2.default)(theme.base00, 70), + TAB_BACK_HOVER_COLOR: (0, _hexRgba2.default)(theme.base03, 40), + TAB_BORDER_COLOR: (0, _hexRgba2.default)(theme.base03, 50), + DIFF_ADD_COLOR: (0, _hexRgba2.default)(theme.base0B, 40), + DIFF_REMOVE_COLOR: (0, _hexRgba2.default)(theme.base08, 40), + DIFF_ARROW_COLOR: theme.base0E, + LINK_COLOR: (0, _hexRgba2.default)(theme.base0E, 90), + LINK_HOVER_COLOR: theme.base0E, + ERROR_COLOR: theme.base08 + }; +}; + +var getSheetFromColorMap = function getSheetFromColorMap(map) { + return { + inspector: { + display: 'flex', + 'flex-direction': 'column', + width: '100%', + height: '100%', + 'font-family': 'monaco, Consolas, "Lucida Console", monospace', + 'font-size': '12px', + 'font-smoothing': 'antialiased', + 'line-height': '1.5em', + + 'background-color': map.BACKGROUND_COLOR, + color: map.TEXT_COLOR + }, + + inspectorWide: { + 'flex-direction': 'row' + }, + + actionList: { + 'flex-basis': '40%', + 'flex-shrink': 0, + 'overflow-x': 'hidden', + 'overflow-y': 'auto', + 'border-bottom-width': '3px', + 'border-bottom-style': 'double', + display: 'flex', + 'flex-direction': 'column', + + 'background-color': map.BACKGROUND_COLOR, + 'border-color': map.LIST_BORDER_COLOR + }, + + actionListHeader: { + display: 'flex', + flex: '0 0 auto', + 'align-items': 'center', + 'border-bottom-width': '1px', + 'border-bottom-style': 'solid', + + 'border-color': map.LIST_BORDER_COLOR + }, + + actionListRows: { + overflow: 'auto' + }, + + actionListHeaderSelector: { + display: 'inline-flex', + 'margin-right': '10px' + }, + + actionListWide: { + 'flex-basis': '40%', + 'border-bottom': 'none', + 'border-right-width': '3px', + 'border-right-style': 'double' + }, + + actionListItem: { + 'border-bottom-width': '1px', + 'border-bottom-style': 'solid', + display: 'flex', + 'justify-content': 'space-between', + padding: '5px 10px', + cursor: 'pointer', + 'user-select': 'none', + + '&:last-child': { + 'border-bottom-width': 0 + }, + + 'border-bottom-color': map.BORDER_COLOR + }, + + actionListItemSelected: { + 'background-color': map.SELECTED_BACKGROUND_COLOR + }, + + actionListItemSkipped: { + 'background-color': map.SKIPPED_BACKGROUND_COLOR + }, + + actionListFromFuture: { + opacity: '0.6' + }, + + actionListItemButtons: { + position: 'relative', + height: '20px', + display: 'flex' + }, + + actionListItemTime: { + display: 'inline', + padding: '4px 6px', + 'border-radius': '3px', + 'font-size': '0.8em', + 'line-height': '1em', + 'flex-shrink': 0, + + 'background-color': map.ACTION_TIME_BACK_COLOR, + color: map.ACTION_TIME_COLOR + }, + + actionListItemSelector: { + display: 'inline-flex' + }, + + actionListItemName: { + overflow: 'hidden', + 'text-overflow': 'ellipsis', + 'line-height': '20px' + }, + + actionListItemNameSkipped: { + 'text-decoration': 'line-through', + opacity: 0.3 + }, + + actionListHeaderSearch: { + outline: 'none', + border: 'none', + width: '100%', + padding: '5px 10px', + 'font-size': '1em', + 'font-family': 'monaco, Consolas, "Lucida Console", monospace', + + 'background-color': map.BACKGROUND_COLOR, + color: map.TEXT_COLOR, + + '&::-webkit-input-placeholder': { + color: map.TEXT_PLACEHOLDER_COLOR + }, + + '&::-moz-placeholder': { + color: map.TEXT_PLACEHOLDER_COLOR + } + }, + + actionListHeaderWrapper: { + position: 'relative', + height: '20px' + }, + + actionPreview: { + flex: 1, + display: 'flex', + 'flex-direction': 'column', + 'flex-grow': 1, + 'overflow-y': 'hidden', + + '& pre': { + border: 'inherit', + 'border-radius': '3px', + 'line-height': 'inherit', + color: 'inherit' + }, + + 'background-color': map.BACKGROUND_COLOR + }, + + actionPreviewContent: { + flex: 1, + 'overflow-y': 'auto' + }, + + stateDiff: { + padding: '5px 0' + }, + + stateDiffEmpty: { + padding: '10px', + + color: map.TEXT_PLACEHOLDER_COLOR + }, + + stateError: { + padding: '10px', + 'margin-left': '14px', + 'font-weight': 'bold', + + color: map.ERROR_COLOR + }, + + inspectedPath: { + padding: '6px 0' + }, + + inspectedPathKey: { + '&:not(:last-child):after': { + content: '" > "' + } + }, + + inspectedPathKeyLink: (0, _defineProperty3.default)({ + cursor: 'pointer', + '&:hover': { + 'text-decoration': 'underline' + }, + + color: map.LINK_COLOR + }, '&:hover', { + color: map.LINK_HOVER_COLOR + }), + + treeItemPin: { + 'font-size': '0.7em', + 'padding-left': '5px', + cursor: 'pointer', + '&:hover': { + 'text-decoration': 'underline' + }, + + color: map.PIN_COLOR + }, + + treeItemHint: { + color: map.ITEM_HINT_COLOR + }, + + previewHeader: { + flex: '0 0 30px', + padding: '5px 10px', + 'align-items': 'center', + 'border-bottom-width': '1px', + 'border-bottom-style': 'solid', + + 'background-color': map.HEADER_BACKGROUND_COLOR, + 'border-bottom-color': map.HEADER_BORDER_COLOR + }, + + tabSelector: { + position: 'relative', + 'z-index': 1, + display: 'inline-flex', + float: 'right' + }, + + selectorButton: { + cursor: 'pointer', + position: 'relative', + padding: '5px 10px', + 'border-style': 'solid', + 'border-width': '1px', + 'border-left-width': 0, + + '&:first-child': { + 'border-left-width': '1px', + 'border-top-left-radius': '3px', + 'border-bottom-left-radius': '3px' + }, + + '&:last-child': { + 'border-top-right-radius': '3px', + 'border-bottom-right-radius': '3px' + }, + + 'background-color': map.TAB_BACK_COLOR, + + '&:hover': { + 'background-color': map.TAB_BACK_HOVER_COLOR + }, + + 'border-color': map.TAB_BORDER_COLOR + }, + + selectorButtonSmall: { + padding: '0px 8px', + 'font-size': '0.8em' + }, + + selectorButtonSelected: { + 'background-color': map.TAB_BACK_SELECTED_COLOR + }, + + diff: { + padding: '2px 3px', + 'border-radius': '3px', + position: 'relative', + + color: map.TEXT_COLOR + }, + + diffWrap: { + position: 'relative', + 'z-index': 1 + }, + + diffAdd: { + 'background-color': map.DIFF_ADD_COLOR + }, + + diffRemove: { + 'text-decoration': 'line-through', + 'background-color': map.DIFF_REMOVE_COLOR + }, + + diffUpdateFrom: { + 'text-decoration': 'line-through', + 'background-color': map.DIFF_REMOVE_COLOR + }, + + diffUpdateTo: { + 'background-color': map.DIFF_ADD_COLOR + }, + + diffUpdateArrow: { + color: map.DIFF_ARROW_COLOR + }, + + rightSlider: { + 'font-smoothing': 'subpixel-antialiased', // http://stackoverflow.com/a/21136111/4218591 + position: 'absolute', + right: 0, + transform: 'translateX(150%)', + transition: 'transform 0.2s ease-in-out' + }, + + rightSliderRotate: { + transform: 'rotateX(90deg)', + transition: 'transform 0.2s ease-in-out 0.08s' + }, + + rightSliderShown: { + position: 'static', + transform: 'translateX(0)' + }, + + rightSliderRotateShown: { + transform: 'rotateX(0)', + transition: 'transform 0.2s ease-in-out 0.18s' + } + }; +}; + +var themeSheet = void 0; + +var getDefaultThemeStyling = function getDefaultThemeStyling(theme) { + if (themeSheet) { + themeSheet.detach(); + } + + themeSheet = _jss2.default.createStyleSheet(getSheetFromColorMap(colorMap(theme))).attach(); + + return themeSheet.classes; +}; + +var base16Themes = exports.base16Themes = (0, _extends3.default)({}, reduxThemes, inspectorThemes); + +var createStylingFromTheme = exports.createStylingFromTheme = (0, _reactBase16Styling.createStyling)(getDefaultThemeStyling, { + defaultBase16: _inspector2.default, + base16Themes: base16Themes +}); \ No newline at end of file diff --git a/lib/utils/getInspectedState.js b/lib/utils/getInspectedState.js new file mode 100644 index 0000000..30a16fb --- /dev/null +++ b/lib/utils/getInspectedState.js @@ -0,0 +1,91 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _defineProperty2 = require('babel-runtime/helpers/defineProperty'); + +var _defineProperty3 = _interopRequireDefault(_defineProperty2); + +var _getIterator2 = require('babel-runtime/core-js/get-iterator'); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +exports.default = getInspectedState; + +var _immutable = require('immutable'); + +var _isIterable = require('./isIterable'); + +var _isIterable2 = _interopRequireDefault(_isIterable); + +var _getType = require('./getType'); + +var _getType2 = _interopRequireDefault(_getType); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function iterateToKey(obj, key) { + // maybe there's a better way, dunno + var idx = 0; + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = (0, _getIterator3.default)(obj), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var entry = _step.value; + + if (idx === key) return entry; + idx++; + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } +} + + +var entryRegex = /\[entry (\d+)\]/; + +function getInspectedState(state, path, convertImmutable) { + state = path && path.length ? (0, _defineProperty3.default)({}, path[path.length - 1], path.reduce(function (s, key) { + if (!s) { + return s; + } + if (_immutable.Iterable.isAssociative(s) || (0, _getType2.default)(s) === 'Map') { + if (!s.has(key) && entryRegex.test(key)) { + var match = key.match(entryRegex); + var entry = iterateToKey(s, parseInt(match && match[1], 10)); + return entry && { + '[key]': entry[0], + '[value]': entry[1] + }; + } + return s.get(key); + } else if ((0, _isIterable2.default)(s)) { + return iterateToKey(s, parseInt(key, 10)); + } + + return s[key]; + }, state)) : state; + + if (convertImmutable) { + try { + state = (0, _immutable.fromJS)(state).toJS(); + } catch (e) {} + } + + return state; +} \ No newline at end of file diff --git a/lib/utils/getType.js b/lib/utils/getType.js new file mode 100644 index 0000000..09e7766 --- /dev/null +++ b/lib/utils/getType.js @@ -0,0 +1,34 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = getType; + +var _immutable = require('immutable'); + +var _objType = require('react-json-tree/lib/objType'); + +var _objType2 = _interopRequireDefault(_objType); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function getType(value) { + if (_immutable.List.isList(value)) { + return 'Immutable List'; + } else if (_immutable.Map.isMap(value)) { + return 'Immutable Map'; + } else if (_immutable.Set.isSet(value)) { + return 'Immutable Set'; + } else if (_immutable.OrderedMap.isOrderedMap(value)) { + return 'Immutable OrderedMap'; + } else if (_immutable.OrderedSet.isOrderedSet(value)) { + return 'Immutable OrderedSet'; + } else if (_immutable.Stack.isStack(value)) { + return 'Immutable Stack'; + } else if (_immutable.Seq.isSeq(value)) { + return 'Immutable Seq'; + } + + return (0, _objType2.default)(value); +} \ No newline at end of file diff --git a/lib/utils/isIterable.js b/lib/utils/isIterable.js new file mode 100644 index 0000000..78c1133 --- /dev/null +++ b/lib/utils/isIterable.js @@ -0,0 +1,17 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _typeof2 = require('babel-runtime/helpers/typeof'); + +var _typeof3 = _interopRequireDefault(_typeof2); + +exports.default = isIterable; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function isIterable(obj) { + return obj !== null && (typeof obj === 'undefined' ? 'undefined' : (0, _typeof3.default)(obj)) === 'object' && !Array.isArray(obj) && typeof obj[window.Symbol.iterator] === 'function'; +} \ No newline at end of file diff --git a/src/tabs/getItemString.js b/src/tabs/getItemString.js index 04ebbbd..1117e83 100644 --- a/src/tabs/getItemString.js +++ b/src/tabs/getItemString.js @@ -5,12 +5,13 @@ import getType from '../utils/getType'; import type { StylingFunction } from 'react-base16-styling'; function getShortTypeString(val: any, diff?: boolean): string { - const type = getType(val); if (diff && Array.isArray(val)) { val = val[val.length === 2 ? 1 : 0]; } + const type = getType(val); + switch (type) { case 'Immutable List': case 'Immutable Stack': diff --git a/src/types.js b/src/types.js index abf25fd..d986b09 100644 --- a/src/types.js +++ b/src/types.js @@ -1,3 +1,5 @@ +// @noflow + export type Action = { timestamp: Date, error: ?string