office-ui-fabric-react
Version:
Reusable React components for building experiences for Microsoft 365.
281 lines • 17.1 kB
JavaScript
define(["require", "exports", "tslib", "react", "../../Utilities", "../../TextField", "./ColorRectangle/ColorRectangle", "./ColorSlider/ColorSlider", "../../utilities/color/consts", "../../utilities/color/getColorFromString", "../../utilities/color/getColorFromRGBA", "../../utilities/color/clamp", "../../utilities/color/updateA", "../../utilities/color/updateT", "../../utilities/color/updateH", "../../utilities/color/correctRGB", "../../utilities/color/correctHex", "./ColorRectangle/ColorRectangle.base"], function (require, exports, tslib_1, React, Utilities_1, TextField_1, ColorRectangle_1, ColorSlider_1, consts_1, getColorFromString_1, getColorFromRGBA_1, clamp_1, updateA_1, updateT_1, updateH_1, correctRGB_1, correctHex_1, ColorRectangle_base_1) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var getClassNames = Utilities_1.classNamesFunction();
var allColorComponents = ['hex', 'r', 'g', 'b', 'a', 't'];
/**
* {@docCategory ColorPicker}
*/
var ColorPickerBase = /** @class */ (function (_super) {
tslib_1.__extends(ColorPickerBase, _super);
function ColorPickerBase(props) {
var _this = _super.call(this, props) || this;
_this._onSVChanged = function (ev, color) {
_this._updateColor(ev, color);
};
_this._onHChanged = function (ev, h) {
_this._updateColor(ev, updateH_1.updateH(_this.state.color, h));
};
/** Callback for when the alpha/transparency slider changes */
_this._onATChanged = function (ev, value) {
var updater = _this.props.alphaType === 'transparency' ? updateT_1.updateT : updateA_1.updateA;
_this._updateColor(ev, updater(_this.state.color, Math.round(value)));
};
_this._onBlur = function (event) {
var _a;
var _b = _this.state, color = _b.color, editingColor = _b.editingColor;
if (!editingColor) {
return;
}
// If there was an intermediate incorrect value (such as too large or empty), correct it.
var value = editingColor.value, component = editingColor.component;
var isHex = component === 'hex';
var isAlpha = component === 'a';
var isTransparency = component === 't';
var minLength = isHex ? consts_1.MIN_HEX_LENGTH : consts_1.MIN_RGBA_LENGTH;
if (value.length >= minLength && (isHex || !isNaN(Number(value)))) {
// Real value. Clamp to appropriate length (hex) or range (rgba).
var newColor = void 0;
if (isHex) {
newColor = getColorFromString_1.getColorFromString('#' + correctHex_1.correctHex(value));
}
else if (isAlpha || isTransparency) {
var updater = isAlpha ? updateA_1.updateA : updateT_1.updateT;
newColor = updater(color, clamp_1.clamp(Number(value), consts_1.MAX_COLOR_ALPHA));
}
else {
newColor = getColorFromRGBA_1.getColorFromRGBA(correctRGB_1.correctRGB(tslib_1.__assign(tslib_1.__assign({}, color), (_a = {}, _a[component] = Number(value), _a))));
}
// Update state and call onChange
_this._updateColor(event, newColor);
}
else {
// Intermediate value was an empty string or too short (hex only).
// Just clear the intermediate state and revert to the previous value.
_this.setState({ editingColor: undefined });
}
};
Utilities_1.initializeComponentRef(_this);
var strings = props.strings; // always defined since it's in defaultProps
Utilities_1.warnDeprecations('ColorPicker', props, {
hexLabel: 'strings.hex',
redLabel: 'strings.red',
greenLabel: 'strings.green',
blueLabel: 'strings.blue',
alphaLabel: 'strings.alpha',
alphaSliderHidden: 'alphaType',
});
// eslint-disable-next-line deprecation/deprecation
if (strings.hue) {
// warnDeprecations can't handle nested deprecated props
Utilities_1.warn("ColorPicker property 'strings.hue' was used but has been deprecated. Use 'strings.hueAriaLabel' instead.");
}
_this.state = {
color: _getColorFromProps(props) || getColorFromString_1.getColorFromString('#ffffff'),
};
_this._textChangeHandlers = {};
for (var _i = 0, allColorComponents_1 = allColorComponents; _i < allColorComponents_1.length; _i++) {
var component = allColorComponents_1[_i];
_this._textChangeHandlers[component] = _this._onTextChange.bind(_this, component);
}
var defaultStrings = ColorPickerBase.defaultProps.strings;
_this._textLabels = {
/* eslint-disable deprecation/deprecation */
r: props.redLabel || strings.red || defaultStrings.red,
g: props.greenLabel || strings.green || defaultStrings.green,
b: props.blueLabel || strings.blue || defaultStrings.blue,
a: props.alphaLabel || strings.alpha || defaultStrings.alpha,
hex: props.hexLabel || strings.hex || defaultStrings.hex,
t: strings.transparency || defaultStrings.transparency,
};
_this._strings = tslib_1.__assign(tslib_1.__assign(tslib_1.__assign({}, defaultStrings), {
// these aria labels default to the visible labels
alphaAriaLabel: _this._textLabels.a, transparencyAriaLabel: _this._textLabels.t }), strings);
return _this;
}
Object.defineProperty(ColorPickerBase.prototype, "color", {
get: function () {
return this.state.color;
},
enumerable: true,
configurable: true
});
ColorPickerBase.prototype.componentDidUpdate = function (prevProps, prevState) {
// if props changed (as opposed to a state update), update the color
if (prevProps !== this.props) {
var color = _getColorFromProps(this.props);
if (color) {
this._updateColor(undefined, color);
}
}
};
ColorPickerBase.prototype.render = function () {
var _this = this;
var props = this.props;
var strings = this._strings;
var textLabels = this._textLabels;
var theme = props.theme, className = props.className, styles = props.styles, alphaType = props.alphaType,
// eslint-disable-next-line deprecation/deprecation
_a = props.alphaSliderHidden,
// eslint-disable-next-line deprecation/deprecation
alphaSliderHidden = _a === void 0 ? alphaType === 'none' : _a;
var color = this.state.color;
var useTransparency = alphaType === 'transparency';
var colorComponents = ['hex', 'r', 'g', 'b', useTransparency ? 't' : 'a'];
var atValue = useTransparency ? color.t : color.a;
var atLabel = useTransparency ? textLabels.t : textLabels.a;
var classNames = getClassNames(styles, {
theme: theme,
className: className,
alphaType: alphaType,
});
var selectedColorAriaParts = [textLabels.r, color.r, textLabels.g, color.g, textLabels.b, color.b];
if (!alphaSliderHidden && typeof atValue === 'number') {
selectedColorAriaParts.push(atLabel, atValue + "%");
}
var ariaLabel = strings.rootAriaLabelFormat.replace('{0}', selectedColorAriaParts.join(' '));
return (React.createElement("div", { className: classNames.root, role: "group", "aria-label": ariaLabel },
React.createElement("div", { className: classNames.panel },
React.createElement(ColorRectangle_1.ColorRectangle, { color: color, onChange: this._onSVChanged, ariaLabel: strings.svAriaLabel, ariaDescription: strings.svAriaDescription, ariaValueFormat: strings.svAriaValueFormat, className: classNames.colorRectangle }),
React.createElement("div", { className: classNames.flexContainer },
React.createElement("div", { className: classNames.flexSlider },
React.createElement(ColorSlider_1.ColorSlider, { className: "is-hue", type: "hue",
// eslint-disable-next-line deprecation/deprecation
ariaLabel: strings.hue || strings.hueAriaLabel, value: color.h, onChange: this._onHChanged }),
!alphaSliderHidden && (React.createElement(ColorSlider_1.ColorSlider, { className: "is-alpha", type: alphaType, ariaLabel: useTransparency ? strings.transparencyAriaLabel : strings.alphaAriaLabel, overlayColor: color.hex, value: atValue, onChange: this._onATChanged }))),
props.showPreview && (React.createElement("div", { className: classNames.flexPreviewBox },
React.createElement("div", { className: classNames.colorSquare + ' is-preview', style: {
backgroundColor: color.str,
} })))),
React.createElement("table", { className: classNames.table, role: "group", cellPadding: "0", cellSpacing: "0" },
React.createElement("thead", null,
React.createElement("tr", { className: classNames.tableHeader },
React.createElement("td", { className: classNames.tableHexCell }, textLabels.hex),
React.createElement("td", null, textLabels.r),
React.createElement("td", null, textLabels.g),
React.createElement("td", null, textLabels.b),
!alphaSliderHidden && React.createElement("td", { className: classNames.tableAlphaCell }, atLabel))),
React.createElement("tbody", null,
React.createElement("tr", null, colorComponents.map(function (comp) {
if ((comp === 'a' || comp === 't') && alphaSliderHidden) {
return null;
}
return (React.createElement("td", { key: comp },
React.createElement(TextField_1.TextField, { className: classNames.input, onChange: _this._textChangeHandlers[comp], onBlur: _this._onBlur, value: _this._getDisplayValue(comp), spellCheck: false, ariaLabel: textLabels[comp], "aria-live": comp !== 'hex' ? 'assertive' : undefined, autoComplete: "off" })));
})))))));
};
ColorPickerBase.prototype._getDisplayValue = function (component) {
var _a = this.state, color = _a.color, editingColor = _a.editingColor;
if (editingColor && editingColor.component === component) {
return editingColor.value;
}
if (component === 'hex') {
return color[component] || '';
}
else if (typeof color[component] === 'number' && !isNaN(color[component])) {
return String(color[component]);
}
return '';
};
ColorPickerBase.prototype._onTextChange = function (component, event, newValue) {
var _a;
var color = this.state.color;
var isHex = component === 'hex';
var isAlpha = component === 'a';
var isTransparency = component === 't';
newValue = (newValue || '').substr(0, isHex ? consts_1.MAX_HEX_LENGTH : consts_1.MAX_RGBA_LENGTH);
// Ignore what the user typed if it contains invalid characters
var validCharsRegex = isHex ? consts_1.HEX_REGEX : consts_1.RGBA_REGEX;
if (!validCharsRegex.test(newValue)) {
return;
}
// Determine if the entry is valid (different methods for hex, alpha, and RGB)
var isValid;
if (newValue === '') {
// Empty string is obviously not valid
isValid = false;
}
else if (isHex) {
// Technically hex values of length 3 are also valid, but committing the value here would
// cause it to be automatically converted to a value of length 6, which may not be what the
// user wanted if they're not finished typing. (Values of length 3 will be committed on blur.)
isValid = newValue.length === consts_1.MAX_HEX_LENGTH;
}
else if (isAlpha || isTransparency) {
isValid = Number(newValue) <= consts_1.MAX_COLOR_ALPHA;
}
else {
isValid = Number(newValue) <= consts_1.MAX_COLOR_RGB;
}
if (!isValid) {
// If the new value is an empty string or other invalid value, save that to display.
// (if the user still hasn't entered anything on blur, the last value is restored)
this.setState({ editingColor: { component: component, value: newValue } });
}
else if (String(color[component]) === newValue) {
// If the new value is the same as the current value, mostly ignore it.
// Exception is that if the user was previously editing the value (but hadn't yet entered
// a new valid value), we should clear the intermediate value.
if (this.state.editingColor) {
this.setState({ editingColor: undefined });
}
}
else {
// Should be a valid color. Update the value.
var newColor = isHex
? getColorFromString_1.getColorFromString('#' + newValue)
: isTransparency
? updateT_1.updateT(color, Number(newValue))
: getColorFromRGBA_1.getColorFromRGBA(tslib_1.__assign(tslib_1.__assign({}, color), (_a = {}, _a[component] = Number(newValue), _a)));
this._updateColor(event, newColor);
}
};
/**
* Update the displayed color and call change handlers if appropriate.
* @param ev - Event if call was triggered by an event (undefined if triggered by props change)
* @param newColor - Updated color
*/
ColorPickerBase.prototype._updateColor = function (ev, newColor) {
if (!newColor) {
return;
}
var _a = this.state, color = _a.color, editingColor = _a.editingColor;
// For black or white, the hue can change without changing the string.
var isDifferentColor = newColor.h !== color.h || newColor.str !== color.str;
if (isDifferentColor || editingColor) {
// If ev is undefined, it's an update from props (which should be unconditionally respected
// and not call onChange).
if (ev && this.props.onChange) {
this.props.onChange(ev, newColor);
if (ev.defaultPrevented) {
return;
}
}
this.setState({ color: newColor, editingColor: undefined });
}
};
ColorPickerBase.defaultProps = {
alphaType: 'alpha',
strings: {
rootAriaLabelFormat: 'Color picker, {0} selected.',
hex: 'Hex',
red: 'Red',
green: 'Green',
blue: 'Blue',
alpha: 'Alpha',
transparency: 'Transparency',
hueAriaLabel: 'Hue',
svAriaLabel: ColorRectangle_base_1.ColorRectangleBase.defaultProps.ariaLabel,
svAriaValueFormat: ColorRectangle_base_1.ColorRectangleBase.defaultProps.ariaValueFormat,
svAriaDescription: ColorRectangle_base_1.ColorRectangleBase.defaultProps.ariaDescription,
},
};
return ColorPickerBase;
}(React.Component));
exports.ColorPickerBase = ColorPickerBase;
function _getColorFromProps(props) {
var color = props.color;
return typeof color === 'string' ? getColorFromString_1.getColorFromString(color) : color;
}
});
//# sourceMappingURL=ColorPicker.base.js.map