plotboilerplate 1.23.3 → 1.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -1
- package/dist/index.esm.js +1684 -394
- package/dist/index.esm.js.map +1 -1
- package/dist/index.esm.min.js +1 -1
- package/dist/index.esm.min.js.map +1 -1
- package/dist/plotboilerplate.browser.min.js +1 -1
- package/dist/plotboilerplate.browser.min.js.map +1 -1
- package/dist/plotboilerplate.js +12450 -11120
- package/dist/plotboilerplate.min.js +1 -1
- package/package.json +9 -5
- package/src/cjs/BezierPath.d.ts +41 -5
- package/src/cjs/BezierPath.js +52 -2
- package/src/cjs/BezierPath.js.map +1 -1
- package/src/cjs/Bounds.d.ts +67 -3
- package/src/cjs/Bounds.js +101 -3
- package/src/cjs/Bounds.js.map +1 -1
- package/src/cjs/Circle.d.ts +46 -4
- package/src/cjs/Circle.js +82 -3
- package/src/cjs/Circle.js.map +1 -1
- package/src/cjs/CircleSector.d.ts +51 -2
- package/src/cjs/CircleSector.js +112 -3
- package/src/cjs/CircleSector.js.map +1 -1
- package/src/cjs/CubicBezierCurve.d.ts +113 -7
- package/src/cjs/CubicBezierCurve.js +281 -33
- package/src/cjs/CubicBezierCurve.js.map +1 -1
- package/src/cjs/Line.d.ts +38 -3
- package/src/cjs/Line.js +64 -1
- package/src/cjs/Line.js.map +1 -1
- package/src/cjs/PlotBoilerplate.d.ts +37 -6
- package/src/cjs/PlotBoilerplate.js +224 -125
- package/src/cjs/PlotBoilerplate.js.map +1 -1
- package/src/cjs/Polygon.d.ts +68 -5
- package/src/cjs/Polygon.js +143 -22
- package/src/cjs/Polygon.js.map +1 -1
- package/src/cjs/Triangle.d.ts +52 -3
- package/src/cjs/Triangle.js +80 -1
- package/src/cjs/Triangle.js.map +1 -1
- package/src/cjs/VEllipse.d.ts +62 -3
- package/src/cjs/VEllipse.js +181 -17
- package/src/cjs/VEllipse.js.map +1 -1
- package/src/cjs/VEllipseSector.d.ts +86 -2
- package/src/cjs/VEllipseSector.js +148 -4
- package/src/cjs/VEllipseSector.js.map +1 -1
- package/src/cjs/Vector.d.ts +12 -2
- package/src/cjs/Vector.js +15 -2
- package/src/cjs/Vector.js.map +1 -1
- package/src/cjs/VertTuple.d.ts +28 -4
- package/src/cjs/VertTuple.js +36 -3
- package/src/cjs/VertTuple.js.map +1 -1
- package/src/cjs/Vertex.d.ts +31 -4
- package/src/cjs/Vertex.js +35 -1
- package/src/cjs/Vertex.js.map +1 -1
- package/src/cjs/interfaces/core.d.ts +67 -0
- package/src/cjs/interfaces/core.js +4 -0
- package/src/cjs/interfaces/core.js.map +1 -1
- package/src/cjs/utils/algorithms/convexPolygonIncircle.d.ts +2 -1
- package/src/cjs/utils/algorithms/convexPolygonIncircle.js +14 -6
- package/src/cjs/utils/algorithms/convexPolygonIncircle.js.map +1 -1
- package/src/cjs/utils/createRandomizedPolygon.d.ts +14 -0
- package/src/cjs/utils/createRandomizedPolygon.js +32 -0
- package/src/cjs/utils/createRandomizedPolygon.js.map +1 -0
- package/src/cjs/utils/datastructures/Color.d.ts +147 -1
- package/src/cjs/utils/datastructures/Color.js +385 -41
- package/src/cjs/utils/datastructures/Color.js.map +1 -1
- package/src/cjs/utils/datastructures/ColorGradient.d.ts +79 -0
- package/src/cjs/utils/datastructures/ColorGradient.js +171 -0
- package/src/cjs/utils/datastructures/ColorGradient.js.map +1 -0
- package/src/cjs/utils/dom/components/ColorGradientPicker.d.ts +245 -0
- package/src/cjs/utils/dom/components/ColorGradientPicker.js +667 -0
- package/src/cjs/utils/dom/components/ColorGradientPicker.js.map +1 -0
- package/src/cjs/utils/dom/components/ColorGradientPickerJSX.d.ts +129 -0
- package/src/cjs/utils/dom/components/ColorGradientPickerJSX.js +520 -0
- package/src/cjs/utils/dom/components/ColorGradientPickerJSX.js.map +1 -0
- package/src/cjs/utils/dom/components/ColorGradientSelector.d.ts +117 -0
- package/src/cjs/utils/dom/components/ColorGradientSelector.js +325 -0
- package/src/cjs/utils/dom/components/ColorGradientSelector.js.map +1 -0
- package/src/cjs/utils/dom/components/Test.d.ts +7 -0
- package/src/cjs/utils/dom/components/Test.js +30 -0
- package/src/cjs/utils/dom/components/Test.js.map +1 -0
- package/src/cjs/utils/dom/guiSizeToggler.js +1 -1
- package/src/cjs/utils/dom/guiSizeToggler.js.map +1 -1
- package/src/cjs/utils/helpers/BezierPathInteractionHelper.d.ts +16 -8
- package/src/cjs/utils/helpers/BezierPathInteractionHelper.js +49 -28
- package/src/cjs/utils/helpers/BezierPathInteractionHelper.js.map +1 -1
- package/src/cjs/utils/helpers/CircleHelper.d.ts +10 -1
- package/src/cjs/utils/helpers/CircleHelper.js +13 -2
- package/src/cjs/utils/helpers/CircleHelper.js.map +1 -1
- package/src/cjs/utils/helpers/CircleSectorHelper.d.ts +11 -2
- package/src/cjs/utils/helpers/CircleSectorHelper.js +20 -20
- package/src/cjs/utils/helpers/CircleSectorHelper.js.map +1 -1
- package/src/cjs/utils/helpers/TriangleHelper.d.ts +57 -0
- package/src/cjs/utils/helpers/TriangleHelper.js +83 -0
- package/src/cjs/utils/helpers/TriangleHelper.js.map +1 -0
- package/src/cjs/utils/helpers/VEllipseHelper.d.ts +32 -0
- package/src/cjs/utils/helpers/VEllipseHelper.js +88 -0
- package/src/cjs/utils/helpers/VEllipseHelper.js.map +1 -0
- package/src/cjs/utils/helpers/VEllipseSectorHelper.d.ts +44 -4
- package/src/cjs/utils/helpers/VEllipseSectorHelper.js +108 -25
- package/src/cjs/utils/helpers/VEllipseSectorHelper.js.map +1 -1
- package/src/cjs/utils/parsers/LinearColorGradientParser.d.ts +78 -0
- package/src/cjs/utils/parsers/LinearColorGradientParser.js +224 -0
- package/src/cjs/utils/parsers/LinearColorGradientParser.js.map +1 -0
- package/src/createDemoDrawables.js +4 -1
- package/src/esm/BezierPath.d.ts +41 -5
- package/src/esm/BezierPath.js +50 -2
- package/src/esm/BezierPath.js.map +1 -1
- package/src/esm/Bounds.d.ts +67 -3
- package/src/esm/Bounds.js +101 -3
- package/src/esm/Bounds.js.map +1 -1
- package/src/esm/Circle.d.ts +46 -4
- package/src/esm/Circle.js +79 -3
- package/src/esm/Circle.js.map +1 -1
- package/src/esm/CircleSector.d.ts +51 -2
- package/src/esm/CircleSector.js +108 -3
- package/src/esm/CircleSector.js.map +1 -1
- package/src/esm/CubicBezierCurve.d.ts +113 -7
- package/src/esm/CubicBezierCurve.js +277 -33
- package/src/esm/CubicBezierCurve.js.map +1 -1
- package/src/esm/Line.d.ts +38 -3
- package/src/esm/Line.js +62 -1
- package/src/esm/Line.js.map +1 -1
- package/src/esm/PlotBoilerplate.d.ts +37 -6
- package/src/esm/PlotBoilerplate.js +224 -125
- package/src/esm/PlotBoilerplate.js.map +1 -1
- package/src/esm/Polygon.d.ts +68 -5
- package/src/esm/Polygon.js +138 -22
- package/src/esm/Polygon.js.map +1 -1
- package/src/esm/Triangle.d.ts +52 -3
- package/src/esm/Triangle.js +77 -1
- package/src/esm/Triangle.js.map +1 -1
- package/src/esm/VEllipse.d.ts +62 -3
- package/src/esm/VEllipse.js +178 -17
- package/src/esm/VEllipse.js.map +1 -1
- package/src/esm/VEllipseSector.d.ts +86 -2
- package/src/esm/VEllipseSector.js +146 -7
- package/src/esm/VEllipseSector.js.map +1 -1
- package/src/esm/Vector.d.ts +12 -2
- package/src/esm/Vector.js +15 -2
- package/src/esm/Vector.js.map +1 -1
- package/src/esm/VertTuple.d.ts +28 -4
- package/src/esm/VertTuple.js +36 -3
- package/src/esm/VertTuple.js.map +1 -1
- package/src/esm/Vertex.d.ts +31 -4
- package/src/esm/Vertex.js +35 -1
- package/src/esm/Vertex.js.map +1 -1
- package/src/esm/interfaces/core.d.ts +67 -0
- package/src/esm/interfaces/core.js +4 -0
- package/src/esm/interfaces/core.js.map +1 -1
- package/src/esm/utils/algorithms/convexPolygonIncircle.d.ts +2 -1
- package/src/esm/utils/algorithms/convexPolygonIncircle.js +15 -7
- package/src/esm/utils/algorithms/convexPolygonIncircle.js.map +1 -1
- package/src/esm/utils/algorithms/createRandomizedPolygon.d.ts +14 -0
- package/src/esm/utils/algorithms/createRandomizedPolygon.js +28 -0
- package/src/esm/utils/algorithms/createRandomizedPolygon.js.map +1 -0
- package/src/esm/utils/createRandomizedPolygon.d.ts +14 -0
- package/src/esm/utils/createRandomizedPolygon.js +28 -0
- package/src/esm/utils/createRandomizedPolygon.js.map +1 -0
- package/src/esm/utils/datastructures/Color.d.ts +147 -1
- package/src/esm/utils/datastructures/Color.js +386 -42
- package/src/esm/utils/datastructures/Color.js.map +1 -1
- package/src/esm/utils/datastructures/ColorGradient.d.ts +79 -0
- package/src/esm/utils/datastructures/ColorGradient.js +166 -0
- package/src/esm/utils/datastructures/ColorGradient.js.map +1 -0
- package/src/esm/utils/dom/components/ColorGradientPicker.d.ts +245 -0
- package/src/esm/utils/dom/components/ColorGradientPicker.js +732 -0
- package/src/esm/utils/dom/components/ColorGradientPicker.js.map +1 -0
- package/src/esm/utils/dom/components/ColorGradientPickerJSX.d.ts +129 -0
- package/src/esm/utils/dom/components/ColorGradientPickerJSX.js +582 -0
- package/src/esm/utils/dom/components/ColorGradientPickerJSX.js.map +1 -0
- package/src/esm/utils/dom/components/ColorGradientSelector.d.ts +117 -0
- package/src/esm/utils/dom/components/ColorGradientSelector.js +332 -0
- package/src/esm/utils/dom/components/ColorGradientSelector.js.map +1 -0
- package/src/esm/utils/dom/components/Test.d.ts +7 -0
- package/src/esm/utils/dom/components/Test.js +26 -0
- package/src/esm/utils/dom/components/Test.js.map +1 -0
- package/src/esm/utils/dom/guiSizeToggler.js +1 -1
- package/src/esm/utils/dom/guiSizeToggler.js.map +1 -1
- package/src/esm/utils/helpers/BezierPathInteractionHelper.d.ts +16 -8
- package/src/esm/utils/helpers/BezierPathInteractionHelper.js +47 -27
- package/src/esm/utils/helpers/BezierPathInteractionHelper.js.map +1 -1
- package/src/esm/utils/helpers/CircleHelper.d.ts +10 -1
- package/src/esm/utils/helpers/CircleHelper.js +13 -2
- package/src/esm/utils/helpers/CircleHelper.js.map +1 -1
- package/src/esm/utils/helpers/CircleSectorHelper.d.ts +11 -2
- package/src/esm/utils/helpers/CircleSectorHelper.js +20 -20
- package/src/esm/utils/helpers/CircleSectorHelper.js.map +1 -1
- package/src/esm/utils/helpers/TriangleHelper.d.ts +57 -0
- package/src/esm/utils/helpers/TriangleHelper.js +78 -0
- package/src/esm/utils/helpers/TriangleHelper.js.map +1 -0
- package/src/esm/utils/helpers/VEllipseHelper.d.ts +32 -0
- package/src/esm/utils/helpers/VEllipseHelper.js +83 -0
- package/src/esm/utils/helpers/VEllipseHelper.js.map +1 -0
- package/src/esm/utils/helpers/VEllipseSectorHelper.d.ts +44 -4
- package/src/esm/utils/helpers/VEllipseSectorHelper.js +107 -24
- package/src/esm/utils/helpers/VEllipseSectorHelper.js.map +1 -1
- package/src/esm/utils/parsers/LinearColorGradientParser.d.ts +78 -0
- package/src/esm/utils/parsers/LinearColorGradientParser.js +217 -0
- package/src/esm/utils/parsers/LinearColorGradientParser.js.map +1 -0
- package/src/external.d.ts +9 -0
- package/src/ts/BezierPath.ts +58 -5
- package/src/ts/Bounds.ts +110 -6
- package/src/ts/Circle.ts +87 -5
- package/src/ts/CircleSector.ts +115 -5
- package/src/ts/CubicBezierCurve.ts +332 -42
- package/src/ts/Line.ts +66 -3
- package/src/ts/PlotBoilerplate.ts +236 -114
- package/src/ts/Polygon.ts +164 -29
- package/src/ts/Triangle.ts +85 -3
- package/src/ts/VEllipse.ts +214 -19
- package/src/ts/VEllipseSector.ts +154 -8
- package/src/ts/Vector.ts +16 -2
- package/src/ts/VertTuple.ts +39 -4
- package/src/ts/Vertex.ts +40 -4
- package/src/ts/interfaces/core.ts +73 -0
- package/src/ts/utils/algorithms/convexPolygonIncircle.ts +82 -78
- package/src/ts/utils/createRandomizedPolygon.ts +31 -0
- package/src/ts/utils/datastructures/Color.ts +423 -44
- package/src/ts/utils/datastructures/ColorGradient.ts +196 -0
- package/src/ts/utils/dom/components/ColorGradientPicker.tsx +877 -0
- package/src/ts/utils/dom/components/ColorGradientSelector.tsx +445 -0
- package/src/ts/utils/dom/components/Test.tsx +44 -0
- package/src/ts/utils/dom/components/_ColorGradientPicker_raw.ts_ +392 -0
- package/src/ts/utils/dom/guiSizeToggler.ts +1 -1
- package/src/ts/utils/helpers/BezierPathInteractionHelper.ts +61 -35
- package/src/ts/utils/helpers/CircleHelper.ts +17 -3
- package/src/ts/utils/helpers/CircleSectorHelper.ts +118 -126
- package/src/ts/utils/helpers/TriangleHelper.ts +102 -0
- package/src/ts/utils/helpers/VEllipseHelper.ts +115 -0
- package/src/ts/utils/helpers/VEllipseSectorHelper.ts +144 -26
- package/src/ts/utils/parsers/LinearColorGradientParser.ts +297 -0
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A simple class for rendering color gradient dropdowns.
|
|
3
|
+
*
|
|
4
|
+
* As native dropdown do not support custom stylings in the way we need, we will implement
|
|
5
|
+
* our own dropdown class.
|
|
6
|
+
*
|
|
7
|
+
* @author Ikaros Kappler
|
|
8
|
+
* @date 2025-08-19
|
|
9
|
+
* @version 1.0.0
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import * as NoReact from "noreact";
|
|
13
|
+
import { JsxElement } from "typescript";
|
|
14
|
+
|
|
15
|
+
import { Color } from "../../datastructures/Color";
|
|
16
|
+
import { ColorGradient } from "../../datastructures/ColorGradient";
|
|
17
|
+
|
|
18
|
+
export type ColorGradientSelectorChangeListener = (
|
|
19
|
+
colorGradient: ColorGradient,
|
|
20
|
+
gradientIndex: number,
|
|
21
|
+
source: ColorGradientSelector
|
|
22
|
+
) => void;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The initial properties to use.
|
|
26
|
+
*/
|
|
27
|
+
export interface ColorGradientSelectorProps {
|
|
28
|
+
containerID?: string;
|
|
29
|
+
initialGradients?: Array<ColorGradient>;
|
|
30
|
+
selectedGradientIndex?: number;
|
|
31
|
+
isMobileMode?: boolean;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export class ColorGradientSelector {
|
|
35
|
+
private readonly baseID: number;
|
|
36
|
+
private readonly elementID: string;
|
|
37
|
+
|
|
38
|
+
private container: HTMLElement;
|
|
39
|
+
private containerRef: NoReact.Ref<HTMLDivElement>;
|
|
40
|
+
private mainButtonContainerRef: NoReact.Ref<HTMLButtonElement>;
|
|
41
|
+
private positioningContainerRef: NoReact.Ref<HTMLDivElement>;
|
|
42
|
+
|
|
43
|
+
private isMobileMode: boolean;
|
|
44
|
+
private isDropdownOpen: boolean = false;
|
|
45
|
+
|
|
46
|
+
private css_buttonWidth = "100px";
|
|
47
|
+
private css_buttonHeight = "1.8em";
|
|
48
|
+
private css_buttonFontSize = "0.725em";
|
|
49
|
+
|
|
50
|
+
private colorGradients: Array<ColorGradient> = [];
|
|
51
|
+
// TODO: this does not really need to be a pair, does it?
|
|
52
|
+
private colorGradientOptionRefs: Array<{
|
|
53
|
+
mainButton: NoReact.Ref<HTMLButtonElement>;
|
|
54
|
+
deleteButton: NoReact.Ref<HTMLButtonElement>;
|
|
55
|
+
}> = [];
|
|
56
|
+
private selectedGradientIndex: number = -1;
|
|
57
|
+
|
|
58
|
+
private readonly installedChangeListeners: Array<ColorGradientSelectorChangeListener> = [];
|
|
59
|
+
|
|
60
|
+
public static readonly DEFAULT_COLOR_GRADIENTS: Array<ColorGradient> = [
|
|
61
|
+
ColorGradient.createDefault(),
|
|
62
|
+
ColorGradient.createFrom(Color.Red, Color.Green),
|
|
63
|
+
ColorGradient.createFrom(Color.Blue, Color.Gold)
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* The constructor: creates a new color gradient picker in the given container.
|
|
68
|
+
* If no container or ID is given then a new unbound `container` will be created (DIV).
|
|
69
|
+
*
|
|
70
|
+
* Pass a container ID or nothing – in the latter case the constructor will create
|
|
71
|
+
* a new DIV element.
|
|
72
|
+
*
|
|
73
|
+
* @param {string?} containerID - (optional) If you want to use an existing container (should be a DIV).
|
|
74
|
+
*/
|
|
75
|
+
constructor(options?: ColorGradientSelectorProps) {
|
|
76
|
+
options = options || {};
|
|
77
|
+
if (options.containerID) {
|
|
78
|
+
const cont = document.getElementById(options.containerID);
|
|
79
|
+
if (!cont) {
|
|
80
|
+
throw "Cannot create ColorGradientPicker. Component ID does not exist.";
|
|
81
|
+
}
|
|
82
|
+
this.container = cont;
|
|
83
|
+
} else {
|
|
84
|
+
this.container = document.createElement("div");
|
|
85
|
+
}
|
|
86
|
+
this.isMobileMode = Boolean(options.isMobileMode);
|
|
87
|
+
if (this.isMobileMode) {
|
|
88
|
+
this.css_buttonWidth = "200px";
|
|
89
|
+
this.css_buttonHeight = "2.5em";
|
|
90
|
+
this.css_buttonFontSize = "1.25em";
|
|
91
|
+
}
|
|
92
|
+
this.baseID = Math.floor(Math.random() * 65535);
|
|
93
|
+
this.elementID = `color-gradient-selector-${this.baseID}`;
|
|
94
|
+
|
|
95
|
+
this.colorGradients =
|
|
96
|
+
typeof options.initialGradients === "undefined" ? ColorGradientSelector.DEFAULT_COLOR_GRADIENTS : options.initialGradients;
|
|
97
|
+
this.selectedGradientIndex = typeof options.selectedGradientIndex === "undefined" ? 0 : options.selectedGradientIndex;
|
|
98
|
+
|
|
99
|
+
document.head.appendChild(this.__createCustomStylesElement());
|
|
100
|
+
this.container.append(this._render());
|
|
101
|
+
} // END constructor
|
|
102
|
+
|
|
103
|
+
// TODO: implement this?
|
|
104
|
+
public setGradients(gradients: Array<ColorGradient>, selectedIndex: number): void {
|
|
105
|
+
// First empty the container
|
|
106
|
+
this.__removeAllChildNodes(this.positioningContainerRef.current);
|
|
107
|
+
this.colorGradients = [];
|
|
108
|
+
this.colorGradientOptionRefs = [];
|
|
109
|
+
this.selectedGradientIndex = selectedIndex;
|
|
110
|
+
// Re-render button array
|
|
111
|
+
gradients.map((grad: ColorGradient) => {
|
|
112
|
+
this.addGradient(grad);
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
public addGradient(gradient: ColorGradient): void {
|
|
117
|
+
// Render a new button
|
|
118
|
+
const index: number = this.colorGradients.length;
|
|
119
|
+
const refMainContainer: NoReact.Ref<HTMLDivElement> = NoReact.useRef<HTMLDivElement>();
|
|
120
|
+
const refActionButton: NoReact.Ref<HTMLButtonElement> = NoReact.useRef<HTMLButtonElement>();
|
|
121
|
+
const refDeleteButton: NoReact.Ref<HTMLButtonElement> = NoReact.useRef<HTMLButtonElement>();
|
|
122
|
+
|
|
123
|
+
this.__renderOptionButton(gradient, index, refMainContainer, refActionButton, refDeleteButton);
|
|
124
|
+
this.colorGradients.push(gradient);
|
|
125
|
+
this.colorGradientOptionRefs.push({ mainButton: refActionButton, deleteButton: refDeleteButton });
|
|
126
|
+
// Add to container
|
|
127
|
+
this.positioningContainerRef.current.appendChild(refMainContainer.current);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// +---------------------------------------------------------------------------------
|
|
131
|
+
// | A helper function to remove all child nodes.
|
|
132
|
+
// +-------------------------------
|
|
133
|
+
private __removeAllChildNodes(node: Node) {
|
|
134
|
+
while (node.lastChild) {
|
|
135
|
+
node.removeChild(node.lastChild);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Adds a new color gradient change listener to this ColorGradientPicker.
|
|
141
|
+
*
|
|
142
|
+
* @param {ColorGradientChangeListener} listener - The listener to add.
|
|
143
|
+
* @returns {boolean} True, if the listener was added and did not exist before.
|
|
144
|
+
*/
|
|
145
|
+
addChangeListener(listener: ColorGradientSelectorChangeListener): boolean {
|
|
146
|
+
for (var i = 0; i < this.installedChangeListeners.length; i++) {
|
|
147
|
+
if (this.installedChangeListeners[i] === listener) {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
this.installedChangeListeners.push(listener);
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
*
|
|
157
|
+
* @param {ColorGradientChangeListener} listener The listener to remove.
|
|
158
|
+
* @returns {boolean} True, if the listener existed and has been removed.
|
|
159
|
+
*/
|
|
160
|
+
removeChangeListener(listener: ColorGradientSelectorChangeListener): boolean {
|
|
161
|
+
for (var i = 0; i < this.installedChangeListeners.length; i++) {
|
|
162
|
+
if (this.installedChangeListeners[i] === listener) {
|
|
163
|
+
this.installedChangeListeners.splice(i, 1);
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
public getSelectedColorGradient(): ColorGradient {
|
|
171
|
+
return this.colorGradients[this.selectedGradientIndex];
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
private __fireChangeEvent() {
|
|
175
|
+
const newColorGradient = this.getSelectedColorGradient();
|
|
176
|
+
for (var i = 0; i < this.installedChangeListeners.length; i++) {
|
|
177
|
+
this.installedChangeListeners[i](newColorGradient, this.selectedGradientIndex, this);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Creates a handler for click events on the main button.
|
|
183
|
+
*
|
|
184
|
+
* @returns
|
|
185
|
+
*/
|
|
186
|
+
private __mainButtonClickHandler(): (evt: MouseEvent) => void {
|
|
187
|
+
const _self = this;
|
|
188
|
+
return (_evt: MouseEvent): void => {
|
|
189
|
+
// _self.mainButtonContainerRef.current.style.visibility = "hidden";
|
|
190
|
+
_self.positioningContainerRef.current.style.visibility = _self.isDropdownOpen ? "hidden" : "visible";
|
|
191
|
+
_self.isDropdownOpen = !_self.isDropdownOpen;
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Creates a handler for click events on one of the option button in the dropdown.
|
|
197
|
+
*
|
|
198
|
+
* @returns
|
|
199
|
+
*/
|
|
200
|
+
private __optionButtonClickHandler(): (evt: MouseEvent) => void {
|
|
201
|
+
const _self = this;
|
|
202
|
+
return (evt: MouseEvent): void => {
|
|
203
|
+
_self.positioningContainerRef.current.style.visibility = "hidden";
|
|
204
|
+
_self.isDropdownOpen = false;
|
|
205
|
+
const targetButton: HTMLButtonElement = evt.currentTarget as HTMLButtonElement;
|
|
206
|
+
const clickedIndex_raw: string = targetButton.dataset["gradientIndex"];
|
|
207
|
+
const clickedIndex: number = Number.parseInt(clickedIndex_raw);
|
|
208
|
+
console.log("clickedIndex", clickedIndex, clickedIndex_raw, targetButton.dataset, targetButton);
|
|
209
|
+
if (Number.isNaN(clickedIndex)) {
|
|
210
|
+
// Stop here. This is not what we want.
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
// Find child: and set selected.
|
|
214
|
+
_self.__setSelectedIndex(clickedIndex);
|
|
215
|
+
_self.__fireChangeEvent();
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
private __optionButtonDeleteHandler(): (evt: MouseEvent) => void {
|
|
220
|
+
const _self = this;
|
|
221
|
+
return (evt: MouseEvent): void => {
|
|
222
|
+
if (this.colorGradientOptionRefs.length === 1) {
|
|
223
|
+
// Keep the last record
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
const targetButton: HTMLButtonElement = evt.currentTarget as HTMLButtonElement;
|
|
227
|
+
const clickedIndex_raw: string = targetButton.dataset["gradientIndex"];
|
|
228
|
+
const clickedIndex: number = Number.parseInt(clickedIndex_raw);
|
|
229
|
+
console.log("clickedIndex", clickedIndex, clickedIndex_raw, targetButton.dataset, targetButton);
|
|
230
|
+
if (Number.isNaN(clickedIndex)) {
|
|
231
|
+
// Stop here. This is not what we want.
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
// Find child: and remove from DOM
|
|
235
|
+
console.log("this.colorGradientOptionRefs", this.colorGradientOptionRefs, "clickedIndex", clickedIndex);
|
|
236
|
+
const refPair = this.colorGradientOptionRefs[clickedIndex];
|
|
237
|
+
refPair.mainButton.current.parentElement.remove();
|
|
238
|
+
// Remove from logic
|
|
239
|
+
// Remove 1 element at the given index
|
|
240
|
+
this.colorGradients.splice(clickedIndex, 1);
|
|
241
|
+
this.colorGradientOptionRefs.splice(clickedIndex, 1);
|
|
242
|
+
// Update all following elements in the list.
|
|
243
|
+
this.__updateOptionDataSetIndices(clickedIndex);
|
|
244
|
+
if (this.selectedGradientIndex >= clickedIndex) {
|
|
245
|
+
// this.selectedGradientIndex--;
|
|
246
|
+
this.__setSelectedIndex(this.selectedGradientIndex);
|
|
247
|
+
}
|
|
248
|
+
console.log("All refs", this.colorGradientOptionRefs);
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Once a slider element was added or removed then the following indices must be updated.
|
|
254
|
+
*
|
|
255
|
+
* @param {number} startIndex - The slider index to start updating at.
|
|
256
|
+
*/
|
|
257
|
+
__updateOptionDataSetIndices(startIndex: number) {
|
|
258
|
+
// Update all elements to the right of the new elelemt
|
|
259
|
+
for (var i = startIndex; i < this.colorGradientOptionRefs.length; i++) {
|
|
260
|
+
this.colorGradientOptionRefs[i].mainButton.current.dataset["gradientIndex"] = `${i}`;
|
|
261
|
+
this.colorGradientOptionRefs[i].deleteButton.current.dataset["gradientIndex"] = `${i}`;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
private __setSelectedIndex(newSelectedIndex: number): void {
|
|
266
|
+
for (var i = 0; i < this.colorGradientOptionRefs.length; i++) {
|
|
267
|
+
const ref: NoReact.Ref<HTMLButtonElement> = this.colorGradientOptionRefs[i].mainButton;
|
|
268
|
+
// Find child: and set selected.
|
|
269
|
+
ref.current.querySelectorAll(".option-gradient-radio-circle")[0].innerHTML = newSelectedIndex === i ? "🞊" : "🞅";
|
|
270
|
+
}
|
|
271
|
+
this.selectedGradientIndex = newSelectedIndex;
|
|
272
|
+
const selectedGradient = this.colorGradients[this.selectedGradientIndex];
|
|
273
|
+
// Display new gradient in the main button
|
|
274
|
+
this.__setMainButtonGradient(selectedGradient);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Sets the backround color of the main button (of this dropdown) element.
|
|
279
|
+
*
|
|
280
|
+
* @param {ColorGradient} gradient - The gradient color to display. Must not be null.
|
|
281
|
+
*/
|
|
282
|
+
private __setMainButtonGradient(gradient: ColorGradient): void {
|
|
283
|
+
const colorDisplay = this.mainButtonContainerRef.current.querySelectorAll(
|
|
284
|
+
".main-button-gradient-display"
|
|
285
|
+
)[0] as HTMLDivElement;
|
|
286
|
+
colorDisplay.style["background"] = gradient.toColorGradientString();
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Renders a new option button for the dropdown menu.
|
|
291
|
+
*
|
|
292
|
+
* @param {ColorGradient} gradient
|
|
293
|
+
* @returns {JsxElement}
|
|
294
|
+
*/
|
|
295
|
+
private __renderOptionButton(
|
|
296
|
+
gradient: ColorGradient,
|
|
297
|
+
index: number,
|
|
298
|
+
refMainContainer: NoReact.Ref<HTMLDivElement>,
|
|
299
|
+
refActionButton: NoReact.Ref<HTMLButtonElement>,
|
|
300
|
+
refDelButton: NoReact.Ref<HTMLButtonElement>
|
|
301
|
+
): JsxElement {
|
|
302
|
+
return (
|
|
303
|
+
<div sx={{ d: "flex", flexDirection: "row" }} ref={refMainContainer}>
|
|
304
|
+
<button
|
|
305
|
+
className="option-gradient-button"
|
|
306
|
+
onClick={this.__optionButtonClickHandler()}
|
|
307
|
+
style={{
|
|
308
|
+
d: "flex",
|
|
309
|
+
w: "100%",
|
|
310
|
+
fontSize: this.css_buttonFontSize,
|
|
311
|
+
minHeight: this.css_buttonHeight,
|
|
312
|
+
maxHeight: this.css_buttonHeight
|
|
313
|
+
}}
|
|
314
|
+
ref={refActionButton}
|
|
315
|
+
data-gradientIndex={`${index}`}
|
|
316
|
+
>
|
|
317
|
+
<div className="option-gradient-radio-circle" sx={{ w: "2em", flexShrink: 2, alignContent: "center" }}>
|
|
318
|
+
{index === 0 ? "🞊" : "🞅"}
|
|
319
|
+
</div>
|
|
320
|
+
<div sx={{ w: "calc( 100% - 2em )", mr: "1em", background: gradient.toColorGradientString() }}> </div>
|
|
321
|
+
</button>
|
|
322
|
+
<button
|
|
323
|
+
classname="option-delete-button"
|
|
324
|
+
sx={{ fontSize: this.css_buttonFontSize, minHeight: this.css_buttonHeight, maxHeight: this.css_buttonHeight }}
|
|
325
|
+
onClick={this.__optionButtonDeleteHandler()}
|
|
326
|
+
data-gradientIndex={`${index}`}
|
|
327
|
+
ref={refDelButton}
|
|
328
|
+
>
|
|
329
|
+
<div sx={{ w: "2em", flexShrink: 2, alignContent: "center" }}>🗑</div>
|
|
330
|
+
</button>
|
|
331
|
+
</div>
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Creates a new array of option buttons (refs).
|
|
337
|
+
* @returns
|
|
338
|
+
*/
|
|
339
|
+
private _renderAllOptionButtons(): Array<JsxElement> {
|
|
340
|
+
const _self = this;
|
|
341
|
+
// First clear all references
|
|
342
|
+
_self.colorGradientOptionRefs = [];
|
|
343
|
+
return this.colorGradients.map((colorGradient: ColorGradient, index: number) => {
|
|
344
|
+
// console.log("num", num, index);
|
|
345
|
+
const refMainContainer: NoReact.Ref<HTMLDivElement> = NoReact.useRef<HTMLDivElement>();
|
|
346
|
+
const refActionButton: NoReact.Ref<HTMLButtonElement> = NoReact.useRef<HTMLButtonElement>();
|
|
347
|
+
const refDelButton: NoReact.Ref<HTMLButtonElement> = NoReact.useRef<HTMLButtonElement>();
|
|
348
|
+
_self.colorGradientOptionRefs.push({ mainButton: refActionButton, deleteButton: refDelButton });
|
|
349
|
+
return this.__renderOptionButton(colorGradient, index, refMainContainer, refActionButton, refDelButton);
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Init the container contents.
|
|
355
|
+
*
|
|
356
|
+
* @private
|
|
357
|
+
*/
|
|
358
|
+
private _render(): HTMLElement {
|
|
359
|
+
const _self = this;
|
|
360
|
+
// console.log("Rendering ...", NoReact);
|
|
361
|
+
this.containerRef = NoReact.useRef<HTMLDivElement>();
|
|
362
|
+
this.mainButtonContainerRef = NoReact.useRef<HTMLButtonElement>();
|
|
363
|
+
this.positioningContainerRef = NoReact.useRef<HTMLDivElement>();
|
|
364
|
+
|
|
365
|
+
const selectedGradient: ColorGradient = this.colorGradients[this.selectedGradientIndex];
|
|
366
|
+
|
|
367
|
+
return (
|
|
368
|
+
<div
|
|
369
|
+
id={this.elementID}
|
|
370
|
+
className="color-gradient-selector"
|
|
371
|
+
style={{ minWidth: this.css_buttonWidth, maxWidth: this.css_buttonWidth, pos: "relative" }}
|
|
372
|
+
ref={this.containerRef}
|
|
373
|
+
// onMouseDown={this.__containerMouseDownHandler()}
|
|
374
|
+
// onClick={this.__containerClickHandler()}
|
|
375
|
+
>
|
|
376
|
+
<button
|
|
377
|
+
className="main-button"
|
|
378
|
+
ref={this.mainButtonContainerRef}
|
|
379
|
+
style={{
|
|
380
|
+
d: "flex",
|
|
381
|
+
minWidth: this.css_buttonWidth,
|
|
382
|
+
maxWidth: this.css_buttonWidth,
|
|
383
|
+
minHeight: this.css_buttonHeight,
|
|
384
|
+
maxHeight: this.css_buttonHeight
|
|
385
|
+
}}
|
|
386
|
+
onClick={this.__mainButtonClickHandler()}
|
|
387
|
+
>
|
|
388
|
+
<div
|
|
389
|
+
className="main-button-gradient-display"
|
|
390
|
+
sx={{ w: `calc( 100% - ${this.css_buttonFontSize} )`, background: selectedGradient.toColorGradientString() }}
|
|
391
|
+
>
|
|
392
|
+
|
|
393
|
+
</div>
|
|
394
|
+
<div sx={{ w: this.css_buttonHeight, flexShrink: 2, fontSize: this.css_buttonFontSize }}>▾</div>
|
|
395
|
+
</button>
|
|
396
|
+
<div
|
|
397
|
+
className="positioning-container"
|
|
398
|
+
ref={this.positioningContainerRef}
|
|
399
|
+
style={{
|
|
400
|
+
minWidth: this.css_buttonWidth,
|
|
401
|
+
maxHeight: "25vh",
|
|
402
|
+
overflowY: "auto",
|
|
403
|
+
v: "hidden",
|
|
404
|
+
d: "flex",
|
|
405
|
+
fd: "column",
|
|
406
|
+
pos: "absolute",
|
|
407
|
+
l: 0,
|
|
408
|
+
zIndex: 999
|
|
409
|
+
}}
|
|
410
|
+
>
|
|
411
|
+
{_self._renderAllOptionButtons()}
|
|
412
|
+
</div>
|
|
413
|
+
</div>
|
|
414
|
+
);
|
|
415
|
+
} // END function render()
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Adds custom styles (global STYLE tag).
|
|
419
|
+
*
|
|
420
|
+
* @private
|
|
421
|
+
*/
|
|
422
|
+
private __createCustomStylesElement = () => {
|
|
423
|
+
// Thanks to Ana Tudor
|
|
424
|
+
// https://css-tricks.com/multi-thumb-sliders-particular-two-thumb-case/
|
|
425
|
+
return (
|
|
426
|
+
<style>{`
|
|
427
|
+
|
|
428
|
+
#${this.elementID} button {
|
|
429
|
+
border: 0px solid lightgray;
|
|
430
|
+
padding: 0.25em;
|
|
431
|
+
background-color: rgba(255,255,255,0.9);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
#${this.elementID} .main-button:hover {
|
|
435
|
+
background-color: rgba(216,216,216,0.9);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
#${this.elementID} .option-gradient-button:hover, #${this.elementID} .option-delete-button:hover {
|
|
439
|
+
background-color: rgba(216,216,216,0.9);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
`}</style>
|
|
443
|
+
);
|
|
444
|
+
};
|
|
445
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author Ikaros Kappler
|
|
3
|
+
* @date 2025-06-25
|
|
4
|
+
* @version 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as NoReact from "noreact";
|
|
8
|
+
import { JsxElement } from "typescript";
|
|
9
|
+
|
|
10
|
+
export const Test = (name: string): JsxElement => {
|
|
11
|
+
const click1 = () => {
|
|
12
|
+
console.log("First clicked");
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const click2 = () => {
|
|
16
|
+
console.log("Second clicked");
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const mouseEnter = (event: Event) => {
|
|
20
|
+
(event.target as HTMLDivElement).style["background-color"] = "grey";
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const mouseOut = (event: Event) => {
|
|
24
|
+
(event.target as HTMLDivElement).style["background-color"] = "DeepSkyBlue";
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<div className="NoReact-main">
|
|
29
|
+
Hello {name}
|
|
30
|
+
<div className="NoReact-child-1" onClick={click1}>
|
|
31
|
+
Hello Nested
|
|
32
|
+
</div>
|
|
33
|
+
<div
|
|
34
|
+
className="NoReact-child-2"
|
|
35
|
+
onClick={click2}
|
|
36
|
+
onMouseEnter={mouseEnter}
|
|
37
|
+
onMouseOut={mouseOut}
|
|
38
|
+
style={{ backgroundColor: "yellow" }}
|
|
39
|
+
>
|
|
40
|
+
Hello Nested 2
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
);
|
|
44
|
+
};
|