105 lines
3.4 KiB
JavaScript
105 lines
3.4 KiB
JavaScript
/* 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 {
|
|
createFactory,
|
|
PureComponent,
|
|
} = require("resource://devtools/client/shared/vendor/react.js");
|
|
const PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.js");
|
|
|
|
const FontPropertyValue = createFactory(
|
|
require("resource://devtools/client/inspector/fonts/components/FontPropertyValue.js")
|
|
);
|
|
|
|
const {
|
|
getStr,
|
|
} = require("resource://devtools/client/inspector/fonts/utils/l10n.js");
|
|
const {
|
|
getUnitFromValue,
|
|
getStepForUnit,
|
|
} = require("resource://devtools/client/inspector/fonts/utils/font-utils.js");
|
|
|
|
class LetterSpacing extends PureComponent {
|
|
static get propTypes() {
|
|
return {
|
|
disabled: PropTypes.bool.isRequired,
|
|
onChange: PropTypes.func.isRequired,
|
|
value: PropTypes.string.isRequired,
|
|
};
|
|
}
|
|
|
|
constructor(props) {
|
|
super(props);
|
|
// Local state for min/max bounds indexed by unit to allow user input that
|
|
// goes out-of-bounds while still providing a meaningful default range. The indexing
|
|
// by unit is needed to account for unit conversion (ex: em to px) where the operation
|
|
// may result in out-of-bounds values. Avoiding React's state and setState() because
|
|
// `value` is a prop coming from the Redux store while min/max are local. Reconciling
|
|
// value/unit changes is needlessly complicated and adds unnecessary re-renders.
|
|
this.historicMin = {};
|
|
this.historicMax = {};
|
|
}
|
|
|
|
getDefaultMinMax(unit) {
|
|
let min;
|
|
let max;
|
|
switch (unit) {
|
|
case "px":
|
|
min = -10;
|
|
max = 10;
|
|
break;
|
|
default:
|
|
min = -0.2;
|
|
max = 0.6;
|
|
break;
|
|
}
|
|
|
|
return { min, max };
|
|
}
|
|
|
|
render() {
|
|
// For a unitless or a NaN value, default unit to "em".
|
|
const unit = getUnitFromValue(this.props.value) || "em";
|
|
// When the initial value of "letter-spacing" is "normal", the parsed value
|
|
// is not a number (NaN). Guard by setting the default value to 0.
|
|
const isKeywordValue = this.props.value === "normal";
|
|
const value = isKeywordValue ? 0 : parseFloat(this.props.value);
|
|
|
|
let { min, max } = this.getDefaultMinMax(unit);
|
|
min = Math.min(min, value);
|
|
max = Math.max(max, value);
|
|
// Allow lower and upper bounds to move to accomodate the incoming value.
|
|
this.historicMin[unit] = this.historicMin[unit]
|
|
? Math.min(this.historicMin[unit], min)
|
|
: min;
|
|
this.historicMax[unit] = this.historicMax[unit]
|
|
? Math.max(this.historicMax[unit], max)
|
|
: max;
|
|
|
|
return FontPropertyValue({
|
|
allowOverflow: true,
|
|
allowUnderflow: true,
|
|
disabled: this.props.disabled,
|
|
label: getStr("fontinspector.letterSpacingLabel"),
|
|
min: this.historicMin[unit],
|
|
max: this.historicMax[unit],
|
|
name: "letter-spacing",
|
|
onChange: this.props.onChange,
|
|
// Increase the increment granularity because letter spacing is very sensitive.
|
|
step: getStepForUnit(unit) / 100,
|
|
// Show the value input and unit only when the value is not a keyword.
|
|
showInput: !isKeywordValue,
|
|
showUnit: !isKeywordValue,
|
|
unit,
|
|
unitOptions: ["em", "rem", "px"],
|
|
value,
|
|
// Show the value as a read-only label if it's a keyword.
|
|
valueLabel: isKeywordValue ? this.props.value : null,
|
|
});
|
|
}
|
|
}
|
|
|
|
module.exports = LetterSpacing;
|