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.

125 lines (124 loc) 5.86 kB
import { jsx as n, jsxs as I } from "react/jsx-runtime"; import y from "react"; import * as f from "d3"; import { Icon as b, Popup as k } from "semantic-ui-react"; import { FormattedMessage as N } from "react-intl"; class T extends y.Component { constructor(t) { super(t), this.zoomRef = y.createRef(), this.lastInternalZoom = null, this.lastUserTransform = null, this.zoomed = this.zoomed.bind(this), this.zoomEnd = this.zoomEnd.bind(this), this.zoomIn = this.zoomIn.bind(this), this.zoomOut = this.zoomOut.bind(this), this.reset = this.reset.bind(this), this.fullView = this.fullView.bind(this), this.transition2fullView = this.transition2fullView.bind(this), this._fullView = this._fullView.bind(this), this.initialized = !1, this.zoom = f.zoom().scaleExtent([0.1, 300]).on("zoom", this.zoomed).on("end", this.zoomEnd); } componentDidMount() { const { zoomEnabled: t = !0 } = this.props, i = this.getSelection(); this._fullView(!1), t && (this.props.editing || (i.on("dblclick.zoom", null), i.on("dblclick", (o) => { o.preventDefault(), i.transition().duration(250).call(this.zoom.scaleBy, 1.5); }), i.on("wheel.zoom", null), i.on("wheel", (o) => { o.preventDefault(); const s = o.deltaY > 0 ? 1 / 1.5 : 1.5; i.transition().duration(250).call(this.zoom.scaleBy, s); }), i.call(this.zoom))), this.fullView(); } componentDidUpdate(t) { const i = this.getSelection(), { zoomEnabled: o, initialPosition: s, readyState: c, height: d, width: h, selectedPoint: e, projection: m, editing: a } = this.props; !this.initialized && this.props.readyToZoom && (this.fullView(), this.initialized = !0); const l = JSON.stringify(t.initialPosition) !== JSON.stringify(s); if (t.zoomEnabled !== o || l) if (o && i || a) { if (s && this.lastInternalZoom) { const r = (S, x = 3) => Number(S.toFixed(x)), { x: p, y: u, k: z } = s, { x: g, y: w, k: V } = this.lastInternalZoom; if (Math.abs(r(p) - r(g)) < 1 && Math.abs(r(u) - r(w)) < 1 && Math.abs(r(z) - r(V)) < 1e-3) { this.lastInternalZoom = null; return; } } i.call(this.zoom).on(".zoom", this.zoom), this.transition2fullView(); } else i && i.on(".zoom", null); !t.readyState && c && this.fullView(), (t.height !== d || t.width !== h) && this.fullView(), e != t.selectedPoint && e && this.zoomTo(m([e.y, e.x])); } zoomed(t) { var o, s; const i = this.getSelection(); i && (i.selectAll("g.zoomable").attr("transform", t.transform), (s = (o = this.props).onZoomed) == null || s.call(o, t.transform), this.props.editing && t.sourceEvent && (this.lastUserTransform = t.transform)); } zoomEnd(t) { var e, m; const { identifier: i, editing: o, width: s, height: c, postMessageOrigin: d = "*" } = this.props, h = this.lastUserTransform || t.transform; if (this.lastUserTransform = null, (m = (e = this.props).onZoomed) == null || m.call(e, h), o) { const a = (g, w = 3) => Number(g.toFixed(w)), { x: l, y: r, k: p } = h, u = { x: a(l), y: a(r), k: a(p) }; this.lastInternalZoom = u; const z = { type: `d3_map_${i}`, value: { ...u, width: s, height: c } }; window.parent.postMessage(z, d); } } zoomIn() { const t = this.getSelection(); if (t) { const i = this.props.editing ? 0 : this.props.transitionDuration || 500; t.transition().duration(i).call(this.zoom.scaleBy, 2); } } zoomTo(t) { const i = f.zoomIdentity.translate(this.props.width / 2, this.props.height / 2).scale(200).translate(-t[0], -t[1]), o = this.getSelection(); this.props.editing || this.props.transitionDuration, o.transition().duration(750).call(this.zoom.transform, i); } zoomOut() { const t = this.getSelection(); if (t) { const i = this.props.editing ? 0 : this.props.transitionDuration || 500; t.transition().duration(i).call(this.zoom.scaleBy, 0.5); } } reset() { const t = this.getSelection(); t && (this.props.editing ? t.call(this.zoom.transform, f.zoomIdentity.translate(0, 0).scale(1)) : this.transition2fullView()); } getSelection() { return f.select(this.zoomRef.current.parentNode.querySelector("svg")); } _fullView(t = !0) { const { initialPosition: i, width: o, height: s, transform: c } = this.props; if (!i) return; const { x: d = 100, y: h = 23, k: e = 1, width: m, height: a } = i; if (!m || !a || !e) return; const l = this.getSelection(); l && (console.log("SVG parent client sizes:", l.node().parentNode.clientWidth, l.node().parentNode.clientHeight), l.transition().duration(t ? 750 : 0).attr("transform", c).call(this.zoom.transform, f.zoomIdentity.translate(d, h).scale(e))); } transition2fullView() { this._fullView(!0); } fullView() { this._fullView(!1); } render() { const { editing: t, zoomEnabled: i = !0 } = this.props; return /* @__PURE__ */ n("div", { ref: this.zoomRef, className: `zoom ${i ? "" : "disabled"}`, children: (t || i) && /* @__PURE__ */ I("div", { children: [ /* @__PURE__ */ n("div", { className: "button plus", onClick: this.zoomIn, children: /* @__PURE__ */ n(b, { name: "plus", size: "small" }) }), /* @__PURE__ */ n("div", { className: "button minus", onClick: this.zoomOut, children: /* @__PURE__ */ n(b, { name: "minus", size: "small" }) }), /* @__PURE__ */ n( k, { content: /* @__PURE__ */ n(N, { id: "map.reset.tooltip", defaultMessage: "Reset zoom" }), trigger: /* @__PURE__ */ n("div", { className: "button reset", onClick: this.reset, children: /* @__PURE__ */ n(b, { name: "repeat", size: "small" }) }) } ) ] }) }); } } export { T as default };