Socket
Socket
Sign inDemoInstall

itk-viewer-transfer-function-editor

Package Overview
Dependencies
Maintainers
2
Versions
20
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

itk-viewer-transfer-function-editor - npm Package Compare versions

Comparing version 1.5.0 to 1.6.0

dist/AxisLabels.d.ts

8

dist/Background.d.ts

@@ -7,4 +7,4 @@ import { ColorRangeType } from './ColorRange';

container: {
appendChild: (shape: SVGGraphicsElement) => void;
removeChild: (shape: SVGGraphicsElement) => void;
appendChild: (shape: SVGGraphicsElement, layer?: "underlay" | "overlay") => void;
removeChild: (shape: SVGGraphicsElement, layer?: "underlay" | "overlay") => void;
addSizeObserver: (cb: () => void) => void;

@@ -23,3 +23,5 @@ getViewBox: () => number[];

root: HTMLDivElement;
svg: SVGSVGElement;
overlay: SVGGElement;
eventTarget: EventTarget;
paddedBorder: SVGRectElement;
};

@@ -26,0 +28,0 @@ canvas: HTMLCanvasElement;

import { Point } from './Point';
import { Points } from './Points';
import { ControlPoint } from './ControlPoint';
import { ContainerType } from './Container';
import { ColorTransferFunction } from './PiecewiseUtils';
import { Line } from './Line';
declare class ColorControlPoint extends ControlPoint {
fadedOpacity: string;
getSvgPosition(): number[];
movePoint(e: PointerEvent): void;
}
declare class ColorLine extends Line {
constructor(container: ContainerType, points: Points);
computeStringPoints(): string;
applyOffset(movementX: number, _: number): void;
}
export declare const ColorRange: () => {

@@ -13,2 +22,3 @@ getPoints: () => Point[];

eventTarget: EventTarget;
points: Points;
};

@@ -18,5 +28,7 @@ export type ColorRangeType = ReturnType<typeof ColorRange>;

points: ColorControlPoint[];
line: ColorLine;
setColorTransferFunction: (colorTransferFunction: ColorTransferFunction) => void;
eventTarget: EventTarget;
};
export type ColorRangeControllerType = ReturnType<typeof ColorRangeController>;
export {};
export declare const PADDING = 11;
type Layer = 'underlay' | 'overlay';
export declare const Container: (parent: HTMLElement) => {
appendChild: (shape: SVGGraphicsElement) => void;
removeChild: (shape: SVGGraphicsElement) => void;
appendChild: (shape: SVGGraphicsElement, layer?: Layer) => void;
removeChild: (shape: SVGGraphicsElement, layer?: Layer) => void;
addSizeObserver: (cb: () => void) => void;

@@ -18,4 +19,7 @@ getViewBox: () => number[];

root: HTMLDivElement;
svg: SVGSVGElement;
overlay: SVGGElement;
eventTarget: EventTarget;
paddedBorder: SVGRectElement;
};
export type ContainerType = ReturnType<typeof Container>;
export {};
export declare const makeTestableContainer: () => {
container: {
appendChild: (shape: SVGGraphicsElement) => void;
removeChild: (shape: SVGGraphicsElement) => void;
appendChild: (shape: SVGGraphicsElement, layer?: "underlay" | "overlay") => void;
removeChild: (shape: SVGGraphicsElement, layer?: "underlay" | "overlay") => void;
addSizeObserver: (cb: () => void) => void;

@@ -18,5 +18,7 @@ getViewBox: () => number[];

root: HTMLDivElement;
svg: SVGSVGElement;
overlay: SVGGElement;
eventTarget: EventTarget;
paddedBorder: SVGRectElement;
};
parent: HTMLDivElement;
};

@@ -11,5 +11,7 @@ import { ContainerType } from './Container';

tooltip: ReturnType<typeof addTooltip>;
fadedOpacity: string;
protected container: ContainerType;
protected isDragging: boolean;
protected isHovered: boolean;
protected pointerEntered: boolean;
readonly point: Point;

@@ -25,2 +27,6 @@ deletable: boolean;

remove(): void;
getIsDragging(): boolean;
protected setIsDragging(isDragging: boolean): void;
getIsHovered(): boolean;
protected setIsHovered(isHovered: boolean): void;
getSvgPosition(): number[];

@@ -27,0 +33,0 @@ updateTooltip(xySvg?: [number, number] | undefined): void;

import { ContainerType } from './Container';
import { Points } from './Points';
export declare class Line {
private readonly points;
private container;
protected readonly points: Points;
protected container: ContainerType;
private onPointsUpdated;
element: SVGPolylineElement;
clickabeElement: SVGPolylineElement;
private dragging;
private pointerEntered;
constructor(container: ContainerType, points: Points);
remove(): void;
update(): void;
computeStringPoints(): string;
drag(e: PointerEvent): void;
applyOffset(movementX: number, movementY: number): void;
startInteraction(): void;
setupInteraction(): void;
}

@@ -19,1 +19,7 @@ export type ChartStyle = {

export declare function rgbaToHexa(rgba: Array<number>): string;
export declare const getNodes: (range: number[], points: Array<[number, number]>) => {
x: number;
y: number;
midpoint: number;
sharpness: number;
}[];
import { Point } from './Point';
export declare const windowPoints: (points: [number, number][], clamp?: boolean) => number[][];
export declare const pointsToWindowedPoints: (points: Point[]) => number[][];
export declare const extendPoints: (points: [number, number][], clampEnds?: boolean) => number[][];
export declare const pointsToExtendedPoints: (points: Point[]) => number[][];
export declare class Points {

@@ -5,0 +5,0 @@ private _points;

@@ -6,6 +6,8 @@ import { ContainerType } from './Container';

points: Points;
readonly eventTarget: EventTarget;
private toDataSpace;
private hovered;
private onPointsUpdated;
private controlPoints;
private isNewPointFromPointer;
private toDataSpace;
constructor(container: ContainerType, points: Points, toDataSpace: (x: number) => number);

@@ -16,2 +18,3 @@ remove(): void;

updatePoints(): void;
updateHovered(hovered: boolean): void;
}

@@ -0,3 +1,4 @@

import { ContainerType } from './Container';
import { ColorTransferFunction } from './PiecewiseUtils';
export { windowPointsForSort } from './PiecewiseUtils';
export { windowPointsForSort, getNodes } from './PiecewiseUtils';
export declare class TransferFunctionEditor {

@@ -12,4 +13,4 @@ eventTarget: EventTarget;

private background;
private dataSpaceConverter;
constructor(root: HTMLElement);
private dataRange;
constructor(root: HTMLElement, container?: ContainerType | undefined);
remove(): void;

@@ -16,0 +17,0 @@ getPoints(): number[][];

@@ -1,5 +0,5 @@

var J = Object.defineProperty;
var Q = (n, t, e) => t in n ? J(n, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : n[t] = e;
var a = (n, t, e) => (Q(n, typeof t != "symbol" ? t + "" : t, e), e);
class N {
var ot = Object.defineProperty;
var st = (n, t, e) => t in n ? ot(n, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : n[t] = e;
var a = (n, t, e) => (st(n, typeof t != "symbol" ? t + "" : t, e), e);
class rt {
constructor(t, e) {

@@ -32,3 +32,3 @@ a(this, "_x");

}
const W = (n, t = !1) => {
const j = (n, t = !1) => {
if (n.length === 0)

@@ -40,12 +40,15 @@ return [

if (n.length === 1) {
const [, i] = n[0];
const [, s] = n[0];
return [
[0, i],
[1, i]
[0, s],
[1, s]
];
}
const e = n[0], o = n[n.length - 1];
return t ? [[e[0], 0], ...n, [o[0], 0]] : [[0, e[1]], ...n, [1, o[1]]];
}, j = (n) => W(n.map(({ x: t, y: e }) => [t, e]));
class tt {
if (t)
return [[e[0], 0], ...n, [o[0], 0]];
const i = [];
return e[0] > 0 && i.push([0, e[1]]), i.push(...n), o[0] < 1 && i.push([1, o[1]]), i;
}, Z = (n) => j(n.map(({ x: t, y: e }) => [t, e]));
class q {
constructor() {

@@ -79,3 +82,3 @@ a(this, "_points", []);

createPoint(t, e) {
const o = new N(t, e);
const o = new rt(t, e);
return o.eventTarget.addEventListener("updated", () => {

@@ -89,3 +92,3 @@ this._points.sort((i, s) => i.x - s.x), this.dispatchUpdatedEvent();

}
const et = (n, t, e, o = {
const at = (n, t, e, o = {
lineWidth: 1,

@@ -111,5 +114,5 @@ strokeStyle: "#000",

n.stroke();
}, _ = 1, nt = (n, t, e, o) => {
}, B = 1, dt = (n, t, e, o) => {
const i = o || document.createElement("canvas");
if (i.setAttribute("width", String(t)), i.setAttribute("height", String(_)), n.getSize() === 0)
if (i.setAttribute("width", String(t)), i.setAttribute("height", String(B)), n.getSize() === 0)
return i;

@@ -121,17 +124,17 @@ const s = n.getUint8Table(

!0
), d = i.getContext("2d");
), d = i.getContext("2d", { willReadFrequently: !0 });
if (d) {
const r = d.getImageData(0, 0, t, _);
for (let l = 0; l < _; l++)
r.data.set(s, l * 4 * t);
const p = _ * t * 4;
for (let l = 3; l < p; l += 4)
r.data[l] = 255;
const r = d.getImageData(0, 0, t, B);
for (let c = 0; c < B; c++)
r.data.set(s, c * 4 * t);
const l = B * t * 4;
for (let c = 3; c < l; c += 4)
r.data[c] = 255;
d.putImageData(r, 0, 0);
}
return i;
}, Pt = (n) => {
const t = W(n);
}, ct = (n) => {
const t = j(n);
return t[0][0] -= 1e-8, t[t.length - 1][0] += 1e-8, t;
}, ot = (n) => {
}, lt = (n) => {
if (!n)

@@ -142,3 +145,3 @@ return [];

};
function it(n, t) {
function ht(n, t) {
if (n.length !== t.length)

@@ -151,12 +154,39 @@ return !1;

}
function I(n) {
function $(n) {
return `#${n.map((e) => Math.floor(e * 255)).map((e) => `0${e.toString(16)}`.slice(-2)).join("")}`;
}
const A = 11, st = 2 * A, rt = () => {
const zt = (n, t) => {
const o = ((r) => {
const l = [];
for (let c = 0; c < r.length - 1; c++) {
const g = r[c], p = r[c + 1];
if (g[1] <= 1 && p[1] >= 1 || g[1] >= 1 && p[1] <= 1) {
const S = g[0] + (1 - g[1]) / (p[1] - g[1]) * (p[0] - g[0]);
l.push(S);
}
}
return l;
})(t), i = [...t, ...o.map((r) => [r, 1])], s = ct(
i
), d = n[1] - n[0];
return s.map(([r, l]) => ({
x: n[0] + d * r,
y: Math.min(l, 1),
// vtk.js volume voxels get 0 opacity if y > 1
midpoint: 0.5,
sharpness: 0
}));
}, L = 11, pt = 2 * L, gt = () => {
const n = document.createElementNS("http://www.w3.org/2000/svg", "svg");
return n.setAttribute(
n.setAttribute(
"style",
"position: absolute; top: 0; left: 0; z-index: 2; box-sizing: border-box; width: 100%; height: 100%;"
), n;
}, at = (n) => {
);
const t = document.createElementNS("http://www.w3.org/2000/svg", "g");
n.appendChild(t);
const e = document.createElementNS("http://www.w3.org/2000/svg", "g");
n.appendChild(e);
const o = document.createElementNS("http://www.w3.org/2000/svg", "defs");
return n.appendChild(o), { svg: n, underlay: t, overlay: e, defs: o };
}, ut = (n) => {
const t = document.createElement("div");

@@ -167,64 +197,76 @@ t.setAttribute(

), n.appendChild(t);
const e = rt();
const { svg: e, overlay: o, underlay: i, defs: s } = gt();
t.appendChild(e);
const o = new EventTarget(), i = (g) => {
o.addEventListener("sizeupdated", g);
const d = new EventTarget(), r = (w) => {
d.addEventListener("sizeupdated", w);
};
new ResizeObserver(() => {
o.dispatchEvent(new Event("sizeupdated"));
d.dispatchEvent(new Event("sizeupdated"));
}).observe(t);
const d = document.createElementNS(
const c = document.createElementNS(
"http://www.w3.org/2000/svg",
"rect"
);
e.appendChild(d), d.setAttribute("fill", "none"), d.setAttribute("stroke", "black");
const r = (g) => {
e.appendChild(g);
}, p = (g) => {
e.removeChild(g);
i.appendChild(c), c.setAttribute("fill", "none"), c.setAttribute("stroke", "black"), c.setAttribute("id", "tfeditor-border");
const g = document.createElementNS(
"http://www.w3.org/2000/svg",
"clipPath"
);
g.setAttribute("id", "border-clip"), s.appendChild(g);
const p = document.createElementNS(
"http://www.w3.org/2000/svg",
"use"
);
p.setAttribute("href", "#tfeditor-border"), g.appendChild(p);
const S = (w, b = "underlay") => {
(b === "underlay" ? i : o).appendChild(w);
}, v = (w, b = "underlay") => {
(b === "underlay" ? i : o).removeChild(w);
};
let l = [0, 1, 0, 1];
const E = () => l, u = (g, w, f = 0, b = 1) => {
const T = l;
l = [g, w, f, b], it(T, l) || o.dispatchEvent(new Event("sizeupdated"));
}, S = () => {
const { top: g, left: w, width: f, height: b } = t.getBoundingClientRect();
let h = [0, 1, 0, 1];
const u = () => h, m = (w, b, f = 0, E = 1) => {
const x = h;
h = [w, b, f, E], ht(x, h) || (d.dispatchEvent(new Event("sizeupdated")), d.dispatchEvent(new Event("viewbox-updated")));
}, P = () => {
const { top: w, left: b, width: f, height: E } = t.getBoundingClientRect();
return {
width: f - 2 * A,
height: b - (st + A),
top: g + A,
left: w + A
width: f - 2 * L,
height: E - (pt + L),
top: w + L,
left: b + L
};
}, c = (g, w) => {
const { top: f, left: b, width: T, height: x } = S(), C = l[1] - l[0] || 1e-3, R = l[3] - l[2] || 1e-3;
}, T = (w, b) => {
const { top: f, left: E, width: x, height: R } = P(), A = h[1] - h[0] || 1e-3, I = h[3] - h[2] || 1e-3;
return [
(g - b) / T * C + l[0],
(1 - (w - f) / x) * R + l[2]
(w - E) / x * A + h[0],
(1 - (b - f) / R) * I + h[2]
];
}, h = (g, w) => {
const { width: f, height: b } = S(), T = l[1] - l[0] || 1e-3, x = (g - l[0]) / T * f + A, C = l[3] - l[2] || 1e-3, R = (1 - (w - l[2]) / C) * b + A;
return [x, R];
}, v = () => {
const [g, w] = h(0, 0), [f, b] = h(1, 1);
return { left: g, bottom: w, right: f, top: b };
}, y = (w, b) => {
const { width: f, height: E } = P(), x = h[1] - h[0] || 1e-3, R = (w - h[0]) / x * f + L, A = h[3] - h[2] || 1e-3, I = (1 - (b - h[2]) / A) * E + L;
return [R, I];
}, k = () => {
const [w, b] = y(0, 0), [f, E] = y(1, 1);
return { left: w, bottom: b, right: f, top: E };
};
return i(() => {
const { left: g, bottom: w, right: f, top: b } = v();
d.setAttribute("x", `${g}`), d.setAttribute("y", `${b}`), d.setAttribute("width", `${Math.max(0, f - g)}`), d.setAttribute("height", `${Math.max(0, w - b)}`);
return r(() => {
const { left: w, bottom: b, right: f, top: E } = k();
c.setAttribute("x", `${w}`), c.setAttribute("y", `${E}`), c.setAttribute("width", `${Math.max(0, f - w)}`), c.setAttribute("height", `${Math.max(0, b - E)}`);
}), {
appendChild: r,
removeChild: p,
addSizeObserver: i,
getViewBox: E,
setViewBox: u,
domToNormalized: c,
normalizedToSvg: h,
borderSize: v,
appendChild: S,
removeChild: v,
addSizeObserver: r,
getViewBox: u,
setViewBox: m,
domToNormalized: T,
normalizedToSvg: y,
borderSize: k,
remove: () => n.removeChild(t),
root: t,
svg: e
overlay: o,
eventTarget: d,
paddedBorder: c
};
};
let V = !1;
const dt = () => {
const vt = () => {
if (V)

@@ -239,17 +281,15 @@ return;

position: absolute;
transform: translate(178px, 410.19px);
border-style: solid;
border-color: black;
border-width: 1px;
border-radius: 2px;
font-size: 12px;
padding: 8px;
visibility: hidden;
max-width: 150px;
padding: 4px 6px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
transition: opacity 0.1s ease-in-out;
opacity: 0;
}
`, document.head.appendChild(n);
};
function lt(n) {
dt();
function mt(n) {
vt();
const t = [10, 10], e = document.createElementNS(

@@ -265,13 +305,13 @@ "http://www.w3.org/2000/svg",

o.setAttribute("class", "tfeditor-svg-tooltip"), e.appendChild(o), n.append(e);
function i(p, l, E) {
let u = l + t[0], S = E + t[1];
o.textContent = p;
const c = n.getBBox(), h = o.getBoundingClientRect();
u > c.width - h.width && (u = l - h.width - t[0]), S > c.height - h.height && (S = E - h.height - t[1]), o.style.transform = `translate(${u}px,${S}px)`;
function i(l, c, g) {
let p = c + t[0], S = g + t[1];
o.textContent = l;
const v = n.getBBox(), h = o.getBoundingClientRect();
p > v.width - h.width && (p = c - h.width - t[0]), S > v.height - h.height && (S = g - h.height - t[1]), o.style.transform = `translate(${p}px,${S}px)`;
}
function s() {
o.style.visibility = "visible";
o.style.opacity = "1";
}
function d() {
o.style.visibility = "hidden";
o.style.opacity = "0";
}

@@ -282,7 +322,7 @@ return { update: i, show: s, hide: d, remove: () => {

}
const ct = "controlPoint", U = (n) => Math.max(0, Math.min(1, n)), z = 2, ht = 8, G = 14, P = G, pt = () => {
const wt = "controlPoint", U = (n) => Math.max(0, Math.min(1, n)), N = 2, bt = 8, K = 14, C = K, ft = () => {
const n = document.createElementNS("http://www.w3.org/2000/svg", "svg");
n.setAttribute("width", String(P * 2)), n.setAttribute("height", String(P * 2)), n.setAttribute(
n.setAttribute("width", String(C * 2)), n.setAttribute("height", String(C * 2)), n.setAttribute(
"viewBox",
`-${P} -${P} ${P * 2} ${P * 2}`
`-${C} -${C} ${C * 2} ${C * 2}`
);

@@ -293,3 +333,3 @@ const t = document.createElementNS(

);
t.setAttribute("r", String(ht)), t.setAttribute("fill", "white"), t.setAttribute("stroke", "black"), t.setAttribute("stroke-width", String(z)), t.setAttribute("class", ct), n.appendChild(t);
t.setAttribute("r", String(bt)), t.setAttribute("fill", "white"), t.setAttribute("stroke", "black"), t.setAttribute("stroke-width", String(N)), t.setAttribute("class", wt), t.style.transition = "opacity 0.05s ease-in-out", n.appendChild(t);
const e = document.createElementNS(

@@ -299,5 +339,5 @@ "http://www.w3.org/2000/svg",

);
return e.setAttribute("r", String(G)), e.setAttribute("fill", "transparent"), e.setAttribute("stroke", "transparent"), e.setAttribute("style", "cursor: move;"), n.appendChild(e), { group: n, circle: t, clickTarget: e };
return e.setAttribute("r", String(K)), e.setAttribute("fill", "transparent"), e.setAttribute("stroke", "transparent"), e.setAttribute("style", "cursor: move;"), n.appendChild(e), { group: n, circle: t, clickTarget: e };
};
class O {
class F {
constructor(t, e, o, i, s = !1) {

@@ -307,5 +347,7 @@ a(this, "element");

a(this, "tooltip");
a(this, "fadedOpacity", "0");
a(this, "container");
a(this, "isDragging", !1);
a(this, "isHovered", !1);
a(this, "pointerEntered", !1);
a(this, "point");

@@ -318,7 +360,7 @@ a(this, "deletable", !0);

a(this, "toDataSpace");
const { group: d, circle: r } = pt();
this.element = d, this.circle = r, this.point = e, this.container = t, this.toDataSpace = o, this.tooltip = lt(this.container.svg), t.addSizeObserver(() => {
const { group: d, circle: r } = ft();
this.element = d, this.circle = r, this.point = e, this.container = t, this.toDataSpace = o, this.tooltip = mt(this.container.overlay), t.addSizeObserver(() => {
this.positionElement();
}), i && this.eventTarget.addEventListener(this.DELETE_EVENT, (p) => {
i(p);
}), i && this.eventTarget.addEventListener(this.DELETE_EVENT, (l) => {
i(l);
}), t.appendChild(this.element), this.positionElement(), this.point.eventTarget.addEventListener(

@@ -330,4 +372,16 @@ "updated",

remove() {
this.tooltip.remove(), this.container.removeChild(this.element);
this.pointerEntered = !1, this.update(), this.tooltip.remove(), this.container.removeChild(this.element);
}
getIsDragging() {
return this.isDragging;
}
setIsDragging(t) {
this.isDragging !== t && (this.isDragging = t, this.eventTarget.dispatchEvent(new Event("dragging-updated")));
}
getIsHovered() {
return this.isHovered;
}
setIsHovered(t) {
this.isHovered !== t && (t ? this.tooltip.show() : this.tooltip.hide(), this.isHovered = t, this.eventTarget.dispatchEvent(new Event("hovered-updated")));
}
getSvgPosition() {

@@ -337,2 +391,3 @@ const { x: t, y: e } = this.point;

}
// Pass xySvg to avoid recomputing
updateTooltip(t = void 0) {

@@ -344,3 +399,3 @@ const { x: e } = this.point, o = this.toDataSpace(e), [i, s] = t ?? this.getSvgPosition();

const [t, e] = this.getSvgPosition();
this.element.setAttribute("x", String(t - P)), this.element.setAttribute("y", String(e - P)), this.updateTooltip([t, e]);
this.element.setAttribute("x", String(t - C)), this.element.setAttribute("y", String(e - C)), this.updateTooltip([t, e]), this.point.x > 1.001 || this.point.x < -1e-3 || this.point.y > 1.001 || this.point.y < -1e-3 ? this.circle.style.opacity = this.fadedOpacity : this.circle.style.opacity = "1";
}

@@ -352,8 +407,8 @@ movePoint(t) {

update() {
this.circle.setAttribute("stroke-width", String(z)), this.isHovered && (this.circle.setAttribute("stroke-width", String(z + 1)), this.updateTooltip(), this.tooltip.show()), this.isDragging && this.circle.setAttribute("stroke-width", String(z * 2)), !this.isDragging && !this.isHovered && this.tooltip.hide();
this.circle.setAttribute("stroke-width", String(N)), this.pointerEntered && (this.circle.setAttribute("stroke-width", String(N + 1)), this.updateTooltip(), this.setIsHovered(!0)), this.isDragging && this.circle.setAttribute("stroke-width", String(N * 2)), !this.isDragging && !this.pointerEntered && this.setIsHovered(!1);
}
startInteraction(t = !1) {
this.isDragging = t, !this.isDragging && this.deletable && this.circle.setAttribute("stroke", "red");
this.setIsDragging(t), !this.isDragging && this.deletable && this.circle.setAttribute("stroke", "red");
const e = (i) => {
this.isDragging || this.circle.setAttribute("stroke", "black"), this.isDragging = !0, this.movePoint(i);
this.isDragging || this.circle.setAttribute("stroke", "black"), this.setIsDragging(!0), this.movePoint(i);
};

@@ -366,3 +421,3 @@ document.addEventListener("pointermove", e);

}
this.isDragging = !1, this.update();
this.setIsDragging(!1), this.update();
};

@@ -373,3 +428,3 @@ document.addEventListener("pointerup", o);

this.element.addEventListener("pointerdown", (t) => {
t.stopPropagation(), this.circle.setAttribute("stroke-width", String(z * 2));
t.stopPropagation(), this.circle.setAttribute("stroke-width", String(N * 2));
const [e, o] = this.container.domToNormalized(

@@ -381,5 +436,5 @@ t.clientX,

}), this.element.addEventListener("pointerenter", () => {
this.isHovered = !0, this.update();
this.pointerEntered = !0, this.update();
}), this.element.addEventListener("pointerleave", () => {
this.isHovered = !1, this.update();
this.pointerEntered = !1, this.update();
});

@@ -391,11 +446,13 @@ }

}
a(O, "styleElement");
class gt {
a(F, "styleElement");
class Et {
constructor(t, e, o) {
a(this, "container");
a(this, "points");
a(this, "eventTarget", new EventTarget());
a(this, "toDataSpace");
a(this, "hovered", !1);
a(this, "onPointsUpdated");
a(this, "controlPoints", []);
a(this, "isNewPointFromPointer", !1);
a(this, "toDataSpace");
this.container = t, this.points = e, this.toDataSpace = o;

@@ -422,15 +479,26 @@ const { root: i } = t;

);
const e = (i) => this.controlPoints.find((s) => s.point === i), o = (i) => this.controlPoints.push(
new O(
const e = (i) => this.controlPoints.find((s) => s.point === i), o = (i) => {
const s = new F(
this.container,
i,
this.toDataSpace,
(s) => this.onControlPointDelete(s),
(d) => this.onControlPointDelete(d),
this.isNewPointFromPointer
)
);
);
s.eventTarget.addEventListener(
"hovered-updated",
() => this.updateHovered(s.getIsHovered())
), this.controlPoints.push(s);
};
this.points.points.filter((i) => !e(i)).forEach(o);
}
updateHovered(t) {
t !== this.hovered && (this.hovered = t, this.eventTarget.dispatchEvent(
new CustomEvent("hovered-updated", {
detail: { hovered: this.hovered }
})
));
}
}
const ut = () => {
const X = () => {
const n = document.createElementNS(

@@ -440,5 +508,5 @@ "http://www.w3.org/2000/svg",

);
return n.setAttribute("fill", "none"), n.setAttribute("stroke", "black"), n.setAttribute("stroke-width", "2"), n;
return n.setAttribute("fill", "none"), n.setAttribute("stroke", "black"), n.setAttribute("stroke-width", "2"), n.setAttribute("style", "cursor: move;"), n.setAttribute("clip-path", "url(#border-clip)"), n;
};
class mt {
class J {
constructor(t, e) {

@@ -449,5 +517,8 @@ a(this, "points");

a(this, "element");
this.container = t, this.points = e, this.element = ut(), this.container.appendChild(this.element), this.onPointsUpdated = () => this.update(), this.points.eventTarget.addEventListener("updated", this.onPointsUpdated), this.container.addSizeObserver(() => {
a(this, "clickabeElement");
a(this, "dragging", !1);
a(this, "pointerEntered", !1);
this.container = t, this.points = e, this.element = X(), this.element.setAttribute("pointer-events", "none"), this.container.appendChild(this.element), this.clickabeElement = X(), this.clickabeElement.setAttribute("stroke-width", "8"), this.clickabeElement.setAttribute("stroke", "none"), this.clickabeElement.setAttribute("pointer-events", "stroke"), this.container.appendChild(this.clickabeElement), this.onPointsUpdated = () => this.update(), this.points.eventTarget.addEventListener("updated", this.onPointsUpdated), this.container.addSizeObserver(() => {
this.update();
}), this.update();
}), this.update(), this.setupInteraction();
}

@@ -458,13 +529,45 @@ remove() {

update() {
if (this.points.points.length === 0) {
this.element.setAttribute("points", "");
if (this.pointerEntered && this.element.setAttribute("stroke-width", "4"), this.dragging && this.element.setAttribute("stroke-width", "5"), !this.pointerEntered && !this.dragging && this.element.setAttribute("stroke-width", "2"), this.points.points.length === 0) {
this.element.setAttribute("points", ""), this.clickabeElement.setAttribute("points", "");
return;
}
const t = j(this.points.points).map(([e, o]) => this.container.normalizedToSvg(e, o)).map(([e, o]) => `${e},${o}`).join(" ");
this.element.setAttribute("points", t);
const t = this.computeStringPoints();
this.element.setAttribute("points", t), this.clickabeElement.setAttribute("points", t);
}
computeStringPoints() {
return Z(this.points.points).map(([t, e]) => this.container.normalizedToSvg(t, e)).map(([t, e]) => `${t},${e}`).join(" ");
}
drag(t) {
const [e, o] = this.container.domToNormalized(0, 0), [i, s] = this.container.domToNormalized(t.movementX, t.movementY), d = i - e, r = s - o;
this.applyOffset(d, r);
}
applyOffset(t, e) {
this.points.points.forEach((o) => {
o.setPosition(o.x + t, o.y + e);
});
}
startInteraction() {
this.element.setAttribute("stroke-width", "5");
const t = (o) => {
this.dragging = !0, this.drag(o);
};
document.addEventListener("pointermove", t);
const e = () => {
document.removeEventListener("pointermove", t), document.removeEventListener("pointerup", e), this.dragging = !1, this.update();
};
document.addEventListener("pointerup", e);
}
setupInteraction() {
this.clickabeElement.addEventListener("pointerdown", (t) => {
t.stopPropagation(), this.startInteraction();
}), this.clickabeElement.addEventListener("pointerenter", () => {
this.pointerEntered = !0, this.update();
}), this.clickabeElement.addEventListener("pointerleave", () => {
this.pointerEntered = !1, this.update();
});
}
}
const H = 1.1, vt = (n) => {
const Y = 1.1, St = (n) => {
n.root.addEventListener("wheel", (t) => {
const e = t.deltaY > 0 ? H : 1 / H, [o] = n.domToNormalized(t.clientX, t.clientY), [i, s] = n.getViewBox(), d = Math.max(
const e = t.deltaY > 0 ? Y : 1 / Y, [o] = n.domToNormalized(t.clientX, t.clientY), [i, s] = n.getViewBox(), d = Math.max(
0,

@@ -475,3 +578,3 @@ i - Math.max(0, o - i) * (e - 1)

});
}, X = "rgba(50, 50, 50, 0.3)", wt = (n, t, e) => {
}, G = "rgba(50, 50, 50, 0.3)", Tt = (n, t, e) => {
const o = document.createElement("canvas");

@@ -481,26 +584,28 @@ n.root.appendChild(o), o.setAttribute("style", "width: 100%; height: 100%; ");

let s, d;
const r = document.createElement("canvas"), p = () => {
const r = document.createElement("canvas"), l = () => {
if (i) {
if (i.clearRect(0, 0, o.width, o.height), s) {
const { width: u, height: S } = n.root.getBoundingClientRect();
o.setAttribute("width", String(u)), o.setAttribute("height", String(S));
const { left: c, right: h, bottom: v, top: m } = n.borderSize();
if (Math.ceil(h - c) < 0)
const { width: v, height: h } = n.root.getBoundingClientRect();
o.setAttribute("width", String(v)), o.setAttribute("height", String(h));
const { left: u, right: m, bottom: P, top: T } = n.borderSize(), y = Math.ceil(m - u);
if (y < 0)
return;
const g = j(t.points), w = [[0, 0], ...g, [1, 0]].map(
([L, k]) => n.normalizedToSvg(L, k)
const k = Z(t.points), M = [[0, 0], ...k, [1, 0]].map(
([D, z]) => n.normalizedToSvg(D, z)
);
i.save(), i.beginPath(), w.forEach(([L, k]) => {
i.lineTo(L, k);
i.save(), i.beginPath(), M.forEach(([D, z]) => {
i.lineTo(D, z);
}), i.clip();
const [f, b] = e.getColorRange(), [T] = n.normalizedToSvg(f, 1), [x] = n.normalizedToSvg(b, 1), C = Math.min(u, Math.max(0, T)), R = Math.min(u, Math.max(0, x)), D = R - C < 2 ? C + 2 : R, $ = Math.ceil(D - C);
const O = new Path2D();
O.rect(u, T, y, P - T), i.clip(O);
const [w, b] = e.getColorRange(), [f] = n.normalizedToSvg(w, 1), [E] = n.normalizedToSvg(b, 1), x = Math.min(v, Math.max(0, f)), R = Math.min(v, Math.max(0, E)), A = R - x < 2 ? x + 2 : R, I = Math.ceil(A - x);
if (s) {
const L = x - T, k = (C - T) / L, K = (D - x) / L, M = s.getMappingRange(), F = M[1] - M[0], Z = [
M[0] + F * k,
M[1] + F * K
const D = E - f, z = (x - f) / D, et = (A - E) / D, _ = s.getMappingRange(), H = _[1] - _[0], nt = [
_[0] + H * z,
_[1] + H * et
];
nt(
dt(
s,
$,
Z,
I,
nt,
r

@@ -513,8 +618,8 @@ ), i.drawImage(

r.height,
Math.floor(C),
Math.floor(m),
$,
Math.ceil(v - m)
Math.floor(x),
Math.floor(T),
I,
Math.ceil(P - T)
);
const q = i.imageSmoothingEnabled;
const it = i.imageSmoothingEnabled;
i.imageSmoothingEnabled = !1, i.drawImage(

@@ -527,5 +632,5 @@ r,

0,
Math.floor(m),
Math.floor(C),
Math.ceil(v - m)
Math.floor(T),
Math.floor(x),
Math.ceil(P - T)
), i.drawImage(

@@ -537,7 +642,7 @@ r,

1,
Math.floor(D),
Math.floor(m),
u - D,
Math.ceil(v - m)
), i.imageSmoothingEnabled = q;
Math.floor(A),
Math.floor(T),
v - A,
Math.ceil(P - T)
), i.imageSmoothingEnabled = it;
}

@@ -547,7 +652,7 @@ i.restore();

if (d) {
const { left: u, right: S, bottom: c, top: h } = n.borderSize(), v = [u, h, S - u, c - h];
et(i, v, d, {
const { left: v, right: h, bottom: u, top: m } = n.borderSize(), P = [v, m, h - v, u - m];
at(i, P, d, {
lineWidth: 1,
strokeStyle: X,
fillStyle: X
strokeStyle: G,
fillStyle: G
});

@@ -557,23 +662,54 @@ }

};
return n.addSizeObserver(p), t.eventTarget.addEventListener("updated", p), e.eventTarget.addEventListener("updated", p), {
let c;
const g = () => {
clearTimeout(c), c = setTimeout(() => {
l();
}, 0);
};
return n.addSizeObserver(g), t.eventTarget.addEventListener("updated", g), e.eventTarget.addEventListener("updated", g), {
container: n,
canvas: o,
setColorTransferFunction: (u) => {
s = u, p();
setColorTransferFunction: (v) => {
s = v, g();
},
setHistogram: (u) => {
d = u, p();
setHistogram: (v) => {
d = v, g();
},
render: p,
render: g,
remove: () => n.root.removeChild(o)
};
}, B = -2.75;
class Y extends O {
}, Q = -2.75;
class Pt extends F {
constructor() {
super(...arguments);
a(this, "fadedOpacity", "1");
}
getSvgPosition() {
const { x: t } = this.point, [e, o] = this.container.normalizedToSvg(t, 0), i = o + B + P;
return [e, i];
const { x: e } = this.point, [o, i] = this.container.normalizedToSvg(e, 0), s = i + Q + C;
return [o, s];
}
movePoint(e) {
super.movePoint(e), this.point.setPosition(this.point.x, 0);
}
}
const ft = () => {
const n = [new N(0, 0), new N(1, 0)], t = () => n.sort((r, p) => r.x - p.x), e = () => t().map((r) => r.x), o = new EventTarget(), i = () => o.dispatchEvent(
class xt extends J {
constructor(t, e) {
super(t, e), this.element.removeAttribute("clip-path"), this.clickabeElement.removeAttribute("clip-path");
}
computeStringPoints() {
return this.points.points.map(({ x: t, y: e }) => [t, e]).map(([t, e]) => this.container.normalizedToSvg(t, e)).map(([t, e]) => `${t},${e + Q + C}`).join(" ");
}
applyOffset(t, e) {
this.points.points.forEach((o) => {
o.setPosition(o.x + t, o.y);
});
}
}
const Ct = () => {
const n = new q();
n.addPoints([
[0, 0],
[1, 0]
]);
const t = () => n.points.sort((r, l) => r.x - l.x), e = () => t().map((r) => r.x), o = new EventTarget(), i = () => o.dispatchEvent(
new CustomEvent("updated", { detail: e() })

@@ -587,83 +723,145 @@ );

};
return n.forEach(d), {
return n.points.forEach(d), {
getPoints: t,
getColorRange: e,
setColorRange: (r) => {
s = !0, t().forEach((p, l) => {
p.x = r[l];
s = !0, t().forEach((l, c) => {
l.x = r[c];
}), s = !1, i();
},
eventTarget: o
eventTarget: o,
points: n
};
}, bt = () => {
const n = document.createElementNS(
"http://www.w3.org/2000/svg",
"polyline"
);
return n.setAttribute("fill", "none"), n.setAttribute("stroke", "black"), n.setAttribute("stroke-width", "1"), n;
}, Et = (n, t, e) => {
const o = bt();
n.appendChild(o);
const i = new N(0.5, B), s = new Y(
n,
i,
e
);
s.deletable = !1;
const d = t.getPoints().map((c) => {
const h = new Y(n, c, e);
return h.deletable = !1, h;
}), r = () => {
const [, c] = n.normalizedToSvg(0, 0), h = c + B + P, v = d.map((m) => [m.point.x, m.point.y]).map(([m, y]) => n.normalizedToSvg(m, y)).map(([m]) => `${m},${h}`).join(" ");
o.setAttribute("points", v);
};
n.addSizeObserver(() => {
r();
}, yt = (n, t, e) => {
const o = new xt(n, t.points), i = t.getPoints().map((p) => {
const S = new Pt(n, p, e);
return S.deletable = !1, S;
});
let p = !1, l = !1;
i.eventTarget.addEventListener("updated", () => {
if (l)
let s;
const d = () => {
if (!s)
return;
const c = d[1].point.x - d[0].point.x;
p = !0, d[0].point.x = i.x - c / 2, d[1].point.x = i.x + c / 2, p = !1, r();
});
let E;
const u = () => {
if (!E)
return;
const c = E.getMappingRange(), h = [];
E.getColor(c[0], h);
const p = s.getMappingRange(), S = [];
s.getColor(p[0], S);
const v = [];
E.getColor(c[1], v);
const m = d.sort((w, f) => w.point.x - f.point.x);
m[0].setColor(I(h)), m[1].setColor(I(v));
const y = [], g = (c[1] - c[0]) / 2 + c[0];
E.getColor(g, y), s.setColor(I(y));
}, S = (c) => {
E = c, u();
s.getColor(p[1], v);
const h = i.sort((u, m) => u.point.x - m.point.x);
h[0].setColor($(S)), h[1].setColor($(v));
}, r = (p) => {
s = p, d();
};
return t.eventTarget.addEventListener("updated", () => {
if (p)
return;
u();
const c = t.getPoints().length;
l = !0, i.x = t.getPoints().reduce((h, v) => h + v.x, 0) / c, r(), l = !1;
}), {
points: d,
setColorTransferFunction: S
t.eventTarget.addEventListener("updated", () => {
d();
});
const l = new EventTarget();
let c = !1;
const g = (p) => {
p !== c && (c = p, l.dispatchEvent(
new CustomEvent("hovered-updated", {
detail: { hovered: c }
})
));
};
}, St = () => {
return [...i].forEach(
(p) => p.eventTarget.addEventListener(
"hovered-updated",
() => g(p.getIsHovered())
)
), {
points: i,
line: o,
setColorTransferFunction: r,
eventTarget: l
};
}, At = (n) => {
const t = [], e = () => {
n(t.some((i) => i));
};
return () => {
const i = t.length, s = (d) => {
t[i] = d, e();
};
return s(!1), s;
};
}, Lt = -2, tt = 12, kt = 21;
let W = !1;
const Rt = () => {
if (W)
return;
W = !0;
const n = document.createElement("style");
n.innerHTML = `
.tfeditor-svg-axis-label {
color: black;
position: absolute;
background-color: white;
border-style: solid;
border-color: black;
border-width: 1px;
font-size: ${tt}px;
padding: 2px 6px;
box-sizing: border-box;
transition: opacity 0.1s ease-in-out;
}
`, document.head.appendChild(n);
}, It = (n, t) => {
const { appendChild: e, addSizeObserver: o, paddedBorder: i } = n;
Rt();
const s = () => {
const u = document.createElementNS(
"http://www.w3.org/2000/svg",
"foreignObject"
);
u.setAttribute("width", "100%"), u.setAttribute("height", "100%"), u.setAttribute("pointer-events", "none");
const m = document.createElementNS(
"http://www.w3.org/1999/xhtml",
"div"
);
return m.setAttribute("class", "tfeditor-svg-axis-label"), u.appendChild(m), e(u, "overlay"), m;
}, d = s(), r = s(), l = document.createElementNS(
"http://www.w3.org/2000/svg",
"rect"
);
e(l), l.setAttribute("fill", "none"), l.setAttribute("stroke", "none"), l.setAttribute("stroke-width", String(kt)), l.setAttribute("pointer-events", "stroke");
const c = (u) => {
const [m, P] = n.normalizedToSvg(u, 0), T = P + Lt + tt;
return [m, T];
}, g = (u, m, P) => {
const T = t.toDataSpace(m);
u.textContent = T === 0 ? "0" : `${T.toPrecision(4)}`;
const [y, k] = c(m), M = u.getBoundingClientRect(), O = P === "start" ? -0.5 : -M.width + 0.5, w = M.height / 2;
u.style.transform = `translate(${y + O}px,${k - w}px)`, ["x", "y", "width", "height"].forEach((b) => {
const f = i.getAttribute(b);
f !== null && l.setAttribute(b, f);
});
}, p = () => {
const [u, m] = n.getViewBox();
g(d, u, "start"), g(r, m, "end");
};
p(), o(p), t.eventTarget.addEventListener("updated", p);
const v = At((u) => {
const m = u ? "1" : "0";
d.style.opacity = m, r.style.opacity = m;
}), h = v();
return l.addEventListener("pointerenter", () => {
h(!0);
}), l.addEventListener("pointerleave", () => {
h(!1);
}), { createSetVisibilityGate: v };
}, Dt = () => {
let n = [0, 1];
const t = new EventTarget();
return {
setRange: (o) => {
n = o;
setRange: (i) => {
n = i, t.dispatchEvent(new CustomEvent("updated", { detail: n }));
},
toDataSpace: (o) => {
const [i, s] = n, d = s - i;
return o * d + i;
}
toDataSpace: (i) => {
const [s, d] = n, r = d - s;
return i * r + s;
},
eventTarget: t
};
};
class Tt {
constructor(t) {
}, Mt = 2e3;
class Nt {
constructor(t, e = void 0) {
a(this, "eventTarget", new EventTarget());

@@ -677,25 +875,45 @@ a(this, "points");

a(this, "background");
a(this, "dataSpaceConverter", St());
this.container = at(t), vt(this.container), this.points = new tt();
const e = [
a(this, "dataRange", Dt());
this.container = e || ut(t), St(this.container), this.points = new q();
const o = [
[0, 0],
[1, 1]
];
this.points.setPoints(e), this.line = new mt(this.container, this.points), this.pointController = new gt(
this.points.setPoints(o), this.line = new J(this.container, this.points), this.pointController = new Et(
this.container,
this.points,
this.dataSpaceConverter.toDataSpace
), this.colorRange = ft(), this.colorRangeController = Et(
this.dataRange.toDataSpace
);
const { createSetVisibilityGate: i } = It(
this.container,
this.dataRange
);
this.colorRange = Ct(), this.colorRangeController = yt(
this.container,
this.colorRange,
this.dataSpaceConverter.toDataSpace
), this.background = wt(this.container, this.points, this.colorRange), this.points.eventTarget.addEventListener("updated", (o) => {
this.dataRange.toDataSpace
), this.background = Tt(this.container, this.points, this.colorRange), this.points.eventTarget.addEventListener("updated", (l) => {
this.eventTarget.dispatchEvent(
new CustomEvent("updated", { detail: o.detail })
new CustomEvent("updated", { detail: l.detail })
);
}), this.colorRange.eventTarget.addEventListener("updated", (o) => {
}), this.colorRange.eventTarget.addEventListener("updated", (l) => {
this.eventTarget.dispatchEvent(
new CustomEvent("colorRange", { detail: o.detail })
new CustomEvent("colorRange", { detail: l.detail })
);
});
const s = i();
this.pointController.eventTarget.addEventListener(
"hovered-updated",
(l) => {
const { hovered: c } = l.detail;
s(c);
}
);
const d = i();
let r;
this.container.eventTarget.addEventListener("viewbox-updated", () => {
d(!0), clearTimeout(r), r = setTimeout(() => {
d(!1);
}, Mt);
});
}

@@ -708,3 +926,3 @@ remove() {

}
// No Points update event on setPoints to avoid emitting 'update' event to user code.
// No Points update event emitted on setPoints event to user code. Avoids circular
// User code responsible for updating downstream piecewise function without update in setPoints case.

@@ -727,12 +945,13 @@ setPoints(t) {

setHistogram(t) {
this.background.setHistogram(ot(t));
this.background.setHistogram(lt(t));
}
setRange(t) {
this.dataSpaceConverter.setRange(t);
this.dataRange.setRange(t);
}
}
export {
Tt as TransferFunctionEditor,
Pt as windowPointsForSort
Nt as TransferFunctionEditor,
zt as getNodes,
ct as windowPointsForSort
};
//# sourceMappingURL=TransferFunctionEditor.es.js.map

@@ -1,2 +0,2 @@

(function(S,v){typeof exports=="object"&&typeof module<"u"?v(exports):typeof define=="function"&&define.amd?define(["exports"],v):(S=typeof globalThis<"u"?globalThis:S||self,v(S.TransferFunctionEditor={}))})(this,function(S){"use strict";var Pt=Object.defineProperty;var Tt=(S,v,y)=>v in S?Pt(S,v,{enumerable:!0,configurable:!0,writable:!0,value:y}):S[v]=y;var a=(S,v,y)=>(Tt(S,typeof v!="symbol"?v+"":v,y),y);class v{constructor(t,e){a(this,"_x");a(this,"_y");a(this,"eventTarget",new EventTarget);this.setPosition(t,e)}get x(){return this._x}set x(t){this._x=t,this.dispatchUpdatedEvent()}get y(){return this._y}set y(t){this._y=t,this.dispatchUpdatedEvent()}setPosition(t,e){this._x=t,this._y=e,this.dispatchUpdatedEvent()}dispatchUpdatedEvent(){this.eventTarget.dispatchEvent(new CustomEvent("updated",{detail:[this.x,this.y]}))}}const y=(n,t=!1)=>{if(n.length===0)return[[0,1],[1,1]];if(n.length===1){const[,i]=n[0];return[[0,i],[1,i]]}const e=n[0],o=n[n.length-1];return t?[[e[0],0],...n,[o[0],0]]:[[0,e[1]],...n,[1,o[1]]]},V=n=>y(n.map(({x:t,y:e})=>[t,e]));class Z{constructor(){a(this,"_points",[]);a(this,"eventTarget",new EventTarget)}get points(){return[...this._points]}addPoint(t,e){const o=this.createPoint(t,e);return this.dispatchUpdatedEvent(),o}addPoints(t){return t.map(([o,i])=>this.createPoint(o,i))}setPoints(t){return[...this._points].forEach(e=>this.deletePoint(e)),this.addPoints(t)}removePoint(t){this.deletePoint(t),this.dispatchUpdatedEvent()}dispatchUpdatedEvent(){this.eventTarget.dispatchEvent(new CustomEvent("updated",{detail:this._points}))}createPoint(t,e){const o=new v(t,e);return o.eventTarget.addEventListener("updated",()=>{this._points.sort((i,s)=>i.x-s.x),this.dispatchUpdatedEvent()}),this._points.push(o),this._points.sort((i,s)=>i.x-s.x),o}deletePoint(t){this._points=this._points.filter(e=>e!==t)}}const q=(n,t,e,o={lineWidth:1,strokeStyle:"#000",fillStyle:void 0,clip:!1})=>{const i=t[3],s=t[2]/(e.length-1),d=i+t[1];n.lineWidth=o.lineWidth,n.strokeStyle=o.strokeStyle,n.beginPath(),n.moveTo(t[0],t[1]+t[3]);for(let r=0;r<e.length;r++)n.lineTo(t[0]+r*s,Math.max(t[1],d-e[r]*i));if(o.fillStyle){if(n.fillStyle=o.fillStyle,n.lineTo(t[0]+t[2],t[1]+t[3]),o.clip){n.clip();return}n.fill()}n.stroke()},N=1,J=(n,t,e,o)=>{const i=o||document.createElement("canvas");if(i.setAttribute("width",String(t)),i.setAttribute("height",String(N)),n.getSize()===0)return i;const s=n.getUint8Table(e[0],e[1],t,!0),d=i.getContext("2d");if(d){const r=d.getImageData(0,0,t,N);for(let l=0;l<N;l++)r.data.set(s,l*4*t);const p=N*t*4;for(let l=3;l<p;l+=4)r.data[l]=255;d.putImageData(r,0,0)}return i},Q=n=>{const t=y(n);return t[0][0]-=1e-8,t[t.length-1][0]+=1e-8,t},tt=n=>{if(!n)return[];const t=n.map(r=>r===0?0:Math.log(r)),e=t.filter(Boolean),o=Math.min(...e),s=Math.max(...e)-o;return t.map(r=>r===0?0:(r-o)/s)};function et(n,t){if(n.length!==t.length)return!1;for(let e=0;e<n.length;e++)if(n[e]!==t[e])return!1;return!0}function B(n){return`#${n.map(e=>Math.floor(e*255)).map(e=>`0${e.toString(16)}`.slice(-2)).join("")}`}const R=11,nt=2*R,ot=()=>{const n=document.createElementNS("http://www.w3.org/2000/svg","svg");return n.setAttribute("style","position: absolute; top: 0; left: 0; z-index: 2; box-sizing: border-box; width: 100%; height: 100%;"),n},it=n=>{const t=document.createElement("div");t.setAttribute("style","position: relative; width: 100%; height: 100%; user-select: none;"),n.appendChild(t);const e=ot();t.appendChild(e);const o=new EventTarget,i=g=>{o.addEventListener("sizeupdated",g)};new ResizeObserver(()=>{o.dispatchEvent(new Event("sizeupdated"))}).observe(t);const d=document.createElementNS("http://www.w3.org/2000/svg","rect");e.appendChild(d),d.setAttribute("fill","none"),d.setAttribute("stroke","black");const r=g=>{e.appendChild(g)},p=g=>{e.removeChild(g)};let l=[0,1,0,1];const C=()=>l,u=(g,w,b=0,E=1)=>{const A=l;l=[g,w,b,E],et(A,l)||o.dispatchEvent(new Event("sizeupdated"))},P=()=>{const{top:g,left:w,width:b,height:E}=t.getBoundingClientRect();return{width:b-2*R,height:E-(nt+R),top:g+R,left:w+R}},c=(g,w)=>{const{top:b,left:E,width:A,height:L}=P(),x=l[1]-l[0]||.001,z=l[3]-l[2]||.001;return[(g-E)/A*x+l[0],(1-(w-b)/L)*z+l[2]]},h=(g,w)=>{const{width:b,height:E}=P(),A=l[1]-l[0]||.001,L=(g-l[0])/A*b+R,x=l[3]-l[2]||.001,z=(1-(w-l[2])/x)*E+R;return[L,z]},f=()=>{const[g,w]=h(0,0),[b,E]=h(1,1);return{left:g,bottom:w,right:b,top:E}};return i(()=>{const{left:g,bottom:w,right:b,top:E}=f();d.setAttribute("x",`${g}`),d.setAttribute("y",`${E}`),d.setAttribute("width",`${Math.max(0,b-g)}`),d.setAttribute("height",`${Math.max(0,w-E)}`)}),{appendChild:r,removeChild:p,addSizeObserver:i,getViewBox:C,setViewBox:u,domToNormalized:c,normalizedToSvg:h,borderSize:f,remove:()=>n.removeChild(t),root:t,svg:e}};let H=!1;const st=()=>{if(H)return;H=!0;const n=document.createElement("style");n.innerHTML=`
(function(P,x){typeof exports=="object"&&typeof module<"u"?x(exports):typeof define=="function"&&define.amd?define(["exports"],x):(P=typeof globalThis<"u"?globalThis:P||self,x(P.TransferFunctionEditor={}))})(this,function(P){"use strict";var zt=Object.defineProperty;var Nt=(P,x,L)=>x in P?zt(P,x,{enumerable:!0,configurable:!0,writable:!0,value:L}):P[x]=L;var a=(P,x,L)=>(Nt(P,typeof x!="symbol"?x+"":x,L),L);class x{constructor(t,e){a(this,"_x");a(this,"_y");a(this,"eventTarget",new EventTarget);this.setPosition(t,e)}get x(){return this._x}set x(t){this._x=t,this.dispatchUpdatedEvent()}get y(){return this._y}set y(t){this._y=t,this.dispatchUpdatedEvent()}setPosition(t,e){this._x=t,this._y=e,this.dispatchUpdatedEvent()}dispatchUpdatedEvent(){this.eventTarget.dispatchEvent(new CustomEvent("updated",{detail:[this.x,this.y]}))}}const L=(n,t=!1)=>{if(n.length===0)return[[0,1],[1,1]];if(n.length===1){const[,s]=n[0];return[[0,s],[1,s]]}const e=n[0],o=n[n.length-1];if(t)return[[e[0],0],...n,[o[0],0]];const i=[];return e[0]>0&&i.push([0,e[1]]),i.push(...n),o[0]<1&&i.push([1,o[1]]),i},X=n=>L(n.map(({x:t,y:e})=>[t,e]));class Y{constructor(){a(this,"_points",[]);a(this,"eventTarget",new EventTarget)}get points(){return[...this._points]}addPoint(t,e){const o=this.createPoint(t,e);return this.dispatchUpdatedEvent(),o}addPoints(t){return t.map(([o,i])=>this.createPoint(o,i))}setPoints(t){return[...this._points].forEach(e=>this.deletePoint(e)),this.addPoints(t)}removePoint(t){this.deletePoint(t),this.dispatchUpdatedEvent()}dispatchUpdatedEvent(){this.eventTarget.dispatchEvent(new CustomEvent("updated",{detail:this._points}))}createPoint(t,e){const o=new x(t,e);return o.eventTarget.addEventListener("updated",()=>{this._points.sort((i,s)=>i.x-s.x),this.dispatchUpdatedEvent()}),this._points.push(o),this._points.sort((i,s)=>i.x-s.x),o}deletePoint(t){this._points=this._points.filter(e=>e!==t)}}const ot=(n,t,e,o={lineWidth:1,strokeStyle:"#000",fillStyle:void 0,clip:!1})=>{const i=t[3],s=t[2]/(e.length-1),d=i+t[1];n.lineWidth=o.lineWidth,n.strokeStyle=o.strokeStyle,n.beginPath(),n.moveTo(t[0],t[1]+t[3]);for(let r=0;r<e.length;r++)n.lineTo(t[0]+r*s,Math.max(t[1],d-e[r]*i));if(o.fillStyle){if(n.fillStyle=o.fillStyle,n.lineTo(t[0]+t[2],t[1]+t[3]),o.clip){n.clip();return}n.fill()}n.stroke()},F=1,st=(n,t,e,o)=>{const i=o||document.createElement("canvas");if(i.setAttribute("width",String(t)),i.setAttribute("height",String(F)),n.getSize()===0)return i;const s=n.getUint8Table(e[0],e[1],t,!0),d=i.getContext("2d",{willReadFrequently:!0});if(d){const r=d.getImageData(0,0,t,F);for(let c=0;c<F;c++)r.data.set(s,c*4*t);const l=F*t*4;for(let c=3;c<l;c+=4)r.data[c]=255;d.putImageData(r,0,0)}return i},G=n=>{const t=L(n);return t[0][0]-=1e-8,t[t.length-1][0]+=1e-8,t},rt=n=>{if(!n)return[];const t=n.map(r=>r===0?0:Math.log(r)),e=t.filter(Boolean),o=Math.min(...e),s=Math.max(...e)-o;return t.map(r=>r===0?0:(r-o)/s)};function at(n,t){if(n.length!==t.length)return!1;for(let e=0;e<n.length;e++)if(n[e]!==t[e])return!1;return!0}function j(n){return`#${n.map(e=>Math.floor(e*255)).map(e=>`0${e.toString(16)}`.slice(-2)).join("")}`}const dt=(n,t)=>{const o=(r=>{const l=[];for(let c=0;c<r.length-1;c++){const g=r[c],p=r[c+1];if(g[1]<=1&&p[1]>=1||g[1]>=1&&p[1]<=1){const S=g[0]+(1-g[1])/(p[1]-g[1])*(p[0]-g[0]);l.push(S)}}return l})(t),i=[...t,...o.map(r=>[r,1])],s=G(i),d=n[1]-n[0];return s.map(([r,l])=>({x:n[0]+d*r,y:Math.min(l,1),midpoint:.5,sharpness:0}))},I=11,ct=2*I,lt=()=>{const n=document.createElementNS("http://www.w3.org/2000/svg","svg");n.setAttribute("style","position: absolute; top: 0; left: 0; z-index: 2; box-sizing: border-box; width: 100%; height: 100%;");const t=document.createElementNS("http://www.w3.org/2000/svg","g");n.appendChild(t);const e=document.createElementNS("http://www.w3.org/2000/svg","g");n.appendChild(e);const o=document.createElementNS("http://www.w3.org/2000/svg","defs");return n.appendChild(o),{svg:n,underlay:t,overlay:e,defs:o}},ht=n=>{const t=document.createElement("div");t.setAttribute("style","position: relative; width: 100%; height: 100%; user-select: none;"),n.appendChild(t);const{svg:e,overlay:o,underlay:i,defs:s}=lt();t.appendChild(e);const d=new EventTarget,r=f=>{d.addEventListener("sizeupdated",f)};new ResizeObserver(()=>{d.dispatchEvent(new Event("sizeupdated"))}).observe(t);const c=document.createElementNS("http://www.w3.org/2000/svg","rect");i.appendChild(c),c.setAttribute("fill","none"),c.setAttribute("stroke","black"),c.setAttribute("id","tfeditor-border");const g=document.createElementNS("http://www.w3.org/2000/svg","clipPath");g.setAttribute("id","border-clip"),s.appendChild(g);const p=document.createElementNS("http://www.w3.org/2000/svg","use");p.setAttribute("href","#tfeditor-border"),g.appendChild(p);const S=(f,w="underlay")=>{(w==="underlay"?i:o).appendChild(f)},v=(f,w="underlay")=>{(w==="underlay"?i:o).removeChild(f)};let h=[0,1,0,1];const u=()=>h,m=(f,w,b=0,E=1)=>{const y=h;h=[f,w,b,E],at(y,h)||(d.dispatchEvent(new Event("sizeupdated")),d.dispatchEvent(new Event("viewbox-updated")))},C=()=>{const{top:f,left:w,width:b,height:E}=t.getBoundingClientRect();return{width:b-2*I,height:E-(ct+I),top:f+I,left:w+I}},T=(f,w)=>{const{top:b,left:E,width:y,height:M}=C(),R=h[1]-h[0]||.001,O=h[3]-h[2]||.001;return[(f-E)/y*R+h[0],(1-(w-b)/M)*O+h[2]]},k=(f,w)=>{const{width:b,height:E}=C(),y=h[1]-h[0]||.001,M=(f-h[0])/y*b+I,R=h[3]-h[2]||.001,O=(1-(w-h[2])/R)*E+I;return[M,O]},D=()=>{const[f,w]=k(0,0),[b,E]=k(1,1);return{left:f,bottom:w,right:b,top:E}};return r(()=>{const{left:f,bottom:w,right:b,top:E}=D();c.setAttribute("x",`${f}`),c.setAttribute("y",`${E}`),c.setAttribute("width",`${Math.max(0,b-f)}`),c.setAttribute("height",`${Math.max(0,w-E)}`)}),{appendChild:S,removeChild:v,addSizeObserver:r,getViewBox:u,setViewBox:m,domToNormalized:T,normalizedToSvg:k,borderSize:D,remove:()=>n.removeChild(t),root:t,overlay:o,eventTarget:d,paddedBorder:c}};let W=!1;const pt=()=>{if(W)return;W=!0;const n=document.createElement("style");n.innerHTML=`
.tfeditor-svg-tooltip {

@@ -6,14 +6,25 @@ color: black;

position: absolute;
transform: translate(178px, 410.19px);
border-style: solid;
border-color: black;
border-width: 1px;
border-radius: 2px;
font-size: 12px;
padding: 8px;
visibility: hidden;
max-width: 150px;
padding: 4px 6px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
transition: opacity 0.1s ease-in-out;
opacity: 0;
}
`,document.head.appendChild(n)};function rt(n){st();const t=[10,10],e=document.createElementNS("http://www.w3.org/2000/svg","foreignObject");e.setAttribute("width","100%"),e.setAttribute("height","100%"),e.setAttribute("pointer-events","none");const o=document.createElementNS("http://www.w3.org/1999/xhtml","div");o.setAttribute("class","tfeditor-svg-tooltip"),e.appendChild(o),n.append(e);function i(p,l,C){let u=l+t[0],P=C+t[1];o.textContent=p;const c=n.getBBox(),h=o.getBoundingClientRect();u>c.width-h.width&&(u=l-h.width-t[0]),P>c.height-h.height&&(P=C-h.height-t[1]),o.style.transform=`translate(${u}px,${P}px)`}function s(){o.style.visibility="visible"}function d(){o.style.visibility="hidden"}return{update:i,show:s,hide:d,remove:()=>{n.removeChild(e)}}}const at="controlPoint",O=n=>Math.max(0,Math.min(1,n)),M=2,dt=8,X=14,T=X,lt=()=>{const n=document.createElementNS("http://www.w3.org/2000/svg","svg");n.setAttribute("width",String(T*2)),n.setAttribute("height",String(T*2)),n.setAttribute("viewBox",`-${T} -${T} ${T*2} ${T*2}`);const t=document.createElementNS("http://www.w3.org/2000/svg","circle");t.setAttribute("r",String(dt)),t.setAttribute("fill","white"),t.setAttribute("stroke","black"),t.setAttribute("stroke-width",String(M)),t.setAttribute("class",at),n.appendChild(t);const e=document.createElementNS("http://www.w3.org/2000/svg","circle");return e.setAttribute("r",String(X)),e.setAttribute("fill","transparent"),e.setAttribute("stroke","transparent"),e.setAttribute("style","cursor: move;"),n.appendChild(e),{group:n,circle:t,clickTarget:e}};class F{constructor(t,e,o,i,s=!1){a(this,"element");a(this,"circle");a(this,"tooltip");a(this,"container");a(this,"isDragging",!1);a(this,"isHovered",!1);a(this,"point");a(this,"deletable",!0);a(this,"DELETE_EVENT","deleteme");a(this,"eventTarget",new EventTarget);a(this,"grabX",0);a(this,"grabY",0);a(this,"toDataSpace");const{group:d,circle:r}=lt();this.element=d,this.circle=r,this.point=e,this.container=t,this.toDataSpace=o,this.tooltip=rt(this.container.svg),t.addSizeObserver(()=>{this.positionElement()}),i&&this.eventTarget.addEventListener(this.DELETE_EVENT,p=>{i(p)}),t.appendChild(this.element),this.positionElement(),this.point.eventTarget.addEventListener("updated",()=>this.positionElement()),this.setupInteraction(),s&&this.startInteraction(!0)}remove(){this.tooltip.remove(),this.container.removeChild(this.element)}getSvgPosition(){const{x:t,y:e}=this.point;return this.container.normalizedToSvg(t,e)}updateTooltip(t=void 0){const{x:e}=this.point,o=this.toDataSpace(e),[i,s]=t??this.getSvgPosition();this.tooltip.update(o.toPrecision(4),i,s)}positionElement(){const[t,e]=this.getSvgPosition();this.element.setAttribute("x",String(t-T)),this.element.setAttribute("y",String(e-T)),this.updateTooltip([t,e])}movePoint(t){const[e,o]=this.container.domToNormalized(t.clientX,t.clientY);this.point.setPosition(O(e+this.grabX),O(o+this.grabY))}update(){this.circle.setAttribute("stroke-width",String(M)),this.isHovered&&(this.circle.setAttribute("stroke-width",String(M+1)),this.updateTooltip(),this.tooltip.show()),this.isDragging&&this.circle.setAttribute("stroke-width",String(M*2)),!this.isDragging&&!this.isHovered&&this.tooltip.hide()}startInteraction(t=!1){this.isDragging=t,!this.isDragging&&this.deletable&&this.circle.setAttribute("stroke","red");const e=i=>{this.isDragging||this.circle.setAttribute("stroke","black"),this.isDragging=!0,this.movePoint(i)};document.addEventListener("pointermove",e);const o=()=>{if(document.removeEventListener("pointermove",e),document.removeEventListener("pointerup",o),!this.isDragging){const i=new CustomEvent(this.DELETE_EVENT,{detail:this});this.eventTarget.dispatchEvent(i)}this.isDragging=!1,this.update()};document.addEventListener("pointerup",o)}setupInteraction(){this.element.addEventListener("pointerdown",t=>{t.stopPropagation(),this.circle.setAttribute("stroke-width",String(M*2));const[e,o]=this.container.domToNormalized(t.clientX,t.clientY);this.grabX=this.point.x-e,this.grabY=this.point.y-o,this.startInteraction()}),this.element.addEventListener("pointerenter",()=>{this.isHovered=!0,this.update()}),this.element.addEventListener("pointerleave",()=>{this.isHovered=!1,this.update()})}setColor(t){this.circle.setAttribute("fill",t)}}a(F,"styleElement");class ct{constructor(t,e,o){a(this,"container");a(this,"points");a(this,"onPointsUpdated");a(this,"controlPoints",[]);a(this,"isNewPointFromPointer",!1);a(this,"toDataSpace");this.container=t,this.points=e,this.toDataSpace=o;const{root:i}=t;i.addEventListener("pointerdown",s=>this.onPointerDown(s)),this.onPointsUpdated=()=>this.updatePoints(),this.points.eventTarget.addEventListener("updated",this.onPointsUpdated),this.updatePoints()}remove(){this.points.eventTarget.removeEventListener("updated",this.onPointsUpdated)}onPointerDown(t){const[e,o]=this.container.domToNormalized(t.clientX,t.clientY).map(O);this.isNewPointFromPointer=!0,this.points.addPoint(e,o),this.isNewPointFromPointer=!1}onControlPointDelete(t){this.points.removePoint(t.detail.point)}updatePoints(){const t=this.controlPoints.filter(i=>!this.points.points.find(s=>s===i.point));t.forEach(i=>i.remove()),this.controlPoints=this.controlPoints.filter(i=>!t.includes(i));const e=i=>this.controlPoints.find(s=>s.point===i),o=i=>this.controlPoints.push(new F(this.container,i,this.toDataSpace,s=>this.onControlPointDelete(s),this.isNewPointFromPointer));this.points.points.filter(i=>!e(i)).forEach(o)}}const ht=()=>{const n=document.createElementNS("http://www.w3.org/2000/svg","polyline");return n.setAttribute("fill","none"),n.setAttribute("stroke","black"),n.setAttribute("stroke-width","2"),n};class pt{constructor(t,e){a(this,"points");a(this,"container");a(this,"onPointsUpdated");a(this,"element");this.container=t,this.points=e,this.element=ht(),this.container.appendChild(this.element),this.onPointsUpdated=()=>this.update(),this.points.eventTarget.addEventListener("updated",this.onPointsUpdated),this.container.addSizeObserver(()=>{this.update()}),this.update()}remove(){this.points.eventTarget.removeEventListener("updated",this.onPointsUpdated)}update(){if(this.points.points.length===0){this.element.setAttribute("points","");return}const t=V(this.points.points).map(([e,o])=>this.container.normalizedToSvg(e,o)).map(([e,o])=>`${e},${o}`).join(" ");this.element.setAttribute("points",t)}}const Y=1.1,gt=n=>{n.root.addEventListener("wheel",t=>{const e=t.deltaY>0?Y:1/Y,[o]=n.domToNormalized(t.clientX,t.clientY),[i,s]=n.getViewBox(),d=Math.max(0,i-Math.max(0,o-i)*(e-1)),r=Math.min(1,(s-i)*e+d);d===i&&r===s||(t.preventDefault(),t.stopPropagation(),n.setViewBox(d,r))})},W="rgba(50, 50, 50, 0.3)",ut=(n,t,e)=>{const o=document.createElement("canvas");n.root.appendChild(o),o.setAttribute("style","width: 100%; height: 100%; ");const i=o.getContext("2d");let s,d;const r=document.createElement("canvas"),p=()=>{if(i){if(i.clearRect(0,0,o.width,o.height),s){const{width:u,height:P}=n.root.getBoundingClientRect();o.setAttribute("width",String(u)),o.setAttribute("height",String(P));const{left:c,right:h,bottom:f,top:m}=n.borderSize();if(Math.ceil(h-c)<0)return;const g=V(t.points),w=[[0,0],...g,[1,0]].map(([D,_])=>n.normalizedToSvg(D,_));i.save(),i.beginPath(),w.forEach(([D,_])=>{i.lineTo(D,_)}),i.clip();const[b,E]=e.getColorRange(),[A]=n.normalizedToSvg(b,1),[L]=n.normalizedToSvg(E,1),x=Math.min(u,Math.max(0,A)),z=Math.min(u,Math.max(0,L)),I=z-x<2?x+2:z,G=Math.ceil(I-x);if(s){const D=L-A,_=(x-A)/D,Et=(I-L)/D,U=s.getMappingRange(),K=U[1]-U[0],St=[U[0]+K*_,U[1]+K*Et];J(s,G,St,r),i.drawImage(r,0,0,r.width,r.height,Math.floor(x),Math.floor(m),G,Math.ceil(f-m));const Ct=i.imageSmoothingEnabled;i.imageSmoothingEnabled=!1,i.drawImage(r,0,0,1,1,0,Math.floor(m),Math.floor(x),Math.ceil(f-m)),i.drawImage(r,r.width-1,0,1,1,Math.floor(I),Math.floor(m),u-I,Math.ceil(f-m)),i.imageSmoothingEnabled=Ct}i.restore()}if(d){const{left:u,right:P,bottom:c,top:h}=n.borderSize(),f=[u,h,P-u,c-h];q(i,f,d,{lineWidth:1,strokeStyle:W,fillStyle:W})}}};return n.addSizeObserver(p),t.eventTarget.addEventListener("updated",p),e.eventTarget.addEventListener("updated",p),{container:n,canvas:o,setColorTransferFunction:u=>{s=u,p()},setHistogram:u=>{d=u,p()},render:p,remove:()=>n.root.removeChild(o)}},$=-2.75;class j extends F{getSvgPosition(){const{x:t}=this.point,[e,o]=this.container.normalizedToSvg(t,0),i=o+$+T;return[e,i]}}const mt=()=>{const n=[new v(0,0),new v(1,0)],t=()=>n.sort((r,p)=>r.x-p.x),e=()=>t().map(r=>r.x),o=new EventTarget,i=()=>o.dispatchEvent(new CustomEvent("updated",{detail:e()}));let s=!1;const d=r=>{r.eventTarget.addEventListener("updated",()=>{s||i()})};return n.forEach(d),{getPoints:t,getColorRange:e,setColorRange:r=>{s=!0,t().forEach((p,l)=>{p.x=r[l]}),s=!1,i()},eventTarget:o}},vt=()=>{const n=document.createElementNS("http://www.w3.org/2000/svg","polyline");return n.setAttribute("fill","none"),n.setAttribute("stroke","black"),n.setAttribute("stroke-width","1"),n},ft=(n,t,e)=>{const o=vt();n.appendChild(o);const i=new v(.5,$),s=new j(n,i,e);s.deletable=!1;const d=t.getPoints().map(c=>{const h=new j(n,c,e);return h.deletable=!1,h}),r=()=>{const[,c]=n.normalizedToSvg(0,0),h=c+$+T,f=d.map(m=>[m.point.x,m.point.y]).map(([m,k])=>n.normalizedToSvg(m,k)).map(([m])=>`${m},${h}`).join(" ");o.setAttribute("points",f)};n.addSizeObserver(()=>{r()});let p=!1,l=!1;i.eventTarget.addEventListener("updated",()=>{if(l)return;const c=d[1].point.x-d[0].point.x;p=!0,d[0].point.x=i.x-c/2,d[1].point.x=i.x+c/2,p=!1,r()});let C;const u=()=>{if(!C)return;const c=C.getMappingRange(),h=[];C.getColor(c[0],h);const f=[];C.getColor(c[1],f);const m=d.sort((w,b)=>w.point.x-b.point.x);m[0].setColor(B(h)),m[1].setColor(B(f));const k=[],g=(c[1]-c[0])/2+c[0];C.getColor(g,k),s.setColor(B(k))},P=c=>{C=c,u()};return t.eventTarget.addEventListener("updated",()=>{if(p)return;u();const c=t.getPoints().length;l=!0,i.x=t.getPoints().reduce((h,f)=>h+f.x,0)/c,r(),l=!1}),{points:d,setColorTransferFunction:P}},wt=()=>{let n=[0,1];return{setRange:o=>{n=o},toDataSpace:o=>{const[i,s]=n,d=s-i;return o*d+i}}};class bt{constructor(t){a(this,"eventTarget",new EventTarget);a(this,"points");a(this,"colorRange");a(this,"colorRangeController");a(this,"line");a(this,"pointController");a(this,"container");a(this,"background");a(this,"dataSpaceConverter",wt());this.container=it(t),gt(this.container),this.points=new Z;const e=[[0,0],[1,1]];this.points.setPoints(e),this.line=new pt(this.container,this.points),this.pointController=new ct(this.container,this.points,this.dataSpaceConverter.toDataSpace),this.colorRange=mt(),this.colorRangeController=ft(this.container,this.colorRange,this.dataSpaceConverter.toDataSpace),this.background=ut(this.container,this.points,this.colorRange),this.points.eventTarget.addEventListener("updated",o=>{this.eventTarget.dispatchEvent(new CustomEvent("updated",{detail:o.detail}))}),this.colorRange.eventTarget.addEventListener("updated",o=>{this.eventTarget.dispatchEvent(new CustomEvent("colorRange",{detail:o.detail}))})}remove(){this.background.remove(),this.container.remove()}getPoints(){return this.points.points.map(({x:t,y:e})=>[t,e])}setPoints(t){this.points.setPoints(t),this.pointController.updatePoints(),this.line.update(),this.background.render()}getColorRange(){return this.colorRange.getColorRange()}setColorRange(t){return this.colorRange.setColorRange(t)}setViewBox(t,e,o=0,i=1){this.container.setViewBox(t,e,o,i)}setColorTransferFunction(t){this.background.setColorTransferFunction(t),this.colorRangeController.setColorTransferFunction(t)}setHistogram(t){this.background.setHistogram(tt(t))}setRange(t){this.dataSpaceConverter.setRange(t)}}S.TransferFunctionEditor=bt,S.windowPointsForSort=Q,Object.defineProperty(S,Symbol.toStringTag,{value:"Module"})});
`,document.head.appendChild(n)};function gt(n){pt();const t=[10,10],e=document.createElementNS("http://www.w3.org/2000/svg","foreignObject");e.setAttribute("width","100%"),e.setAttribute("height","100%"),e.setAttribute("pointer-events","none");const o=document.createElementNS("http://www.w3.org/1999/xhtml","div");o.setAttribute("class","tfeditor-svg-tooltip"),e.appendChild(o),n.append(e);function i(l,c,g){let p=c+t[0],S=g+t[1];o.textContent=l;const v=n.getBBox(),h=o.getBoundingClientRect();p>v.width-h.width&&(p=c-h.width-t[0]),S>v.height-h.height&&(S=g-h.height-t[1]),o.style.transform=`translate(${p}px,${S}px)`}function s(){o.style.opacity="1"}function d(){o.style.opacity="0"}return{update:i,show:s,hide:d,remove:()=>{n.removeChild(e)}}}const ut="controlPoint",$=n=>Math.max(0,Math.min(1,n)),N=2,vt=8,Z=14,A=Z,mt=()=>{const n=document.createElementNS("http://www.w3.org/2000/svg","svg");n.setAttribute("width",String(A*2)),n.setAttribute("height",String(A*2)),n.setAttribute("viewBox",`-${A} -${A} ${A*2} ${A*2}`);const t=document.createElementNS("http://www.w3.org/2000/svg","circle");t.setAttribute("r",String(vt)),t.setAttribute("fill","white"),t.setAttribute("stroke","black"),t.setAttribute("stroke-width",String(N)),t.setAttribute("class",ut),t.style.transition="opacity 0.05s ease-in-out",n.appendChild(t);const e=document.createElementNS("http://www.w3.org/2000/svg","circle");return e.setAttribute("r",String(Z)),e.setAttribute("fill","transparent"),e.setAttribute("stroke","transparent"),e.setAttribute("style","cursor: move;"),n.appendChild(e),{group:n,circle:t,clickTarget:e}};class V{constructor(t,e,o,i,s=!1){a(this,"element");a(this,"circle");a(this,"tooltip");a(this,"fadedOpacity","0");a(this,"container");a(this,"isDragging",!1);a(this,"isHovered",!1);a(this,"pointerEntered",!1);a(this,"point");a(this,"deletable",!0);a(this,"DELETE_EVENT","deleteme");a(this,"eventTarget",new EventTarget);a(this,"grabX",0);a(this,"grabY",0);a(this,"toDataSpace");const{group:d,circle:r}=mt();this.element=d,this.circle=r,this.point=e,this.container=t,this.toDataSpace=o,this.tooltip=gt(this.container.overlay),t.addSizeObserver(()=>{this.positionElement()}),i&&this.eventTarget.addEventListener(this.DELETE_EVENT,l=>{i(l)}),t.appendChild(this.element),this.positionElement(),this.point.eventTarget.addEventListener("updated",()=>this.positionElement()),this.setupInteraction(),s&&this.startInteraction(!0)}remove(){this.pointerEntered=!1,this.update(),this.tooltip.remove(),this.container.removeChild(this.element)}getIsDragging(){return this.isDragging}setIsDragging(t){this.isDragging!==t&&(this.isDragging=t,this.eventTarget.dispatchEvent(new Event("dragging-updated")))}getIsHovered(){return this.isHovered}setIsHovered(t){this.isHovered!==t&&(t?this.tooltip.show():this.tooltip.hide(),this.isHovered=t,this.eventTarget.dispatchEvent(new Event("hovered-updated")))}getSvgPosition(){const{x:t,y:e}=this.point;return this.container.normalizedToSvg(t,e)}updateTooltip(t=void 0){const{x:e}=this.point,o=this.toDataSpace(e),[i,s]=t??this.getSvgPosition();this.tooltip.update(o.toPrecision(4),i,s)}positionElement(){const[t,e]=this.getSvgPosition();this.element.setAttribute("x",String(t-A)),this.element.setAttribute("y",String(e-A)),this.updateTooltip([t,e]),this.point.x>1.001||this.point.x<-.001||this.point.y>1.001||this.point.y<-.001?this.circle.style.opacity=this.fadedOpacity:this.circle.style.opacity="1"}movePoint(t){const[e,o]=this.container.domToNormalized(t.clientX,t.clientY);this.point.setPosition($(e+this.grabX),$(o+this.grabY))}update(){this.circle.setAttribute("stroke-width",String(N)),this.pointerEntered&&(this.circle.setAttribute("stroke-width",String(N+1)),this.updateTooltip(),this.setIsHovered(!0)),this.isDragging&&this.circle.setAttribute("stroke-width",String(N*2)),!this.isDragging&&!this.pointerEntered&&this.setIsHovered(!1)}startInteraction(t=!1){this.setIsDragging(t),!this.isDragging&&this.deletable&&this.circle.setAttribute("stroke","red");const e=i=>{this.isDragging||this.circle.setAttribute("stroke","black"),this.setIsDragging(!0),this.movePoint(i)};document.addEventListener("pointermove",e);const o=()=>{if(document.removeEventListener("pointermove",e),document.removeEventListener("pointerup",o),!this.isDragging){const i=new CustomEvent(this.DELETE_EVENT,{detail:this});this.eventTarget.dispatchEvent(i)}this.setIsDragging(!1),this.update()};document.addEventListener("pointerup",o)}setupInteraction(){this.element.addEventListener("pointerdown",t=>{t.stopPropagation(),this.circle.setAttribute("stroke-width",String(N*2));const[e,o]=this.container.domToNormalized(t.clientX,t.clientY);this.grabX=this.point.x-e,this.grabY=this.point.y-o,this.startInteraction()}),this.element.addEventListener("pointerenter",()=>{this.pointerEntered=!0,this.update()}),this.element.addEventListener("pointerleave",()=>{this.pointerEntered=!1,this.update()})}setColor(t){this.circle.setAttribute("fill",t)}}a(V,"styleElement");class ft{constructor(t,e,o){a(this,"container");a(this,"points");a(this,"eventTarget",new EventTarget);a(this,"toDataSpace");a(this,"hovered",!1);a(this,"onPointsUpdated");a(this,"controlPoints",[]);a(this,"isNewPointFromPointer",!1);this.container=t,this.points=e,this.toDataSpace=o;const{root:i}=t;i.addEventListener("pointerdown",s=>this.onPointerDown(s)),this.onPointsUpdated=()=>this.updatePoints(),this.points.eventTarget.addEventListener("updated",this.onPointsUpdated),this.updatePoints()}remove(){this.points.eventTarget.removeEventListener("updated",this.onPointsUpdated)}onPointerDown(t){const[e,o]=this.container.domToNormalized(t.clientX,t.clientY).map($);this.isNewPointFromPointer=!0,this.points.addPoint(e,o),this.isNewPointFromPointer=!1}onControlPointDelete(t){this.points.removePoint(t.detail.point)}updatePoints(){const t=this.controlPoints.filter(i=>!this.points.points.find(s=>s===i.point));t.forEach(i=>i.remove()),this.controlPoints=this.controlPoints.filter(i=>!t.includes(i));const e=i=>this.controlPoints.find(s=>s.point===i),o=i=>{const s=new V(this.container,i,this.toDataSpace,d=>this.onControlPointDelete(d),this.isNewPointFromPointer);s.eventTarget.addEventListener("hovered-updated",()=>this.updateHovered(s.getIsHovered())),this.controlPoints.push(s)};this.points.points.filter(i=>!e(i)).forEach(o)}updateHovered(t){t!==this.hovered&&(this.hovered=t,this.eventTarget.dispatchEvent(new CustomEvent("hovered-updated",{detail:{hovered:this.hovered}})))}}const q=()=>{const n=document.createElementNS("http://www.w3.org/2000/svg","polyline");return n.setAttribute("fill","none"),n.setAttribute("stroke","black"),n.setAttribute("stroke-width","2"),n.setAttribute("style","cursor: move;"),n.setAttribute("clip-path","url(#border-clip)"),n};class K{constructor(t,e){a(this,"points");a(this,"container");a(this,"onPointsUpdated");a(this,"element");a(this,"clickabeElement");a(this,"dragging",!1);a(this,"pointerEntered",!1);this.container=t,this.points=e,this.element=q(),this.element.setAttribute("pointer-events","none"),this.container.appendChild(this.element),this.clickabeElement=q(),this.clickabeElement.setAttribute("stroke-width","8"),this.clickabeElement.setAttribute("stroke","none"),this.clickabeElement.setAttribute("pointer-events","stroke"),this.container.appendChild(this.clickabeElement),this.onPointsUpdated=()=>this.update(),this.points.eventTarget.addEventListener("updated",this.onPointsUpdated),this.container.addSizeObserver(()=>{this.update()}),this.update(),this.setupInteraction()}remove(){this.points.eventTarget.removeEventListener("updated",this.onPointsUpdated)}update(){if(this.pointerEntered&&this.element.setAttribute("stroke-width","4"),this.dragging&&this.element.setAttribute("stroke-width","5"),!this.pointerEntered&&!this.dragging&&this.element.setAttribute("stroke-width","2"),this.points.points.length===0){this.element.setAttribute("points",""),this.clickabeElement.setAttribute("points","");return}const t=this.computeStringPoints();this.element.setAttribute("points",t),this.clickabeElement.setAttribute("points",t)}computeStringPoints(){return X(this.points.points).map(([t,e])=>this.container.normalizedToSvg(t,e)).map(([t,e])=>`${t},${e}`).join(" ")}drag(t){const[e,o]=this.container.domToNormalized(0,0),[i,s]=this.container.domToNormalized(t.movementX,t.movementY),d=i-e,r=s-o;this.applyOffset(d,r)}applyOffset(t,e){this.points.points.forEach(o=>{o.setPosition(o.x+t,o.y+e)})}startInteraction(){this.element.setAttribute("stroke-width","5");const t=o=>{this.dragging=!0,this.drag(o)};document.addEventListener("pointermove",t);const e=()=>{document.removeEventListener("pointermove",t),document.removeEventListener("pointerup",e),this.dragging=!1,this.update()};document.addEventListener("pointerup",e)}setupInteraction(){this.clickabeElement.addEventListener("pointerdown",t=>{t.stopPropagation(),this.startInteraction()}),this.clickabeElement.addEventListener("pointerenter",()=>{this.pointerEntered=!0,this.update()}),this.clickabeElement.addEventListener("pointerleave",()=>{this.pointerEntered=!1,this.update()})}}const J=1.1,wt=n=>{n.root.addEventListener("wheel",t=>{const e=t.deltaY>0?J:1/J,[o]=n.domToNormalized(t.clientX,t.clientY),[i,s]=n.getViewBox(),d=Math.max(0,i-Math.max(0,o-i)*(e-1)),r=Math.min(1,(s-i)*e+d);d===i&&r===s||(t.preventDefault(),t.stopPropagation(),n.setViewBox(d,r))})},Q="rgba(50, 50, 50, 0.3)",bt=(n,t,e)=>{const o=document.createElement("canvas");n.root.appendChild(o),o.setAttribute("style","width: 100%; height: 100%; ");const i=o.getContext("2d");let s,d;const r=document.createElement("canvas"),l=()=>{if(i){if(i.clearRect(0,0,o.width,o.height),s){const{width:v,height:h}=n.root.getBoundingClientRect();o.setAttribute("width",String(v)),o.setAttribute("height",String(h));const{left:u,right:m,bottom:C,top:T}=n.borderSize(),k=Math.ceil(m-u);if(k<0)return;const D=X(t.points),_=[[0,0],...D,[1,0]].map(([z,U])=>n.normalizedToSvg(z,U));i.save(),i.beginPath(),_.forEach(([z,U])=>{i.lineTo(z,U)}),i.clip();const B=new Path2D;B.rect(u,T,k,C-T),i.clip(B);const[f,w]=e.getColorRange(),[b]=n.normalizedToSvg(f,1),[E]=n.normalizedToSvg(w,1),y=Math.min(v,Math.max(0,b)),M=Math.min(v,Math.max(0,E)),R=M-y<2?y+2:M,O=Math.ceil(R-y);if(s){const z=E-b,U=(y-b)/z,Dt=(R-E)/z,H=s.getMappingRange(),it=H[1]-H[0],Mt=[H[0]+it*U,H[1]+it*Dt];st(s,O,Mt,r),i.drawImage(r,0,0,r.width,r.height,Math.floor(y),Math.floor(T),O,Math.ceil(C-T));const Ot=i.imageSmoothingEnabled;i.imageSmoothingEnabled=!1,i.drawImage(r,0,0,1,1,0,Math.floor(T),Math.floor(y),Math.ceil(C-T)),i.drawImage(r,r.width-1,0,1,1,Math.floor(R),Math.floor(T),v-R,Math.ceil(C-T)),i.imageSmoothingEnabled=Ot}i.restore()}if(d){const{left:v,right:h,bottom:u,top:m}=n.borderSize(),C=[v,m,h-v,u-m];ot(i,C,d,{lineWidth:1,strokeStyle:Q,fillStyle:Q})}}};let c;const g=()=>{clearTimeout(c),c=setTimeout(()=>{l()},0)};return n.addSizeObserver(g),t.eventTarget.addEventListener("updated",g),e.eventTarget.addEventListener("updated",g),{container:n,canvas:o,setColorTransferFunction:v=>{s=v,g()},setHistogram:v=>{d=v,g()},render:g,remove:()=>n.root.removeChild(o)}},tt=-2.75;class Et extends V{constructor(){super(...arguments);a(this,"fadedOpacity","1")}getSvgPosition(){const{x:e}=this.point,[o,i]=this.container.normalizedToSvg(e,0),s=i+tt+A;return[o,s]}movePoint(e){super.movePoint(e),this.point.setPosition(this.point.x,0)}}class St extends K{constructor(t,e){super(t,e),this.element.removeAttribute("clip-path"),this.clickabeElement.removeAttribute("clip-path")}computeStringPoints(){return this.points.points.map(({x:t,y:e})=>[t,e]).map(([t,e])=>this.container.normalizedToSvg(t,e)).map(([t,e])=>`${t},${e+tt+A}`).join(" ")}applyOffset(t,e){this.points.points.forEach(o=>{o.setPosition(o.x+t,o.y)})}}const Tt=()=>{const n=new Y;n.addPoints([[0,0],[1,0]]);const t=()=>n.points.sort((r,l)=>r.x-l.x),e=()=>t().map(r=>r.x),o=new EventTarget,i=()=>o.dispatchEvent(new CustomEvent("updated",{detail:e()}));let s=!1;const d=r=>{r.eventTarget.addEventListener("updated",()=>{s||i()})};return n.points.forEach(d),{getPoints:t,getColorRange:e,setColorRange:r=>{s=!0,t().forEach((l,c)=>{l.x=r[c]}),s=!1,i()},eventTarget:o,points:n}},Pt=(n,t,e)=>{const o=new St(n,t.points),i=t.getPoints().map(p=>{const S=new Et(n,p,e);return S.deletable=!1,S});let s;const d=()=>{if(!s)return;const p=s.getMappingRange(),S=[];s.getColor(p[0],S);const v=[];s.getColor(p[1],v);const h=i.sort((u,m)=>u.point.x-m.point.x);h[0].setColor(j(S)),h[1].setColor(j(v))},r=p=>{s=p,d()};t.eventTarget.addEventListener("updated",()=>{d()});const l=new EventTarget;let c=!1;const g=p=>{p!==c&&(c=p,l.dispatchEvent(new CustomEvent("hovered-updated",{detail:{hovered:c}})))};return[...i].forEach(p=>p.eventTarget.addEventListener("hovered-updated",()=>g(p.getIsHovered()))),{points:i,line:o,setColorTransferFunction:r,eventTarget:l}},xt=n=>{const t=[],e=()=>{n(t.some(i=>i))};return()=>{const i=t.length,s=d=>{t[i]=d,e()};return s(!1),s}},Ct=-2,et=12,yt=21;let nt=!1;const At=()=>{if(nt)return;nt=!0;const n=document.createElement("style");n.innerHTML=`
.tfeditor-svg-axis-label {
color: black;
position: absolute;
background-color: white;
border-style: solid;
border-color: black;
border-width: 1px;
font-size: ${et}px;
padding: 2px 6px;
box-sizing: border-box;
transition: opacity 0.1s ease-in-out;
}
`,document.head.appendChild(n)},Lt=(n,t)=>{const{appendChild:e,addSizeObserver:o,paddedBorder:i}=n;At();const s=()=>{const u=document.createElementNS("http://www.w3.org/2000/svg","foreignObject");u.setAttribute("width","100%"),u.setAttribute("height","100%"),u.setAttribute("pointer-events","none");const m=document.createElementNS("http://www.w3.org/1999/xhtml","div");return m.setAttribute("class","tfeditor-svg-axis-label"),u.appendChild(m),e(u,"overlay"),m},d=s(),r=s(),l=document.createElementNS("http://www.w3.org/2000/svg","rect");e(l),l.setAttribute("fill","none"),l.setAttribute("stroke","none"),l.setAttribute("stroke-width",String(yt)),l.setAttribute("pointer-events","stroke");const c=u=>{const[m,C]=n.normalizedToSvg(u,0),T=C+Ct+et;return[m,T]},g=(u,m,C)=>{const T=t.toDataSpace(m);u.textContent=T===0?"0":`${T.toPrecision(4)}`;const[k,D]=c(m),_=u.getBoundingClientRect(),B=C==="start"?-.5:-_.width+.5,f=_.height/2;u.style.transform=`translate(${k+B}px,${D-f}px)`,["x","y","width","height"].forEach(w=>{const b=i.getAttribute(w);b!==null&&l.setAttribute(w,b)})},p=()=>{const[u,m]=n.getViewBox();g(d,u,"start"),g(r,m,"end")};p(),o(p),t.eventTarget.addEventListener("updated",p);const v=xt(u=>{const m=u?"1":"0";d.style.opacity=m,r.style.opacity=m}),h=v();return l.addEventListener("pointerenter",()=>{h(!0)}),l.addEventListener("pointerleave",()=>{h(!1)}),{createSetVisibilityGate:v}},kt=()=>{let n=[0,1];const t=new EventTarget;return{setRange:i=>{n=i,t.dispatchEvent(new CustomEvent("updated",{detail:n}))},toDataSpace:i=>{const[s,d]=n,r=d-s;return i*r+s},eventTarget:t}},Rt=2e3;class It{constructor(t,e=void 0){a(this,"eventTarget",new EventTarget);a(this,"points");a(this,"colorRange");a(this,"colorRangeController");a(this,"line");a(this,"pointController");a(this,"container");a(this,"background");a(this,"dataRange",kt());this.container=e||ht(t),wt(this.container),this.points=new Y;const o=[[0,0],[1,1]];this.points.setPoints(o),this.line=new K(this.container,this.points),this.pointController=new ft(this.container,this.points,this.dataRange.toDataSpace);const{createSetVisibilityGate:i}=Lt(this.container,this.dataRange);this.colorRange=Tt(),this.colorRangeController=Pt(this.container,this.colorRange,this.dataRange.toDataSpace),this.background=bt(this.container,this.points,this.colorRange),this.points.eventTarget.addEventListener("updated",l=>{this.eventTarget.dispatchEvent(new CustomEvent("updated",{detail:l.detail}))}),this.colorRange.eventTarget.addEventListener("updated",l=>{this.eventTarget.dispatchEvent(new CustomEvent("colorRange",{detail:l.detail}))});const s=i();this.pointController.eventTarget.addEventListener("hovered-updated",l=>{const{hovered:c}=l.detail;s(c)});const d=i();let r;this.container.eventTarget.addEventListener("viewbox-updated",()=>{d(!0),clearTimeout(r),r=setTimeout(()=>{d(!1)},Rt)})}remove(){this.background.remove(),this.container.remove()}getPoints(){return this.points.points.map(({x:t,y:e})=>[t,e])}setPoints(t){this.points.setPoints(t),this.pointController.updatePoints(),this.line.update(),this.background.render()}getColorRange(){return this.colorRange.getColorRange()}setColorRange(t){return this.colorRange.setColorRange(t)}setViewBox(t,e,o=0,i=1){this.container.setViewBox(t,e,o,i)}setColorTransferFunction(t){this.background.setColorTransferFunction(t),this.colorRangeController.setColorTransferFunction(t)}setHistogram(t){this.background.setHistogram(rt(t))}setRange(t){this.dataRange.setRange(t)}}P.TransferFunctionEditor=It,P.getNodes=dt,P.windowPointsForSort=G,Object.defineProperty(P,Symbol.toStringTag,{value:"Module"})});
//# sourceMappingURL=TransferFunctionEditor.umd.js.map
{
"name": "itk-viewer-transfer-function-editor",
"version": "1.5.0",
"version": "1.6.0",
"description": "Interface to interactively edit opacity transfer functions, etc",

@@ -22,3 +22,3 @@ "files": [

"build": "vite build && tsc --project tsconfig.build.json",
"build:watch": "vite build --watch",
"watch": "vite build --watch",
"test": "vitest",

@@ -25,0 +25,0 @@ "format": "prettier --write .",

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc