Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keyboard shortcuts and fuzzy search #141

Merged
merged 13 commits into from
Apr 25, 2016
40 changes: 40 additions & 0 deletions dist/client/handleShortCuts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"use strict";

Object.defineProperty(exports, "__esModule", {
value: true
});

var _extends2 = require("babel-runtime/helpers/extends");

var _extends3 = _interopRequireDefault(_extends2);

exports.default = handleShortCuts;

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function isModifierPressed(e) {
return (e.ctrlKey || e.keyCode === 91 || e.metaKey) && e.shiftKey;
}

function handleShortCuts(e, syncedStore) {
if (isModifierPressed(e) && e.keyCode === 80) {
e.preventDefault();
var newData = (0, _extends3.default)({}, syncedStore.getData());
newData.showSearchBox = !newData.showSearchBox;
syncedStore.setData(newData);
} else if (isModifierPressed(e) && e.keyCode === 76) {
e.preventDefault();
var _newData = (0, _extends3.default)({}, syncedStore.getData());
_newData.showControls = !_newData.showControls;
syncedStore.setData(_newData);
} else if (e.keyCode === 27) {
var _newData2 = (0, _extends3.default)({}, syncedStore.data);
_newData2.showSearchBox = false;
syncedStore.setData(_newData2);
} else if (isModifierPressed(e) && e.keyCode === 66) {
e.preventDefault();
var _newData3 = (0, _extends3.default)({}, syncedStore.getData());
_newData3.showLogger = !_newData3.showLogger;
syncedStore.setData(_newData3);
}
}
10 changes: 9 additions & 1 deletion dist/client/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ var _config_api = require('./config_api');

var _config_api2 = _interopRequireDefault(_config_api);

var _handleShortCuts = require('./handleShortCuts');

var _handleShortCuts2 = _interopRequireDefault(_handleShortCuts);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var storyStore = new _story_store2.default();
Expand All @@ -42,4 +46,8 @@ function getSyncedStore() {
var storiesOf = exports.storiesOf = clientApi.storiesOf.bind(clientApi);
var action = exports.action = clientApi.action.bind(clientApi);
var linkTo = exports.linkTo = clientApi.linkTo.bind(clientApi);
var configure = exports.configure = configApi.configure.bind(configApi);
var configure = exports.configure = configApi.configure.bind(configApi);

window.onkeydown = function (e) {
return (0, _handleShortCuts2.default)(e, syncedStore);
};
1 change: 1 addition & 0 deletions dist/client/init_admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ var syncedStore = (0, _.getSyncedStore)();
syncedStore.watchData(function (data) {
(0, _admin2.default)(data);
});

(0, _admin2.default)(syncedStore.getData());
12 changes: 6 additions & 6 deletions dist/client/story_store.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de

var cnt = 0;

var StoreStore = function () {
function StoreStore() {
(0, _classCallCheck3.default)(this, StoreStore);
var StoryStore = function () {
function StoryStore() {
(0, _classCallCheck3.default)(this, StoryStore);

this._data = {};
}

(0, _createClass3.default)(StoreStore, [{
(0, _createClass3.default)(StoryStore, [{
key: "addStory",
value: function addStory(kind, name, fn) {
if (!this._data[kind]) {
Expand Down Expand Up @@ -125,7 +125,7 @@ var StoreStore = function () {
});
}
}]);
return StoreStore;
return StoryStore;
}();

exports.default = StoreStore;
exports.default = StoryStore;
7 changes: 5 additions & 2 deletions dist/client/synced_store.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,11 @@ var _uuid2 = _interopRequireDefault(_uuid);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var Data = function () {
function Data(window) {
function Data(window, handleShortCuts) {
(0, _classCallCheck3.default)(this, Data);

this._window = window;
this._handleShortCuts = handleShortCuts;
this._parsedQs = _queryString2.default.parse(window.location.search);

// We need to check whether we are inside a iframe or not.
Expand All @@ -58,7 +59,9 @@ var Data = function () {
this._dataId = this._iframeMode ? this._parsedQs.dataId : _uuid2.default.v4();
this._data = {
iframeMode: this._iframeMode,
dataId: this._dataId
dataId: this._dataId,
showControls: true,
showLogger: true
};

this._handlers = [];
Expand Down
253 changes: 253 additions & 0 deletions dist/client/ui/FuzzySearch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
'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 _classnames = require('classnames');

var _classnames2 = _interopRequireDefault(_classnames);

var _fuse = require('fuse.js');

var _fuse2 = _interopRequireDefault(_fuse);

var _ = require('../');

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var syncedStore = (0, _.getSyncedStore)();

var searchBoxStyle = {
border: '1px solid #eee',
borderRadius: 2,
padding: '8px 10px',
lineHeight: '24px',
width: '100%',
outline: 'none',
fontSize: 20,
fontFamily: 'inherit',
color: '#666',
boxSizing: 'border-box',
transition: 'border .2s ease'
};

var searchBoxWrapper = {
padding: '4px',
boxShadow: '0 4px 15px 4px rgba(0,0,0,0.2)',
borderRadius: 2,
backgroundColor: '#ffffff',
marginTop: '50px'
};

var resultsStyle = {
backgroundColor: '#fff',
position: 'relative',
padding: '12px',
borderTop: '1px solid #eee',
color: '#666',
fontSize: 14
};

var selectedResultStyle = {
backgroundColor: '#f9f9f9',
position: 'relative',
padding: '12px',
borderTop: '1px solid #eee',
color: '#666',
fontSize: 14
};

var resultsWrapperStyle = {
width: '100%',
boxShadow: '0px 12px 30px 2px rgba(0, 0, 0, 0.1)',
border: '1px solid #eee',
borderTop: 0,
boxSizing: 'border-box'
};

var kindStyle = {
float: 'right',
color: '#bbb',
fontStyle: 'italic'
};

function mainDivStyle(width) {
return {
width: width,
position: 'fixed',
left: '50%',
marginLeft: -(width / 2),
zIndex: 99
};
}

var FuzzySearch = function (_Component) {
(0, _inherits3.default)(FuzzySearch, _Component);

function FuzzySearch(props) {
(0, _classCallCheck3.default)(this, FuzzySearch);

var _this = (0, _possibleConstructorReturn3.default)(this, (0, _getPrototypeOf2.default)(FuzzySearch).call(this, props));

_this.state = {
results: [],
selectedIndex: 0
};
_this.handleChange = _this.handleChange.bind(_this);
_this.handleKeyPress = _this.handleKeyPress.bind(_this);
_this.fuse = new _fuse2.default(props.list, props.options);
return _this;
}

(0, _createClass3.default)(FuzzySearch, [{
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(newProps) {
this.fuse.set(newProps.list);
}
}, {
key: 'getResultsTemplate',
value: function getResultsTemplate() {
var _this2 = this;

return this.state.results.map(function (val, i) {
var style = _this2.state.selectedIndex === i ? selectedResultStyle : resultsStyle;
return _react2.default.createElement(
'div',
{ key: i, style: style },
val.story,
_react2.default.createElement(
'span',
{ style: kindStyle },
'in ',
val.kind
)
);
});
}
}, {
key: 'handleKeyPress',
value: function handleKeyPress(e) {
var _this3 = this;

if (e.keyCode === 40 && this.state.selectedIndex < this.state.results.length - 1) {
this.setState({
selectedIndex: this.state.selectedIndex + 1
});
} else if (e.keyCode === 38 && this.state.selectedIndex > 0) {
this.setState({
selectedIndex: this.state.selectedIndex - 1
});
} else if (e.keyCode === 13) {
var selected = this.state.results[this.state.selectedIndex];
this.props.onSelect(selected.kind, selected.story);
this.setState({
results: [],
selectedIndex: 0
}, function () {
_this3.refs.searchBox.value = '';
var newData = (0, _extends3.default)({}, syncedStore.getData());
newData.showSearchBox = false;
syncedStore.setData(newData);
});
}
}
}, {
key: 'handleChange',
value: function handleChange(e) {
this.setState({
results: this.fuse.search(e.target.value)
});
}
}, {
key: 'render',
value: function render() {
var _props = this.props;
var className = _props.className;
var width = _props.width;
var placeholder = _props.placeholder;
var show = _props.show;


var mainClass = (0, _classnames2.default)('react-fuzzy-search', className);

var showSearchBox = show || syncedStore.getData().showSearchBox;

return _react2.default.createElement(
'span',
null,
showSearchBox && _react2.default.createElement(
'div',
{ className: mainClass, style: mainDivStyle(width), onKeyDown: this.handleKeyPress },
_react2.default.createElement(
'div',
{ style: searchBoxWrapper },
_react2.default.createElement('input', {
type: 'text',
className: 'searchBox',
style: searchBoxStyle,
onChange: this.handleChange,
ref: 'searchBox',
placeholder: placeholder,
autoFocus: true
})
),
this.state.results && this.state.results.length > 0 && _react2.default.createElement(
'div',
{ style: resultsWrapperStyle },
this.getResultsTemplate()
)
)
);
}
}]);
return FuzzySearch;
}(_react.Component);

exports.default = FuzzySearch;


FuzzySearch.propTypes = {
className: _react.PropTypes.string,
onSelect: _react.PropTypes.func.isRequired,
width: _react.PropTypes.number,
list: _react.PropTypes.array.isRequired,
options: _react.PropTypes.object.isRequired,
placeholder: _react.PropTypes.string,
show: _react.PropTypes.bool
};

FuzzySearch.defaultProps = {
width: 430,
show: false
};

exports.default = FuzzySearch;
Loading