UNPKG

@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.

813 lines (812 loc) 25.9 kB
import { jsx as c, jsxs as p, Fragment as pe } from "react/jsx-runtime"; import { useState as S, useEffect as Ht, Fragment as He } from "react"; import Wt from "./Tooltip.js"; import { ResponsiveBar as Tt } from "@nivo/bar"; import { injectIntl as _t } from "react-intl"; import { useTheme as St } from "@nivo/theming"; import { line as We } from "d3-shape"; import Te from "./LineLayer.js"; import be from "papaparse"; import At from "../../layout/FlexWrapDetector.js"; import ge from "../../utils/deviceType.js"; const jt = "middle", Pt = "top", J = "#66676d", _e = "#dddddd", Rt = "none", U = "_Color", Yt = ({ editing: x, legends: R, marginLeft: Se, marginTop: q, marginRight: Ae, marginBottom: Q, options: u, intl: g, format: b, colors: $, groupMode: F, height: je, showLegends: G, legendPosition: D, tickRotation: E, offsetText: ee, tickColor: te, layout: o, reverse: H, offsetY: Pe, csvLineLayerData: ve, tooltip: ae, lineLayerEnabled: ne, overlays: W, maxValue: re, valueScale: Re, colorGenerator: v, legendLabel: Ne, overrideTickColor: Ye, fixedMinValue: le, fixedMaxValue: se, barPadding: Ke, barLabelPosition: Ie, barInnerPadding: Xe, tooltipEnabled: Ce, xLabelColor: w, barLabelColor: Y, legendCheckBack: I, legendLabelBack: ie, legendLabelColor: ce, highlightXAxisLine: Ze, showTickLine: A, showRightAxis: Je, offsetRight: Ue, offsetBottom: Le, confidenceIntervals: de, showGroupTotal: qe, groupTotalLabel: ke, groupTotalFormat: De, groupTotalMeasure: we, groupTotalOffset: z, groupTotalFixedPosition: K, tooltipEnableMarkdown: Qe, xAxisTickValues: Ge, yAxisTickValues: et, mobileCustomization: tt, minMaxClamp: Kt, reverseLegend: at, enableGridY: nt, enableGridX: rt, customAxisFormat: M, previewMode: B, showLegendsInColumns: lt = !1, numberOfLegendColumns: st = 4 }) => { var $e; const it = ["mobile", "tablet", "midTablet"].includes( ge() ), X = ["tablet", "midTablet"].includes(ge()), C = ge() === "mobile", he = 30, me = 15, m = JSON.parse(decodeURIComponent(tt)), Me = it && ((m == null ? void 0 : m.showCustomization) ?? !1), T = Me && B !== "Desktop", _ = !x && Me, ue = () => Y === "null" || Y === null || !Y ? "#000000" : Y, [L, ct] = S([]), { colorBy: j } = $, Oe = {}; W.forEach((e, t) => { Oe[t] = !0; }); const [N, dt] = S(Oe), [Fe, ht] = S(50), [Xt, mt] = S(q), [Ct, Ee] = S(0), [ut, ft] = S(Q), P = ((e, t, i, n, l) => { let s = []; return e.data && (s = t.colorBy === "index" ? e.data.map((r) => { let a, h = !0; return i.indexOf(r[e.indexBy]) > -1 ? (h = !1, a = n) : a = r[U] ? r[U] : l.getColor(r.id, r), { enabled: h, color: a, id: r[e.indexBy], label: r[e.indexBy] }; }) : e.keys.map((r) => { let a, h = !0; return i.indexOf(r) > -1 ? (h = !1, a = n) : a = l.getColorByKey(r), { enabled: h, color: a, id: r, label: r }; })), s; })( u, $, L, Rt, v ), ze = () => (at && P.reverse(), /* @__PURE__ */ p(pe, { children: [ G && P.map((e) => /* @__PURE__ */ p( "div", { className: `legend item ${e.enabled ? "" : "ignore"}`, onClick: () => Lt(e.id), children: [ I && /* @__PURE__ */ c( "input", { className: e.enabled ? "" : "ignore", type: "checkbox", checked: e.enabled, style: { backgroundColor: I ? j === "values" ? te : e.color : "none", color: "#000" } } ), !I && /* @__PURE__ */ c( "input", { type: "checkbox", checked: e.enabled, style: { color: "#000" } } ), I && /* @__PURE__ */ c( "span", { className: "checkmark-with-bg", style: { backgroundColor: e.color } } ), !I && /* @__PURE__ */ c("span", { className: "checkmark" }), ie && /* @__PURE__ */ c( "label", { className: e.enabled ? "" : "ignore", style: { backgroundColor: j === "values" ? te : e.color, color: ce }, children: e.label } ), !ie && /* @__PURE__ */ c( "label", { className: e.enabled ? "" : "ignore", style: { color: ce }, children: e.label } ) ] } )), j === "values" && /* @__PURE__ */ p("div", { className: "legend item", children: [ /* @__PURE__ */ c( "label", { className: "range min", style: { backgroundColor: v.getColorByValue( v.minValue ), color: "#fff" } } ), /* @__PURE__ */ c("label", { children: g.formatNumber( b.style === "percent" ? v.minValue / 100 : v.minValue, { ...b, minimumFractionDigits: 0 } ) }) ] }), j === "values" && /* @__PURE__ */ p("div", { className: "legend item", children: [ /* @__PURE__ */ c( "label", { className: "range max", style: { backgroundColor: v.getColorByValue( v.maxValue ), color: "#fff" }, children: " " } ), /* @__PURE__ */ c("label", { children: g.formatNumber( b.style === "percent" ? v.maxValue / 100 : v.maxValue, { ...b, minimumFractionDigits: 0 } ) }) ] }), G && ne && W.map((e, t) => /* @__PURE__ */ p("div", { className: "legend item", onClick: () => kt(t), children: [ /* @__PURE__ */ c( "input", { className: I && N[t] ? "" : "ignore", type: "checkbox", checked: N[t], style: { backgroundColor: N[t] && I === !0 ? e.lineColor : "none", color: "#000" } } ), /* @__PURE__ */ c( "span", { className: I ? "checkmark-with-bg" : "checkmark", style: { backgroundColor: N[t] && I === !0 ? e.lineColor : "none" } } ), /* @__PURE__ */ c( "label", { className: N[t] ? "" : "ignore", style: { backgroundColor: N[t] && ie === !0 ? e.lineColor : "none", color: ce }, children: e.title } ) ] })) ] })); Ht(() => { (() => { const i = 5 * Math.max(P.length - 5, 0); ht(i); })(); }, [P]); const ot = { bottom: `-${Fe}px` }, xt = { bottom: `-${Fe}px`, gap: "0px" // top: "0px", }, yt = (e) => fe(e, "1 0", _e, "Y"), pt = (e) => fe(e, "4 4", J, "X"), bt = (e) => fe(e, "1 0", _e, "X"), gt = (e) => { const t = P.find((i) => i.id === e.value); return t ? t.color : "#FFFFFF"; }, vt = (e) => { const { yScale: t, bars: i } = e; return /* @__PURE__ */ c(He, { children: i.filter((n) => n.data.value != null).map((n) => { let l = n.data.indexValue; u.dimensionsMetadata && u.dimensionsMetadata.size > 1 && (l = n.data.id); const s = de.filter( (r) => r.serieLabel == l )[0]; if (s && s.low && s.high) { const r = t(parseFloat(s.low)), a = t(parseFloat(s.high)); return /* @__PURE__ */ p("g", { children: [ /* @__PURE__ */ c( "line", { y1: r, y2: a, x1: n.x + n.width / 2, x2: n.x + n.width / 2, strokeWidth: 1, stroke: J } ), /* @__PURE__ */ c( "line", { y1: r, y2: r, x1: n.x + n.width / 2 - 3, x2: n.x + n.width / 2 + 3, strokeWidth: 1, stroke: J } ), /* @__PURE__ */ c( "line", { y1: a, y2: a, x1: n.x + n.width / 2 - 3, x2: n.x + n.width / 2 + 3, strokeWidth: 1, stroke: J } ) ] }); } }) }); }, fe = (e, t, i, n) => { const { yScale: l, innerWidth: s, innerHeight: r } = e; let a, h; return n == "X" ? (a = [0, s], h = We().x((f, V) => V === 0 ? -10 : f).y(() => l(0))) : (a = [0, r], h = We().x(() => 0).y((f) => f)), /* @__PURE__ */ c(He, { children: /* @__PURE__ */ c( "path", { d: h(a), fill: "none", stroke: i, style: { pointerEvents: "none", strokeDasharray: t } } ) }); }, O = (e, t) => L ? ($.colorBy === "index" || $.colorBy === "id" || $.colorBy === "values") && !t ? e.filter((i) => L.indexOf(i[u.indexBy]) === -1) : e ? e.filter((i) => L.indexOf(i) === -1) : [] : e, Nt = (e) => { const t = St(); if (!e.value) return ""; const i = Object.assign({}, e); (_ || T) && ye.includes(String(i.value)) && (i.value = ""); let n; Ye ? n = te : n = gt(e); let l = [], s = ""; if (T || _) { const a = String(i.value).split(" "); let h = 25; x && B === "Mobile" || C && !x ? h = (m == null ? void 0 : m.mobileMaxTickLength) ?? 25 : x && B === "Tablet" || X && !x ? h = (m == null ? void 0 : m.tabletMaxTickLength) ?? 25 : window.matchMedia("(min-width: 768px) and (max-width: 1250px)").matches && !x && (h = 15), a.forEach((f) => { s.length + String(f).length <= h ? s += (s ? " " : "") + f : (l.push(s), s = f); }), s && l.push(s); } else l = [i.value]; let r = 12; return C ? r = (m == null ? void 0 : m.mobileYAxisLineHeight) ?? 12 : X && (r = (m == null ? void 0 : m.tabletYAxisLineHeight) ?? 12), E > 0 && E < 180 ? /* @__PURE__ */ p("g", { transform: `translate(${e.x},${e.y + 30})`, children: [ A && /* @__PURE__ */ c( "line", { stroke: n, strokeWidth: 1.5, y1: -32, y2: -12 } ), /* @__PURE__ */ c("g", { transform: `translate(0, ${e.y + ee})`, children: l.map((a, h) => /* @__PURE__ */ c( "text", { transform: `rotate(${E})`, textAnchor: "start", y: typeof e.value == "number" ? 0 : h * r, dominantBaseline: "middle", style: { ...t.axis.ticks.text, fill: w === "null" ? "black" : w, fontSize: "12px", fontFamily: "sans-serif" }, children: a }, a )) }) ] }) : E > 180 && E < 360 ? /* @__PURE__ */ p("g", { transform: `translate(${e.x},${e.y + 30})`, children: [ A && /* @__PURE__ */ c( "line", { stroke: n, strokeWidth: 1.5, y1: -32, y2: -12 } ), /* @__PURE__ */ c("g", { transform: `translate(0, ${e.y + ee})`, children: l.map((a, h) => /* @__PURE__ */ c( "text", { transform: `rotate(${E})`, textAnchor: "end", y: typeof e.value == "number" ? 0 : h * r, dominantBaseline: "middle", style: { ...t.axis.ticks.text, fill: w === "null" ? "black" : w, fontSize: "12px", fontFamily: "sans-serif" }, children: a }, h )) }) ] }) : /* @__PURE__ */ p("g", { transform: `translate(${e.x},${e.y + 30})`, children: [ A && /* @__PURE__ */ c( "line", { stroke: n, strokeWidth: 1.5, y1: -32, y2: -12 } ), /* @__PURE__ */ c("g", { transform: `translate(0, ${e.y + ee})`, children: l.map((a, h) => /* @__PURE__ */ c( "text", { transform: `rotate(${E})`, textAnchor: "middle", y: typeof e.value == "number" ? 0 : h * r, dominantBaseline: "middle", style: { ...t.axis.ticks.text, fill: w === "null" ? "black" : w, fontSize: "12px", fontFamily: "sans-serif" }, children: a }, h )) }) ] }); }, It = (e) => { if (!e.value || (T || _) && ye.includes(String(e.value))) return ""; let t = e.value; if (o === "vertical") { const a = M || b; t = g.formatNumber( a.style === "percent" ? t / 100 : t, { ...a } ); } let i = 25; x && B === "Mobile" || C && !x ? i = (m == null ? void 0 : m.mobileMaxTickLength) ?? 25 : x && B === "Tablet" || X && !x ? i = (m == null ? void 0 : m.tabletMaxTickLength) ?? 25 : window.matchMedia("(min-width: 768px) and (max-width: 1250px)").matches && !x && (i = 15); const n = typeof t == "string" ? t.split(" ") : [t], l = []; let s = ""; n.forEach((a) => { s.length + String(a).length <= i ? s += (s ? " " : "") + a : (l.push(s), s = a); }), s && l.push(s); let r = 12; return x && B === "Mobile" || C && !x ? r = (m == null ? void 0 : m.mobileYAxisLineHeight) ?? 12 : (x && B === "Tablet" || X && !x) && (r = (m == null ? void 0 : m.tabletYAxisLineHeight) ?? 12), /* @__PURE__ */ p("g", { transform: `translate(${e.x},${e.y})`, children: [ /* @__PURE__ */ c("line", { x1: -5, x2: 0, y1: 0, y2: 0, stroke: "#000", strokeWidth: 1 }), l.map((a, h) => /* @__PURE__ */ c( "text", { x: -10, y: typeof t == "number" ? 0 : h * r, textAnchor: "end", dominantBaseline: "middle", style: { fill: w === "null" ? "black" : w, fontSize: "12px", fontFamily: "sans-serif" }, children: a }, a )) ] }); }, Lt = (e) => { const t = L.slice(); if (t.indexOf(e) > -1) { const i = t.indexOf(e); t.splice(i, 1); } else t.push(e); ct(t); }, kt = (e) => { const t = Object.assign({}, N); t[e] = !t[e], dt(t); }, Dt = ({ bars: e }) => /* @__PURE__ */ c("g", { children: e.map((t) => { const { width: i, height: n, y: l, x: s, data: r } = t; if (o === "horizontal" && n <= me || o === "vertical" && i <= he) return; const a = r.value ? g.formatNumber( b.style === "percent" ? r.value / 100 : r.value, b ) : "", h = a.length; let f, V; if (o === "vertical" && i >= he || o === "horizontal" && n >= me) return o === "vertical" ? (f = l - 6, V = s + i / 2 - h * 3.5) : (f = l + n / 2 + 4, V = s + i + 5), /* @__PURE__ */ c( "text", { y: f, x: V, style: { fill: ue() }, children: `${a}` } ); }) }), wt = (e) => { const t = u.data.filter((n) => L.indexOf(n[u.indexBy]) == -1).map((n) => n[u.indexBy]), { bars: i } = e; return /* @__PURE__ */ c("g", { children: t.filter( (n) => i.filter((l) => l.data.indexValue == n).length > 0 ).map((n) => { var Z; const l = i.filter((d) => d.data.indexValue == n); let s = "right", r = 0, a = 0; if (o == "horizontal") F === "stacked" ? (K ? r = e.innerWidth - 20 : (r = l.map((d) => d.width).reduce((d, y) => d + y), H && (r = e.innerWidth - r)), a = e.yScale(n) + l[0].height / 2) : (K ? r = e.innerWidth : (r = l.map((d) => d.width).reduce((d, y) => d > y ? d : y), H && (r = e.innerWidth - r)), a = e.yScale(n) + l.map((d) => d.height).reduce((d, y) => d + y) / 2), r = r + parseInt(z) + 5; else if (s = "middle", F === "stacked") r = e.xScale(n) + l[0].width / 2, K ? a = a - parseInt(z) : H ? a = parseInt(z) + l.map((d) => d.height).reduce((d, y) => d + y) + 14 : a = e.innerHeight - parseInt(z) - l.map((d) => d.height).reduce((d, y) => d + y) - 5; else if (r = e.xScale(n) + l.map((d) => d.width).reduce((d, y) => d + y) / 2, H && (a = e.innerHeight), K) a = a - parseInt(z); else { if (l.length % 2 == 1) { const d = Math.floor(l.length / 2); a = l[d].height; } else { const d = l.length / 2; a = Math.max( l[d].height, l[d - 1].height ); } H ? a = a + 14 + parseInt(z) : a = e.innerHeight - a - parseInt(z) - 5; } const h = u.data.filter( (d) => d[u.indexBy] === n )[0]; let f = h.parent_variables ? h.parent_variables[we] : h[we]; const V = j !== "index" ? (Z = L == null ? void 0 : L.map((d) => h[d])) == null ? void 0 : Z.reduce((d, y) => d + y, 0) : 0; return f -= V, /* @__PURE__ */ c("text", { y: a, x: r, style: { fill: ue() }, children: /* @__PURE__ */ p("tspan", { textAnchor: s, children: [ ke ? ke + " " : "", g.formatNumber( De.style === "percent" ? f / 100 : f, De ) ] }) }); }) }); }, Mt = { top: q, right: Ae, bottom: Q, left: Se }; let oe; ve && (oe = be.parse(ve, { header: !1, dynamicTyping: !0 }), Math.max(...oe.data.map((e) => e[1])), Math.min(...oe.data.map((e) => e[1]))); const Be = () => { const e = []; if (de && de.forEach((t) => { t.low && e.push(parseFloat(t.low)), t.high && e.push(parseFloat(t.high)); }), u.data) { const t = O(u.data, !1), i = O(u.keys, !0); t.forEach((n) => { i.forEach((l) => { n[l] && e.push(n[l]); }); }); } return ne && W && W.forEach((t, i) => { if (N[i] !== !1) if (t.app === "csv" && t.csvLineLayerData) { const n = be.parse(t.csvLineLayerData, { header: !1, dynamicTyping: !0 }); n.data && n.data.filter((l) => l[1] !== null && typeof l[1] == "number").forEach((l) => e.push(l[1])); } else t.measure[0] && u.data && u.data.forEach((n) => { var s; const l = (s = n.variables) == null ? void 0 : s[t.measure[0]]; l !== null && typeof l == "number" && e.push(l); }); }), e; }, Ot = () => { const e = Be(), t = e.length > 0 ? Math.max(...e) : 0; if (re === "fixed" && se !== null && se !== "") return Number(se); if (F === "stacked" && re !== "fixed") { const i = O(u.data, !1), n = O(u.keys, !0); let l = n.length > 0 ? n : u.keys; const s = Math.max( ...i.map((r) => l.map((a) => r[a] ? r[a] : 0)).map( (r) => r.length > 0 ? r.reduce((a, h) => a + h, 0) : 0 ) ); return Math.max(s, t) * 1.1; } return t * 1.05; }, Ft = () => { const e = Be(), t = e.length > 0 ? Math.min(...e) : 0; return re === "fixed" && le !== null && String(le) !== "" ? Number(le) : t > 0 ? t * 0.9 : t * 1.1; }, Et = Number(Ot()), zt = Number(Ft()), Bt = Math.min(0, zt), Vt = Math.max(0, Et), k = ["grid", "axes", "bars"]; qe && k.push(wt), k.push(yt), k.push(bt), ne && W && W.forEach((e, t) => { if (N[t] == !0 || N[t] == null) { const { csvLineLayerData: i, lineColor: n, tooltip: l } = e; if (e.app == "csv") { const s = be.parse(i, { header: !1, dynamicTyping: !0 }); if (s.data && s.data.filter((r) => r[1] !== null).length > 0) { s.data = s.data.filter((a) => a[1] !== null); const r = Te( s, n, o, F, O(u.keys, !0), l, e.title, "" ); k.push(r); } } else if (e.measure[0]) { const s = {}, r = u.data.map((f) => [ f[u.indexBy], f.variables[e.measure[0]] ]), a = u.metadata.measures ? u.metadata.measures.filter((f) => f.value == e.measure[0]) : []; s.data = r; const h = Te( s, n, o, F, O(u.keys, !0), l, e.title, a.length > 0 ? a[0].label : "" ); k.push(h); } } }), Ie === Pt && k.push(Dt), Ze && k.push(pt), k.push(vt); let xe = parseInt(et); const Ve = () => /* @__PURE__ */ c(pe, { children: G && Ne && /* @__PURE__ */ c("div", { className: "legend item", children: /* @__PURE__ */ c("label", { className: "legend-title", children: Ne }) }) }), ye = []; if (_ || T) { xe = Number.parseInt(m.yAxisTickValues); const e = new Map(Object.entries((($e = m == null ? void 0 : m.labels) == null ? void 0 : $e.xAxis) ?? {})); for (const [t, i] of e) i || ye.push(t); } let $t = parseInt(je + "") - ut; return /* @__PURE__ */ c("div", { style: { height: $t + "px" }, className: "bar-chart", children: (u == null ? void 0 : u.data) && u.data.length > 0 && /* @__PURE__ */ p(pe, { children: [ /* @__PURE__ */ c( Tt, { colorBy: $.colorBy, animate: !0, enableLabel: Ie == jt, ...u, maxValue: Vt, minValue: Bt, keys: O(u.keys, !0), data: O(u.data, !1), groupMode: F || "grouped", margin: Mt, innerPadding: Xe, valueScale: { type: Re, clamp: !0 }, colors: (e) => e && e.data[U] ? e.data[U] : v.getColor(e.id, e.data), borderColor: "#000", reverse: H, axisTop: null, axisRight: Je ? { tickSize: o == "horizontal" && A || o === "vertical" ? 5 : 0, tickPadding: 5, tickRotation: 0, tickValues: xe, legend: R.right, legendPosition: "middle", legendOffset: parseInt(Ue), format: (e) => { if (!e) return ""; if (o == "vertical") { const t = M || b; return g.formatNumber( t.style === "percent" ? e / 100 : e, { ...t } ); } return e; } } : null, axisBottom: (T || _) && (m == null ? void 0 : m.xAxisDisabled) === !0 ? null : o === "horizontal" ? { legend: R.bottom, legendPosition: "middle", legendOffset: parseInt(Le), tickPadding: 5, tickRotation: 0, tickValues: parseInt(Ge), format: (e) => { if (!e) return ""; if (o == "horizontal") { const t = M || b; return g.formatNumber( t.style === "percent" ? e / 100 : e, { ...t } ); } return e; } } : { legend: R.bottom, legendPosition: "middle", legendOffset: parseInt(Le), renderTick: Nt }, axisLeft: { tickSize: o === "horizontal" && A || o === "vertical" ? 5 : 0, tickPadding: 5, tickRotation: 0, tickValues: xe, legend: R.left, legendPosition: "middle", legendOffset: Number.parseInt(Pe), ...T || _ ? { renderTick: It } : { format: (e) => { if (!e) return ""; if (o === "vertical") { const t = M || b; return g.formatNumber( t.style === "percent" ? e / 100 : e, { ...t } ); } return e; } } }, enableGridY: nt, enableGridX: rt, layout: o, labelSkipWidth: he, labelSkipHeight: me, padding: Ke, labelTextColor: ue(), label: (e) => g.formatNumber( b.style === "percent" && e.value ? e.value / 100 : e.value, b ), layers: k, onMouseEnter: (e) => { }, onMouseLeave: (e) => { }, motionStiffness: 130, motionDamping: 15, tooltip: (e) => Ce && ae && ae.trim().length > 0 ? /* @__PURE__ */ c( Wt, { intl: g, format: b, d: e, tooltip: ae, tooltipEnableMarkdown: Qe } ) : null, theme: { tooltip: { basic: { whiteSpace: "pre", display: "flex", alignItems: "center" }, container: { background: "transparent", boxShadow: "" }, table: {}, tableCell: { padding: "3px 5px" } } } } ), (D === "top" || D === "bottom") && /* @__PURE__ */ c( "div", { className: `legends container has-standard-12-font-size ${D}`, children: /* @__PURE__ */ p("div", { className: "legend-sections", children: [ /* @__PURE__ */ c("div", { className: "title-section", children: Ve() }), /* @__PURE__ */ c( At, { onWrapChange: (e) => { D === "top" ? (mt(q + e / 2 * 40), Ee(e)) : (ft(Q + e / 2 * 25), Ee(e)); }, className: "legends container has-standard-12-font-size items-section", useColumns: lt, numberOfLegendColumns: st, children: ze() } ) ] }) } ), (D === "right" || D === "left") && /* @__PURE__ */ p( "div", { className: `legends container has-standard-12-font-size ${D}`, style: D === "right" ? ot : xt, children: [ Ve(), ze() ] } ) ] }) }); }, sa = _t(Yt); export { sa as default };