Bug 1246807 - Implement Editable width / height inputs r=jryans
This commit is contained in:
@@ -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',
|
||||||
|
|||||||
@@ -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({
|
||||||
|
|
||||||
|
|||||||
164
devtools/client/responsive.html/components/viewport-dimension.js
Normal file
164
devtools/client/responsive.html/components/viewport-dimension.js
Normal 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,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
});
|
||||||
@@ -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,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
8
devtools/client/responsive.html/constants.js
Normal file
8
devtools/client/responsive.html/constants.js
Normal 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;
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -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',
|
||||||
|
|||||||
Reference in New Issue
Block a user