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.

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