Bug 1246807 - Implement Editable width / height inputs r=jryans

This commit is contained in:
Gabriel Luong
2016-02-22 13:15:26 -05:00
parent fe5ab5d454
commit edb078d94e
7 changed files with 232 additions and 4 deletions

View File

@@ -7,6 +7,7 @@
DevToolsModules( DevToolsModules(
'browser.js', 'browser.js',
'resizable-viewport.js', 'resizable-viewport.js',
'viewport-dimension.js',
'viewport-toolbar.js', 'viewport-toolbar.js',
'viewport.js', 'viewport.js',
'viewports.js', 'viewports.js',

View File

@@ -9,12 +9,13 @@
const { DOM: dom, createClass, createFactory, PropTypes } = const { DOM: dom, createClass, createFactory, PropTypes } =
require("devtools/client/shared/vendor/react"); require("devtools/client/shared/vendor/react");
const Constants = require("../constants");
const Types = require("../types"); const Types = require("../types");
const Browser = createFactory(require("./browser")); const Browser = createFactory(require("./browser"));
const ViewportToolbar = createFactory(require("./viewport-toolbar")); const ViewportToolbar = createFactory(require("./viewport-toolbar"));
const VIEWPORT_MIN_WIDTH = 280; const VIEWPORT_MIN_WIDTH = Constants.MIN_VIEWPORT_DIMENSION;
const VIEWPORT_MIN_HEIGHT = 280; const VIEWPORT_MIN_HEIGHT = Constants.MIN_VIEWPORT_DIMENSION;
module.exports = createClass({ module.exports = createClass({

View File

@@ -0,0 +1,164 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { DOM: dom, createClass, PropTypes } =
require("devtools/client/shared/vendor/react");
const Constants = require("../constants");
const Types = require("../types");
module.exports = createClass({
displayName: "ViewportDimension",
propTypes: {
viewport: PropTypes.shape(Types.viewport).isRequired,
onResizeViewport: PropTypes.func.isRequired,
},
getInitialState() {
let { width, height } = this.props.viewport;
return {
width,
height,
isEditing: false,
isInvalid: false,
};
},
componentWillReceiveProps(nextProps) {
let { width, height } = nextProps.viewport;
this.setState({
width,
height,
});
},
validateInput(value) {
let isInvalid = true;
// Check the value is a number and greater than MIN_VIEWPORT_DIMENSION
if (/^\d{3,4}$/.test(value) &&
parseInt(value, 10) >= Constants.MIN_VIEWPORT_DIMENSION) {
isInvalid = false;
}
this.setState({
isInvalid,
});
},
onInputBlur() {
this.onInputSubmit();
this.setState({
isEditing: false,
inInvalid: false,
});
},
onInputChange({ target }) {
if (target.value.length > 4) {
return;
}
if (this.refs.widthInput == target) {
this.setState({ width: target.value });
this.validateInput(target.value);
}
if (this.refs.heightInput == target) {
this.setState({ height: target.value });
this.validateInput(target.value);
}
},
onInputFocus() {
this.setState({
isEditing: true,
});
},
onInputKeyUp({ target, keyCode }) {
// On Enter, submit the input
if (keyCode == 13) {
this.onInputSubmit();
}
// On Esc, blur the target
if (keyCode == 27) {
target.blur();
}
},
onInputSubmit() {
if (this.state.isInvalid) {
let { width, height } = this.props.viewport;
this.setState({
width,
height,
isInvalid: false,
});
return;
}
this.props.onResizeViewport(parseInt(this.state.width, 10),
parseInt(this.state.height, 10));
},
render() {
let editableClass = "viewport-dimension-editable";
let inputClass = "viewport-dimension-input";
if (this.state.isEditing) {
editableClass += " editing";
inputClass += " editing";
}
if (this.state.isInvalid) {
editableClass += " invalid";
}
return dom.div(
{
className: "viewport-dimension",
},
dom.div(
{
className: editableClass,
},
dom.input({
ref: "widthInput",
className: inputClass,
size: 4,
value: this.state.width,
onBlur: this.onInputBlur,
onChange: this.onInputChange,
onFocus: this.onInputFocus,
onKeyUp: this.onInputKeyUp,
}),
dom.span({
className: "viewport-dimension-separator",
}, "×"),
dom.input({
ref: "heightInput",
className: inputClass,
size: 4,
value: this.state.height,
onBlur: this.onInputBlur,
onChange: this.onInputChange,
onFocus: this.onInputFocus,
onKeyUp: this.onInputKeyUp,
})
)
);
},
});

View File

@@ -9,6 +9,7 @@ const { DOM: dom, createClass, createFactory, PropTypes } =
const Types = require("../types"); const Types = require("../types");
const ResizableViewport = createFactory(require("./resizable-viewport")); const ResizableViewport = createFactory(require("./resizable-viewport"));
const ViewportDimension = createFactory(require("./viewport-dimension"));
module.exports = createClass({ module.exports = createClass({
@@ -38,6 +39,10 @@ module.exports = createClass({
viewport, viewport,
onResizeViewport, onResizeViewport,
onRotateViewport, onRotateViewport,
}),
ViewportDimension({
viewport,
onResizeViewport,
}) })
); );
}, },

View File

@@ -0,0 +1,8 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
// The minimum viewport width and height
exports.MIN_VIEWPORT_DIMENSION = 280;

View File

@@ -7,10 +7,14 @@
.theme-light { .theme-light {
--viewport-box-shadow: 0 4px 4px 0 rgba(155, 155, 155, 0.26); --viewport-box-shadow: 0 4px 4px 0 rgba(155, 155, 155, 0.26);
--viewport-dimension-color: var(--theme-splitter-color);
--viewport-dimension-editing-color: var(--theme-body-color);
} }
.theme-dark { .theme-dark {
--viewport-box-shadow: 0 4px 4px 0 rgba(105, 105, 105, 0.26); --viewport-box-shadow: 0 4px 4px 0 rgba(105, 105, 105, 0.26);
--viewport-dimension-color: var(--theme-body-color);
--viewport-dimension-editing-color: var(--theme-selection-color);
} }
* { * {
@@ -57,11 +61,11 @@ body {
display: inline-block; display: inline-block;
/* Align all viewports to the top */ /* Align all viewports to the top */
vertical-align: top; vertical-align: top;
border: 1px solid var(--theme-splitter-color);
box-shadow: var(--viewport-box-shadow);
} }
.resizable-viewport { .resizable-viewport {
border: 1px solid var(--theme-splitter-color);
box-shadow: var(--viewport-box-shadow);
position: relative; position: relative;
} }
@@ -152,3 +156,47 @@ body {
bottom: -4px; bottom: -4px;
cursor: s-resize; cursor: s-resize;
} }
/**
* Viewport Dimension Label
*/
.viewport-dimension {
display: flex;
justify-content: center;
font: 10px sans-serif;
margin-top: 10px;
}
.viewport-dimension-editable {
border-bottom: 1px solid transparent;
}
.viewport-dimension-editable,
.viewport-dimension-input {
color: var(--viewport-dimension-color);
transition: all 0.25s ease;
}
.viewport-dimension-editable.editing,
.viewport-dimension-input.editing {
color: var(--viewport-dimension-editing-color);
}
.viewport-dimension-editable.editing {
border-bottom: 1px solid var(--theme-selection-background);
}
.viewport-dimension-editable.editing.invalid {
border-bottom: 1px solid #d92215;
}
.viewport-dimension-input {
background: transparent;
border: none;
text-align: center;
}
.viewport-dimension-span {
-moz-user-select: none;
}

View File

@@ -13,6 +13,7 @@ DIRS += [
DevToolsModules( DevToolsModules(
'app.js', 'app.js',
'constants.js',
'index.css', 'index.css',
'manager.js', 'manager.js',
'reducers.js', 'reducers.js',