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.

557 lines (556 loc) 19.2 kB
var v = Object.defineProperty; var C = (g, p, s) => p in g ? v(g, p, { enumerable: !0, configurable: !0, writable: !0, value: s }) : g[p] = s; var u = (g, p, s) => C(g, typeof p != "symbol" ? p + "" : p, s); import { jsx as o, jsxs as f } from "react/jsx-runtime"; import O from "react"; import { Container as L } from "semantic-ui-react"; import w from "./Background.js"; import S from "./Stomach.js"; import E from "./Liver.js"; import N from "./Bounds.js"; import A from "./Blood.js"; import b from "./Lungs.js"; import T from "./Head.js"; import k from "./Eyes.js"; import D from "./Brain.js"; import B from "./Heart.js"; import q from "./Erectile.js"; import * as y from "d3"; import W from "./Ectopic.js"; import { injectIntl as $, FormattedMessage as x } from "react-intl"; import Y from "../../translations/en.json.js"; import z from "../../translations/fr.json.js"; import G from "../../translations/am.json.js"; import M from "../../utils/deviceType.js"; class I extends O.Component { constructor(s) { super(s); u(this, "localeYDims", { en: "60", fr: "40", am: "40" }); u(this, "localeXdims", { en: "-250", fr: "-280", am: "-280" }); u(this, "titleDims", { am: 160, fr: 180, en: 180 }); u(this, "titleLineWidths", { Cancers: { am: 125, // Wider for Amharic text fr: 58, en: 58 }, OtherConditions: { am: 158, // Much wider for Amharic text fr: 118, en: 118 } }); u(this, "mobileOptions", { Cancers: { x: this.titleDims[this.props.intl.locale], y: 25 }, OtherConditions: { x: this.isIphone() && this.props.intl.locale === "am" ? 370 : 350, y: 25 }, viewBoxDims: "0 0 550 520" }); this.state = { counter: 0, isMobile: ["mobile", "tablet"].includes(M()), isClicked: !1, selectedOption: "Cancers", orientation: this.getScreenOrientation() }, this.onMouseOut = this.onMouseOut.bind(this), this.onMouseOver = this.onMouseOver.bind(this), this.updateLayout = this.updateLayout.bind(this), this.updateSvgLabels = this.updateSvgLabels.bind(this), this.handleTextClick = this.handleTextClick.bind(this), this.handleOrientationChange = this.handleOrientationChange.bind(this), this.messages = { en: Y, fr: z, am: G }; } updateLayout() { this.setState({ isMobile: ["mobile", "tablet"].includes(M()) }); } getScreenOrientation() { var s; return ((s = window.screen.orientation) == null ? void 0 : s.type) || (window.innerWidth > window.innerHeight ? "landscape-primary" : "portrait-primary"); } isIphone() { const s = navigator.userAgent.toLowerCase(); return /iphone/i.test(s); } handleOrientationChange() { setTimeout(() => { this.setState({ orientation: this.getScreenOrientation() }, () => { this.updateLayout(), this.updateSvgLabels(); }); }, 100); } handleTextClick(s) { if (!this.state.isMobile) return; const e = s.target.closest("svg"), t = s.target.closest(".title"), r = s.target.closest(".title-rect"); if (t || r) { [...e.querySelectorAll(".title, .title-rect, .title-line")].forEach( (a) => a.classList.remove("on") ); const d = t || r, i = d.getAttribute("data-option"); d.classList.add("on"); const c = d.closest("g"), h = c.querySelector(".title-rect"), n = c.querySelector(".title"); h && h.classList.add("on"), n && n.classList.add("on"); const m = c.querySelector(".title-line"); m && m.classList.add("on"), i && this.setState({ selectedOption: i }); } } onMouseOut() { y.select(".body.parts").selectAll("g.system").transition().duration(0).delay(200).style("opacity", 1), y.select(".body.parts").selectAll("circle").remove(), y.select(".body.parts").selectAll("line").remove(); } onMouseOver(s, e, t) { const r = y.select(".body.parts"), d = r.select(s); s && (r.selectAll("g.system").transition().duration(200).style("opacity", 0), d.transition().style("opacity", 1)); const i = e.node().getBBox(); let c, h, n, m; i.x < 0 ? (c = i.x + i.width + 5, n = c > 0 ? 30 : -5, h = i.y + i.height / 2, m = i.y + i.height / 2) : (c = i.x - 5, n = 140, h = i.y + i.height / 2, m = i.y + i.height / 2), r.select("svg").append("line").attr("x1", c).attr("y1", h).attr("x2", c).attr("y2", h).transition().duration(100).attr("x2", n).attr("y2", m), r.select("svg").append("line").attr("x1", n).attr("y1", i.y + i.height / 2).attr("x2", n).attr("y2", i.y + i.height / 2).transition().duration(100).delay(100).attr("x2", t.tx).attr("y2", t.ty), r.select("svg").append("circle").attr("r", 0).attr("cx", t.tx).attr("cy", t.ty).attr("opacity", 0.6).attr("fill", "#000").transition().delay(200).duration(30).attr("r", 6); } componentDidMount() { window.addEventListener("resize", this.updateLayout), window.screen.orientation ? window.screen.orientation.addEventListener( "change", this.handleOrientationChange ) : window.addEventListener("resize", this.handleOrientationChange), this.updateLayout(), this.updateSvgLabels(), this.addOnClassToSelectedElements(); } addOnClassToSelectedElements() { const { selectedOption: s } = this.state, e = document.querySelector("svg"); if (!e) return; [...e.querySelectorAll(".title, .title-rect, .title-line")].forEach( (i) => i.classList.remove("on") ); const t = e.querySelector(`[data-option="${s}"].title`), r = e.querySelector(`[data-option="${s}"].title-rect`); let d = null; if (t || r) { const i = (t || r).closest("g"); d = i ? i.querySelector(".title-line") : null; } t && t.classList.add("on"), r && r.classList.add("on"), d && d.classList.add("on"); } updateSvgLabels() { const s = y.select(".body.parts"), e = this.props.intl, t = this.messages[e.locale], r = [ { label: e.formatMessage({ id: "oropharyngeal.cancer", defaultMessage: t["oropharyngeal.cancer"] }), selector: ".stomach", tx: 90, ty: 60 }, { label: e.formatMessage({ id: "laryngeal.cancer", defaultMessage: t["laryngeal.cancer"] }), selector: ".larynx", tx: 80, ty: 90 }, { label: e.formatMessage({ id: "oesophageal.ancer", defaultMessage: t["oesophageal.cancer"] }), selector: ".stomach", tx: 77, ty: 95 }, { label: e.formatMessage({ id: "tracheal.bronchial.lung.cancer", defaultMessage: t["tracheal.bronchial.lung.cancer"] }), selector: ".larynx", tx: e.locale === "en" ? 80 : 90, ty: 120 }, { label: e.formatMessage({ id: "acute.myeloid.leukaemia", defaultMessage: t["acute.myeloid.leukaemia"] }), selector: ".blood", tx: 90, ty: 200 }, { label: e.formatMessage({ id: "stomach.cancer", defaultMessage: t["stomach.cancer"] }), selector: ".stomach", tx: 80, ty: 150 }, { label: e.formatMessage({ id: "liver.cancer", defaultMessage: t["liver.cancer"] }), selector: ".stomach", tx: 80, ty: 150 }, { label: e.formatMessage({ id: "pancreatic.cancer", defaultMessage: t["pancreatic.cancer"] }), selector: ".stomach", tx: 105, ty: 160 }, { label: e.formatMessage({ id: "colorectal.cancer", defaultMessage: t["colorectal.cancer"] }), selector: ".stomach", tx: 85, ty: 250 }, { label: e.formatMessage({ id: "kidney.cancer", defaultMessage: t["kidney.cancer"] }), selector: ".stomach", tx: 65, ty: 185 }, { label: e.formatMessage({ id: "bladder.cancer", defaultMessage: t["bladder.cancer"] }), selector: ".erectile", tx: 85, ty: 250 }, { label: e.formatMessage({ id: "cervical.cancer", defaultMessage: t["cervical.cancer"] }), selector: ".Ectopic", tx: 85, ty: 275 } ], d = [ { label: e.formatMessage({ id: "stroke", defaultMessage: t.stroke }), selector: ".brain", tx: 97, ty: 39 }, { label: e.formatMessage({ id: "blindness.decreased.eyesight", defaultMessage: t["blindness.decreased.eyesight"] }), selector: ".eyes", tx: 97, ty: 39 }, { label: e.formatMessage({ id: "periodontitis", defaultMessage: t.periodontitis }), selector: ".stomach", tx: 90, ty: 60 }, { label: e.formatMessage({ id: "aortic.aneurysm", defaultMessage: t["aortic.aneurysm"] }), selector: ".blood", tx: 90, ty: 120 }, { label: e.formatMessage({ id: "heart.disease", defaultMessage: t["heart.disease"] }), selector: ".heart", tx: 90, ty: 140 }, { label: e.formatMessage({ id: "pneumonia", defaultMessage: t.pneumonia }), selector: ".lungs", tx: 85, ty: 130 }, { label: e.formatMessage({ id: "atherosclerotic.peripheral.vascular.disease", defaultMessage: t["atherosclerotic.peripheral.vascular.disease"] }), selector: ".blood", tx: 90, ty: 380 }, { label: e.formatMessage({ id: "copd", defaultMessage: t.copd }), selector: ".lungs", tx: 85, ty: 130 }, { label: e.formatMessage({ id: "tuberculosis", defaultMessage: t.tuberculosis }), selector: ".lungs", tx: 85, ty: 130 }, { label: e.formatMessage({ id: "asthma", defaultMessage: t.asthma }), selector: ".lungs", tx: 85, ty: 130 }, { label: e.formatMessage({ id: "diabetes", defaultMessage: t.diabetes }), selector: ".stomach", tx: 105, ty: 160 }, { label: e.formatMessage({ id: "hip.fractures", defaultMessage: t["hip.fractures"] }), selector: ".bounds", tx: 90, ty: 230 }, { label: e.formatMessage({ id: "rheumatoid.arthritis", defaultMessage: t["rheumatoid.arthritis"] }), selector: ".bounds", tx: 134, ty: 275 }, { label: e.formatMessage({ id: "impaired.immune.function", defaultMessage: t["impaired.immune.function"] }), selector: null, tx: 85, ty: 130 }, { label: e.formatMessage({ id: "erectile.dysfunction", defaultMessage: t["erectile.dysfunction"] }), selector: ".erectile", tx: 107, ty: 290 }, { label: e.formatMessage({ id: "reduced.fertility.men", defaultMessage: t["reduced.fertility.men"] }), selector: ".erectile", tx: 95, ty: 290 }, { label: e.formatMessage({ id: "ectopic.pregnancy", defaultMessage: t["ectopic.pregnancy"] }), selector: ".Ectopic", tx: 90, ty: 250 }, { label: e.formatMessage({ id: "reduced.fertility.women", defaultMessage: t["reduced.fertility.women"] }), selector: ".Ectopic", tx: 95, ty: 242 } ]; s.select("svg").selectAll("text.label").remove(); const { selectedOption: i, isMobile: c } = this.state, h = i === "Cancers" ? r : d; let n = 60; const m = (a, l) => c && this.props.intl.locale === "am" ? 140 : c ? 160 : -250; e.locale === "en" ? c ? s.select("svg").selectAll("text.label").data(h).enter().append("text").attr("class", "label").attr("x", m).attr("y", (a, l) => n + l * 25).text((a) => a.label) : (n = 90, s.select("svg").selectAll("text.left").data(r).enter().append("text").attr("class", "label").attr("x", (a, l) => -250).attr("y", (a, l) => n + l * 25).text((a) => a.label), s.select("svg").selectAll("text.right").data(d).enter().append("text").attr("class", "label").attr("x", (a, l) => 200).attr("y", (a, l) => n + l * 25).text((a) => a.label)) : (e.locale === "fr" || e.locale === "am") && (c ? s.select("svg").selectAll("text.label").data(h).enter().append("text").attr("class", "label").attr("x", m).attr("y", (a, l) => n + l * 25).text((a) => a.label) : (s.select("svg").selectAll("text.left").data(r).enter().append("text").attr("class", "label").attr("x", (a, l) => -280).attr("y", (a, l) => n + l * 25).text((a) => a.label), s.select("svg").selectAll("text.right").data(d).enter().append("text").attr("class", "label").attr("x", (a, l) => 200).attr("y", (a, l) => n + l * 25).text((a) => a.label))), s.select("svg").selectAll("text.label").on("mouseover", (a, l) => { this.onMouseOver(l.selector, y.select(a.currentTarget), l, { tx: l.tx, ty: l.ty }); }).on("mouseout", (a, l) => { this.onMouseOut(); }); } componentDidUpdate(s, e) { (e.selectedOption !== this.state.selectedOption || e.orientation !== this.state.orientation) && (this.updateSvgLabels(), this.addOnClassToSelectedElements()); } componentWillUnmount() { window.removeEventListener("resize", this.updateLayout), window.screen.orientation ? window.screen.orientation.removeEventListener( "change", this.handleOrientationChange ) : window.removeEventListener("resize", this.handleOrientationChange); } render() { return /* @__PURE__ */ o(L, { className: "body parts", children: /* @__PURE__ */ f( "svg", { className: "body root", viewBox: this.state.isMobile ? this.mobileOptions.viewBoxDims : "-300 0 900 520", xmlns: "http://www.w3.org/2000/svg", children: [ /* @__PURE__ */ o(w, { className: "backGround" }), /* @__PURE__ */ o(N, { className: "system bounds" }), /* @__PURE__ */ o(T, { className: "system head" }), /* @__PURE__ */ o(b, { className: "system larynx" }), /* @__PURE__ */ o(b, { className: "system lungs" }), /* @__PURE__ */ o(S, { className: "system stomach" }), /* @__PURE__ */ o(E, { className: "system liver" }), /* @__PURE__ */ o(D, { className: "system brain" }), /* @__PURE__ */ o(k, { className: "system eyes" }), /* @__PURE__ */ o(A, { className: "system blood" }), /* @__PURE__ */ o(B, { className: "system heart" }), /* @__PURE__ */ o(q, { className: "system erectile" }), /* @__PURE__ */ o(W, { className: "system Ectopic" }), /* @__PURE__ */ f("g", { onClick: this.handleTextClick, children: [ /* @__PURE__ */ o( "rect", { className: "title-rect", "data-option": "Cancers", x: this.state.isMobile ? this.mobileOptions.Cancers.x - 20 : "", y: this.state.isMobile ? this.mobileOptions.Cancers.y - 20 : this.localeYDims[this.props.intl.locale], rx: "5", ry: "5", width: "100", height: "30" } ), /* @__PURE__ */ o( "text", { x: this.state.isMobile ? this.mobileOptions.Cancers.x : this.localeXdims[this.props.intl.locale], y: this.state.isMobile ? this.mobileOptions.Cancers.y : this.localeYDims[this.props.intl.locale], className: "title", "data-option": "Cancers", children: /* @__PURE__ */ o( x, { id: "ailments.title", defaultMessage: "{cancers}", values: { cancers: this.messages[this.props.intl.locale]["ailments.title"] } } ) } ), this.state.isMobile && /* @__PURE__ */ o( "rect", { className: "title-line", x: this.state.isMobile ? this.mobileOptions.Cancers.x - 18 : "-250", y: this.state.isMobile ? this.mobileOptions.Cancers.y + 7 : "", width: this.titleLineWidths.Cancers[this.props.intl.locale] || this.titleLineWidths.Cancers.en, height: "3", fill: "#E5EBED" } ) ] }), /* @__PURE__ */ f("g", { onClick: this.handleTextClick, children: [ /* @__PURE__ */ o( "rect", { className: "title-rect", "data-option": "OtherConditions", x: this.state.isMobile ? this.mobileOptions.OtherConditions.x - 65 : "", y: this.state.isMobile ? this.mobileOptions.OtherConditions.y - 20 : this.localeYDims[this.props.intl.locale], rx: "5", ry: "5", width: "155", height: "30" } ), /* @__PURE__ */ o( "text", { x: this.state.isMobile ? this.mobileOptions.OtherConditions.x - 50 : "200", y: this.state.isMobile ? this.mobileOptions.OtherConditions.y : this.localeYDims[this.props.intl.locale], className: "title", "data-option": "OtherConditions", children: /* @__PURE__ */ o( x, { id: "ailments.otherConditions", defaultMessage: "{otherConditions}", values: { otherConditions: this.messages[this.props.intl.locale]["ailments.otherConditions"] } } ) } ), this.state.isMobile && /* @__PURE__ */ o( "rect", { className: "title-line", x: this.state.isMobile ? this.mobileOptions.OtherConditions.x - 68 : "200", y: this.state.isMobile ? this.mobileOptions.OtherConditions.y + 7 : "60", width: this.titleLineWidths.OtherConditions[this.props.intl.locale] || this.titleLineWidths.OtherConditions.en, height: "3", fill: "#E5EBED" } ) ] }) ] } ) }); } } const ne = $(I); export { ne as default };