зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1478397
- Part 7: Add a flex item selector in the flexbox panel. r=rcaliman
This commit is contained in:
Родитель
22d4bb0074
Коммит
74d7f402ee
|
@ -4,11 +4,15 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { createRef, PureComponent } = require("devtools/client/shared/vendor/react");
|
||||
const { createFactory, createRef, PureComponent } = require("devtools/client/shared/vendor/react");
|
||||
const dom = require("devtools/client/shared/vendor/react-dom-factories");
|
||||
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
||||
const { translateNodeFrontToGrip } = require("devtools/client/inspector/shared/utils");
|
||||
|
||||
loader.lazyGetter(this, "FlexItemSelector", function() {
|
||||
return createFactory(require("./FlexItemSelector"));
|
||||
});
|
||||
|
||||
// Reps
|
||||
const { REPS, MODE } = require("devtools/client/shared/components/reps/reps");
|
||||
const { Rep } = REPS;
|
||||
|
@ -25,6 +29,7 @@ class FlexContainer extends PureComponent {
|
|||
onSetFlexboxOverlayColor: PropTypes.func.isRequired,
|
||||
onShowBoxModelHighlighterForNode: PropTypes.func.isRequired,
|
||||
onToggleFlexboxHighlighter: PropTypes.func.isRequired,
|
||||
onToggleFlexItemShown: PropTypes.func.isRequired,
|
||||
setSelectedNode: PropTypes.func.isRequired,
|
||||
};
|
||||
}
|
||||
|
@ -96,6 +101,33 @@ class FlexContainer extends PureComponent {
|
|||
nodeFront.scrollIntoView().catch(e => console.error(e));
|
||||
}
|
||||
|
||||
renderFlexItemSelector() {
|
||||
const {
|
||||
flexbox,
|
||||
onToggleFlexItemShown,
|
||||
} = this.props;
|
||||
const {
|
||||
flexItems,
|
||||
highlighted,
|
||||
} = flexbox;
|
||||
|
||||
if (!highlighted || !flexItems.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const selectedFlexItem = flexItems.find(item => item.shown);
|
||||
|
||||
if (!selectedFlexItem) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return FlexItemSelector({
|
||||
flexItem: selectedFlexItem,
|
||||
flexItems,
|
||||
onToggleFlexItemShown,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
flexbox,
|
||||
|
@ -110,47 +142,50 @@ class FlexContainer extends PureComponent {
|
|||
|
||||
return (
|
||||
dom.div({ className: "flex-container devtools-monospace" },
|
||||
dom.label({},
|
||||
dom.input(
|
||||
dom.div({},
|
||||
dom.label({},
|
||||
dom.input(
|
||||
{
|
||||
className: "devtools-checkbox-toggle",
|
||||
checked: highlighted,
|
||||
onChange: this.onFlexboxCheckboxClick,
|
||||
type: "checkbox",
|
||||
}
|
||||
),
|
||||
Rep(
|
||||
{
|
||||
defaultRep: ElementNode,
|
||||
mode: MODE.TINY,
|
||||
object: translateNodeFrontToGrip(nodeFront),
|
||||
onDOMNodeMouseOut: () => onHideBoxModelHighlighter(),
|
||||
onDOMNodeMouseOver: () => onShowBoxModelHighlighterForNode(nodeFront),
|
||||
onInspectIconClick: () => this.onFlexboxInspectIconClick(nodeFront),
|
||||
}
|
||||
)
|
||||
),
|
||||
dom.div(
|
||||
{
|
||||
className: "devtools-checkbox-toggle",
|
||||
checked: highlighted,
|
||||
onChange: this.onFlexboxCheckboxClick,
|
||||
type: "checkbox",
|
||||
className: "layout-color-swatch",
|
||||
ref: this.swatchEl,
|
||||
style: {
|
||||
backgroundColor: color,
|
||||
},
|
||||
title: color,
|
||||
}
|
||||
),
|
||||
Rep(
|
||||
// The SwatchColorPicker relies on the nextSibling of the swatch element to
|
||||
// apply the selected color. This is why we use a span in display: none for
|
||||
// now. Ideally we should modify the SwatchColorPickerTooltip to bypass this
|
||||
// requirement. See https://bugzilla.mozilla.org/show_bug.cgi?id=1341578
|
||||
dom.span(
|
||||
{
|
||||
defaultRep: ElementNode,
|
||||
mode: MODE.TINY,
|
||||
object: translateNodeFrontToGrip(nodeFront),
|
||||
onDOMNodeMouseOut: () => onHideBoxModelHighlighter(),
|
||||
onDOMNodeMouseOver: () => onShowBoxModelHighlighterForNode(nodeFront),
|
||||
onInspectIconClick: () => this.onFlexboxInspectIconClick(nodeFront),
|
||||
}
|
||||
className: "layout-color-value",
|
||||
ref: this.colorValueEl,
|
||||
},
|
||||
color
|
||||
)
|
||||
),
|
||||
dom.div(
|
||||
{
|
||||
className: "layout-color-swatch",
|
||||
ref: this.swatchEl,
|
||||
style: {
|
||||
backgroundColor: color,
|
||||
},
|
||||
title: color,
|
||||
}
|
||||
),
|
||||
// The SwatchColorPicker relies on the nextSibling of the swatch element to apply
|
||||
// the selected color. This is why we use a span in display: none for now.
|
||||
// Ideally we should modify the SwatchColorPickerTooltip to bypass this
|
||||
// requirement. See https://bugzilla.mozilla.org/show_bug.cgi?id=1341578
|
||||
dom.span(
|
||||
{
|
||||
className: "layout-color-value",
|
||||
ref: this.colorValueEl,
|
||||
},
|
||||
color
|
||||
)
|
||||
this.renderFlexItemSelector()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
/* 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 { PureComponent } = require("devtools/client/shared/vendor/react");
|
||||
const dom = require("devtools/client/shared/vendor/react-dom-factories");
|
||||
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
||||
const { translateNodeFrontToGrip } = require("devtools/client/inspector/shared/utils");
|
||||
|
||||
// Reps
|
||||
const { REPS, MODE } = require("devtools/client/shared/components/reps/reps");
|
||||
const { Rep } = REPS;
|
||||
const ElementNode = REPS.ElementNode;
|
||||
|
||||
const Types = require("../types");
|
||||
|
||||
loader.lazyRequireGetter(this, "showMenu", "devtools/client/shared/components/menu/utils", true);
|
||||
|
||||
class FlexItemSelector extends PureComponent {
|
||||
static get propTypes() {
|
||||
return {
|
||||
flexItem: PropTypes.shape(Types.flexItem).isRequired,
|
||||
flexItems: PropTypes.arrayOf(PropTypes.shape(Types.flexItem)).isRequired,
|
||||
onToggleFlexItemShown: PropTypes.func.isRequired,
|
||||
};
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.onShowFlexItemMenu = this.onShowFlexItemMenu.bind(this);
|
||||
}
|
||||
|
||||
onShowFlexItemMenu(event) {
|
||||
const {
|
||||
flexItem,
|
||||
flexItems,
|
||||
onToggleFlexItemShown,
|
||||
} = this.props;
|
||||
const menuItems = [];
|
||||
|
||||
for (const item of flexItems) {
|
||||
const grip = translateNodeFrontToGrip(item.nodeFront);
|
||||
menuItems.push({
|
||||
label: getLabel(grip),
|
||||
type: "checkbox",
|
||||
checked: item === flexItem,
|
||||
click: () => onToggleFlexItemShown(item.nodeFront),
|
||||
});
|
||||
}
|
||||
|
||||
showMenu(menuItems, {
|
||||
button: event.target,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { flexItem } = this.props;
|
||||
|
||||
return (
|
||||
dom.div({ className: "flex-item-selector-wrapper" },
|
||||
dom.button(
|
||||
{
|
||||
id: "flex-item-selector",
|
||||
className: "devtools-button devtools-dropdown-button",
|
||||
onClick: this.onShowFlexItemMenu,
|
||||
},
|
||||
Rep(
|
||||
{
|
||||
defaultRep: ElementNode,
|
||||
mode: MODE.TINY,
|
||||
object: translateNodeFrontToGrip(flexItem.nodeFront)
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a selector label of the Element Rep from the grip. This is based on the
|
||||
* getElements() function in our devtools-reps component for a ElementNode.
|
||||
*
|
||||
* @param {Object} grip
|
||||
* Grip-like object that can be used with Reps.
|
||||
* @return {String} selector label of the element node.
|
||||
*/
|
||||
function getLabel(grip) {
|
||||
const {
|
||||
attributes,
|
||||
nodeName,
|
||||
isAfterPseudoElement,
|
||||
isBeforePseudoElement
|
||||
} = grip.preview;
|
||||
|
||||
if (isAfterPseudoElement || isBeforePseudoElement) {
|
||||
return `::${isAfterPseudoElement ? "after" : "before"}`;
|
||||
}
|
||||
|
||||
let label = nodeName;
|
||||
|
||||
if (attributes.id) {
|
||||
label += `#${attributes.id}`;
|
||||
}
|
||||
|
||||
if (attributes.class) {
|
||||
label += attributes.class
|
||||
.trim()
|
||||
.split(/\s+/)
|
||||
.map(cls => `.${cls}`)
|
||||
.join("");
|
||||
}
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
module.exports = FlexItemSelector;
|
|
@ -95,6 +95,7 @@ class Flexbox extends PureComponent {
|
|||
onSetFlexboxOverlayColor,
|
||||
onShowBoxModelHighlighterForNode,
|
||||
onToggleFlexboxHighlighter,
|
||||
onToggleFlexItemShown,
|
||||
setSelectedNode,
|
||||
} = this.props;
|
||||
|
||||
|
@ -115,6 +116,7 @@ class Flexbox extends PureComponent {
|
|||
onSetFlexboxOverlayColor,
|
||||
onShowBoxModelHighlighterForNode,
|
||||
onToggleFlexboxHighlighter,
|
||||
onToggleFlexItemShown,
|
||||
setSelectedNode,
|
||||
}),
|
||||
this.renderFlexItemList(),
|
||||
|
|
|
@ -10,5 +10,6 @@ DevToolsModules(
|
|||
'FlexContainerProperties.js',
|
||||
'FlexItem.js',
|
||||
'FlexItemList.js',
|
||||
'FlexItemSelector.js',
|
||||
'FlexItemSizingProperties.js',
|
||||
)
|
||||
|
|
|
@ -2,6 +2,14 @@
|
|||
* 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/. */
|
||||
|
||||
:root {
|
||||
--flex-item-selector-wrapper-border-color: var(--theme-content-color3);
|
||||
}
|
||||
|
||||
:root.theme-dark {
|
||||
--flex-item-selector-wrapper-border-color: var(--theme-content-color1);
|
||||
}
|
||||
|
||||
#layout-container {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
@ -112,6 +120,46 @@
|
|||
background-color: transparent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flex Item Selector
|
||||
*/
|
||||
|
||||
.flex-item-selector-wrapper {
|
||||
margin-inline-start: 25px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.flex-item-selector-wrapper::before {
|
||||
position: absolute;
|
||||
left: -12px;
|
||||
top: 3px;
|
||||
content: '';
|
||||
display: block;
|
||||
border-left: 0.5px solid var(--flex-item-selector-wrapper-border-color);
|
||||
height: 0.8em;
|
||||
border-bottom: 0.5px solid var(--flex-item-selector-wrapper-border-color);
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
|
||||
#flex-item-selector {
|
||||
background-position: right 4px center;
|
||||
padding-left: 0;
|
||||
vertical-align: middle;
|
||||
width: 140px;
|
||||
}
|
||||
|
||||
#flex-item-selector .objectBox-node {
|
||||
display: inline-block;
|
||||
font-size: 12px;
|
||||
overflow: hidden;
|
||||
padding-top: 0.15em;
|
||||
text-align: left;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
width: 85%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flex Item Sizing Properties
|
||||
*/
|
||||
|
|
Загрузка…
Ссылка в новой задаче