@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
JavaScript
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
};