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.

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