@milaboratories/graph-maker 1.1.136 → 1.1.137
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/dist/GraphMaker/constantsCommon.d.ts +2 -0
- package/dist/GraphMaker/constantsCommon.d.ts.map +1 -1
- package/dist/GraphMaker/constantsCommon.js +19 -17
- package/dist/GraphMaker/constantsCommon.js.map +1 -1
- package/dist/GraphMaker/forms/AxesSettingsForm/HeatmapAxesSettingsForm.vue.d.ts.map +1 -1
- package/dist/GraphMaker/forms/AxesSettingsForm/HeatmapAxesSettingsForm.vue.js +144 -122
- package/dist/GraphMaker/forms/AxesSettingsForm/HeatmapAxesSettingsForm.vue.js.map +1 -1
- package/dist/GraphMaker/index.vue.js +72 -72
- package/dist/GraphMaker/index.vue.js.map +1 -1
- package/dist/GraphMaker/utils/createChartSettingsForRender/getAxesDataFromForms.d.ts.map +1 -1
- package/dist/GraphMaker/utils/createChartSettingsForRender/getAxesDataFromForms.js +9 -9
- package/dist/GraphMaker/utils/createChartSettingsForRender/getAxesDataFromForms.js.map +1 -1
- package/dist/node_modules/@milaboratories/miplots4/dist/heatmap/ChartRenderer.js +246 -228
- package/dist/node_modules/@milaboratories/miplots4/dist/heatmap/ChartRenderer.js.map +1 -1
- package/dist/node_modules/@milaboratories/miplots4/dist/heatmap/components/Captions/GroupCaptions.js +46 -37
- package/dist/node_modules/@milaboratories/miplots4/dist/heatmap/components/Captions/GroupCaptions.js.map +1 -1
- package/dist/node_modules/@milaboratories/miplots4/dist/heatmap/components/Chart.js +63 -61
- package/dist/node_modules/@milaboratories/miplots4/dist/heatmap/components/Chart.js.map +1 -1
- package/dist/node_modules/@milaboratories/miplots4/dist/heatmap/components/ChartsGroup.js +4 -4
- package/dist/node_modules/@milaboratories/miplots4/dist/heatmap/components/Dendrograms.js +57 -51
- package/dist/node_modules/@milaboratories/miplots4/dist/heatmap/components/Dendrograms.js.map +1 -1
- package/dist/node_modules/@milaboratories/miplots4/dist/heatmap/getDendrograms.js +33 -33
- package/dist/node_modules/@milaboratories/miplots4/dist/heatmap/getDendrograms.js.map +1 -1
- package/dist/node_modules/@milaboratories/miplots4/dist/heatmap/index.js +20 -20
- package/dist/node_modules/@milaboratories/miplots4/dist/heatmap/utils/calculateCaptionTails.js +89 -54
- package/dist/node_modules/@milaboratories/miplots4/dist/heatmap/utils/calculateCaptionTails.js.map +1 -1
- package/dist/node_modules/@milaboratories/miplots4/dist/heatmap/utils/calculateChartSideElementSizes.js +19 -19
- package/dist/node_modules/@milaboratories/miplots4/dist/heatmap/utils/calculateChartSideElementSizes.js.map +1 -1
- package/dist/node_modules/@milaboratories/miplots4/dist/scatterplot/ChartRenderer.js +181 -168
- package/dist/node_modules/@milaboratories/miplots4/dist/scatterplot/ChartRenderer.js.map +1 -1
- package/dist/node_modules/@milaboratories/miplots4/dist/scatterplot/components/ChartsGroup.js +1 -1
- package/dist/node_modules/@milaboratories/miplots4/dist/scatterplot/components/ChartsGroup.js.map +1 -1
- package/dist/node_modules/@milaboratories/miplots4/dist/scatterplot/index.js +5 -5
- package/dist/node_modules/@milaboratories/miplots4/dist/scatterplot-umap/components/Lasso.js +144 -120
- package/dist/node_modules/@milaboratories/miplots4/dist/scatterplot-umap/components/Lasso.js.map +1 -1
- package/dist/node_modules/@milaboratories/miplots4/dist/scatterplot-umap/components/LowerSVG.js +35 -35
- package/dist/node_modules/@milaboratories/miplots4/dist/scatterplot-umap/components/LowerSVG.js.map +1 -1
- package/dist/node_modules/@milaboratories/miplots4/dist/scatterplot-umap/index.js +1 -1
- package/dist/node_modules/@milaboratories/miplots4/dist/scatterplot-umap/index.js.map +1 -1
- package/package.json +2 -2
package/dist/node_modules/@milaboratories/miplots4/dist/scatterplot-umap/components/Lasso.js
CHANGED
|
@@ -1,138 +1,138 @@
|
|
|
1
|
-
import { j as
|
|
2
|
-
import { SCATTERPLOT_LASSO_EVENTS as
|
|
3
|
-
import { BLACK as
|
|
1
|
+
import { j as l } from "../../node_modules/react/jsx-runtime.js";
|
|
2
|
+
import { SCATTERPLOT_LASSO_EVENTS as x } from "../constants.js";
|
|
3
|
+
import { BLACK as F } from "../../constants.js";
|
|
4
4
|
import { r as n } from "../../_virtual/index.js";
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
const
|
|
8
|
-
function
|
|
5
|
+
import fe from "../../node_modules/d3-drag/src/drag.js";
|
|
6
|
+
import U from "../../node_modules/d3-selection/src/select.js";
|
|
7
|
+
const y = "#845CFF", G = "#CFD1DB", de = 20, B = 3, pe = 6, he = 10;
|
|
8
|
+
function ke({
|
|
9
9
|
scales: r,
|
|
10
10
|
chartSizes: k,
|
|
11
|
-
zoomStateKey:
|
|
12
|
-
defaultPolygons:
|
|
11
|
+
zoomStateKey: I,
|
|
12
|
+
defaultPolygons: H,
|
|
13
13
|
onPolygonsApply: j,
|
|
14
|
-
onLassoControlsStateUpdate:
|
|
14
|
+
onLassoControlsStateUpdate: J
|
|
15
15
|
}) {
|
|
16
16
|
n.useEffect(() => {
|
|
17
17
|
function e() {
|
|
18
|
-
M.current !== null && (E([...
|
|
18
|
+
M.current !== null && (E([...d.current.filter((s, o) => o !== M.current)]), A(null), j(d.current));
|
|
19
19
|
}
|
|
20
|
-
function t(
|
|
21
|
-
|
|
20
|
+
function t(s) {
|
|
21
|
+
N(s.detail);
|
|
22
22
|
}
|
|
23
|
-
function
|
|
24
|
-
|
|
23
|
+
function a() {
|
|
24
|
+
q(v.current - 1);
|
|
25
25
|
}
|
|
26
|
-
function
|
|
27
|
-
|
|
26
|
+
function c() {
|
|
27
|
+
q(v.current + 1);
|
|
28
28
|
}
|
|
29
|
-
return document.addEventListener(
|
|
30
|
-
document.removeEventListener(
|
|
29
|
+
return document.addEventListener(x.delete, e), document.addEventListener(x.selectMode, t), document.addEventListener(x.back, a), document.addEventListener(x.forward, c), () => {
|
|
30
|
+
document.removeEventListener(x.delete, e), document.removeEventListener(x.selectMode, t), document.removeEventListener(x.back, a), document.removeEventListener(x.forward, c);
|
|
31
31
|
};
|
|
32
32
|
}, []);
|
|
33
|
-
const [
|
|
33
|
+
const [p, Q] = n.useState("pen"), [S, V] = n.useState(H), d = n.useRef(H), [Y, K] = n.useState(null), [L, Z] = n.useState(null), M = n.useRef(null), [u, _] = n.useState([]), h = n.useRef(u), [b, ee] = n.useState([{ newPolygonPoints: u, closedPolygons: S }]), [m, W] = n.useState(0), w = n.useRef(b), v = n.useRef(m), [f, te] = n.useState(null), C = n.useRef(null), [P, T] = n.useState(!1), g = n.useRef(null), O = n.useRef(null), $ = n.useCallback(function() {
|
|
34
34
|
const e = {
|
|
35
|
-
newPolygonPoints: [...
|
|
36
|
-
closedPolygons: [...
|
|
35
|
+
newPolygonPoints: [...h.current],
|
|
36
|
+
closedPolygons: [...d.current]
|
|
37
37
|
}, t = w.current.slice(0, v.current + 1);
|
|
38
|
-
t.push(e), t.length >
|
|
39
|
-
}, []),
|
|
38
|
+
t.push(e), t.length > he && t.shift(), ee(t), W(t.length - 1), w.current = t, v.current = t.length - 1;
|
|
39
|
+
}, []), q = n.useCallback(function(e) {
|
|
40
40
|
if (e > w.current.length - 1 || e < 0)
|
|
41
41
|
return;
|
|
42
|
-
|
|
42
|
+
N("selection");
|
|
43
43
|
const t = w.current[e];
|
|
44
|
-
E(t.closedPolygons, !1), R(t.newPolygonPoints, !1),
|
|
44
|
+
E(t.closedPolygons, !1), R(t.newPolygonPoints, !1), W(e), v.current = e;
|
|
45
45
|
}, []);
|
|
46
46
|
function E(e, t = !0) {
|
|
47
|
-
|
|
47
|
+
V(e), d.current = e, t && $();
|
|
48
48
|
}
|
|
49
49
|
function R(e, t = !0) {
|
|
50
|
-
|
|
50
|
+
h.current = e, _(e), t && $();
|
|
51
51
|
}
|
|
52
|
-
function
|
|
52
|
+
function A(e) {
|
|
53
53
|
Z(e), M.current = e;
|
|
54
54
|
}
|
|
55
|
-
function
|
|
56
|
-
if (
|
|
57
|
-
if (
|
|
58
|
-
const t = { points:
|
|
59
|
-
E([...
|
|
55
|
+
function N(e) {
|
|
56
|
+
if (Q(e), e === "selection" && (A(null), O.current = null, g.current = null), e === "pen") {
|
|
57
|
+
if (h.current.length > 2) {
|
|
58
|
+
const t = { points: h.current, closed: !0 };
|
|
59
|
+
E([...d.current, t]), j([...d.current, t]);
|
|
60
60
|
}
|
|
61
|
-
|
|
61
|
+
D();
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
|
-
function
|
|
64
|
+
function D(e = !0) {
|
|
65
65
|
C.current = null, R([], e);
|
|
66
66
|
}
|
|
67
|
-
function
|
|
68
|
-
e.key === "Escape" &&
|
|
67
|
+
function X(e) {
|
|
68
|
+
e.key === "Escape" && D();
|
|
69
69
|
}
|
|
70
|
-
n.useEffect(() => (document.addEventListener("keydown",
|
|
70
|
+
n.useEffect(() => (document.addEventListener("keydown", X), () => document.removeEventListener("keydown", X)), []), n.useEffect(() => {
|
|
71
71
|
var e;
|
|
72
|
-
(e =
|
|
73
|
-
}, [
|
|
74
|
-
const
|
|
75
|
-
if (T(!1), !C.current ||
|
|
72
|
+
(e = O.current) == null || e.attr("cx", (t) => r.x(t.p[0])).attr("cy", (t) => r.y(t.p[1]));
|
|
73
|
+
}, [I, k.chartWidth, k.chartHeight]);
|
|
74
|
+
const ne = n.useCallback(function() {
|
|
75
|
+
if (T(!1), !C.current || p === "pen")
|
|
76
76
|
return;
|
|
77
|
-
const e = [...C.current], t = r.x.invert(e[0]),
|
|
78
|
-
if (!
|
|
79
|
-
R([[t,
|
|
77
|
+
const e = [...C.current], t = r.x.invert(e[0]), a = r.y.invert(e[1]);
|
|
78
|
+
if (!h.current.length) {
|
|
79
|
+
R([[t, a]]);
|
|
80
80
|
return;
|
|
81
81
|
}
|
|
82
|
-
const
|
|
83
|
-
if (!P ||
|
|
84
|
-
R([...
|
|
82
|
+
const c = h.current;
|
|
83
|
+
if (!P || c.length < 3)
|
|
84
|
+
R([...c, [t, a]]);
|
|
85
85
|
else {
|
|
86
|
-
const
|
|
87
|
-
|
|
86
|
+
const s = { points: [...c], closed: !0 };
|
|
87
|
+
D(!1), E([...S, s]), setTimeout(() => j([...S, s]), 0);
|
|
88
88
|
}
|
|
89
|
-
}, [
|
|
90
|
-
const t = [e.nativeEvent.offsetX, e.nativeEvent.offsetY],
|
|
91
|
-
if (
|
|
92
|
-
const
|
|
93
|
-
T(
|
|
89
|
+
}, [p, P]), re = n.useCallback(function(e) {
|
|
90
|
+
const t = [e.nativeEvent.offsetX, e.nativeEvent.offsetY], a = h.current, c = h.current[0];
|
|
91
|
+
if (c) {
|
|
92
|
+
const s = r.x(c[0]), o = r.y(c[1]), i = a.length > 1 ? Math.sqrt((t[0] - s) ** 2 + (t[1] - o) ** 2) : 1 / 0;
|
|
93
|
+
T(i < de);
|
|
94
94
|
} else
|
|
95
95
|
T(!1);
|
|
96
|
-
|
|
96
|
+
te(t), C.current = t;
|
|
97
97
|
}, []);
|
|
98
|
-
function
|
|
99
|
-
g.current &&
|
|
98
|
+
function se() {
|
|
99
|
+
g.current && U(g.current).data([]).exit().remove();
|
|
100
100
|
}
|
|
101
101
|
function ce(e) {
|
|
102
|
-
e !== g.current && e && (
|
|
102
|
+
e !== g.current && e && (se(), g.current = e, le(L));
|
|
103
103
|
}
|
|
104
|
-
const
|
|
105
|
-
if (
|
|
106
|
-
const t =
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
const
|
|
110
|
-
...
|
|
111
|
-
points:
|
|
112
|
-
(
|
|
104
|
+
const le = n.useCallback(function(e) {
|
|
105
|
+
if (p !== "selection" && e !== null) {
|
|
106
|
+
const t = fe().on("drag", function(s) {
|
|
107
|
+
const o = U(this), i = o.data()[0];
|
|
108
|
+
i[0] = s.x, i[1] = s.y, i.p = [r.x.invert(i[0]), r.y.invert(i[1])], o.attr("cx", i[0]).attr("cy", i[1]);
|
|
109
|
+
const oe = d.current.map((z, ue) => e !== ue ? z : {
|
|
110
|
+
...z,
|
|
111
|
+
points: z.points.map(
|
|
112
|
+
(ie, ae) => ae === i.idx ? [r.x.invert(i[0]), r.y.invert(i[1])] : ie
|
|
113
113
|
)
|
|
114
114
|
});
|
|
115
|
-
E(
|
|
115
|
+
E(oe, !1);
|
|
116
116
|
}).on("end", function() {
|
|
117
|
-
|
|
118
|
-
}),
|
|
119
|
-
|
|
117
|
+
$(), j(d.current);
|
|
118
|
+
}), a = d.current[e].points.map((s, o) => ({ idx: o, p: s })), c = U(g.current).selectAll("circle").data(a, (s) => s.idx).join("circle");
|
|
119
|
+
O.current = c, c.attr("cx", (s) => r.x(s.p[0])).attr("cy", (s) => r.y(s.p[1])).attr("r", B).attr("fill", "white").attr("stroke", y), c.call(t);
|
|
120
120
|
}
|
|
121
121
|
}, []);
|
|
122
122
|
return n.useEffect(() => {
|
|
123
|
-
|
|
124
|
-
mode:
|
|
125
|
-
backEnabled:
|
|
126
|
-
forwardEnabled:
|
|
123
|
+
J(p === "pen" ? {
|
|
124
|
+
mode: p,
|
|
125
|
+
backEnabled: m > 0,
|
|
126
|
+
forwardEnabled: m < b.length - 1,
|
|
127
127
|
deleteEnabled: L !== null
|
|
128
128
|
} : {
|
|
129
|
-
mode:
|
|
130
|
-
backEnabled:
|
|
131
|
-
forwardEnabled:
|
|
129
|
+
mode: p,
|
|
130
|
+
backEnabled: m > 0,
|
|
131
|
+
forwardEnabled: m < b.length - 1,
|
|
132
132
|
deleteEnabled: !1
|
|
133
133
|
});
|
|
134
|
-
}, [
|
|
135
|
-
/* @__PURE__ */
|
|
134
|
+
}, [p, L, m, b]), /* @__PURE__ */ l.jsx(l.Fragment, { children: /* @__PURE__ */ l.jsxs("g", { children: [
|
|
135
|
+
/* @__PURE__ */ l.jsx("defs", { children: /* @__PURE__ */ l.jsx(
|
|
136
136
|
"pattern",
|
|
137
137
|
{
|
|
138
138
|
id: "diagonalStripes",
|
|
@@ -140,93 +140,117 @@ function ve({
|
|
|
140
140
|
height: "5",
|
|
141
141
|
patternTransform: "rotate(45 0 0)",
|
|
142
142
|
patternUnits: "userSpaceOnUse",
|
|
143
|
-
children: /* @__PURE__ */
|
|
143
|
+
children: /* @__PURE__ */ l.jsx("line", { x1: "0", y1: "0", x2: "0", y2: "10", stroke: y, strokeWidth: "1" })
|
|
144
144
|
}
|
|
145
145
|
) }),
|
|
146
|
-
/* @__PURE__ */
|
|
146
|
+
/* @__PURE__ */ l.jsx(
|
|
147
147
|
"rect",
|
|
148
148
|
{
|
|
149
149
|
fill: "transparent",
|
|
150
150
|
width: k.chartWidth,
|
|
151
151
|
height: k.chartHeight,
|
|
152
|
-
onMouseMove:
|
|
153
|
-
onClick:
|
|
152
|
+
onMouseMove: re,
|
|
153
|
+
onClick: ne
|
|
154
154
|
}
|
|
155
155
|
),
|
|
156
156
|
S.map((e, t) => {
|
|
157
|
-
const
|
|
158
|
-
return /* @__PURE__ */
|
|
159
|
-
/* @__PURE__ */
|
|
157
|
+
const a = t === Y, c = t === L, s = e.points.map((o) => [r.x(o[0]), r.y(o[1])]).map((o, i) => (i === 0 ? "M" : "L") + o[0] + "," + o[1]).join("") + "z";
|
|
158
|
+
return /* @__PURE__ */ l.jsxs("g", { children: [
|
|
159
|
+
/* @__PURE__ */ l.jsx(
|
|
160
160
|
"path",
|
|
161
161
|
{
|
|
162
|
-
d:
|
|
163
|
-
fill:
|
|
164
|
-
stroke:
|
|
165
|
-
onMouseOver: () =>
|
|
166
|
-
onMouseLeave: () =>
|
|
167
|
-
onClick: () =>
|
|
168
|
-
style: { pointerEvents:
|
|
162
|
+
d: s,
|
|
163
|
+
fill: a && !c ? "url(#diagonalStripes)" : "transparent",
|
|
164
|
+
stroke: c || a ? y : F,
|
|
165
|
+
onMouseOver: () => K(t),
|
|
166
|
+
onMouseLeave: () => K(null),
|
|
167
|
+
onClick: () => A(t),
|
|
168
|
+
style: { pointerEvents: p === "selection" || c ? "none" : "auto" }
|
|
169
169
|
}
|
|
170
170
|
),
|
|
171
|
-
|
|
171
|
+
c && /* @__PURE__ */ l.jsx("g", { ref: (o) => ce(o) })
|
|
172
172
|
] }, t);
|
|
173
173
|
}),
|
|
174
|
-
/* @__PURE__ */
|
|
174
|
+
/* @__PURE__ */ l.jsx(
|
|
175
175
|
"polyline",
|
|
176
176
|
{
|
|
177
|
-
points:
|
|
178
|
-
stroke:
|
|
177
|
+
points: u.map((e) => `${r.x(e[0])},${r.y(e[1])}`).join(" "),
|
|
178
|
+
stroke: F,
|
|
179
179
|
fill: "none",
|
|
180
180
|
style: { pointerEvents: "none" }
|
|
181
181
|
}
|
|
182
182
|
),
|
|
183
|
-
|
|
184
|
-
/* @__PURE__ */
|
|
183
|
+
u.length > 1 && f && /* @__PURE__ */ l.jsxs("g", { style: { pointerEvents: "none" }, children: [
|
|
184
|
+
/* @__PURE__ */ l.jsx(
|
|
185
|
+
"circle",
|
|
186
|
+
{
|
|
187
|
+
cx: r.x(u[0][0]),
|
|
188
|
+
cy: r.y(u[0][1]),
|
|
189
|
+
r: pe,
|
|
190
|
+
fill: "none",
|
|
191
|
+
stroke: G,
|
|
192
|
+
strokeDasharray: "3 3"
|
|
193
|
+
}
|
|
194
|
+
),
|
|
195
|
+
/* @__PURE__ */ l.jsx(
|
|
196
|
+
"line",
|
|
197
|
+
{
|
|
198
|
+
x1: f[0],
|
|
199
|
+
y1: f[1],
|
|
200
|
+
x2: r.x(u[0][0]),
|
|
201
|
+
y2: r.y(u[0][1]),
|
|
202
|
+
stroke: G,
|
|
203
|
+
strokeDasharray: "3 3"
|
|
204
|
+
}
|
|
205
|
+
)
|
|
206
|
+
] }),
|
|
207
|
+
u.length > 0 && f && /* @__PURE__ */ l.jsxs("g", { style: { pointerEvents: "none" }, children: [
|
|
208
|
+
/* @__PURE__ */ l.jsx(
|
|
185
209
|
"line",
|
|
186
210
|
{
|
|
187
|
-
x1: r.x(
|
|
188
|
-
y1: r.y(
|
|
189
|
-
x2:
|
|
190
|
-
y2:
|
|
191
|
-
stroke:
|
|
211
|
+
x1: r.x(u[u.length - 1][0]),
|
|
212
|
+
y1: r.y(u[u.length - 1][1]),
|
|
213
|
+
x2: f[0],
|
|
214
|
+
y2: f[1],
|
|
215
|
+
stroke: y
|
|
192
216
|
}
|
|
193
217
|
),
|
|
194
|
-
|
|
218
|
+
u.map((e, t) => /* @__PURE__ */ l.jsx(
|
|
195
219
|
"circle",
|
|
196
220
|
{
|
|
197
221
|
cx: r.x(e[0]),
|
|
198
222
|
cy: r.y(e[1]),
|
|
199
|
-
r:
|
|
223
|
+
r: B,
|
|
200
224
|
fill: "white",
|
|
201
|
-
stroke:
|
|
225
|
+
stroke: t > 0 ? y : F
|
|
202
226
|
},
|
|
203
227
|
t
|
|
204
228
|
)),
|
|
205
|
-
/* @__PURE__ */
|
|
229
|
+
/* @__PURE__ */ l.jsx(
|
|
206
230
|
"circle",
|
|
207
231
|
{
|
|
208
|
-
cx:
|
|
209
|
-
cy:
|
|
210
|
-
r:
|
|
232
|
+
cx: f[0],
|
|
233
|
+
cy: f[1],
|
|
234
|
+
r: B,
|
|
211
235
|
fill: "white",
|
|
212
|
-
stroke:
|
|
236
|
+
stroke: y
|
|
213
237
|
}
|
|
214
238
|
)
|
|
215
239
|
] }),
|
|
216
|
-
P &&
|
|
240
|
+
P && f && /* @__PURE__ */ l.jsx(
|
|
217
241
|
"circle",
|
|
218
242
|
{
|
|
219
|
-
cx:
|
|
220
|
-
cy:
|
|
243
|
+
cx: f[0] + 5,
|
|
244
|
+
cy: f[1] - 5,
|
|
221
245
|
r: 2,
|
|
222
246
|
fill: "none",
|
|
223
|
-
stroke:
|
|
247
|
+
stroke: y,
|
|
224
248
|
strokeWidth: 0.5
|
|
225
249
|
}
|
|
226
250
|
)
|
|
227
251
|
] }) });
|
|
228
252
|
}
|
|
229
253
|
export {
|
|
230
|
-
|
|
254
|
+
ke as Lasso
|
|
231
255
|
};
|
|
232
256
|
//# sourceMappingURL=Lasso.js.map
|
package/dist/node_modules/@milaboratories/miplots4/dist/scatterplot-umap/components/Lasso.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Lasso.js","sources":["../../../../../../../node_modules/@milaboratories/miplots4/src/scatterplot-umap/components/Lasso.tsx"],"sourcesContent":["import {SCATTERPLOT_LASSO_EVENTS} from '../constants';\nimport type {LassoControlsState, LassoMode} from '../types';\nimport type {Polygon} from '../types';\nimport type {Selection} from 'd3-selection';\nimport {select} from 'd3-selection';\nimport {BLACK} from '../../constants';\nimport type {ChartScales, ChartSizes, Point} from '../types';\nimport type {MouseEvent} from 'react';\nimport React, {useCallback, useEffect, useRef, useState} from 'react';\nimport {drag} from 'd3-drag';\n\nconst SELECTION_COLOR = '#845CFF';\nconst CLOSING_DISTANCE = 20;\nconst R = 3;\nconst MAX_HISTORY_LENGTH = 10;\n\ntype CircleData = { // moving point for editing\n idx: number;\n p: Point;\n};\ntype CirclesSelection = Selection<SVGCircleElement, CircleData, SVGGElement | null, CircleData>;\n\ntype HistoryFrame = {\n newPolygonPoints: Point[],\n closedPolygons: Polygon[]\n}\n\n// Mode = 'selection': creating new polygons, pan with button\n// Mode = 'pen': selecting polygon to edit or delete, any zooming actions\nexport function Lasso({\n scales,\n chartSizes,\n zoomStateKey,\n defaultPolygons,\n onPolygonsApply,\n onLassoControlsStateUpdate,\n}: {\n scales: ChartScales;\n chartSizes: ChartSizes;\n zoomStateKey: string;\n defaultPolygons: Polygon[];\n onPolygonsApply: (data: Polygon[]) => void;\n onLassoControlsStateUpdate: (v: LassoControlsState) => void;\n}) {\n useEffect(() => {\n // Events from outer controls\n function onPolygonDelete() {\n if (selectedPolygonRef.current === null) {\n return;\n }\n updatePolygons([...closedPolygonsRef.current.filter((_p, idx) => idx !== selectedPolygonRef.current)]);\n updateSelectedPolygon(null);\n onPolygonsApply(closedPolygonsRef.current);\n }\n\n function onModeSelect(e: CustomEvent<LassoMode>) {\n updateMode(e.detail);\n }\n function onClickBack() {\n loadHistoryItem(historyIndexRef.current - 1);\n }\n function onClickForward() {\n loadHistoryItem(historyIndexRef.current + 1);\n }\n document.addEventListener(SCATTERPLOT_LASSO_EVENTS.delete, onPolygonDelete);\n document.addEventListener(SCATTERPLOT_LASSO_EVENTS.selectMode, onModeSelect as EventListener);\n document.addEventListener(SCATTERPLOT_LASSO_EVENTS.back, onClickBack);\n document.addEventListener(SCATTERPLOT_LASSO_EVENTS.forward, onClickForward);\n return () => {\n document.removeEventListener(SCATTERPLOT_LASSO_EVENTS.delete, onPolygonDelete);\n document.removeEventListener(SCATTERPLOT_LASSO_EVENTS.selectMode, onModeSelect as EventListener);\n document.removeEventListener(SCATTERPLOT_LASSO_EVENTS.back, onClickBack);\n document.removeEventListener(SCATTERPLOT_LASSO_EVENTS.forward, onClickForward);\n };\n }, []);\n\n // inner state\n const [lassoMode, setLassoMode] = useState<LassoMode>('pen');\n\n const [closedPolygons, setClosedPolygons] = useState<Polygon[]>(defaultPolygons);\n const closedPolygonsRef = useRef<Polygon[]>(defaultPolygons);\n\n const [hoveredPolygon, setHoveredPolygon] = useState<number | null>(null);\n\n const [selectedPolygon, setSelectedPolygon] = useState<number | null>(null);\n const selectedPolygonRef = useRef<number | null>(null);\n\n const [newPolygonPoints, setNewPolygonPoints] = useState<Point[]>([]);\n const newPolygonPointsRef = useRef(newPolygonPoints);\n\n const [history, setHistory] = useState<HistoryFrame[]>([{newPolygonPoints, closedPolygons}]);\n const [historyIndex, setHistoryIndex] = useState(0);\n const historyRef = useRef(history);\n const historyIndexRef = useRef(historyIndex);\n\n const [movingPoint, setMovingPoint] = useState<null | Point>(null);\n const movingPointRef = useRef<null | Point>(null);\n\n const [closeToStartPoint, setCloseToStartPoint] = useState(false);\n\n const selectedCirclesContainerRef = useRef<SVGGElement | null>(null);\n const selectedCirclesSelectionRef = useRef<CirclesSelection | null>(null);\n\n const saveCurrentStateToHistory = useCallback(function () {\n const newHistoryItem = {\n newPolygonPoints: [...newPolygonPointsRef.current],\n closedPolygons: [...closedPolygonsRef.current]\n };\n const newHistory = historyRef.current.slice(0, historyIndexRef.current + 1);\n newHistory.push(newHistoryItem);\n if (newHistory.length > MAX_HISTORY_LENGTH) {\n newHistory.shift();\n }\n setHistory(newHistory);\n setHistoryIndex(newHistory.length - 1);\n historyRef.current = newHistory;\n historyIndexRef.current = newHistory.length - 1;\n }, []);\n\n const loadHistoryItem = useCallback(function (index:number) {\n if (index > historyRef.current.length - 1 || index < 0) {\n return;\n }\n updateMode('selection');\n const historyState = historyRef.current[index];\n updatePolygons(historyState.closedPolygons, false);\n updateNewPolygon(historyState.newPolygonPoints, false);\n setHistoryIndex(index);\n historyIndexRef.current = index;\n }, []);\n function updatePolygons(p: Polygon[], saveToHistory = true) {\n setClosedPolygons(p);\n closedPolygonsRef.current = p;\n if (saveToHistory) {\n saveCurrentStateToHistory();\n }\n }\n\n function updateNewPolygon(points:Point[], saveToHistory = true) {\n newPolygonPointsRef.current = points;\n setNewPolygonPoints(points);\n if (saveToHistory) {\n saveCurrentStateToHistory();\n }\n }\n\n function updateSelectedPolygon(idx: number | null) {\n setSelectedPolygon(idx);\n selectedPolygonRef.current = idx;\n }\n\n function updateMode(v: LassoMode) {\n setLassoMode(v);\n if (v === 'selection') {\n updateSelectedPolygon(null);\n selectedCirclesSelectionRef.current = null;\n selectedCirclesContainerRef.current = null;\n }\n if (v === 'pen') {\n if (newPolygonPointsRef.current.length > 2) {\n const polygon:Polygon = {points: newPolygonPointsRef.current, closed: true};\n updatePolygons([...closedPolygonsRef.current, polygon]);\n onPolygonsApply([...closedPolygonsRef.current, polygon]);\n }\n clearNotFinishedPolygon();\n }\n }\n function clearNotFinishedPolygon(saveToHistory = true) {\n movingPointRef.current = null;\n updateNewPolygon([], saveToHistory);\n }\n\n function onKeyDown(e: KeyboardEvent) {\n const escape = e.key === 'Escape';\n if (!escape) {\n return;\n }\n clearNotFinishedPolygon();\n }\n\n useEffect(() => {\n document.addEventListener('keydown', onKeyDown);\n return () => document.removeEventListener('keydown', onKeyDown);\n }, []);\n\n useEffect(() => {\n selectedCirclesSelectionRef.current?.attr('cx', d => scales.x(d.p[0])).attr('cy', d => scales.y(d.p[1]));\n }, [zoomStateKey, chartSizes.chartWidth, chartSizes.chartHeight]);\n\n const onNewPointAddByClick = useCallback(function () {\n setCloseToStartPoint(false);\n if (!movingPointRef.current || lassoMode === 'pen') {\n return;\n }\n const currentCoords = [...movingPointRef.current] as Point;\n const x = scales.x.invert(currentCoords[0]);\n const y = scales.y.invert(currentCoords[1]);\n\n if (!newPolygonPointsRef.current.length) {\n updateNewPolygon([[x, y]]);\n return;\n }\n\n const points = newPolygonPointsRef.current;\n const tooFar = !closeToStartPoint;\n if (tooFar || points.length < 3) {\n updateNewPolygon([...points, [x, y]]);\n } else {\n const polygon:Polygon = {points: [...points], closed: true};\n clearNotFinishedPolygon(false);\n updatePolygons([...closedPolygons, polygon]);\n // to avoid freezing of ui updating in case of big amount of points to apply polygons and change opacity\n setTimeout(() => onPolygonsApply([...closedPolygons, polygon]), 0);\n }\n }, [lassoMode, closeToStartPoint]);\n\n const onMouseMove = useCallback(function(e: MouseEvent<SVGRectElement>) {\n const p: Point = [e.nativeEvent.offsetX, e.nativeEvent.offsetY];\n const points = newPolygonPointsRef.current;\n const startPoint = newPolygonPointsRef.current[0];\n if (startPoint) {\n const startX = scales.x(startPoint[0]);\n const startY = scales.y(startPoint[1]);\n const distance = points.length > 1\n ? Math.sqrt((p[0] - startX) ** 2 + (p[1] - startY) ** 2)\n : Infinity;\n setCloseToStartPoint(distance < CLOSING_DISTANCE);\n } else {\n setCloseToStartPoint(false);\n }\n\n setMovingPoint(p);\n movingPointRef.current = p;\n }, []);\n\n function clearSelectedCircles() {\n if (selectedCirclesContainerRef.current) {\n select(selectedCirclesContainerRef.current).data([]).exit().remove();\n }\n }\n\n function updateSelectedCircles(el: SVGGElement | null) {\n if (el !== selectedCirclesContainerRef.current && el) {\n clearSelectedCircles();\n selectedCirclesContainerRef.current = el;\n onPolygonSelect(selectedPolygon);\n }\n }\n\n const onPolygonSelect = useCallback(function (idx: number | null) {\n if (lassoMode === 'selection') {\n return;\n }\n if (idx !== null) {\n const d = drag<SVGCircleElement, CircleData, SVGGElement | null>()\n .on('drag', function (e) {\n const el = select<SVGCircleElement, CircleData>(this);\n const d = el.data()[0] as number[] & CircleData;\n d[0] = e.x;\n d[1] = e.y;\n d.p = [scales.x.invert(d[0]), scales.y.invert(d[1])];\n el.attr('cx', d[0]).attr('cy', d[1]);\n const editedPolygons = closedPolygonsRef.current.map((polygon, polygonIdx) => {\n return idx !== polygonIdx ? polygon : {\n ...polygon,\n points: polygon.points.map((el, pointIdx) =>\n pointIdx === d.idx ? ([scales.x.invert(d[0]), scales.y.invert(d[1])] as Point) : el\n ),\n };\n });\n updatePolygons(editedPolygons, false);\n })\n .on('end', function () {\n saveCurrentStateToHistory();\n onPolygonsApply(closedPolygonsRef.current);\n });\n const draggablePointsData = closedPolygonsRef.current[idx].points.map((p, idx) => ({idx, p}));\n const selectedCircles = select(selectedCirclesContainerRef.current)\n .selectAll<SVGCircleElement, CircleData>('circle')\n .data(draggablePointsData, (d) => d.idx)\n .join('circle');\n selectedCirclesSelectionRef.current = selectedCircles;\n\n selectedCircles\n .attr('cx', d => scales.x(d.p[0]))\n .attr('cy', d => scales.y(d.p[1]))\n .attr('r', R)\n .attr('fill', 'white')\n .attr('stroke', SELECTION_COLOR);\n selectedCircles.call(d);\n }\n }, []);\n\n useEffect(() => {\n if (lassoMode === 'pen') {\n onLassoControlsStateUpdate({\n mode: lassoMode,\n backEnabled: historyIndex > 0,\n forwardEnabled: historyIndex < history.length - 1,\n deleteEnabled: selectedPolygon !== null,\n });\n } else {\n onLassoControlsStateUpdate({\n mode: lassoMode,\n backEnabled: historyIndex > 0,\n forwardEnabled: historyIndex < history.length - 1,\n deleteEnabled: false,\n });\n }\n }, [lassoMode, selectedPolygon, historyIndex, history]);\n\n return (\n <>\n <g>\n <defs>\n <pattern\n id=\"diagonalStripes\"\n width=\"5\"\n height=\"5\"\n patternTransform=\"rotate(45 0 0)\"\n patternUnits=\"userSpaceOnUse\"\n >\n <line x1=\"0\" y1=\"0\" x2=\"0\" y2=\"10\" stroke={SELECTION_COLOR} strokeWidth=\"1\" />\n </pattern>\n </defs>\n <rect\n fill=\"transparent\"\n width={chartSizes.chartWidth}\n height={chartSizes.chartHeight}\n onMouseMove={onMouseMove}\n onClick={onNewPointAddByClick}\n />\n {closedPolygons.map((p, idx) => {\n const isHovered = idx === hoveredPolygon;\n const isSelected = idx === selectedPolygon;\n const points = p.points.map(p => [scales.x(p[0]), scales.y(p[1])]);\n const pathD =\n points\n .map((p, idx) => {\n return (idx === 0 ? 'M' : 'L') + p[0] + ',' + p[1];\n })\n .join('') + 'z';\n return (\n <g key={idx}>\n <path\n d={pathD}\n fill={isHovered && !isSelected ? 'url(#diagonalStripes)' : 'transparent'}\n stroke={isSelected || isHovered ? SELECTION_COLOR : BLACK}\n onMouseOver={() => setHoveredPolygon(idx)}\n onMouseLeave={() => setHoveredPolygon(null)}\n onClick={() => updateSelectedPolygon(idx)}\n style={{pointerEvents: lassoMode === 'selection' || isSelected ? 'none' : 'auto'}}\n />\n {isSelected && <g ref={el => updateSelectedCircles(el)} />}\n </g>\n );\n })}\n <polyline\n points={newPolygonPoints.map((p) => `${scales.x(p[0])},${scales.y(p[1])}`).join(' ')}\n stroke={BLACK}\n fill=\"none\"\n style={{pointerEvents: 'none'}}\n />\n {newPolygonPoints.length > 0 && movingPoint && (\n <g style={{pointerEvents: 'none'}}>\n <line\n x1={scales.x(newPolygonPoints[newPolygonPoints.length - 1][0])}\n y1={scales.y(newPolygonPoints[newPolygonPoints.length - 1][1])}\n x2={movingPoint[0]}\n y2={movingPoint[1]}\n stroke={SELECTION_COLOR}\n />\n {newPolygonPoints.map((p, idx) => (\n <circle\n key={idx}\n cx={scales.x(p[0])}\n cy={scales.y(p[1])}\n r={R}\n fill=\"white\"\n stroke={SELECTION_COLOR}\n />\n ))}\n <circle\n cx={movingPoint[0]}\n cy={movingPoint[1]}\n r={R}\n fill=\"white\"\n stroke={SELECTION_COLOR}\n />\n </g>\n )}\n {closeToStartPoint && movingPoint && (\n <circle\n cx={movingPoint[0] + 5}\n cy={movingPoint[1] - 5}\n r={2}\n fill=\"none\"\n stroke={SELECTION_COLOR}\n strokeWidth={0.5}\n />\n )}\n </g>\n </>\n );\n}\n"],"names":["SELECTION_COLOR","CLOSING_DISTANCE","R","MAX_HISTORY_LENGTH","Lasso","scales","chartSizes","zoomStateKey","defaultPolygons","onPolygonsApply","onLassoControlsStateUpdate","useEffect","onPolygonDelete","selectedPolygonRef","updatePolygons","closedPolygonsRef","_p","idx","updateSelectedPolygon","onModeSelect","e","updateMode","onClickBack","loadHistoryItem","historyIndexRef","onClickForward","SCATTERPLOT_LASSO_EVENTS","lassoMode","setLassoMode","useState","closedPolygons","setClosedPolygons","useRef","hoveredPolygon","setHoveredPolygon","selectedPolygon","setSelectedPolygon","newPolygonPoints","setNewPolygonPoints","newPolygonPointsRef","history","setHistory","historyIndex","setHistoryIndex","historyRef","movingPoint","setMovingPoint","movingPointRef","closeToStartPoint","setCloseToStartPoint","selectedCirclesContainerRef","selectedCirclesSelectionRef","saveCurrentStateToHistory","useCallback","newHistoryItem","newHistory","index","historyState","updateNewPolygon","p","saveToHistory","points","v","polygon","clearNotFinishedPolygon","onKeyDown","_a","d","onNewPointAddByClick","currentCoords","x","y","onMouseMove","startPoint","startX","startY","distance","clearSelectedCircles","select","updateSelectedCircles","el","onPolygonSelect","drag","editedPolygons","polygonIdx","pointIdx","draggablePointsData","selectedCircles","jsx","Fragment","i","isHovered","isSelected","pathD","BLACK","jsxs"],"mappings":"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","x_google_ignoreList":[0]}
|
|
1
|
+
{"version":3,"file":"Lasso.js","sources":["../../../../../../../node_modules/@milaboratories/miplots4/src/scatterplot-umap/components/Lasso.tsx"],"sourcesContent":["import {SCATTERPLOT_LASSO_EVENTS} from '../constants';\nimport type {LassoControlsState, LassoMode} from '../types';\nimport type {Polygon} from '../types';\nimport type {Selection} from 'd3-selection';\nimport {select} from 'd3-selection';\nimport {BLACK} from '../../constants';\nimport type {ChartScales, ChartSizes, Point} from '../types';\nimport type {MouseEvent} from 'react';\nimport React, {useCallback, useEffect, useRef, useState} from 'react';\nimport {drag} from 'd3-drag';\n\nconst SELECTION_COLOR = '#845CFF';\nconst START_GREY = '#CFD1DB';\nconst CLOSING_DISTANCE = 20;\nconst R = 3;\nconst R_START = 6;\nconst MAX_HISTORY_LENGTH = 10;\n\ntype CircleData = { // moving point for editing\n idx: number;\n p: Point;\n};\ntype CirclesSelection = Selection<SVGCircleElement, CircleData, SVGGElement | null, CircleData>;\n\ntype HistoryFrame = {\n newPolygonPoints: Point[],\n closedPolygons: Polygon[]\n}\n\n// Mode = 'selection': creating new polygons, pan with button\n// Mode = 'pen': selecting polygon to edit or delete, any zooming actions\nexport function Lasso({\n scales,\n chartSizes,\n zoomStateKey,\n defaultPolygons,\n onPolygonsApply,\n onLassoControlsStateUpdate,\n}: {\n scales: ChartScales;\n chartSizes: ChartSizes;\n zoomStateKey: string;\n defaultPolygons: Polygon[];\n onPolygonsApply: (data: Polygon[]) => void;\n onLassoControlsStateUpdate: (v: LassoControlsState) => void;\n}) {\n useEffect(() => {\n // Events from outer controls\n function onPolygonDelete() {\n if (selectedPolygonRef.current === null) {\n return;\n }\n updatePolygons([...closedPolygonsRef.current.filter((_p, idx) => idx !== selectedPolygonRef.current)]);\n updateSelectedPolygon(null);\n onPolygonsApply(closedPolygonsRef.current);\n }\n\n function onModeSelect(e: CustomEvent<LassoMode>) {\n updateMode(e.detail);\n }\n function onClickBack() {\n loadHistoryItem(historyIndexRef.current - 1);\n }\n function onClickForward() {\n loadHistoryItem(historyIndexRef.current + 1);\n }\n document.addEventListener(SCATTERPLOT_LASSO_EVENTS.delete, onPolygonDelete);\n document.addEventListener(SCATTERPLOT_LASSO_EVENTS.selectMode, onModeSelect as EventListener);\n document.addEventListener(SCATTERPLOT_LASSO_EVENTS.back, onClickBack);\n document.addEventListener(SCATTERPLOT_LASSO_EVENTS.forward, onClickForward);\n return () => {\n document.removeEventListener(SCATTERPLOT_LASSO_EVENTS.delete, onPolygonDelete);\n document.removeEventListener(SCATTERPLOT_LASSO_EVENTS.selectMode, onModeSelect as EventListener);\n document.removeEventListener(SCATTERPLOT_LASSO_EVENTS.back, onClickBack);\n document.removeEventListener(SCATTERPLOT_LASSO_EVENTS.forward, onClickForward);\n };\n }, []);\n\n // inner state\n const [lassoMode, setLassoMode] = useState<LassoMode>('pen');\n\n const [closedPolygons, setClosedPolygons] = useState<Polygon[]>(defaultPolygons);\n const closedPolygonsRef = useRef<Polygon[]>(defaultPolygons);\n\n const [hoveredPolygon, setHoveredPolygon] = useState<number | null>(null);\n\n const [selectedPolygon, setSelectedPolygon] = useState<number | null>(null);\n const selectedPolygonRef = useRef<number | null>(null);\n\n const [newPolygonPoints, setNewPolygonPoints] = useState<Point[]>([]);\n const newPolygonPointsRef = useRef(newPolygonPoints);\n\n const [history, setHistory] = useState<HistoryFrame[]>([{newPolygonPoints, closedPolygons}]);\n const [historyIndex, setHistoryIndex] = useState(0);\n const historyRef = useRef(history);\n const historyIndexRef = useRef(historyIndex);\n\n const [movingPoint, setMovingPoint] = useState<null | Point>(null);\n const movingPointRef = useRef<null | Point>(null);\n\n const [closeToStartPoint, setCloseToStartPoint] = useState(false);\n\n const selectedCirclesContainerRef = useRef<SVGGElement | null>(null);\n const selectedCirclesSelectionRef = useRef<CirclesSelection | null>(null);\n\n const saveCurrentStateToHistory = useCallback(function () {\n const newHistoryItem = {\n newPolygonPoints: [...newPolygonPointsRef.current],\n closedPolygons: [...closedPolygonsRef.current]\n };\n const newHistory = historyRef.current.slice(0, historyIndexRef.current + 1);\n newHistory.push(newHistoryItem);\n if (newHistory.length > MAX_HISTORY_LENGTH) {\n newHistory.shift();\n }\n setHistory(newHistory);\n setHistoryIndex(newHistory.length - 1);\n historyRef.current = newHistory;\n historyIndexRef.current = newHistory.length - 1;\n }, []);\n\n const loadHistoryItem = useCallback(function (index:number) {\n if (index > historyRef.current.length - 1 || index < 0) {\n return;\n }\n updateMode('selection');\n const historyState = historyRef.current[index];\n updatePolygons(historyState.closedPolygons, false);\n updateNewPolygon(historyState.newPolygonPoints, false);\n setHistoryIndex(index);\n historyIndexRef.current = index;\n }, []);\n function updatePolygons(p: Polygon[], saveToHistory = true) {\n setClosedPolygons(p);\n closedPolygonsRef.current = p;\n if (saveToHistory) {\n saveCurrentStateToHistory();\n }\n }\n\n function updateNewPolygon(points:Point[], saveToHistory = true) {\n newPolygonPointsRef.current = points;\n setNewPolygonPoints(points);\n if (saveToHistory) {\n saveCurrentStateToHistory();\n }\n }\n\n function updateSelectedPolygon(idx: number | null) {\n setSelectedPolygon(idx);\n selectedPolygonRef.current = idx;\n }\n\n function updateMode(v: LassoMode) {\n setLassoMode(v);\n if (v === 'selection') {\n updateSelectedPolygon(null);\n selectedCirclesSelectionRef.current = null;\n selectedCirclesContainerRef.current = null;\n }\n if (v === 'pen') {\n if (newPolygonPointsRef.current.length > 2) {\n const polygon:Polygon = {points: newPolygonPointsRef.current, closed: true};\n updatePolygons([...closedPolygonsRef.current, polygon]);\n onPolygonsApply([...closedPolygonsRef.current, polygon]);\n }\n clearNotFinishedPolygon();\n }\n }\n function clearNotFinishedPolygon(saveToHistory = true) {\n movingPointRef.current = null;\n updateNewPolygon([], saveToHistory);\n }\n\n function onKeyDown(e: KeyboardEvent) {\n const escape = e.key === 'Escape';\n if (!escape) {\n return;\n }\n clearNotFinishedPolygon();\n }\n\n useEffect(() => {\n document.addEventListener('keydown', onKeyDown);\n return () => document.removeEventListener('keydown', onKeyDown);\n }, []);\n\n useEffect(() => {\n selectedCirclesSelectionRef.current?.attr('cx', d => scales.x(d.p[0])).attr('cy', d => scales.y(d.p[1]));\n }, [zoomStateKey, chartSizes.chartWidth, chartSizes.chartHeight]);\n\n const onNewPointAddByClick = useCallback(function () {\n setCloseToStartPoint(false);\n if (!movingPointRef.current || lassoMode === 'pen') {\n return;\n }\n const currentCoords = [...movingPointRef.current] as Point;\n const x = scales.x.invert(currentCoords[0]);\n const y = scales.y.invert(currentCoords[1]);\n\n if (!newPolygonPointsRef.current.length) {\n updateNewPolygon([[x, y]]);\n return;\n }\n\n const points = newPolygonPointsRef.current;\n const tooFar = !closeToStartPoint;\n if (tooFar || points.length < 3) {\n updateNewPolygon([...points, [x, y]]);\n } else {\n const polygon:Polygon = {points: [...points], closed: true};\n clearNotFinishedPolygon(false);\n updatePolygons([...closedPolygons, polygon]);\n // to avoid freezing of ui updating in case of big amount of points to apply polygons and change opacity\n setTimeout(() => onPolygonsApply([...closedPolygons, polygon]), 0);\n }\n }, [lassoMode, closeToStartPoint]);\n\n const onMouseMove = useCallback(function(e: MouseEvent<SVGRectElement>) {\n const p: Point = [e.nativeEvent.offsetX, e.nativeEvent.offsetY];\n const points = newPolygonPointsRef.current;\n const startPoint = newPolygonPointsRef.current[0];\n if (startPoint) {\n const startX = scales.x(startPoint[0]);\n const startY = scales.y(startPoint[1]);\n const distance = points.length > 1\n ? Math.sqrt((p[0] - startX) ** 2 + (p[1] - startY) ** 2)\n : Infinity;\n setCloseToStartPoint(distance < CLOSING_DISTANCE);\n } else {\n setCloseToStartPoint(false);\n }\n\n setMovingPoint(p);\n movingPointRef.current = p;\n }, []);\n\n function clearSelectedCircles() {\n if (selectedCirclesContainerRef.current) {\n select(selectedCirclesContainerRef.current).data([]).exit().remove();\n }\n }\n\n function updateSelectedCircles(el: SVGGElement | null) {\n if (el !== selectedCirclesContainerRef.current && el) {\n clearSelectedCircles();\n selectedCirclesContainerRef.current = el;\n onPolygonSelect(selectedPolygon);\n }\n }\n\n const onPolygonSelect = useCallback(function (idx: number | null) {\n if (lassoMode === 'selection') {\n return;\n }\n if (idx !== null) {\n const d = drag<SVGCircleElement, CircleData, SVGGElement | null>()\n .on('drag', function (e) {\n const el = select<SVGCircleElement, CircleData>(this);\n const d = el.data()[0] as number[] & CircleData;\n d[0] = e.x;\n d[1] = e.y;\n d.p = [scales.x.invert(d[0]), scales.y.invert(d[1])];\n el.attr('cx', d[0]).attr('cy', d[1]);\n const editedPolygons = closedPolygonsRef.current.map((polygon, polygonIdx) => {\n return idx !== polygonIdx ? polygon : {\n ...polygon,\n points: polygon.points.map((el, pointIdx) =>\n pointIdx === d.idx ? ([scales.x.invert(d[0]), scales.y.invert(d[1])] as Point) : el\n ),\n };\n });\n updatePolygons(editedPolygons, false);\n })\n .on('end', function () {\n saveCurrentStateToHistory();\n onPolygonsApply(closedPolygonsRef.current);\n });\n const draggablePointsData = closedPolygonsRef.current[idx].points.map((p, idx) => ({idx, p}));\n const selectedCircles = select(selectedCirclesContainerRef.current)\n .selectAll<SVGCircleElement, CircleData>('circle')\n .data(draggablePointsData, (d) => d.idx)\n .join('circle');\n selectedCirclesSelectionRef.current = selectedCircles;\n\n selectedCircles\n .attr('cx', d => scales.x(d.p[0]))\n .attr('cy', d => scales.y(d.p[1]))\n .attr('r', R)\n .attr('fill', 'white')\n .attr('stroke', SELECTION_COLOR);\n selectedCircles.call(d);\n }\n }, []);\n\n useEffect(() => {\n if (lassoMode === 'pen') {\n onLassoControlsStateUpdate({\n mode: lassoMode,\n backEnabled: historyIndex > 0,\n forwardEnabled: historyIndex < history.length - 1,\n deleteEnabled: selectedPolygon !== null,\n });\n } else {\n onLassoControlsStateUpdate({\n mode: lassoMode,\n backEnabled: historyIndex > 0,\n forwardEnabled: historyIndex < history.length - 1,\n deleteEnabled: false,\n });\n }\n }, [lassoMode, selectedPolygon, historyIndex, history]);\n\n return (\n <>\n <g>\n <defs>\n <pattern\n id=\"diagonalStripes\"\n width=\"5\"\n height=\"5\"\n patternTransform=\"rotate(45 0 0)\"\n patternUnits=\"userSpaceOnUse\"\n >\n <line x1=\"0\" y1=\"0\" x2=\"0\" y2=\"10\" stroke={SELECTION_COLOR} strokeWidth=\"1\" />\n </pattern>\n </defs>\n <rect\n fill=\"transparent\"\n width={chartSizes.chartWidth}\n height={chartSizes.chartHeight}\n onMouseMove={onMouseMove}\n onClick={onNewPointAddByClick}\n />\n {closedPolygons.map((p, idx) => {\n const isHovered = idx === hoveredPolygon;\n const isSelected = idx === selectedPolygon;\n const points = p.points.map(p => [scales.x(p[0]), scales.y(p[1])]);\n const pathD =\n points\n .map((p, idx) => {\n return (idx === 0 ? 'M' : 'L') + p[0] + ',' + p[1];\n })\n .join('') + 'z';\n return (\n <g key={idx}>\n <path\n d={pathD}\n fill={isHovered && !isSelected ? 'url(#diagonalStripes)' : 'transparent'}\n stroke={isSelected || isHovered ? SELECTION_COLOR : BLACK}\n onMouseOver={() => setHoveredPolygon(idx)}\n onMouseLeave={() => setHoveredPolygon(null)}\n onClick={() => updateSelectedPolygon(idx)}\n style={{pointerEvents: lassoMode === 'selection' || isSelected ? 'none' : 'auto'}}\n />\n {isSelected && <g ref={el => updateSelectedCircles(el)} />}\n </g>\n );\n })}\n <polyline\n points={newPolygonPoints.map((p) => `${scales.x(p[0])},${scales.y(p[1])}`).join(' ')}\n stroke={BLACK}\n fill=\"none\"\n style={{pointerEvents: 'none'}}\n />\n {newPolygonPoints.length > 1 && movingPoint && (\n <g style={{pointerEvents: 'none'}}>\n <circle\n cx={scales.x(newPolygonPoints[0][0])}\n cy={scales.y(newPolygonPoints[0][1])}\n r={R_START}\n fill=\"none\"\n stroke={START_GREY}\n strokeDasharray=\"3 3\"\n />\n <line\n x1={movingPoint[0]}\n y1={movingPoint[1]}\n x2={scales.x(newPolygonPoints[0][0])}\n y2={scales.y(newPolygonPoints[0][1])}\n stroke={START_GREY}\n strokeDasharray=\"3 3\"\n />\n </g>\n )}\n {newPolygonPoints.length > 0 && movingPoint && (\n <g style={{pointerEvents: 'none'}}>\n <line\n x1={scales.x(newPolygonPoints[newPolygonPoints.length - 1][0])}\n y1={scales.y(newPolygonPoints[newPolygonPoints.length - 1][1])}\n x2={movingPoint[0]}\n y2={movingPoint[1]}\n stroke={SELECTION_COLOR}\n />\n {newPolygonPoints.map((p, idx) => (\n <circle\n key={idx}\n cx={scales.x(p[0])}\n cy={scales.y(p[1])}\n r={R}\n fill=\"white\"\n stroke={idx > 0 ? SELECTION_COLOR : BLACK}\n />\n ))}\n <circle\n cx={movingPoint[0]}\n cy={movingPoint[1]}\n r={R}\n fill=\"white\"\n stroke={SELECTION_COLOR}\n />\n </g>\n )}\n {closeToStartPoint && movingPoint && (\n <circle\n cx={movingPoint[0] + 5}\n cy={movingPoint[1] - 5}\n r={2}\n fill=\"none\"\n stroke={SELECTION_COLOR}\n strokeWidth={0.5}\n />\n )}\n </g>\n </>\n );\n}\n"],"names":["SELECTION_COLOR","START_GREY","CLOSING_DISTANCE","R","R_START","MAX_HISTORY_LENGTH","Lasso","scales","chartSizes","zoomStateKey","defaultPolygons","onPolygonsApply","onLassoControlsStateUpdate","useEffect","onPolygonDelete","selectedPolygonRef","updatePolygons","closedPolygonsRef","_p","idx","updateSelectedPolygon","onModeSelect","e","updateMode","onClickBack","loadHistoryItem","historyIndexRef","onClickForward","SCATTERPLOT_LASSO_EVENTS","lassoMode","setLassoMode","useState","closedPolygons","setClosedPolygons","useRef","hoveredPolygon","setHoveredPolygon","selectedPolygon","setSelectedPolygon","newPolygonPoints","setNewPolygonPoints","newPolygonPointsRef","history","setHistory","historyIndex","setHistoryIndex","historyRef","movingPoint","setMovingPoint","movingPointRef","closeToStartPoint","setCloseToStartPoint","selectedCirclesContainerRef","selectedCirclesSelectionRef","saveCurrentStateToHistory","useCallback","newHistoryItem","newHistory","index","historyState","updateNewPolygon","p","saveToHistory","points","v","polygon","clearNotFinishedPolygon","onKeyDown","_a","d","onNewPointAddByClick","currentCoords","x","y","onMouseMove","startPoint","startX","startY","distance","clearSelectedCircles","select","updateSelectedCircles","el","onPolygonSelect","drag","editedPolygons","polygonIdx","pointIdx","draggablePointsData","selectedCircles","jsx","Fragment","c","isHovered","isSelected","pathD","BLACK","jsxs"],"mappings":";;;;;;AAWA,MAAMA,IAAkB,WAClBC,IAAa,WACbC,KAAmB,IACnBC,IAAI,GACJC,KAAU,GACVC,KAAqB;AAepB,SAASC,GAAM;AAAA,EAClB,QAAAC;AAAAA,EACA,YAAAC;AAAAA,EACA,cAAAC;AAAAA,EACA,iBAAAC;AAAAA,EACA,iBAAAC;AAAAA,EACA,4BAAAC;AACJ,GAOG;AACCC,EAAAA,EAAAA,UAAU,MAAM;AAEZ,aAASC,IAAkB;AACnBC,MAAAA,EAAmB,YAAY,SAGnCC,EAAe,CAAC,GAAGC,EAAkB,QAAQ,OAAO,CAACC,GAAIC,MAAQA,MAAQJ,EAAmB,OAAO,CAAC,CAAC,GACrGK,EAAsB,IAAI,GAC1BT,EAAgBM,EAAkB,OAAO;AAAA,IAC7C;AAEA,aAASI,EAAaC,GAA2B;AAC7CC,MAAAA,EAAWD,EAAE,MAAM;AAAA,IACvB;AACA,aAASE,IAAc;AACnBC,MAAAA,EAAgBC,EAAgB,UAAU,CAAC;AAAA,IAC/C;AACA,aAASC,IAAiB;AACtBF,MAAAA,EAAgBC,EAAgB,UAAU,CAAC;AAAA,IAC/C;AACA,WAAA,SAAS,iBAAiBE,EAAyB,QAAQd,CAAe,GAC1E,SAAS,iBAAiBc,EAAyB,YAAYP,CAA6B,GAC5F,SAAS,iBAAiBO,EAAyB,MAAMJ,CAAW,GACpE,SAAS,iBAAiBI,EAAyB,SAASD,CAAc,GACnE,MAAM;AACT,eAAS,oBAAoBC,EAAyB,QAAQd,CAAe,GAC7E,SAAS,oBAAoBc,EAAyB,YAAYP,CAA6B,GAC/F,SAAS,oBAAoBO,EAAyB,MAAMJ,CAAW,GACvE,SAAS,oBAAoBI,EAAyB,SAASD,CAAc;AAAA,IACjF;AAAA,EACJ,GAAG,CAAA,CAAE;AAGL,QAAM,CAACE,GAAWC,CAAY,IAAIC,EAAAA,SAAoB,KAAK,GAErD,CAACC,GAAgBC,CAAiB,IAAIF,EAAAA,SAAoBrB,CAAe,GACzEO,IAAoBiB,EAAAA,OAAkBxB,CAAe,GAErD,CAACyB,GAAgBC,CAAiB,IAAIL,EAAAA,SAAwB,IAAI,GAElE,CAACM,GAAiBC,CAAkB,IAAIP,EAAAA,SAAwB,IAAI,GACpEhB,IAAqBmB,EAAAA,OAAsB,IAAI,GAE/C,CAACK,GAAkBC,CAAmB,IAAIT,EAAAA,SAAkB,CAAA,CAAE,GAC9DU,IAAsBP,EAAAA,OAAOK,CAAgB,GAE7C,CAACG,GAASC,EAAU,IAAIZ,EAAAA,SAAyB,CAAC,EAAC,kBAAAQ,GAAkB,gBAAAP,EAAAA,CAAe,CAAC,GACrF,CAACY,GAAcC,CAAe,IAAId,EAAAA,SAAS,CAAC,GAC5Ce,IAAaZ,EAAAA,OAAOQ,CAAO,GAC3BhB,IAAkBQ,EAAAA,OAAOU,CAAY,GAErC,CAACG,GAAaC,EAAc,IAAIjB,EAAAA,SAAuB,IAAI,GAC3DkB,IAAiBf,EAAAA,OAAqB,IAAI,GAE1C,CAACgB,GAAmBC,CAAoB,IAAIpB,EAAAA,SAAS,EAAK,GAE1DqB,IAA8BlB,EAAAA,OAA2B,IAAI,GAC7DmB,IAA8BnB,EAAAA,OAAgC,IAAI,GAElEoB,IAA4BC,EAAAA,YAAY,WAAY;AACtD,UAAMC,IAAiB;AAAA,MACnB,kBAAkB,CAAC,GAAGf,EAAoB,OAAO;AAAA,MACjD,gBAAgB,CAAC,GAAGxB,EAAkB,OAAO;AAAA,IAAA,GAE3CwC,IAAaX,EAAW,QAAQ,MAAM,GAAGpB,EAAgB,UAAU,CAAC;AAC1E+B,MAAW,KAAKD,CAAc,GAC1BC,EAAW,SAASpD,MACpBoD,EAAW,SAEfd,GAAWc,CAAU,GACrBZ,EAAgBY,EAAW,SAAS,CAAC,GACrCX,EAAW,UAAUW,GACrB/B,EAAgB,UAAU+B,EAAW,SAAS;AAAA,EAClD,GAAG,CAAA,CAAE,GAEAhC,IAAkB8B,EAAAA,YAAY,SAAUG,GAAc;AACvD,QAAIA,IAAQZ,EAAW,QAAQ,SAAS,KAAKY,IAAQ;AACjD;AAEJnC,IAAAA,EAAW,WAAW;AACtB,UAAMoC,IAAeb,EAAW,QAAQY,CAAK;AAC7C1C,IAAAA,EAAe2C,EAAa,gBAAgB,EAAK,GACjDC,EAAiBD,EAAa,kBAAkB,EAAK,GACrDd,EAAgBa,CAAK,GACrBhC,EAAgB,UAAUgC;AAAAA,EAC9B,GAAG,CAAA,CAAE;AACL,WAAS1C,EAAe6C,GAAcC,IAAgB,IAAM;AACxD7B,IAAAA,EAAkB4B,CAAC,GACnB5C,EAAkB,UAAU4C,GACxBC,KACAR,EAAAA;AAAAA,EAER;AAEA,WAASM,EAAiBG,GAAgBD,IAAgB,IAAM;AAC5DrB,MAAoB,UAAUsB,GAC9BvB,EAAoBuB,CAAM,GACtBD,KACAR,EAAAA;AAAAA,EAER;AAEA,WAASlC,EAAsBD,GAAoB;AAC/CmB,IAAAA,EAAmBnB,CAAG,GACtBJ,EAAmB,UAAUI;AAAAA,EACjC;AAEA,WAASI,EAAWyC,GAAc;AAO9B,QANAlC,EAAakC,CAAC,GACVA,MAAM,gBACN5C,EAAsB,IAAI,GAC1BiC,EAA4B,UAAU,MACtCD,EAA4B,UAAU,OAEtCY,MAAM,OAAO;AACb,UAAIvB,EAAoB,QAAQ,SAAS,GAAG;AACxC,cAAMwB,IAAkB,EAAC,QAAQxB,EAAoB,SAAS,QAAQ,GAAA;AACtEzB,QAAAA,EAAe,CAAC,GAAGC,EAAkB,SAASgD,CAAO,CAAC,GACtDtD,EAAgB,CAAC,GAAGM,EAAkB,SAASgD,CAAO,CAAC;AAAA,MAC3D;AACAC,MAAAA,EAAAA;AAAAA,IACJ;AAAA,EACJ;AACA,WAASA,EAAwBJ,IAAgB,IAAM;AACnDb,IAAAA,EAAe,UAAU,MACzBW,EAAiB,CAAA,GAAIE,CAAa;AAAA,EACtC;AAEA,WAASK,EAAU,GAAkB;AAClB,MAAE,QAAQ,YAIzBD,EAAAA;AAAAA,EACJ;AAEArD,EAAAA,EAAAA,UAAU,OACN,SAAS,iBAAiB,WAAWsD,CAAS,GACvC,MAAM,SAAS,oBAAoB,WAAWA,CAAS,IAC/D,CAAA,CAAE,GAELtD,EAAAA,UAAU,MAAM;;AACZ,KAAAuD,IAAAf,EAA4B,YAA5B,QAAAe,EAAqC,KAAK,MAAM,CAAAC,MAAK9D,EAAO,EAAE8D,EAAE,EAAE,CAAC,CAAC,CAAA,EAAG,KAAK,MAAM,CAAAA,MAAK9D,EAAO,EAAE8D,EAAE,EAAE,CAAC,CAAC,CAAA;AAAA,EAC1G,GAAG,CAAC5D,GAAcD,EAAW,YAAYA,EAAW,WAAW,CAAC;AAEhE,QAAM8D,KAAuBf,EAAAA,YAAY,WAAY;AAEjD,QADAJ,EAAqB,EAAK,GACtB,CAACF,EAAe,WAAWpB,MAAc;AACzC;AAEJ,UAAM0C,IAAgB,CAAC,GAAGtB,EAAe,OAAO,GAC1CuB,IAAIjE,EAAO,EAAE,OAAOgE,EAAc,CAAC,CAAC,GACpCE,IAAIlE,EAAO,EAAE,OAAOgE,EAAc,CAAC,CAAC;AAE1C,QAAI,CAAC9B,EAAoB,QAAQ,QAAQ;AACrCmB,MAAAA,EAAiB,CAAC,CAACY,GAAGC,CAAC,CAAC,CAAC;AACzB;AAAA,IACJ;AAEA,UAAMV,IAAStB,EAAoB;AAEnC,QADe,CAACS,KACFa,EAAO,SAAS;AAC1BH,MAAAA,EAAiB,CAAC,GAAGG,GAAQ,CAACS,GAAGC,CAAC,CAAC,CAAC;AAAA,SACjC;AACH,YAAMR,IAAkB,EAAC,QAAQ,CAAC,GAAGF,CAAM,GAAG,QAAQ,GAAA;AACtDG,MAAAA,EAAwB,EAAK,GAC7BlD,EAAe,CAAC,GAAGgB,GAAgBiC,CAAO,CAAC,GAE3C,WAAW,MAAMtD,EAAgB,CAAC,GAAGqB,GAAgBiC,CAAO,CAAC,GAAG,CAAC;AAAA,IACrE;AAAA,EACJ,GAAG,CAACpC,GAAWqB,CAAiB,CAAC,GAE3BwB,KAAcnB,EAAAA,YAAY,SAAS,GAA+B;AACpE,UAAMM,IAAW,CAAC,EAAE,YAAY,SAAS,EAAE,YAAY,OAAO,GACxDE,IAAStB,EAAoB,SAC7BkC,IAAalC,EAAoB,QAAQ,CAAC;AAChD,QAAIkC,GAAY;AACZ,YAAMC,IAASrE,EAAO,EAAEoE,EAAW,CAAC,CAAC,GAC/BE,IAAStE,EAAO,EAAEoE,EAAW,CAAC,CAAC,GAC/BG,IAAWf,EAAO,SAAS,IAC3B,KAAK,MAAMF,EAAE,CAAC,IAAIe,MAAW,KAAKf,EAAE,CAAC,IAAIgB,MAAW,CAAC,IACrD;AACN1B,MAAAA,EAAqB2B,IAAW5E,EAAgB;AAAA,IACpD;AACIiD,MAAAA,EAAqB,EAAK;AAG9BH,IAAAA,GAAea,CAAC,GAChBZ,EAAe,UAAUY;AAAAA,EAC7B,GAAG,CAAA,CAAE;AAEL,WAASkB,KAAuB;AACxB3B,IAAAA,EAA4B,WAC5B4B,EAAO5B,EAA4B,OAAO,EAAE,KAAK,EAAE,EAAE,KAAA,EAAO,OAAA;AAAA,EAEpE;AAEA,WAAS6B,GAAsBC,GAAwB;AAC/CA,UAAO9B,EAA4B,WAAW8B,MAC9CH,GAAAA,GACA3B,EAA4B,UAAU8B,GACtCC,GAAgB9C,CAAe;AAAA,EAEvC;AAEA,QAAM8C,KAAkB5B,EAAAA,YAAY,SAAUpC,GAAoB;AAC9D,QAAIU,MAAc,eAGdV,MAAQ,MAAM;AACd,YAAMkD,IAAIe,GAAAA,EACL,GAAG,QAAQ,SAAU9D,GAAG;AACrB,cAAM4D,IAAKF,EAAqC,IAAI,GAC9CX,IAAIa,EAAG,KAAA,EAAO,CAAC;AACrBb,QAAAA,EAAE,CAAC,IAAI/C,EAAE,GACT+C,EAAE,CAAC,IAAI/C,EAAE,GACT+C,EAAE,IAAI,CAAC9D,EAAO,EAAE,OAAO8D,EAAE,CAAC,CAAC,GAAG9D,EAAO,EAAE,OAAO8D,EAAE,CAAC,CAAC,CAAC,GACnDa,EAAG,KAAK,MAAMb,EAAE,CAAC,CAAC,EAAE,KAAK,MAAMA,EAAE,CAAC,CAAC;AACnC,cAAMgB,KAAiBpE,EAAkB,QAAQ,IAAI,CAACgD,GAASqB,OACpDnE,MAAQmE,KAAarB,IAAU;AAAA,UAClC,GAAGA;AAAAA,UACH,QAAQA,EAAQ,OAAO;AAAA,YAAI,CAACiB,IAAIK,OAC5BA,OAAalB,EAAE,MAAO,CAAC9D,EAAO,EAAE,OAAO8D,EAAE,CAAC,CAAC,GAAG9D,EAAO,EAAE,OAAO8D,EAAE,CAAC,CAAC,CAAC,IAAca;AAAAA,UAAAA;AAAAA,QAAA,CAG5F;AACDlE,QAAAA,EAAeqE,IAAgB,EAAK;AAAA,MACxC,CAAC,EACA,GAAG,OAAO,WAAY;AACnB/B,QAAAA,KACA3C,EAAgBM,EAAkB,OAAO;AAAA,MAC7C,CAAC,GACCuE,IAAsBvE,EAAkB,QAAQE,CAAG,EAAE,OAAO,IAAI,CAAC0C,GAAG1C,OAAS,EAAC,KAAAA,GAAK,GAAA0C,EAAAA,EAAG,GACtF4B,IAAkBT,EAAO5B,EAA4B,OAAO,EAC7D,UAAwC,QAAQ,EAChD,KAAKoC,GAAqB,CAACnB,MAAMA,EAAE,GAAG,EACtC,KAAK,QAAQ;AAClBhB,MAAAA,EAA4B,UAAUoC,GAEtCA,EACK,KAAK,MAAM,CAAApB,MAAK9D,EAAO,EAAE8D,EAAE,EAAE,CAAC,CAAC,CAAC,EAChC,KAAK,MAAM,CAAAA,MAAK9D,EAAO,EAAE8D,EAAE,EAAE,CAAC,CAAC,CAAC,EAChC,KAAK,KAAKlE,CAAC,EACX,KAAK,QAAQ,OAAO,EACpB,KAAK,UAAUH,CAAe,GACnCyF,EAAgB,KAAKpB,CAAC;AAAA,IAC1B;AAAA,EACJ,GAAG,CAAA,CAAE;AAELxD,SAAAA,EAAAA,UAAU,MAAM;AAERD,IAAAA,EADAiB,MAAc,QACa;AAAA,MACvB,MAAMA;AAAAA,MACN,aAAae,IAAe;AAAA,MAC5B,gBAAgBA,IAAeF,EAAQ,SAAS;AAAA,MAChD,eAAeL,MAAoB;AAAA,IAAA,IAGZ;AAAA,MACvB,MAAMR;AAAAA,MACN,aAAae,IAAe;AAAA,MAC5B,gBAAgBA,IAAeF,EAAQ,SAAS;AAAA,MAChD,eAAe;AAAA,IAAA,CANlB;AAAA,EAST,GAAG,CAACb,GAAWQ,GAAiBO,GAAcF,CAAO,CAAC,GAGlDgD,gBAAAA,EAAAA,IAAAC,EAAAA,UAAA,EACI,UAAAC,gBAAAA,EAAA,KAAC,KAAA,EACG,UAAA;AAAA,IAAAF,gBAAAA,EAAAA,IAAC,QAAA,EACG,UAAAA,gBAAAA,EAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACG,IAAG;AAAA,QACH,OAAM;AAAA,QACN,QAAO;AAAA,QACP,kBAAiB;AAAA,QACjB,cAAa;AAAA,QAEb,UAAAA,gBAAAA,EAAAA,IAAC,QAAA,EAAK,IAAG,KAAI,IAAG,KAAI,IAAG,KAAI,IAAG,MAAK,QAAQ1F,GAAiB,aAAY,KAAI;AAAA,MAAA;AAAA,IAAA,GAEpF;AAAA,IACA0F,gBAAAA,EAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACG,MAAK;AAAA,QACL,OAAOlF,EAAW;AAAA,QAClB,QAAQA,EAAW;AAAA,QACnB,aAAAkE;AAAAA,QACA,SAASJ;AAAAA,MAAA;AAAA,IAAA;AAAA,IAEZtC,EAAe,IAAI,CAAC6B,GAAG1C,MAAQ;AAC5B,YAAM0E,IAAY1E,MAAQgB,GACpB2D,IAAa3E,MAAQkB,GAErB0D,IADSlC,EAAE,OAAO,IAAI,CAAAA,MAAK,CAACtD,EAAO,EAAEsD,EAAE,CAAC,CAAC,GAAGtD,EAAO,EAAEsD,EAAE,CAAC,CAAC,CAAC,CAAC,EAGxD,IAAI,CAACA,GAAG1C,OACGA,MAAQ,IAAI,MAAM,OAAO0C,EAAE,CAAC,IAAI,MAAMA,EAAE,CAAC,CACpD,EACA,KAAK,EAAE,IAAI;AACpB,aAAA+B,gBAAAA,EAAA,KACK,KAAA,EACG,UAAA;AAAA,QAAAF,gBAAAA,EAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YACG,GAAGK;AAAAA,YACH,MAAMF,KAAa,CAACC,IAAa,0BAA0B;AAAA,YAC3D,QAAQA,KAAcD,IAAY7F,IAAkBgG;AAAAA,YACpD,aAAa,MAAM5D,EAAkBjB,CAAG;AAAA,YACxC,cAAc,MAAMiB,EAAkB,IAAI;AAAA,YAC1C,SAAS,MAAMhB,EAAsBD,CAAG;AAAA,YACxC,OAAO,EAAC,eAAeU,MAAc,eAAeiE,IAAa,SAAS,OAAA;AAAA,UAAA;AAAA,QAAM;AAAA,QAEnFA,KAAcJ,gBAAAA,EAAAA,IAAC,KAAA,EAAE,KAAK,CAAAR,MAAMD,GAAsBC,CAAE,EAAA,CAAG;AAAA,MAAA,EAAA,GAVpD/D,CAWR;AAAA,IAER,CAAC;AAAA,IACDuE,gBAAAA,EAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACG,QAAQnD,EAAiB,IAAI,CAACsB,MAAM,GAAGtD,EAAO,EAAEsD,EAAE,CAAC,CAAC,CAAC,IAAItD,EAAO,EAAEsD,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,GAAG;AAAA,QACnF,QAAQmC;AAAAA,QACR,MAAK;AAAA,QACL,OAAO,EAAC,eAAe,OAAA;AAAA,MAAA;AAAA,IAAM;AAAA,IAEhCzD,EAAiB,SAAS,KAAKQ,KAC5BkD,gBAAAA,EAAAA,KAAC,KAAA,EAAE,OAAO,EAAC,eAAe,OAAA,GACtB,UAAA;AAAA,MAAAP,gBAAAA,EAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UACG,IAAInF,EAAO,EAAEgC,EAAiB,CAAC,EAAE,CAAC,CAAC;AAAA,UACnC,IAAIhC,EAAO,EAAEgC,EAAiB,CAAC,EAAE,CAAC,CAAC;AAAA,UACnC,GAAGnC;AAAAA,UACH,MAAK;AAAA,UACL,QAAQH;AAAAA,UACR,iBAAgB;AAAA,QAAA;AAAA,MAAA;AAAA,MAEpByF,gBAAAA,EAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UACG,IAAI3C,EAAY,CAAC;AAAA,UACjB,IAAIA,EAAY,CAAC;AAAA,UACjB,IAAIxC,EAAO,EAAEgC,EAAiB,CAAC,EAAE,CAAC,CAAC;AAAA,UACnC,IAAIhC,EAAO,EAAEgC,EAAiB,CAAC,EAAE,CAAC,CAAC;AAAA,UACnC,QAAQtC;AAAAA,UACR,iBAAgB;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA,GAExB;AAAA,IAEHsC,EAAiB,SAAS,KAAKQ,KAC5BkD,gBAAAA,EAAAA,KAAC,KAAA,EAAE,OAAO,EAAC,eAAe,OAAA,GACtB,UAAA;AAAA,MAAAP,gBAAAA,EAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UACG,IAAInF,EAAO,EAAEgC,EAAiBA,EAAiB,SAAS,CAAC,EAAE,CAAC,CAAC;AAAA,UAC7D,IAAIhC,EAAO,EAAEgC,EAAiBA,EAAiB,SAAS,CAAC,EAAE,CAAC,CAAC;AAAA,UAC7D,IAAIQ,EAAY,CAAC;AAAA,UACjB,IAAIA,EAAY,CAAC;AAAA,UACjB,QAAQ/C;AAAAA,QAAA;AAAA,MAAA;AAAA,MAEXuC,EAAiB,IAAI,CAACsB,GAAG1C,MACtBuE,gBAAAA,EAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UAEG,IAAInF,EAAO,EAAEsD,EAAE,CAAC,CAAC;AAAA,UACjB,IAAItD,EAAO,EAAEsD,EAAE,CAAC,CAAC;AAAA,UACjB,GAAG1D;AAAAA,UACH,MAAK;AAAA,UACL,QAAQgB,IAAM,IAAInB,IAAkBgG;AAAAA,QAAA;AAAA,QAL/B7E;AAAAA,MAAA,CAOZ;AAAA,MACDuE,gBAAAA,EAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UACG,IAAI3C,EAAY,CAAC;AAAA,UACjB,IAAIA,EAAY,CAAC;AAAA,UACjB,GAAG5C;AAAAA,UACH,MAAK;AAAA,UACL,QAAQH;AAAAA,QAAA;AAAA,MAAA;AAAA,IAAA,GAEhB;AAAA,IAEHkD,KAAqBH,KAClB2C,gBAAAA,EAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACG,IAAI3C,EAAY,CAAC,IAAI;AAAA,QACrB,IAAIA,EAAY,CAAC,IAAI;AAAA,QACrB,GAAG;AAAA,QACH,MAAK;AAAA,QACL,QAAQ/C;AAAAA,QACR,aAAa;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA,EACjB,CAER,EAAA,CACJ;AAER;","x_google_ignoreList":[0]}
|