@devgateway/dvz-ui-react
Version:
A modular, embeddable React component library for data visualization and UI, built with TypeScript. Provides reusable components for charts, maps, dashboards, and more, with built-in support for internationalization and Redux integration.
452 lines (451 loc) • 18.4 kB
JavaScript
import { jsx as Z } from "react/jsx-runtime";
import "react";
import pt from "./BaseLayer.js";
import ct from "../data/DataProvider.js";
import ut from "../data/DataConsumer.js";
import * as M from "d3";
import { injectIntl as dt } from "react-intl";
import Y from "./BreaksStyles.js";
import ot from "./GradientColors.js";
const W = (D) => D ? D.toString().replace(/ /g, "_") : "", k = (D) => D ? "pattern_" + W(D) : "";
class ht extends pt {
constructor() {
super(), this.state = { geoJson: null, json: null }, this.getTooltipVariables = this.getTooltipVariables.bind(this), this.resize = this.resize.bind(this), this.createLayer = this.createLayer.bind(this), this.createCentroids = this.createCentroids.bind(this), this.createPatterns = this.createPatterns.bind(this), this.createPaths = this.createPaths.bind(this);
}
createLayer(e) {
const l = this.joinData(e, this.props.app, this.props.featureJoinAttribute, this.props.data, this.props.measures, this.props.patternDiscriminator);
this.createDataLayer(l), this.props.onReady && this.props.onReady();
}
resize() {
const {
markerLabelSize: e,
markFillColor: l,
markBorderColor: C,
markSizeScale: i,
measures: u,
data: h,
breaks: c,
gradientScheme: x,
gradientReverse: o,
labelFontSize: f
} = this.props, n = this.props.transform ? this.props.transform.k : 1;
super.resize();
const d = new Y({
breaks: c,
defaultFillColor: l,
defaultBorderColor: C,
defaultSize: i
});
new ot({
data: h.children,
measure: u[0],
defaultFillColor: l,
gradientScheme: x,
gradientReverse: o
}), this.g.selectAll(".centroids .point").attr("r", (p) => d.getSize(p.properties._value) * 1 / n), this.g.selectAll(".point-label").attr("font-size", (p) => e * (1 / n) + "px");
}
getTooltipVariables(e) {
const { apiJoinAttribute: l } = this.props;
return e.properties._value ? {
...e.properties,
meta: {
[l]: e.properties.meta ? e.properties.meta.value : "",
...e.properties.meta,
value: e.properties._value
}
} : {};
}
createDataLayer(e) {
const {
app: l,
svg: C,
format: i,
id: u,
file: h,
path: c,
onLayerCreated: x,
labelFilter: o = [],
labelField: f,
labelFontSize: n,
labelColor: d,
fillColor: p,
borderColor: m,
tooltip: z,
markFillColor: b,
markLabelColor: T,
markBorderColor: J,
markSizeScale: N,
markerLabelSize: H,
featureJoinAttribute: tt,
apiJoinAttribute: K,
measures: I,
editing: et,
data: w,
patternDiscriminator: S,
patternDiscriminatorLabel: Q,
breaks: $,
gradientScheme: G,
gradientReverse: E,
patterns: L,
projection: rt,
useBreaks: X,
useGradients: V,
useCentroidPoint: U,
usePattern: j,
waitForFilters: at,
intl: q,
patternsVisible: R = !0,
togglePatterns: B,
colorLayerVisible: O = !0,
visible: it
} = this.props;
if (this.gRef && this.gRef.current) {
this.g = M.select(this.gRef.current), this.g.attr("class", "base-layer");
const F = e.features.filter((A) => A.properties._value != null);
this.createPaths(e), U || this.createColors(F), j && this.createPatterns(e), f != "none" && this.createLabels(e), U && this.createCentroids(F);
}
}
createColors(e) {
const {
app: l,
svg: C,
format: i,
id: u,
file: h,
path: c,
onLayerCreated: x,
labelFilter: o = [],
labelField: f,
labelFontSize: n,
labelColor: d,
fillColor: p,
borderColor: m,
tooltip: z,
markFillColor: b,
markLabelColor: T,
markBorderColor: J,
markSizeScale: N,
markerLabelSize: H,
featureJoinAttribute: tt,
apiJoinAttribute: K,
measures: I,
editing: et,
data: w,
patternDiscriminator: S,
patternDiscriminatorLabel: Q,
breaks: $,
gradientScheme: G,
gradientReverse: E,
patterns: L,
projection: rt,
useBreaks: X,
useGradients: V,
useCentroidPoint: U,
usePattern: j,
waitForFilters: at,
intl: q,
patternsVisible: R = !0,
togglePatterns: B,
colorLayerVisible: O = !0,
visible: it
} = this.props, F = new Y({
breaks: $,
defaultFillColor: b,
defaultBorderColor: J,
defaultSize: N
}), A = new ot({
data: w.children,
measure: I[0],
defaultFillColor: b,
gradientScheme: G,
gradientReverse: E
});
this.g && (this.g.selectAll("path").attr("fill", (s) => !s || !s.properties || !s.properties._value ? p : V ? A.getColor(s.properties._value) : F.getColor(s.properties._value)).attr("stroke", m).attr("id", "state-borders").attr("d", c).on("mouseenter", (s, y) => {
y.properties._value && this.showToolTip(z, this.getTooltipVariables(y), V ? A.getColor(y.properties._value) : F.getColor(y.properties._value), y);
}).on("mouseleave", (s) => {
this.hiddenToolTip(s);
}).on("mousemove", (s) => {
this.moveToolTip(s);
}), O || this.g.selectAll(".borders").style("fill", this.props.fillColor), this.g.attr("transform", this.props.transform));
}
createCentroids(e) {
const {
app: l,
svg: C,
format: i,
id: u,
file: h,
path: c,
onLayerCreated: x,
labelFilter: o = [],
labelField: f,
labelFontSize: n,
labelColor: d,
fillColor: p,
borderColor: m,
tooltip: z,
markFillColor: b,
markLabelColor: T,
markBorderColor: J,
markSizeScale: N,
markerLabelSize: H,
featureJoinAttribute: tt,
apiJoinAttribute: K,
measures: I,
editing: et,
data: w,
patternDiscriminator: S,
patternDiscriminatorLabel: Q,
breaks: $,
gradientScheme: G,
gradientReverse: E,
patterns: L,
projection: rt,
useBreaks: X,
useGradients: V,
useCentroidPoint: U,
usePattern: j,
waitForFilters: at,
intl: q,
patternsVisible: R = !0,
togglePatterns: B,
colorLayerVisible: O = !0,
visible: it
} = this.props, F = new Y({
breaks: $,
defaultFillColor: b,
defaultBorderColor: J,
defaultSize: N
}), A = new ot({
data: w.children,
measure: I[0],
defaultFillColor: b,
gradientScheme: G,
gradientReverse: E
});
if (this.g) {
const s = {
style: i.style === "compacted" ? "decimal" : i.style,
notation: i.style === "compacted" ? "compact" : "standard",
currency: i.currency,
minimumFractionDigits: parseInt(i.minimumFractionDigits),
maximumFractionDigits: parseInt(i.maximumFractionDigits)
}, y = this.props.transform ? this.props.transform.k : 1;
this.g.selectAll(".centroids").remove();
const g = this.g.selectAll("centroids").data(e).enter().append("g").attr("class", "centroids");
g.append("circle").attr("fill", (a) => V ? A.getColor(a.properties._value) : F.getColor(a.properties._value, !0)).attr("stroke", J).attr("class", "point").attr("stroke-width", 2).style("vector-effect", "non-scaling-stroke").attr("cx", (a) => c.centroid(a)[0]).attr("cy", (a) => c.centroid(a)[1]).attr("r", (a) => F.getSize(a.properties._value) * 1 / y).on("mouseenter", (a, t) => {
if (t.properties._value) {
const v = {
...t.properties,
meta: {
[K]: t.properties.meta ? t.properties.meta.value : "",
...t.properties.meta,
value: t.properties._value
}
};
this.showToolTip(z, v, V ? A.getColor(t.properties._value) : F.getColor(t.properties._value));
}
}).on("mouseleave", (a) => {
this.hiddenToolTip();
}), g.append("text").attr("class", "point-label").attr("x", (a) => c.centroid(a)[0]).attr("y", (a) => c.centroid(a)[1]).attr("font-size", (a) => H * (1 / y) + "px").attr("text-anchor", "middle").attr("dominant-baseline", "middle").style("pointer-events", "none").attr("fill", T).text((a) => q.formatNumber(i.style === "percent" ? a.properties._value / 100 : a.properties._value, s)).on("mouseover", (a) => {
}), O || this.g.selectAll(".centroids").style("display", "none");
}
}
createPatterns(e) {
const {
app: l,
svg: C,
format: i,
id: u,
file: h,
path: c,
onLayerCreated: x,
labelFilter: o = [],
labelField: f,
labelFontSize: n,
labelColor: d,
fillColor: p,
borderColor: m,
tooltip: z,
markFillColor: b,
markLabelColor: T,
markBorderColor: J,
markSizeScale: N,
markerLabelSize: H,
featureJoinAttribute: tt,
apiJoinAttribute: K,
measures: I,
editing: et,
data: w,
patternDiscriminator: S,
patternDiscriminatorLabel: Q,
breaks: $,
gradientScheme: G,
gradientReverse: E,
patterns: L,
projection: rt,
useBreaks: X,
useGradients: V,
useCentroidPoint: U,
usePattern: j,
waitForFilters: at,
intl: q,
patternsVisible: R = !0,
togglePatterns: B,
colorLayerVisible: O = !0,
visible: it
} = this.props, F = new Y({
breaks: $,
defaultFillColor: b,
defaultBorderColor: J,
defaultSize: N
}), A = this.props.transform ? this.props.transform.k : 1, s = 10 * 1 / A, y = 10 * 1 / A;
let g = [];
if (l == "csv" && S != "none")
g = [...new Set(w.data.map((t) => t[S]))].map((t) => ({
key: t,
type: L[t + "_symbol"],
color: L[t + "_color"],
rotation: L[t + "_rotation"]
}));
else if (S != "none") {
const t = w.metadata ? w.metadata.types.filter((v) => v.dimension == S) : [];
g = t && t.length > 0 ? t[0].items.map((v) => {
const _ = v.value;
return {
key: _,
type: L[_ + "_symbol"],
color: L[_ + "_color"],
rotation: L[_ + "_rotation"]
};
}) : [];
}
this.g.selectAll("defs").remove();
const a = this.g.append("defs");
if (a.selectAll("pattern").remove(), a.selectAll("pattern").data(g).enter().append("pattern").attr("id", (t) => k(t.key)).attr("patternUnits", "userSpaceOnUse").attr("width", s).attr("height", y).attr("x", 0).attr("y", 0).attr("patternTransform", (t) => `rotate(${t.rotation})`), g.forEach((t) => {
t.type === "lines" && a.select("#" + k(t.key)).append("rect").attr("x", 0.05).attr("width", s / 2).attr("height", y).attr("opacity", 1).attr("fill", t.color), t.type === "squares" && a.select("#" + k(t.key)).append("rect").attr("width", s / 2).attr("height", y / 2).attr("fill", t.color).attr("opacity", 1).attr("stroke-width", 1), t.type === "dots" && a.select("#" + k(t.key)).append("circle").attr("cx", s / 2).attr("cy", y / 2).attr("r", s / 2.5).attr("fill", t.color).attr("opacity", 1).attr("stroke-width", 1), t.type === "triangle" && a.select("#" + k(t.key)).append("polygon").attr("points", `${s / 2} 0, 0 ${s}, ${s} ${s} `).attr("fill", t.color).attr("opacity", 1).attr("stroke-width", 1);
}), g = g.filter((t) => t.type != null).sort((t, v) => new Intl.Collator(q.locale, { caseFirst: "upper", numeric: !0, sensitivity: "variant" }).compare(t.key, v.key)), j && e && e.features) {
this.g.selectAll(".shape-pattern").remove(), R && e.features.forEach((r) => {
let P = [];
r.properties && r.properties.meta && (P = l != "csv" ? r.properties.meta[S] ? r.properties.meta[S] : [] : [r.properties.meta[S]], P && P.length > 0 && P.forEach((lt) => {
this.g.append("path").attr("d", c(r)).datum(lt).attr("class", "shape-pattern").attr("opacity", (st) => {
if (X)
return 0.7;
}).attr("fill", (st) => "transparent").attr("style", () => "none;fill:url(#" + k(lt) + ");").on("mouseenter", () => {
this.showToolTip(z, this.getTooltipVariables(r), V ? gradientColors.getColor(r.properties._value) : F.getColor(r.properties._value));
}).on("mousemove", (st) => {
this.moveToolTip();
}).on("mouseleave", (st) => {
this.hiddenToolTip();
});
}));
}), M.select(this.gRef.current.parentNode.parentNode).select(`.layer_${W(u)}`).select("svg").remove();
const t = M.select(this.gRef.current.parentNode.parentNode).select(`.layer_${W(u)}`).append("svg");
t.attr("height", 30 + g.length * 23 + "px");
const v = t.append("svg").append("g"), _ = v.append("defs");
_.selectAll("pattern").remove(), R && (_.selectAll("pattern").data(g).enter().append("pattern").attr("id", (r) => "l_" + k(r.key)).attr("patternUnits", "userSpaceOnUse").attr("width", 5).attr("height", 5).attr("x", 0).attr("y", 0).attr("patternTransform", (r) => `rotate(${r.rotation ? r.rotation : 0})`), g.forEach((r) => {
r.type === "lines" && _.select("#l_" + k(r.key)).append("rect").attr("x", 0).attr("width", 1).attr("height", 10).attr("opacity", 0.75).attr("fill", r.color), r.type === "squares" && _.select("#l_" + k(r.key)).append("rect").attr("width", 3).attr("height", 3).attr("fill", r.color).attr("opacity", 1).attr("stroke-width", 1), r.type === "dots" && _.select("#l_" + k(r.key)).append("circle").attr("cx", 2).attr("cy", 2).attr("r", 2).attr("fill", r.color).attr("opacity", 1).attr("stroke-width", 1), r.type === "triangle" && _.select("#l_" + k(r.key)).append("polygon").attr("points", "5,0 8,8 0,5").attr("fill", r.color).attr("opacity", 1).attr("stroke-width", 1);
}));
let nt = R ? "☑ " : "☐ ";
v.append("text").attr("class", "patterns-checkbox").attr("x", 10).attr("y", 20).text((r) => nt).attr("font-size", "22px").on("click", () => {
B && B(u);
}), v.append("text").attr("class", "patterns-title").attr("x", 25).attr("y", 7).text((r) => l === "csv" ? S : Q).on("click", () => {
B && B(u);
}), R && (v.selectAll(".legend-squares").data(g).enter().append("rect").attr("width", 15).attr("height", 15).attr("y", (r, P) => P * 22 + 30).attr("x", 15).attr("stroke", m).attr("style", (r) => "none;fill:url(#l_" + k(r.key) + ");"), v.selectAll(".patterns-labels").data(g).enter().append("text").attr("class", "patterns-labels").attr("y", (r, P) => P * 22 + 30).attr("x", 32).text((r) => r.key));
}
}
joinData(e, l, C, i, u, h) {
const c = e.features.map((o) => {
const f = o.properties[C];
if (l != "csv" && i && i.children) {
const n = i.children.filter((d) => d.value == f);
if (n.length > 0) {
const d = n[0][u[0]];
if (o.properties.meta = n[0], o.properties._value = d, h && h != "none") {
const p = n[0] && n[0].children ? n[0].children.filter((m) => m.type == h).map((m) => m.value) : [];
o.properties.meta[h] = p;
}
} else
o.properties._value = null;
} else if (l == "csv") {
const n = i.data.filter((d) => d[i.meta.fields[0]] == f);
n.length > 0 ? (o.properties.meta = n[0], o.properties._value = n[0][i.meta.fields[1]]) : o.properties._value = null;
} else
o.properties._value = null;
return o;
});
return { ...e, features: c };
}
componentDidUpdate(e, l, C) {
const { app: i, file: u, featureJoinAttribute: h, data: c, measures: x, patternDiscriminator: o, editing: f, usePattern: n } = this.props;
if ((f || JSON.stringify(e.data) !== JSON.stringify(c)) && this.create(), e.visible != this.props.visible) {
debugger;
this.g.style("display", this.props.visible ? "" : "none");
}
if (e.patternsVisible != this.props.patternsVisible) {
const p = M.select(this.gRef.current.parentNode.parentNode).select(`.layer_${W(this.props.id)}`);
p.select(".patterns-checkbox").text(this.props.patternsVisible ? "☑ " : "☐ "), p.selectAll(".patterns-labels").style("display", this.props.patternsVisible ? "" : "none"), p.selectAll("rect").style("display", this.props.patternsVisible ? "" : "none"), p.select("svg").attr("height", this.props.patternsVisible ? 30 + (p.selectAll("rect").size() - 1) * 23 + "px" : "30px"), this.g.selectAll(".shape-pattern").style("display", this.props.patternsVisible ? "" : "none");
}
e.colorLayerVisible != this.props.colorLayerVisible && (this.g.selectAll(".borders").style("fill", (d) => this.props.colorLayerVisible ? null : this.props.fillColor), this.g.selectAll(".centroids").style("display", this.props.colorLayerVisible ? "block" : "none")), e.usePattern != this.props.usePattern && (this.props.usePattern || M.select(this.gRef.current.parentNode.parentNode).select(`.layer_${W(this.props.id)}`).select("svg").remove()), this.g && this.resize();
}
componentDidMount() {
super.componentDidMount();
}
render() {
const {
id: e,
file: l,
path: C,
zoom: i,
labelFilter: u = [],
labelField: h,
labelFontSize: c,
labelColor: x,
fillColor: o,
borderColor: f,
featureJoinAttribute: n,
apiJoinAttribute: d,
dvzProxyDatasetId: p,
editing: m
} = this.props;
return /* @__PURE__ */ Z("g", { id: "data-" + e, className: "data " + e, ref: this.gRef });
}
}
const ft = (D) => {
const {
id: e,
unique: l,
filters: C,
csv: i,
app: u,
group: h = "default",
apiJoinAttribute: c,
editing: x,
patternDiscriminator: o,
dvzProxyDatasetId: f,
intl: n,
settings: d,
waitForFilters: p
} = D, m = {}, z = C || {};
return z && z.forEach && z.forEach((b) => {
b.value != null && b.value.filter((T) => T != null && T.toString().trim() != "").length > 0 && (m[b.param] = b.value);
}), f && (m.dvzProxyDatasetId = f), /* @__PURE__ */ Z(
ct,
{
waitForFilters: p,
editing: x,
params: m,
app: u,
csv: decodeURIComponent(i),
group: h,
ignoreErrors: !0,
isSvg: !0,
store: [u, l, e],
source: c + (o != "none" ? "/" + o : ""),
children: /* @__PURE__ */ Z(ut, { children: /* @__PURE__ */ Z(ht, { ...D }) })
}
);
}, Ft = dt(ft);
export {
Ft as default
};