coral-spectrum/coral-component-colorinput/src/scripts/ColorInputColorProperties.js
/**
* Copyright 2019 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
import {BaseComponent} from '../../../coral-base-component';
import BaseColorInputAbstractSubview from './BaseColorInputAbstractSubview';
import Color from './Color';
import '../../../coral-component-button';
import '../../../coral-component-textfield';
import './ColorInputSlider';
import propertiesSubview from '../templates/colorProperties';
import {commons, i18n} from '../../../coral-utils';
import {Decorator} from '../../../coral-decorator';
const CLASSNAME = '_coral-ColorInput-colorProperties';
/**
@class Coral.ColorInput.ColorProperties
@classdesc A ColorInput Color properties component
@htmltag coral-colorinput-colorproperties
@extends {HTMLElement}
@extends {BaseComponent}
@extends {BaseColorInputAbstractSubview}
*/
const ColorInputColorProperties = Decorator(class extends BaseColorInputAbstractSubview(BaseComponent(HTMLElement)) {
/** @ignore */
constructor() {
super();
this._delegateEvents(commons.extend(this._events, {
'change [handle="redSlider"]': '_onRedSliderChange',
'change [handle="greenSlider"]': '_onGreenSliderChange',
'change [handle="blueSlider"]': '_onBlueSliderChange',
'change [handle="alphaSlider"]': '_onAlphaSliderChange',
'change ._coral-ColorInput-editHex': '_onChangeHex',
'change ._coral-ColorInput-editRgba': '_onChangeRgba'
}));
// Templates
this._elements = {};
propertiesSubview.call(this._elements, {commons, i18n});
}
/** @ignore */
_onColorInputChange() {
const newColor = this._colorinput.valueAsColor;
const colorPreview = this._elements.colorPreview2;
let rgba;
if (!newColor) {
// update the colorPreview background color, state, and label
colorPreview.setAttribute('aria-pressed', 'true');
colorPreview.setAttribute('aria-label', i18n.get('Color not set'));
// reset Hex value to empty
this._elements.hexInput.value = '';
} else {
rgba = newColor.rgba;
// update the colorPreview background color, state, and label
colorPreview.style.backgroundColor = newColor.rgbValue;
colorPreview.setAttribute('aria-pressed', 'false');
colorPreview.setAttribute('aria-label', i18n.get('{value}, Color', {
value: parseFloat(rgba.a) === 1 ? newColor.value : newColor.rgbaValue
}));
// update the Hex input value
this._elements.hexInput.value = newColor.hexValue.substr(1);
}
const prefixes = ['red', 'green', 'blue', 'alpha'];
const prefixesLength = prefixes.length;
let prefix;
let abbr;
let isAlpha;
let val;
// update rgba slider and input values
for (let i = 0 ; i < prefixesLength ; i++) {
prefix = prefixes[i];
abbr = prefix.substr(0, 1);
isAlpha = i === prefixesLength - 1;
// default slider and input value
val = isAlpha ? 100 : 127;
// with new color, get appropriate RGBA value
if (newColor) {
if (!rgba) {
val = '';
} else if (isAlpha) {
val = parseInt(rgba[abbr] * 100, 10);
} else {
val = rgba[abbr];
}
}
// update the slider and input values
this._elements[`${prefix}Slider`].value = this._elements[`${prefix}Input`].value = val;
}
if (colorPreview === document.activeElement) {
// force blur and focus on colorButton so that new color or state is announced
colorPreview.blur();
// delay focus by 100ms so that screen reader has time to adjust to label with updated color value
window.setTimeout(() => {
colorPreview.focus();
}, 100);
}
}
/** @ignore */
_onRedSliderChange(event) {
this._elements.redInput.value = this._elements.redSlider.value;
this._onChangeRgba(event);
}
/** @ignore */
_onGreenSliderChange(event) {
this._elements.greenInput.value = this._elements.greenSlider.value;
this._onChangeRgba(event);
}
/** @ignore */
_onBlueSliderChange(event) {
this._elements.blueInput.value = this._elements.blueSlider.value;
this._onChangeRgba(event);
}
/** @ignore */
_onAlphaSliderChange(event) {
this._elements.alphaInput.value = this._elements.alphaSlider.value;
this._onChangeRgba(event);
}
/** @ignore */
_onChangeHex(event) {
event.stopPropagation();
// Value of hexInput field is without '#'.
const value = `#${this._elements.hexInput.value}`;
const color = new Color();
color.value = value;
if (color.hex === null) {
// no valid color value
this._elements.hexInput.value = '';
// Save last valid color
if (this._colorinput.valueAsColor !== null) {
this.constructor._lastValidColor = this._colorinput.valueAsColor;
}
this._colorinput._setActiveColor(null);
} else {
this._colorinput._setActiveColor(color);
}
}
/** @ignore */
_onChangeRgba(event) {
event.stopPropagation();
const r = parseInt(this._elements.redInput.value, 10);
const g = parseInt(this._elements.greenInput.value, 10);
const b = parseInt(this._elements.blueInput.value, 10);
const a = parseInt(this._elements.alphaInput.value, 10);
let colorValid = true;
if (isNaN(r) || r < 0 || r > 255) {
colorValid = false;
this._elements.redInput.value = '';
}
if (isNaN(g) || g < 0 || g > 255) {
colorValid = false;
this._elements.greenInput.value = '';
}
if (isNaN(b) || b < 0 || b > 255) {
colorValid = false;
this._elements.blueInput.value = '';
}
if (isNaN(a) || a < 0 || a > 100) {
colorValid = false;
this._elements.alphaInput.value = '';
}
if (colorValid) {
const color = new Color();
color.rgba = {
r: r,
g: g,
b: b,
a: a / 100
};
this._colorinput._setActiveColor(color);
}
}
/** @ignore */
render() {
super.render();
this.classList.add(CLASSNAME);
// Support cloneNode
const subview = this.querySelector('._coral-ColorInput-propertiesSubview');
if (subview) {
subview.remove();
}
this.appendChild(this._elements.propertiesSubview);
}
});
export default ColorInputColorProperties;