plotboilerplate
Version:
A simple javascript plotting boilerplate for 2d stuff.
667 lines • 35.3 kB
JavaScript
"use strict";
/**
* Approach for a 'simple' color gradient picker for my PlotBoilerplate library.
*
* As it turned out a bit more complex in the end – due to the fact that color gradient
* picking is not a super simple task – so I used JSX here. Thus a JSX library is required
* to get this running: NoReact.
*
*
* @author Ikaros Kappler
* @date 2025-06-27
* @modified 2025-09-10 Fixing a color select bug on MacOS.
* @version 1.0.0
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.ColorGradientPicker = void 0;
var NoReact = require("noreact");
var Color_1 = require("../../datastructures/Color");
var ColorGradient_1 = require("../../datastructures/ColorGradient");
var ColorGradientPicker = /** @class */ (function () {
/**
* The constructor: creates a new color gradient picker in the given container.
* If no container or ID is given then a new unbound `container` will be created (DIV).
*
* Pass a container ID or nothing – in the latter case the constructor will create
* a new DIV element.
*
* @param {string?} containerID - (optional) If you want to use an existing container (should be a DIV).
* @param {boolean?} isMobileMode - (optional) If `true` then the elements are rendered in double size.
*/
function ColorGradientPicker(containerID, isMobileMode) {
var _this = this;
this._sliderElementRefs = [];
this.sliderMin = 0;
this.sliderMax = 100;
// Only used during initialization!
this.isMobileMode = false;
this.css_indicatorWidth_num = 1.0;
this.css_indicatorWidth = "1em";
this.css_indicatorHeight = "1em";
this.css_thumbWidth = "0.5em";
this.css_thumbHeight = "1.333em";
this.css_containerHeight = "20px";
this.installedChangeListeners = [];
this.__mouseDownPosition = null;
/**
* Creates a callback function for range slider.
*
* @returns
*/
this.__createSliderChangeHandler = function () {
var _self = _this;
return function (e) {
var targetSlider = e.target;
// console.log("Clicked", targetSlider ? targetSlider.getAttribute("id") : null);
if (!targetSlider) {
return false;
}
var currentSliderValue = Number.parseFloat(targetSlider.value);
var rangeSliderIndexRaw = targetSlider.dataset["rangeSliderIndex"];
// console.log("rangeSliderIndexRaw", rangeSliderIndexRaw);
if (!rangeSliderIndexRaw) {
return false;
}
var rangeSliderIndex = Number.parseInt(rangeSliderIndexRaw);
var leftSliderValue = _this.__getSliderValue(rangeSliderIndex - 1, _self.sliderMin);
var rightSliderValue = _this.__getSliderValue(rangeSliderIndex + 1, _self.sliderMax);
if (leftSliderValue >= currentSliderValue) {
targetSlider.value = "".concat(leftSliderValue);
_self.__updateBackgroundGradient();
_self.__updateColorIndicator(rangeSliderIndex);
return false;
}
else if (rightSliderValue <= currentSliderValue) {
targetSlider.value = "".concat(rightSliderValue);
_self.__updateBackgroundGradient();
_self.__updateColorIndicator(rangeSliderIndex);
return false;
}
else {
_self.__updateBackgroundGradient();
_self.__updateColorIndicator(rangeSliderIndex);
return true;
}
};
};
/**
* Adds custom styles (global STYLE tag).
*
* @private
*/
this.__createCustomStylesElement = function () {
// Thanks to Ana Tudor
// https://css-tricks.com/multi-thumb-sliders-particular-two-thumb-case/
return (NoReact.createElement("style", null, "\n #".concat(_this.elementID, " {\n margin-top: 1em;\n }\n\n #").concat(_this.elementID, " input[type='range'] {\n\n -webkit-appearance: none;\n\n grid-column: 1;\n grid-row: 2;\n \n /* same as before */\n background: none; /* get rid of white Chrome background */\n color: #000;\n font: inherit; /* fix too small font-size in both Chrome & Firefox */\n margin: 0;\n pointer-events: none; /* let clicks pass through */\n }\n\n #").concat(_this.elementID, " input[type='range']::-webkit-slider-runnable-track {\n -webkit-appearance: none;\n\n background: none; /* get rid of Firefox track background */\n height: 100%;\n width: 100%;\n\n pointer-events: none;\n }\n\n #").concat(_this.elementID, " input[type='range']::-webkit-slider-thumb {\n -webkit-appearance: none;\n background: currentcolor;\n border: none; /* get rid of Firefox thumb border */\n border-radius: 6px; /* get rid of Firefox corner rounding */\n pointer-events: auto; /* catch clicks */\n width: ").concat(_this.css_thumbWidth, "; \n height: ").concat(_this.css_thumbHeight, ";\n }\n\n #").concat(_this.elementID, " input[type='range']:focus::-webkit-slider-thumb {\n border: 2px solid white;\n }\n\n #").concat(_this.elementID, " input[type='range']::-moz-range-track {\n -webkit-appearance: none;\n background: none; /* get rid of Firefox track background */\n height: 100%;\n width: 100%;\n pointer-events: none;\n }\n\n #").concat(_this.elementID, " input[type='range']::-moz-range-thumb {\n /* -webkit-appearance: none; */\n background: currentcolor;\n border: none; /* get rid of Firefox thumb border */\n border-radius: 6px; /* get rid of Firefox corner rounding */\n pointer-events: auto; /* catch clicks */\n width: ").concat(_this.css_thumbWidth, "; \n height: ").concat(_this.css_thumbHeight, ";\n }\n\n #").concat(_this.elementID, " input[type='range']:focus::-moz-range-thumb {\n border: 2px solid white;\n }\n\n #").concat(_this.elementID, " input[type='range'] {\n /* same as before */\n z-index: 1;\n }\n \n #").concat(_this.elementID, " input[type='range']:focus {\n z-index: 2;\n /* outline: dotted 1px orange; */\n color: darkorange;\n }\n\n body.darkmode #").concat(_this.elementID, " .color-remove-button { \n background-color: #1e2937;\n color: grey;\n }\n\n body.darkmode #").concat(_this.elementID, " .color-remove-button:hover,\n body.darkmode #").concat(_this.elementID, " .color-remove-button:active { \n background-color: rgba(216,216,216,0.9);\n }\n\n ")));
};
if (containerID) {
var cont = document.getElementById(containerID);
if (!cont) {
throw "Cannot create ColorGradientPicker. Component ID does not exist.";
}
this.container = cont;
}
else {
this.container = document.createElement("div");
}
this.baseID = Math.floor(Math.random() * 65535);
this.elementID = "color-gradient-picker-".concat(this.baseID);
this.colorGradient = ColorGradient_1.ColorGradient.createDefault();
this.isMobileMode = Boolean(isMobileMode);
if (isMobileMode) {
// Double size :)
this.css_indicatorWidth_num = 2.0;
this.css_indicatorWidth = "2em";
this.css_indicatorHeight = "2em";
this.css_thumbWidth = "1.0em";
this.css_thumbHeight = "2.666em";
this.css_containerHeight = "40px";
}
document.head.appendChild(this.__createCustomStylesElement());
this.container.append(this._render());
this.__initializeDataSets();
this.__updateColorIndicator(0);
this.__updateBackgroundGradient();
} // END constructor
ColorGradientPicker.prototype.setGradient = function (gradient, fireChangeEvent) {
// We are lazy: just throw away everything and rebuild all.
this.__removeAllChildNodes(this.container);
this.colorGradient = gradient;
this.container.append(this._render());
this.__initializeDataSets();
this.__updateColorIndicator(0);
this.__updateBackgroundGradient();
if (fireChangeEvent) {
this.__fireChangeEvent();
}
};
// +---------------------------------------------------------------------------------
// | A helper function to remove all child nodes.
// +-------------------------------
ColorGradientPicker.prototype.__removeAllChildNodes = function (node) {
while (node.lastChild) {
node.removeChild(node.lastChild);
}
};
// +---------------------------------------------------------------------------------
// | Used during initialization: define dataset values for each slider.
// +-------------------------------
ColorGradientPicker.prototype.__initializeDataSets = function () {
for (var i = 0; i < this._sliderElementRefs.length; i++) {
var sliderColor = this.colorGradient.values[i].color;
// console.log("Setting up slider color data set", i, sliderColor, sliderColor.cssRGB(), sliderColor.cssHEX());
this._sliderElementRefs[i].current.dataset.colorValue = sliderColor.cssRGB();
this._sliderElementRefs[i].current.dataset.colorValueHEX = sliderColor.cssHEX();
}
};
/**
* Adds a new color gradient change listener to this ColorGradientPicker.
*
* @param {ColorGradientChangeListener} listener - The listener to add.
* @returns {boolean} True, if the listener was added and did not exist before.
*/
ColorGradientPicker.prototype.addChangeListener = function (listener) {
for (var i = 0; i < this.installedChangeListeners.length; i++) {
if (this.installedChangeListeners[i] === listener) {
return false;
}
}
this.installedChangeListeners.push(listener);
return true;
};
/**
*
* @param {ColorGradientChangeListener} listener The listener to remove.
* @returns {boolean} True, if the listener existed and has been removed.
*/
ColorGradientPicker.prototype.removeChangeListener = function (listener) {
for (var i = 0; i < this.installedChangeListeners.length; i++) {
if (this.installedChangeListeners[i] === listener) {
this.installedChangeListeners.splice(i, 1);
return true;
}
}
return false;
};
/**
* Fires a change event to all installed listeners.
*/
ColorGradientPicker.prototype.__fireChangeEvent = function () {
var newColorGradient = this.getColorGradient();
for (var i = 0; i < this.installedChangeListeners.length; i++) {
this.installedChangeListeners[i](newColorGradient, this);
}
};
/**
* Creates a new color range input element.
*
* @private
* @param {number} baseID
* @param index
* @param sliderMin
* @param sliderMax
* @param initialValue
* @param initialColor
* @returns
*/
ColorGradientPicker.prototype.__createColorRangeInput = function (index, sliderMin, sliderMax, initialValue, initialColor) {
var sliderHandler = this.__createSliderChangeHandler();
var ref = NoReact.useRef();
// this._sliderElementRefs.push(ref);
this._sliderElementRefs.splice(index, 0, ref);
// console.log("new _sliderElementRefs", this._sliderElementRefs);
// Update all elements to the right of the new elelemt
this.__updateSliderDataSetIndices(index + 1);
return (NoReact.createElement("input", { id: "rage-slider-".concat(this.baseID, "-").concat(index), type: "range", min: sliderMin, max: sliderMax, value: initialValue, style: { pos: "absolute", l: "0px", t: "0px", w: "100%", h: "60%" }, "data-range-slider-index": "".concat(index), "data-colorValue": initialColor.cssRGB(), "data-colorValueHEX": initialColor.cssHEX(), onChange: sliderHandler, onClick: sliderHandler, ref: ref }));
};
/**
* Get the absolute length of this range, in slider units.
* @returns
*/
ColorGradientPicker.prototype.getRangeLength = function () {
return this.sliderMax - this.sliderMin;
};
/**
* Handles color value changes.
*
* @returns
*/
ColorGradientPicker.prototype.__colorChangeHandler = function () {
var _this = this;
var _self = this;
return function (_evt) {
// console.log("__colorChangeHandler");
var activeSliderIndex_raw = _this.colorInputRef.current.dataset.activeSliderIndex;
if (!activeSliderIndex_raw) {
console.warn("Cannot update color indicator; no active range slider set. This is likely a program error and should not happen.");
return false;
}
var activeSliderIndex = Number.parseInt(activeSliderIndex_raw);
if (Number.isNaN(activeSliderIndex) || activeSliderIndex < 0 || activeSliderIndex >= _self._sliderElementRefs.length) {
console.warn("Cannot update color indicator; active index invalid or out of bounds. This is likely a program error and should not happen.", activeSliderIndex);
return false;
}
var newColor = _self.colorInputRef.current.value;
var rangeSlider = _self._sliderElementRefs[activeSliderIndex].current;
rangeSlider.dataset.colorValue = newColor;
// rangeSlider.dataset["colorValue"] = newColor;
_this.colorIndicatorColorButtonRef.current.style["background-color"] = newColor;
_self.__updateBackgroundGradient();
_self.__fireChangeEvent();
return true;
};
};
/**
* Removed the current color slider from the DOM and highlights the left neighbour.
*
* @returns {boolean} True if the element could be successfully removed.
*/
ColorGradientPicker.prototype.__handleRemoveColor = function () {
// const colorInput : HTMLInputElement | null = evt.target;
// console.log("__colorChangeHandler");
var activeSliderIndex_raw = this.colorInputRef.current.dataset.activeSliderIndex;
if (!activeSliderIndex_raw) {
console.warn("Cannot remove color indicator; no active range slider set.");
return false;
}
var activeSliderIndex = Number.parseInt(activeSliderIndex_raw);
if (Number.isNaN(activeSliderIndex) || activeSliderIndex < 0 || activeSliderIndex >= this._sliderElementRefs.length) {
console.warn("Cannot remove color indicator; active index invalid or out of bounds.", activeSliderIndex);
return false;
}
if (activeSliderIndex === 0 || activeSliderIndex + 1 === this.getRangeLength()) {
console.warn("Cannot remove color indicator; leftmost and rightmost slider must not be removed.", activeSliderIndex);
return false;
}
var sliderElementRef = this._sliderElementRefs[activeSliderIndex];
sliderElementRef.current.remove();
this._sliderElementRefs.splice(activeSliderIndex, 1);
// Update all elements to the right of the removed elelemt
this.__updateSliderDataSetIndices(activeSliderIndex);
// Set left element active
this.__updateColorIndicator(activeSliderIndex - 1);
this.__updateBackgroundGradient();
this.__fireChangeEvent();
return true;
};
/**
* Once a slider element was added or removed then the following indices must be updated.
*
* @param {number} startIndex - The slider index to start updating at.
*/
ColorGradientPicker.prototype.__updateSliderDataSetIndices = function (startIndex) {
// Update all elements to the right of the new elelemt
for (var i = startIndex; i < this._sliderElementRefs.length; i++) {
this._sliderElementRefs[i].current.setAttribute("data-range-slider-index", "".concat(i));
this._sliderElementRefs[i].current.setAttribute("id", "rage-slider-".concat(this.baseID, "-").concat(i));
}
};
/**
* To avoid too many sliders added on each click, check if the mouse was moved in the meantime (detect drag event).
*
* @returns
*/
ColorGradientPicker.prototype.__containerMouseDownHandler = function () {
var _self = this;
return function (event) {
_self.__mouseDownPosition = { x: event.clientX, y: event.clientY };
// console.log("__containerMouseDownHandler _self.__mouseDownPosition", _self.__mouseDownPosition);
};
};
/**
* Creates a handler for click events on the container. If the click event is far
* enough from existing sliders, then it can be added.
*
* @returns
*/
ColorGradientPicker.prototype.__containerClickHandler = function () {
var _this = this;
var _self = this;
var maxDifference = _self.getRangeLength() * 0.03;
return function (evt) {
// console.log("Container click handler");
var relativeValue = _self.__clickEventToRelativeValue(evt);
if (relativeValue < 0 || relativeValue > 1.0) {
// Clicked somewhere outside the range
return;
}
// Check if element was moved in the meantime
if (_self.__mouseDownPosition && Math.abs(_self.__mouseDownPosition.x - evt.clientX) >= 10.0) {
// Ignore event if mouse was moved more than 10 pixels between down- and up-event
// console.log("Mouse was moved more than 10 px. Cancelling.");
_self.__mouseDownPosition = null;
return;
}
var absoluteValue = _this.__relativeToAbsolute(relativeValue);
// console.log("click", "relativeValue", relativeValue, "absoluteValue", absoluteValue);
// Check if click position (ratio) is far enough away from any slider
var _a = _self.__locateClosestSliderValue(absoluteValue), leftSliderIndex = _a[0], closestSliderValue = _a[1];
var diff = Math.abs(closestSliderValue - absoluteValue);
if (diff >= maxDifference) {
// console.log("Add slider here");
_self.__addSliderAt(absoluteValue, leftSliderIndex);
}
else {
// console.debug("Don't add slider here.");
}
// Finally clear mousedown-position
_self.__mouseDownPosition = null;
};
};
/**
* Find that slider (index) that's value is closest to the given absolute value. The function will return
* the closest value and the left index, indicating the containing interval index.
*
* @param {number} absoluteValue - The value to look for.
* @returns {[number,number]} A pair of left slider index and closest value.
*/
ColorGradientPicker.prototype.__locateClosestSliderValue = function (absoluteValue) {
// As the colorGradient always reflects the slider values we can just ust the color gradient itself to search.
var relativeValue = this.__absoluteToRelative(absoluteValue);
var colorGradientEntry = this.colorGradient.locateClosestRatio(relativeValue);
return [colorGradientEntry[0], this.__relativeToAbsolute(colorGradientEntry[1].ratio)];
};
/**
* Convert the click event to the relative x value in [0..1].
*
* @param {MouseEvent} evt - The mouse event.
* @returns {number} The relative x value.
*/
ColorGradientPicker.prototype.__clickEventToRelativeValue = function (evt) {
var target = evt.target;
var rect = target.getBoundingClientRect();
var x = evt.clientX - rect.left; //x position within the element.
var width = rect.width; // target.clientWidth;
var relativeValue = x / width;
// console.log("width", width, "x", x, "relativeValue", relativeValue);
return relativeValue;
};
/**
* Adds a slider at the given interval index.
*
* @param {number} absoluteValue - The absolute new slider value.
* @param {number} leftSliderIndex - The new slider's position (interval index).
*/
ColorGradientPicker.prototype.__addSliderAt = function (absoluteValue, leftSliderIndex) {
// console.log("__addSliderAt", "absoluteValue", absoluteValue, "leftSliderIndex", leftSliderIndex);
var leftSlider = this._sliderElementRefs[leftSliderIndex].current;
// const colorAtPosition = this.__getSliderColorAt(relativeValue);
var newColor = this.__getSliderColorAt(absoluteValue);
var newSliderIndex = leftSliderIndex + 1;
var _newSlider = this.__createColorRangeInput(newSliderIndex, this.sliderMin, this.sliderMax, absoluteValue, newColor // initialColor: string
);
var sliderRef = this._sliderElementRefs[newSliderIndex];
leftSlider.after(sliderRef.current);
sliderRef.current.dataset.colorValue = newColor.cssRGB();
sliderRef.current.dataset.colorValueHEX = newColor.cssHEX();
// No visible change, but let's reflect this in the output gradient anyway
this.__updateBackgroundGradient();
// Highlight the newly added range slider
this.__updateColorIndicator(newSliderIndex);
this.__fireChangeEvent();
};
/**
* Get the slider color at the given absolute value. That value must be inside the [MIN_VALUE, MAX_VALUE] interval.
* @param absoluteValue
* @returns
*/
ColorGradientPicker.prototype.__getSliderColorAt = function (absoluteValue) {
// console.log("__getSliderColorAt", "absoluteValue", absoluteValue);
// Locate interval
var leftIndex = this.__locateIntervalAt(absoluteValue);
var leftSliderValue = this.__getSliderValue(leftIndex, NaN);
var rightSliderValue = this.__getSliderValue(leftIndex + 1, NaN);
if (Number.isNaN(leftSliderValue) || Number.isNaN(rightSliderValue)) {
console.warn("[Warn] Failed to determine left/right slider values at indices ".concat(leftIndex, " or ").concat(rightSliderValue, ". Cannot proceed for absolute value ").concat(absoluteValue, "."));
return null;
}
var leftColorString = this.__getSliderColorString(leftIndex, null);
var rightColorString = this.__getSliderColorString(leftIndex + 1, null);
if (!leftColorString || !rightColorString) {
console.warn("[Warn] Failed to determine left/right color string values at indices ".concat(leftIndex, " or ").concat(rightSliderValue, ". Cannot proceed for absolute value ").concat(absoluteValue, "."));
return null;
}
var positionInsideInterval = (absoluteValue - leftSliderValue) / (rightSliderValue - leftSliderValue);
// console.log("leftColorString", leftColorString, "rightColorString", rightColorString);
var leftColorObject = Color_1.Color.parse(leftColorString);
var rightColorObject = Color_1.Color.parse(rightColorString);
var newColor = leftColorObject.interpolate(rightColorObject, positionInsideInterval);
return newColor;
};
/**
* Locate the slider interval that contains the given (absolute) slider value. The given value must be
* somewhere between MIN_VALUE and MAX_VALUE (usually between 0 and 100 in the default configuraion.).
*
* @param {number} absoluteValue - The absolute value to search for.
* @returns {number} The left slider inder the containing interval is starting with – or -1 if out of bounds.
*/
ColorGradientPicker.prototype.__locateIntervalAt = function (absoluteValue) {
for (var i = 0; i + 1 < this._sliderElementRefs.length; i++) {
if (this.__getSliderValue(i, this.sliderMin) <= absoluteValue &&
absoluteValue < this.__getSliderValue(i + 1, this.sliderMax)) {
return i;
}
}
return -1;
};
/**
* Converts a relative value in [0..1] to [min..max].
* @param relativeValue
*/
ColorGradientPicker.prototype.__relativeToAbsolute = function (relativeValue) {
return this.sliderMin + (this.sliderMax - this.sliderMin) * relativeValue;
};
/**
* Converts a relative value in [0..1] to [min..max].
* @param relativeValue
*/
ColorGradientPicker.prototype.__absoluteToRelative = function (absolute) {
return (absolute - this.sliderMin) / (this.sliderMax - this.sliderMin);
};
/**
* Get the value of the n-th rangel slider.
*
* @param {number} sliderIndex
* @param {number} fallback
* @returns
*/
ColorGradientPicker.prototype.__getSliderValue = function (sliderIndex, fallback) {
if (sliderIndex < 0 || sliderIndex >= this._sliderElementRefs.length) {
return fallback;
}
return Number.parseFloat(this._sliderElementRefs[sliderIndex].current.value);
};
/**
* Get all current slider values as an array.
* @returns
*/
ColorGradientPicker.prototype.__getAllSliderValues = function () {
var _this = this;
return this._sliderElementRefs.map(function (ref, index) { return _this.__getSliderValue(index, NaN); });
};
/**
* Updates the container's background to display the configured color gradient.
*
* @private
*/
ColorGradientPicker.prototype.__updateBackgroundGradient = function () {
var _this = this;
// const colorGradient = this.getColorGradient();
this.colorGradient = new ColorGradient_1.ColorGradient(this.__getAllSliderValues().map(function (sliderValue, sliderIndex) { return ({
color: _this.__getSliderColor(sliderIndex, null),
ratio: _this.__absoluteToRelative(sliderValue)
}); }), this.colorGradient.angle);
this.containerRef.current.style["background"] = this.colorGradient.toColorGradientString();
};
/**
* After changes this function updates the color indicator button.
*
* @param {number} rangeSliderIndex - The new active slider index.
*/
ColorGradientPicker.prototype.__updateColorIndicator = function (rangeSliderIndex) {
var colorValue = this.__getSliderColorHEXString(rangeSliderIndex, "#808080");
var ratio = this.__getSliderPercentage(rangeSliderIndex);
// Set left offset of color input container
this.colorInputContainerRef.current.style["left"] = "calc( ".concat(ratio * 100, "% + ").concat((1.0 - ratio) * this.css_indicatorWidth_num * 0.5, "em - ").concat(ratio * this.css_indicatorWidth_num * 0.5, "em)");
// Also set offset of colot input element (safari will open the native color dialog at this position)
this.colorInputRef.current.style["left"] = "calc( ".concat(ratio * 100, "% + ").concat((1.0 - ratio) * this.css_indicatorWidth_num * 0.5, "em - ").concat(ratio * this.css_indicatorWidth_num * 0.5, "em)");
this.colorIndicatorColorButtonRef.current.style["background-color"] = colorValue;
this.colorInputRef.current.value = colorValue;
// console.log("Setting new color value", this.colorInputRef.current.value, colorValue);
this.colorInputRef.current.dataset.activeSliderIndex = "".concat(rangeSliderIndex);
if (rangeSliderIndex <= 0 || rangeSliderIndex + 1 >= this._sliderElementRefs.length) {
this.colorIndicatorRemoveButtonRef.current.style["visibility"] = "hidden";
}
else {
this.colorIndicatorRemoveButtonRef.current.style["visibility"] = "visible";
}
};
/**
* Get a color gradient CSS value string from the current editor settings.
*
* @instance
* @memberof ColorGradientPicker
* @returns {ColorGradient}
*/
ColorGradientPicker.prototype.getColorGradient = function () {
return this.colorGradient;
};
/**
* Get the configured color value of the n-th rangel slider.
*
* @param {number} sliderIndex
* @param {string} fallback
* @returns
*/
ColorGradientPicker.prototype.__getSliderColorString = function (sliderIndex, fallback) {
if (sliderIndex < 0 || sliderIndex >= this._sliderElementRefs.length) {
return fallback;
}
var colorValue = this._sliderElementRefs[sliderIndex].current.dataset.colorValue;
return colorValue ? colorValue : fallback;
};
/**
* Get the configured color value of the n-th rangel slider.
*
* @param {number} sliderIndex
* @param {string} fallback
* @returns
*/
ColorGradientPicker.prototype.__getSliderColorHEXString = function (sliderIndex, fallback) {
if (sliderIndex < 0 || sliderIndex >= this._sliderElementRefs.length) {
return fallback;
}
var colorValue = this._sliderElementRefs[sliderIndex].current.dataset.colorValueHEX;
return colorValue ? colorValue : fallback;
};
/**
* Get get color of this gradient picker at the given slider index.
*
* @param {number} sliderIndex - The index to get the slider color from. Something between 0 and _sliderElementRefs.length.
* @param {Color} fallback
* @returns
*/
ColorGradientPicker.prototype.__getSliderColor = function (sliderIndex, fallback) {
if (sliderIndex < 0 || sliderIndex >= this._sliderElementRefs.length) {
return fallback;
}
var colorValueString = this._sliderElementRefs[sliderIndex].current.dataset["colorValue"];
var colorValue = Color_1.Color.parse(colorValueString);
return colorValue ? colorValue : fallback;
};
/**
* Get the slider's value in a mapped range of 0.0 ... 1.0.
*
* @param sliderIndex
* @returns
*/
ColorGradientPicker.prototype.__getSliderPercentage = function (sliderIndex) {
var sliderValue = this.__getSliderValue(sliderIndex, 0.0);
var percentage = (this.sliderMin + sliderValue) / (this.sliderMax - this.sliderMin);
return percentage;
};
/**
* Init the container contents.
*
* @private
*/
ColorGradientPicker.prototype._render = function () {
var _this = this;
var _self = this;
// console.log("Rendering ...", NoReact);
this._sliderElementRefs = [];
this.colorIndicatorColorButtonRef = NoReact.useRef();
this.colorIndicatorRemoveButtonRef = NoReact.useRef();
this.colorInputRef = NoReact.useRef();
this.colorInputContainerRef = NoReact.useRef();
this.containerRef = NoReact.useRef();
/**
* This helper method is called when the tiny color button below the active slider is clicked. The method
* triggers the colorInput dialog to be triggered.
*
* @param {Event} evt
*/
var handleIndicatorButtonClick = function (evt) {
evt.preventDefault(); // Prevent other inputs to react to this event.
evt.stopPropagation();
// But fake a click on the input element
// console.log("Current selected color: " + _self.colorInputRef.current.value);
_self.colorInputRef.current.click();
};
/**
* This helper method is called when the remove-color button is clicked. It removes the
* currently active color slider – if possible (leftmost and rightmost slider cannot be removed).
* @param evt
*/
var handleRemoveColorButtonClick = function (evt) {
evt.preventDefault(); // Prevent other inputs to react to this event.
evt.stopPropagation();
_self.__handleRemoveColor();
};
return (NoReact.createElement("div", { id: this.elementID, style: {
d: "flex",
fd: "column",
w: "100%",
h: this.css_containerHeight,
pos: "relative",
mb: this.isMobileMode ? "5em" : "3em"
}, ref: this.containerRef, onMouseDown: this.__containerMouseDownHandler(), onClick: this.__containerClickHandler() },
this.colorGradient.values.map(function (colorGradientItem, index) {
var initialValue = _self.__relativeToAbsolute(colorGradientItem.ratio);
return _this.__createColorRangeInput(index, _this.sliderMin, _this.sliderMax, initialValue, colorGradientItem.color);
}),
NoReact.createElement("div", { style: { w: "100%" } },
NoReact.createElement("input", { id: "color-indicator-input-".concat(this.baseID), type: "color", style: { v: "hidden", pos: "absolute", l: 0 },
// data-active-slider-index=""
ref: this.colorInputRef, onInput: this.__colorChangeHandler() }),
NoReact.createElement("div", { ref: this.colorInputContainerRef, style: {
pos: "absolute",
b: "0px",
l: "0%",
d: "flex",
fd: "column",
transform: "translate(0%, 100%)"
} },
NoReact.createElement("button", { id: "color-indicator-button-".concat(this.baseID), className: "color-indicator-button", style: {
backgroundColor: "grey",
borderRadius: "50%",
border: "1px solid grey",
w: this.css_indicatorWidth, // "1em",
h: this.css_indicatorHeight, // "1em",
transform: "translate(-50%, 0%)"
}, onClick: handleIndicatorButtonClick, ref: this.colorIndicatorColorButtonRef }),
NoReact.createElement("button", { id: "color-remove-button-".concat(this.baseID), className: "color-remove-button", style: {
borderRadius: "10%",
border: "1px solid grey",
w: this.css_indicatorWidth, // "1em",
h: this.css_indicatorHeight, // "1em",
transform: "translate(-50%, 50%)",
lineHeight: "0.5em",
p: 0
}, onClick: handleRemoveColorButtonClick, ref: this.colorIndicatorRemoveButtonRef },
NoReact.createElement("span", { style: { fontSize: this.isMobileMode ? "1.0em" : "0.5em" } }, "\uD83D\uDDD1"))))));
}; // END function render()
return ColorGradientPicker;
}());
exports.ColorGradientPicker = ColorGradientPicker;
//# sourceMappingURL=ColorGradientPicker.js.map