lwc-plugin-min-max-price-markers
Version:
A plugin to display min/max prices Markers.
294 lines (293 loc) • 11 kB
JavaScript
var b = Object.defineProperty;
var x = (i, t, e) => t in i ? b(i, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : i[t] = e;
var a = (i, t, e) => (x(i, typeof t != "symbol" ? t + "" : t, e), e);
import { MismatchDirection as w } from "lightweight-charts";
const z = (i, ...t) => {
for (const e of t)
for (const s in e)
e[s] === void 0 || !Object.prototype.hasOwnProperty.call(e, s) || ["__proto__", "constructor", "prototype"].includes(s) || (typeof e[s] != "object" || i[s] === void 0 || Array.isArray(e[s]) ? i[s] = e[s] : g(i[s], e[s]));
return i;
}, g = (i, ...t) => z(i, ...t), T = (i) => "value" in i && typeof i.value == "number", C = (i) => "open" in i && "high" in i && "low" in i && "close" in i, R = "-apple-system, BlinkMacSystemFont, 'Trebuchet MS', Roboto, Ubuntu, sans-serif", v = (i) => {
const { fontSize: t } = i;
let { fontStyle: e, fontFamily: s } = i;
return e !== void 0 ? e = `${e} ` : e = "", s || (s = R), `${e}${t}px ${s}`;
}, V = /[2-9]/g;
class O {
// --------------------------------------------------
constructor(t = 50) {
a(this, "_maxSize");
a(this, "_actualSize", 0);
a(this, "_usageTick", 1);
a(this, "_oldestTick", 1);
a(this, "_tick2Labels", {});
a(this, "_cache", /* @__PURE__ */ new Map());
this._maxSize = t;
}
// --------------------------------------------------
reset() {
this._actualSize = 0, this._cache.clear(), this._usageTick = 1, this._oldestTick = 1, this._tick2Labels = {};
}
// --------------------------------------------------
measureText(t, e, s) {
return this._getMetrics(t, e, s).width;
}
// --------------------------------------------------
yMidCorrection(t, e, s) {
const r = this._getMetrics(t, e, s);
return ((r.actualBoundingBoxAscent || 0) - (r.actualBoundingBoxDescent || 0)) / 2;
}
// --------------------------------------------------
_getMetrics(t, e, s) {
const r = s || V, o = String(e).replace(r, "0");
if (this._cache.has(o))
return this._cache.get(o).metrics;
if (this._actualSize === this._maxSize) {
const _ = this._tick2Labels[this._oldestTick];
delete this._tick2Labels[this._oldestTick], this._cache.delete(_), this._oldestTick++, this._actualSize--;
}
t.save(), t.textBaseline = "middle";
const n = t.measureText(o);
return t.restore(), n.width === 0 && e.length || (this._cache.set(o, { metrics: n, tick: this._usageTick }), this._tick2Labels[this._usageTick] = o, this._actualSize++, this._usageTick++), n;
}
}
const m = {
textColor: "#000",
zOrder: "aboveSeries"
}, S = 10, y = 4 + S;
class F {
constructor() {
a(this, "_data", null);
a(this, "_textWidthCache", new O());
a(this, "_fontSize", 10);
a(this, "_fontFamily", "Roboto, sans-serif");
a(this, "_font", v({
fontSize: this._fontSize,
fontFamily: this._fontFamily
}));
a(this, "_zOrder", "normal");
}
// --------------------------------------------------
setData(t) {
this._data = t;
}
// --------------------------------------------------
setParams(t) {
const { fontSize: e, fontFamily: s, zOrder: r } = t;
(this._fontSize !== e || this._fontFamily !== s) && (this._fontSize = e, this._fontFamily = s, this._font = v({
fontSize: this._fontSize,
fontFamily: this._fontFamily
}), this._textWidthCache.reset()), this._zOrder = r;
}
// --------------------------------------------------
draw(t) {
this._zOrder !== "aboveSeries" && t.useBitmapCoordinateSpace((e) => {
this._drawImpl(e);
});
}
// --------------------------------------------------
drawBackground(t) {
this._zOrder === "aboveSeries" && t.useBitmapCoordinateSpace(
(e) => {
this._drawImpl(e);
}
);
}
// --------------------------------------------------
_drawImpl(t) {
const { context: e, horizontalPixelRatio: s, verticalPixelRatio: r } = t;
if (this._data !== null) {
e.textBaseline = "middle", e.font = this._font;
for (let o = 0; o < this._data.length; o++) {
const n = this._data[o];
n.text && (n.text.width = this._textWidthCache.measureText(
e,
n.text.content
), n.text.height = this._fontSize, n.text.x = n.variant === "left" ? n.x - n.text.width - y : n.x + y, I(n, e, s, r));
}
}
}
}
const I = (i, t, e, s) => {
i.text && (t.fillStyle = i.color, L(
t,
i.text.content,
i.text.x,
i.text.y,
e,
s
), t.strokeStyle = i.color, q(
i.variant === "left",
t,
M(i, e, s)
));
}, M = (i, t, e) => ({
x: Math.round(i.x * t),
y: i.y * e,
pixelRatio: t
}), q = (i, t, e) => {
const s = e.x, r = e.y;
t.beginPath(), t.lineWidth = 1 * e.pixelRatio, i ? (t.moveTo(s, r), t.lineTo(s - S, r)) : (t.moveTo(s, r), t.lineTo(s + S, r)), t.stroke();
}, L = (i, t, e, s, r, o) => {
i.save(), i.scale(r, o), i.fillText(t, e, s), i.restore();
};
class B {
// --------------------------------------------------
constructor(t) {
a(this, "_chart");
a(this, "_series");
a(this, "_data", []);
a(this, "_options");
a(this, "_invalidated", !0);
a(this, "_dataInvalidated", !0);
a(this, "_markers", []);
a(this, "_renderer", new F());
this._chart = t.chart, this._series = t.series, this._options = t.options, this._data = [];
}
// --------------------------------------------------
renderer() {
if (!this._series.options().visible)
return null;
this._invalidated && this._makeValid();
const t = this._chart.options().layout;
return this._renderer.setParams({
fontSize: t.fontSize,
fontFamily: t.fontFamily,
zOrder: this._options.zOrder
}), this._renderer.setData(this._data), this._renderer;
}
// --------------------------------------------------
setMarkers(t) {
this._markers = t.markers, this.update("data");
}
// --------------------------------------------------
update(t) {
this._invalidated = !0, t === "data" && (this._dataInvalidated = !0);
}
// --------------------------------------------------
updateOptions(t) {
this._invalidated = !0, this._options = t;
}
// --------------------------------------------------
zOrder() {
return this._options.zOrder === "aboveSeries" ? "top" : this._options.zOrder;
}
// --------------------------------------------------
_makeValid() {
const t = this._chart.timeScale(), e = this._markers;
if (e != null && e.length && (this._dataInvalidated && (this._data = e.map((s) => ({
time: s.time,
x: 0,
y: 0,
color: this._options.textColor,
text: void 0,
variant: s.variant
})), this._dataInvalidated = !1), !!this._data.length)) {
for (let s = 0; s < this._data.length; s++) {
const r = this._data[s], n = this._markers[s].price, _ = this._series.dataByIndex(
r.time,
w.None
), l = this._series.priceToCoordinate(n);
!_ || !l || (r.x = t.logicalToCoordinate(
r.time
), r.y = l, r.text = {
content: `${this._series.priceFormatter().format(n)}`,
x: 0,
y: l,
width: 0,
height: 0
});
}
this._invalidated = !1;
}
}
}
class P {
// --------------------------------------------------
constructor(t) {
a(this, "_paneView", null);
a(this, "_chart", null);
a(this, "_series", null);
a(this, "_requestUpdate");
a(this, "_recalculationRequired", !0);
a(this, "_markers", []);
a(this, "_options", m);
// --------------------------------------------------
a(this, "_dataChangedHandler", (t) => this._onDataChanged(t));
// --------------------------------------------------
a(this, "_visibleRangeChanged", (t) => this._onVisibleRangeChanged(t));
this._options = t != null && t.options ? g(m, t.options) : m;
}
// --------------------------------------------------
applyOptions(t) {
this._options = g(this._options, t);
}
// --------------------------------------------------
attached(t) {
this._recalculateMarkers(), this._chart = t.chart, this._series = t.series, this._paneView = new B({
series: this._series,
chart: this._chart,
options: this._options
}), this._requestUpdate = t.requestUpdate, this._recalculationRequired = !0, this.requestUpdate(), this._series.subscribeDataChanged(this._dataChangedHandler), this._chart.timeScale().subscribeVisibleLogicalRangeChange(this._visibleRangeChanged);
}
// --------------------------------------------------
requestUpdate() {
this._requestUpdate && this._requestUpdate();
}
// --------------------------------------------------
detached() {
var t, e;
(t = this._chart) == null || t.timeScale().unsubscribeVisibleLogicalRangeChange(this._visibleRangeChanged), (e = this._series) == null || e.unsubscribeDataChanged(this._dataChangedHandler), this._requestUpdate = void 0, this._markers = [], this._paneView = null, this._series = null, this._chart = null;
}
// --------------------------------------------------
paneViews() {
return this._paneView ? [this._paneView] : [];
}
// --------------------------------------------------
updateAllViews() {
this._paneView && (this._recalculateMarkers(), this._paneView.setMarkers({ markers: this._markers }), this._paneView.updateOptions(this._options), this._paneView.update());
}
// --------------------------------------------------
_onDataChanged(t) {
!this._chart || !this._series || (this._recalculationRequired = !0, this.requestUpdate());
}
// --------------------------------------------------
_onVisibleRangeChanged(t) {
!this._chart || !this._series || !t || (this._recalculationRequired = !0, this.requestUpdate());
}
// --------------------------------------------------
_recalculateMarkers() {
if (!this._recalculationRequired || !this._chart || !this._series)
return;
this._markers = [];
const t = this._chart.timeScale(), e = this._series.data(), s = t.getVisibleLogicalRange();
if (!s || !e.length)
return;
const r = this._series.barsInLogicalRange(s);
if (!r)
return;
const o = r.from, n = r.to;
if (!o || !n)
return;
const _ = e.length;
let l = -1 / 0, d = null, u = 1 / 0, f = null;
for (let p = 0; p < _; p++) {
const h = e[p], c = h.time;
c < o || c > n || (C(h) ? (h.high > l && (l = h.high, d = c), h.low < u && (u = h.low, f = c)) : T(h) && (h.value > l && (l = h.value, d = c), h.value < u && (u = h.value, f = c)));
}
if (!d || !f)
return;
const k = f > d;
this._markers.push({
time: t.timeToIndex(d, !0),
price: l,
variant: k ? "right" : "left"
}), this._markers.push({
time: t.timeToIndex(f, !0),
price: u,
variant: k ? "left" : "right"
}), this._recalculationRequired = !1;
}
}
export {
P as MinMaxPriceMarkers
};