@luxalgo/vela 0.8.0 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE +1 -1
- package/README.md +16 -8
- package/dist/{DataProvider-BrlxntPN.d.cts → DataProvider-COGDs9Xg.d.cts} +1 -1
- package/dist/{DataProvider-DwFIoV4r.d.ts → DataProvider-DpOWZD8F.d.ts} +1 -1
- package/dist/{chunk-KA77UTRF.js → chunk-27UTYE7T.js} +25 -2
- package/dist/{chunk-EZ5FWVLA.js → chunk-DPAA3SRT.js} +94 -13
- package/dist/{chunk-BZQM2XO7.js → chunk-HKNO24GD.js} +13 -1
- package/dist/{chunk-2IAETM2I.js → chunk-NLDTVFOI.js} +79 -6
- package/dist/{chunk-E3GU6AUI.js → chunk-R2JMNIHY.js} +68 -23
- package/dist/{chunk-QBPUT5SU.js → chunk-T3DZIR5Y.js} +211 -54
- package/dist/{contributions-tjNExo1o.d.ts → contributions-Cgm9RJYP.d.cts} +38 -11
- package/dist/{contributions-CtlptxR8.d.cts → contributions-bWgwyiVi.d.ts} +38 -11
- package/dist/index.cjs +317 -62
- package/dist/index.d.cts +8 -8
- package/dist/index.d.ts +8 -8
- package/dist/index.js +4 -4
- package/dist/{options-BnEPUuVV.d.ts → options-NAUHiQEC.d.cts} +3 -3
- package/dist/{options-BnEPUuVV.d.cts → options-NAUHiQEC.d.ts} +3 -3
- package/dist/{plugin-BWxJRKzS.d.cts → plugin-CjjzZX2F.d.cts} +4 -4
- package/dist/{plugin-e2WUEtiI.d.ts → plugin-CqxWoDKS.d.ts} +4 -4
- package/dist/plugin.cjs +20 -6
- package/dist/plugin.d.cts +5 -5
- package/dist/plugin.d.ts +5 -5
- package/dist/plugin.js +2 -2
- package/dist/providers/binance.d.cts +2 -2
- package/dist/providers/binance.d.ts +2 -2
- package/dist/providers/coinbase.d.cts +2 -2
- package/dist/providers/coinbase.d.ts +2 -2
- package/dist/providers/hyperliquid.d.cts +2 -2
- package/dist/providers/hyperliquid.d.ts +2 -2
- package/dist/{side-panel-HF0IAzwf.d.cts → side-panel-wMNfgyZb.d.cts} +13 -0
- package/dist/{side-panel-HF0IAzwf.d.ts → side-panel-wMNfgyZb.d.ts} +13 -0
- package/dist/{statusline-model-zKXtGIjj.d.ts → statusline-model-Dih6FGWP.d.ts} +3 -3
- package/dist/{statusline-model-DFY7tuHj.d.cts → statusline-model-Dpfpq54A.d.cts} +3 -3
- package/dist/ui.cjs +115 -5
- package/dist/ui.d.cts +28 -2
- package/dist/ui.d.ts +28 -2
- package/dist/ui.js +3 -3
- package/dist/vela.global.js +317 -62
- package/dist/vela.global.min.js +61 -68
- package/dist/widget.cjs +476 -85
- package/dist/widget.d.cts +20 -10
- package/dist/widget.d.ts +20 -10
- package/dist/widget.js +7 -7
- package/dist/workspace.cjs +476 -85
- package/dist/workspace.d.cts +6 -6
- package/dist/workspace.d.ts +6 -6
- package/dist/workspace.js +6 -6
- package/package.json +3 -3
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { deserializeDrawing, chartTypes, rendererLayers, isLineLikeSeries, seriesShownOn, foldBaseModulation, registerChartType, rendererDefaults, getDrawingType, settingsRowVisible, normalizeSettingsRow, Magnifier, TextLabel, Callout, resetDrawingSettings, registerNativeIndicator, chartType, getNativeIndicator, nativeIndicatorDescriptors, nativeInstanceChannel, drawingTypes, settingsRowValueKeys, formatDuration, RegressionChannel, FixedRangeVolumeProfile, DEFAULT_DRAWING_COLOR, SegmentDrawing, ArrowMark, GlyphStamp, RadialFib, FibSpiral, DedekindTessellation, MachFigure, GannSquare, FibRatios, MeasureBox, PositionTool, AnchoredVwap, PatternDrawing, Comment, PriceNote, Signpost, Note, PriceLabel, GANN_SQUARE_ARCS, magnifierTimeframeLabel, lineSegmentIntersection, MAGNIFIER_TIMEFRAME_OPTIONS, GLYPH_OPTIONS, STAMP_SIZE_OPTIONS, LINE_STYLE_OPTIONS, DEDEKIND_CURVATURE_OPTIONS, MACH_NUMBER_OPTIONS, MACH_WAVE_COUNT_OPTIONS, TEXT_SIZE_OPTIONS, createDrawing, inputVisible, seriesInScale, tickerModifierIds, CalloutBase, DIRECTION_OPTIONS, stableSeriesId } from './chunk-
|
|
2
|
-
import { themeTokens, Dialog, closeOpenPopovers, closeWidthPopover, fieldSection, buildFieldControl, fieldSeparator, fieldGrid, fieldRow, CALLOUT_STYLE_ID, CALLOUT_CSS, Popover, blendOver, splitColor, CalloutBubble, Menu, TextArea, NumberInput, buildColorPicker, isPopoverOpen, DatePicker, eventDismissedPopover, toggleSelectList, normalizeDateInput, openPopoverTrigger, fieldGridColumns, FIELD_GAP_PX, STATIC_TOKENS } from './chunk-
|
|
3
|
-
import { icon, iconAt, withAlpha, WARNING, ACCENT, NEUTRAL, INFO, BULLISH, BEARISH, isDarkColor, injectStyles, SERIES_LINE, CHIP_PLATE, CROSSHAIR, TRADE_EXIT, TRADE_SHORT, TRADE_LONG, iconMarkup, overlayScrollbarCss, SLATE_DEEP, VALID, INVALID, SLATE, FIELD_FOCUS_CSS, FIELD_FOCUS_RING, svg24, svg24Solid } from './chunk-
|
|
1
|
+
import { deserializeDrawing, chartTypes, rendererLayers, isLineLikeSeries, seriesShownOn, foldBaseModulation, registerChartType, rendererDefaults, getDrawingType, settingsRowVisible, normalizeSettingsRow, Magnifier, TextLabel, Callout, resetDrawingSettings, registerNativeIndicator, chartType, getNativeIndicator, nativeIndicatorDescriptors, nativeInstanceChannel, drawingTypes, settingsRowValueKeys, formatDuration, RegressionChannel, FixedRangeVolumeProfile, DEFAULT_DRAWING_COLOR, SegmentDrawing, ArrowMark, GlyphStamp, RadialFib, FibSpiral, DedekindTessellation, MachFigure, GannSquare, FibRatios, MeasureBox, PositionTool, AnchoredVwap, PatternDrawing, Comment, PriceNote, Signpost, Note, PriceLabel, GANN_SQUARE_ARCS, magnifierTimeframeLabel, lineSegmentIntersection, MAGNIFIER_TIMEFRAME_OPTIONS, GLYPH_OPTIONS, STAMP_SIZE_OPTIONS, LINE_STYLE_OPTIONS, DEDEKIND_CURVATURE_OPTIONS, MACH_NUMBER_OPTIONS, MACH_WAVE_COUNT_OPTIONS, TEXT_SIZE_OPTIONS, createDrawing, inputVisible, seriesInScale, tickerModifierIds, CalloutBase, DIRECTION_OPTIONS, FibRetracement, stableSeriesId } from './chunk-DPAA3SRT.js';
|
|
2
|
+
import { themeTokens, Dialog, closeOpenPopovers, closeWidthPopover, fieldSection, buildFieldControl, fieldSeparator, fieldGrid, fieldRow, CALLOUT_STYLE_ID, CALLOUT_CSS, Popover, blendOver, splitColor, CalloutBubble, Menu, TextArea, NumberInput, buildColorPicker, isPopoverOpen, DatePicker, eventDismissedPopover, toggleSelectList, normalizeDateInput, openPopoverTrigger, fieldGridColumns, FIELD_GAP_PX, STATIC_TOKENS } from './chunk-NLDTVFOI.js';
|
|
3
|
+
import { icon, iconAt, withAlpha, WARNING, ACCENT, NEUTRAL, INFO, BULLISH, BEARISH, announceSurface, isDarkColor, injectStyles, SERIES_LINE, CHIP_PLATE, CROSSHAIR, TRADE_EXIT, TRADE_SHORT, TRADE_LONG, iconMarkup, overlayScrollbarCss, SLATE_DEEP, VALID, INVALID, SLATE, FIELD_FOCUS_CSS, FIELD_FOCUS_RING, svg24, svg24Solid } from './chunk-HKNO24GD.js';
|
|
4
4
|
|
|
5
5
|
// src/core/events/EventBus.ts
|
|
6
6
|
var TypedEventBus = class {
|
|
@@ -3013,6 +3013,7 @@ var DrawingToolbar = class {
|
|
|
3013
3013
|
);
|
|
3014
3014
|
}
|
|
3015
3015
|
}
|
|
3016
|
+
announceSurface(fly, true, "menu", cell);
|
|
3016
3017
|
}
|
|
3017
3018
|
openMagnetFlyout() {
|
|
3018
3019
|
const cell = this.magnetCell;
|
|
@@ -3036,6 +3037,7 @@ var DrawingToolbar = class {
|
|
|
3036
3037
|
})
|
|
3037
3038
|
);
|
|
3038
3039
|
}
|
|
3040
|
+
announceSurface(fly, true, "menu", cell);
|
|
3039
3041
|
}
|
|
3040
3042
|
flyoutHeader(text) {
|
|
3041
3043
|
const t = this.theme;
|
|
@@ -3104,9 +3106,11 @@ var DrawingToolbar = class {
|
|
|
3104
3106
|
}
|
|
3105
3107
|
closeFlyout() {
|
|
3106
3108
|
this.starEls.clear();
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
+
const fly = this.flyout;
|
|
3110
|
+
if (fly) {
|
|
3109
3111
|
this.flyout = null;
|
|
3112
|
+
announceSurface(fly, false, "menu", this.flyoutCell);
|
|
3113
|
+
fly.remove();
|
|
3110
3114
|
this.flyoutCell?.classList.remove("vela-open");
|
|
3111
3115
|
this.flyoutCell = null;
|
|
3112
3116
|
this.flyoutOwnerId = null;
|
|
@@ -5791,15 +5795,23 @@ var Batch = class {
|
|
|
5791
5795
|
this.seg(x + w, y + h, x, y + h, lineWidth, c);
|
|
5792
5796
|
this.seg(x, y + h, x, y, lineWidth, c);
|
|
5793
5797
|
}
|
|
5794
|
-
/**
|
|
5798
|
+
/**
|
|
5799
|
+
* Filled circle (triangle fan), feathered like a line: the rim is padded by {@link AA_PAD} and
|
|
5800
|
+
* edgeDist runs from 0 at the center to the padded radius at the rim, with edgeHalf = r. The
|
|
5801
|
+
* distance grows linearly along each spoke, so the shader's line feather gives a round soft edge.
|
|
5802
|
+
*/
|
|
5795
5803
|
circle(cx, cy, r, c, segments = 16) {
|
|
5796
|
-
|
|
5804
|
+
const ext = r + AA_PAD;
|
|
5805
|
+
let px = cx + ext;
|
|
5797
5806
|
let py = cy;
|
|
5807
|
+
this.ensure(segments * 3);
|
|
5798
5808
|
for (let i = 1; i <= segments; i += 1) {
|
|
5799
5809
|
const a = i / segments * Math.PI * 2;
|
|
5800
|
-
const nx = cx + Math.cos(a) *
|
|
5801
|
-
const ny = cy + Math.sin(a) *
|
|
5802
|
-
this.
|
|
5810
|
+
const nx = cx + Math.cos(a) * ext;
|
|
5811
|
+
const ny = cy + Math.sin(a) * ext;
|
|
5812
|
+
this.v(cx, cy, c, 0, r);
|
|
5813
|
+
this.v(px, py, c, ext, r);
|
|
5814
|
+
this.v(nx, ny, c, ext, r);
|
|
5803
5815
|
px = nx;
|
|
5804
5816
|
py = ny;
|
|
5805
5817
|
}
|
|
@@ -5980,7 +5992,7 @@ var WebGL2Backend = class {
|
|
|
5980
5992
|
}
|
|
5981
5993
|
mount(canvas) {
|
|
5982
5994
|
this.canvas = canvas;
|
|
5983
|
-
this.gl = canvas.getContext("webgl2", { alpha: true, antialias:
|
|
5995
|
+
this.gl = canvas.getContext("webgl2", { alpha: true, antialias: false, depth: false, stencil: false, premultipliedAlpha: true });
|
|
5984
5996
|
if (!this.gl) return;
|
|
5985
5997
|
if (!this.initGL()) {
|
|
5986
5998
|
this.gl = null;
|
|
@@ -7239,6 +7251,12 @@ var InputController = class {
|
|
|
7239
7251
|
this.lastTapT = 0;
|
|
7240
7252
|
this.lastTapX = 0;
|
|
7241
7253
|
this.lastTapY = 0;
|
|
7254
|
+
// Whether the last two primary presses were claimed by the drawings layer. A double-click
|
|
7255
|
+
// is the last press plus the one before it; a tool-driven click pair must never fall through
|
|
7256
|
+
// to the pane maximize toggle, even when the tool disarmed itself between the two clicks
|
|
7257
|
+
// (a finished placement leaves plain cursor mode for the second click).
|
|
7258
|
+
this.lastPressDrawing = false;
|
|
7259
|
+
this.prevPressDrawing = false;
|
|
7242
7260
|
this.onTouchContextMenu = (e) => {
|
|
7243
7261
|
if (this.touches.size === 0) return;
|
|
7244
7262
|
if (!(e.target instanceof Node) || !this.el?.contains(e.target)) return;
|
|
@@ -7293,19 +7311,24 @@ var InputController = class {
|
|
|
7293
7311
|
this.moved = false;
|
|
7294
7312
|
this.startX = x;
|
|
7295
7313
|
this.startY = y;
|
|
7314
|
+
this.prevPressDrawing = this.lastPressDrawing;
|
|
7315
|
+
this.lastPressDrawing = false;
|
|
7296
7316
|
if (this.deps.drawingsClaim?.(x, y)) {
|
|
7297
7317
|
this.region = "drawing";
|
|
7318
|
+
this.lastPressDrawing = true;
|
|
7298
7319
|
this.deps.drawingsPointerDown?.(x, y, this.snapMode(e), e.shiftKey, e.ctrlKey || e.metaKey);
|
|
7299
7320
|
this.capture(e.pointerId);
|
|
7300
7321
|
return;
|
|
7301
7322
|
}
|
|
7302
7323
|
if (e.shiftKey && this.regionAt(x, y) === "data" && this.deps.drawingsMeasureStart?.(x, y, this.snapMode(e))) {
|
|
7303
7324
|
this.region = "drawing";
|
|
7325
|
+
this.lastPressDrawing = true;
|
|
7304
7326
|
this.capture(e.pointerId);
|
|
7305
7327
|
return;
|
|
7306
7328
|
}
|
|
7307
7329
|
if ((e.ctrlKey || e.metaKey) && this.regionAt(x, y) === "data" && this.deps.drawingsMarqueeStart?.(x, y)) {
|
|
7308
7330
|
this.region = "drawing";
|
|
7331
|
+
this.lastPressDrawing = true;
|
|
7309
7332
|
this.capture(e.pointerId);
|
|
7310
7333
|
return;
|
|
7311
7334
|
}
|
|
@@ -7421,7 +7444,7 @@ var InputController = class {
|
|
|
7421
7444
|
this.deps.drawingsPointerUp?.(x, y, this.snapMode(e));
|
|
7422
7445
|
} else if (tapRelease && this.region === "data") {
|
|
7423
7446
|
this.deps.onClick(x, y);
|
|
7424
|
-
} else if (this.dragging && this.region === "data") {
|
|
7447
|
+
} else if (this.dragging && this.region === "data" && wasTouch) {
|
|
7425
7448
|
const stale = e.timeStamp - this.lastT > FLING_STALE_MS;
|
|
7426
7449
|
if (!stale && Math.abs(this.vx) > FLING_MIN_SPEED) {
|
|
7427
7450
|
const pitch = this.deps.getCoords().pxPerBar();
|
|
@@ -7627,6 +7650,7 @@ var InputController = class {
|
|
|
7627
7650
|
if (region === "price") this.deps.resetPriceScale(x, y);
|
|
7628
7651
|
else if (region === "separator") this.deps.resetPaneSize(y);
|
|
7629
7652
|
else if (region === "time") this.deps.resetView();
|
|
7653
|
+
else if (this.lastPressDrawing || this.prevPressDrawing) return;
|
|
7630
7654
|
else this.deps.dataDblClick(x, y);
|
|
7631
7655
|
}
|
|
7632
7656
|
};
|
|
@@ -9828,6 +9852,7 @@ function timeTicks(fromMs, toMs, target = 8, offsetMs = 0) {
|
|
|
9828
9852
|
const step = pickStep(span / Math.max(1, target));
|
|
9829
9853
|
const zFrom = fromMs + offsetMs;
|
|
9830
9854
|
const zTo = toMs + offsetMs;
|
|
9855
|
+
if (step >= MONTH) return calendarTicks(zFrom, zTo, step >= YEAR ? 12 : step >= 3 * MONTH ? 3 : 1, offsetMs);
|
|
9831
9856
|
const first = Math.ceil(zFrom / step) * step;
|
|
9832
9857
|
const out = [];
|
|
9833
9858
|
for (let zt = first; zt <= zTo; zt += step) {
|
|
@@ -9858,6 +9883,18 @@ function timeTicks(fromMs, toMs, target = 8, offsetMs = 0) {
|
|
|
9858
9883
|
}
|
|
9859
9884
|
return out;
|
|
9860
9885
|
}
|
|
9886
|
+
function calendarTicks(zFrom, zTo, months, offsetMs) {
|
|
9887
|
+
const d0 = new Date(zFrom);
|
|
9888
|
+
let idx = d0.getUTCFullYear() * 12 + d0.getUTCMonth();
|
|
9889
|
+
if (Date.UTC(Math.floor(idx / 12), idx % 12, 1) < zFrom) idx += 1;
|
|
9890
|
+
idx = Math.ceil(idx / months) * months;
|
|
9891
|
+
const out = [];
|
|
9892
|
+
for (let zt = Date.UTC(Math.floor(idx / 12), idx % 12, 1); zt <= zTo; idx += months, zt = Date.UTC(Math.floor(idx / 12), idx % 12, 1)) {
|
|
9893
|
+
const label = months === 12 ? String(Math.floor(idx / 12)) : MONTHS[idx % 12];
|
|
9894
|
+
out.push({ time: zt - offsetMs, label, major: true });
|
|
9895
|
+
}
|
|
9896
|
+
return out;
|
|
9897
|
+
}
|
|
9861
9898
|
|
|
9862
9899
|
// src/renderers/native/chrome/countdown.ts
|
|
9863
9900
|
function countdownText(barOpen, barMs, now2) {
|
|
@@ -13821,6 +13858,12 @@ var DrawingInteraction = class {
|
|
|
13821
13858
|
activeDragId() {
|
|
13822
13859
|
return this.state.kind === "pressed" && this.state.moved ? this.state.id : null;
|
|
13823
13860
|
}
|
|
13861
|
+
/** The store drawings a live drag is moving — the pressed one and its riders — or none
|
|
13862
|
+
* before the drag passes the slop. A Ctrl-drag moves copies, so its sources stay put. */
|
|
13863
|
+
movingIds() {
|
|
13864
|
+
if (this.state.kind !== "pressed" || !this.state.moved || this.state.clones) return /* @__PURE__ */ new Set();
|
|
13865
|
+
return /* @__PURE__ */ new Set([this.state.id, ...this.state.riders.map((r) => r.id)]);
|
|
13866
|
+
}
|
|
13824
13867
|
/** The drawing under a press that has not been released yet (drag or click undecided), or null. */
|
|
13825
13868
|
pressedId() {
|
|
13826
13869
|
return this.state.kind === "pressed" ? this.state.id : null;
|
|
@@ -14479,6 +14522,17 @@ var DrawingSettingsDialog = class {
|
|
|
14479
14522
|
}
|
|
14480
14523
|
}));
|
|
14481
14524
|
}
|
|
14525
|
+
if (drawing instanceof FibRetracement) {
|
|
14526
|
+
const fib = drawing;
|
|
14527
|
+
grid.appendChild(fieldRow({
|
|
14528
|
+
label: "Reverse",
|
|
14529
|
+
bool: true,
|
|
14530
|
+
toggle: {
|
|
14531
|
+
checked: fib.reverse,
|
|
14532
|
+
onChange: (v) => actions.patch({ reverse: v })
|
|
14533
|
+
}
|
|
14534
|
+
}));
|
|
14535
|
+
}
|
|
14482
14536
|
levels.forEach((lv, i) => {
|
|
14483
14537
|
const row = document.createElement("div");
|
|
14484
14538
|
row.className = "vela-field-span";
|
|
@@ -15632,6 +15686,8 @@ var UserDrawingController = class {
|
|
|
15632
15686
|
this.drawings = [];
|
|
15633
15687
|
/** Ids painted on an interleave layer this frame — the top canvas paints only their handles. */
|
|
15634
15688
|
this.sliced = /* @__PURE__ */ new Set();
|
|
15689
|
+
/** Interleaved drawings mid-drag: painted on the top canvas, left out of their slice. */
|
|
15690
|
+
this.lifted = /* @__PURE__ */ new Set();
|
|
15635
15691
|
/** Cached slice canvases, keyed `paneId|beforeZ`, reused across frames to avoid churn. */
|
|
15636
15692
|
this.sliceCache = /* @__PURE__ */ new Map();
|
|
15637
15693
|
/** Series boundaries per pane as of the last `prepareSlices` — lets a repaint between data
|
|
@@ -15719,7 +15775,7 @@ var UserDrawingController = class {
|
|
|
15719
15775
|
selectedIds: () => this.selectedIds,
|
|
15720
15776
|
emit: (i) => this.emit(i),
|
|
15721
15777
|
changed: () => {
|
|
15722
|
-
this.
|
|
15778
|
+
this.syncLift();
|
|
15723
15779
|
this.render();
|
|
15724
15780
|
},
|
|
15725
15781
|
openSettings: (id, x, y) => this.openSettingsById(id, x, y),
|
|
@@ -16345,6 +16401,20 @@ var UserDrawingController = class {
|
|
|
16345
16401
|
/** A drawing that paints inside the series stack changed (content, not hover): its pixels
|
|
16346
16402
|
* live in the backend composite, so this layer alone can't show the change — ask for a
|
|
16347
16403
|
* data frame, which re-runs `prepareSlices` before the backend composites. */
|
|
16404
|
+
/** A drawing being dragged leaves its interleave slice for the top canvas, so each pointer
|
|
16405
|
+
* move repaints one 2D layer instead of re-rasterizing and re-uploading a plot-sized slice
|
|
16406
|
+
* texture through the data frame. The slices rebuild once as the drag starts and once as it
|
|
16407
|
+
* ends (release, cancel), when the lifted set changes. */
|
|
16408
|
+
syncLift() {
|
|
16409
|
+
const moving = this.interaction.movingIds();
|
|
16410
|
+
let same = moving.size === this.lifted.size;
|
|
16411
|
+
if (same) {
|
|
16412
|
+
for (const id of moving) if (!this.lifted.has(id)) same = false;
|
|
16413
|
+
}
|
|
16414
|
+
if (same) return;
|
|
16415
|
+
this.lifted = new Set(moving);
|
|
16416
|
+
this.invalidateSlices();
|
|
16417
|
+
}
|
|
16348
16418
|
invalidateSlices() {
|
|
16349
16419
|
if (this.sliced.size > 0 || this.drawings.some((d) => this.isInterleaved(d))) this.deps.requestDataPaint();
|
|
16350
16420
|
}
|
|
@@ -16363,7 +16433,7 @@ var UserDrawingController = class {
|
|
|
16363
16433
|
const theme = this.deps.theme();
|
|
16364
16434
|
const buckets = /* @__PURE__ */ new Map();
|
|
16365
16435
|
for (const d of this.drawings) {
|
|
16366
|
-
if (!d.visible) continue;
|
|
16436
|
+
if (!d.visible || this.lifted.has(d.id)) continue;
|
|
16367
16437
|
const beforeZ = sliceKeyFor(d.zIndex, this.lastBounds.get(d.paneId) ?? []);
|
|
16368
16438
|
if (beforeZ === null) continue;
|
|
16369
16439
|
const key = `${d.paneId}|${beforeZ}`;
|
|
@@ -16415,8 +16485,9 @@ var UserDrawingController = class {
|
|
|
16415
16485
|
mutedLabel: edited instanceof TextLabel ? edited.id : null
|
|
16416
16486
|
};
|
|
16417
16487
|
this.painter.seriesLook = this.deps.seriesLook();
|
|
16418
|
-
|
|
16419
|
-
this.painter.
|
|
16488
|
+
const onTop = (d) => !this.isInterleaved(d) || this.lifted.has(d.id);
|
|
16489
|
+
this.painter.paintAll(ctx, this.drawings.filter(onTop), proj, this.deps.theme(), targets);
|
|
16490
|
+
this.painter.paintHighlights(ctx, this.drawings.filter((d) => !onTop(d)), proj, handleIdsFor(targets));
|
|
16420
16491
|
const clones = this.interaction.dragClones();
|
|
16421
16492
|
if (clones) this.painter.paintAll(ctx, clones, proj, this.deps.theme(), { selected: new Set(clones.map((c) => c.id)) });
|
|
16422
16493
|
this.layoutTextEditor();
|
|
@@ -17667,23 +17738,21 @@ function stackLayers(entries, candleZ) {
|
|
|
17667
17738
|
return { below, above };
|
|
17668
17739
|
}
|
|
17669
17740
|
|
|
17670
|
-
// src/renderers/native/chrome/
|
|
17671
|
-
var
|
|
17672
|
-
var
|
|
17741
|
+
// src/renderers/native/chrome/vela-logos.ts
|
|
17742
|
+
var VELA_MARK_SVG = '<svg viewBox="0 -142 161.66 148" aria-hidden="true"><g fill="currentColor"><path d="M0 -140L32.91 -140L77.52 -62.73L61.06 -34.24Z"/><path d="M161.66 -140L128.75 -140L84.14 -62.73L100.59 -34.24Z"/><path d="M80.83 -52.04L95.85 -26.02L80.83 0L65.81 -26.02Z"/></g></svg>';
|
|
17743
|
+
var VELA_LETTERS_SVG = '<svg viewBox="161.66 -142 310.57 148" aria-hidden="true"><g fill="currentColor"><path d="M226.3 1.17Q200.81 1.17 186.12 -12.99Q171.42 -27.15 171.42 -51.17Q171.42 -75.2 185.87 -89.6Q200.33 -104 224.25 -104Q247.4 -104 261.7 -90.58Q276.01 -77.15 276.3 -54.59Q276.3 -49.9 275.42 -45.02H200.81V-43.55Q201.2 -32.62 207.75 -26.42Q214.29 -20.21 225.03 -20.21Q233.72 -20.21 239.34 -23.93Q244.95 -27.64 246.81 -34.77H274.64Q272.1 -19.14 259.16 -8.98Q246.22 1.17 226.3 1.17ZM201.5 -63.38H247.88Q246.42 -72.75 240.27 -77.88Q234.12 -83.01 224.45 -83.01Q215.17 -83.01 208.92 -77.73Q202.67 -72.46 201.5 -63.38ZM287.54 0V-140.04H315.76V0ZM429.34 -23.83H432.56V0H418.11Q407.76 0 403.36 -4.44Q398.97 -8.89 399.16 -16.8Q387.83 1.17 365.57 1.17Q348.48 1.17 337.88 -6.74Q327.29 -14.65 327.29 -29Q327.29 -45.41 339.45 -54.3Q351.6 -63.18 374.55 -63.18H394.96V-68.16Q394.96 -75.2 390.08 -79.3Q385.2 -83.4 376.51 -83.4Q368.3 -83.4 363.03 -79.98Q357.76 -76.56 356.88 -70.8H329.73Q331.19 -85.84 344.08 -94.92Q356.97 -104 377.29 -104Q399.06 -104 410.88 -94.43Q422.7 -84.86 422.7 -66.6V-30.18Q422.7 -26.37 424.26 -25.1Q425.82 -23.83 429.34 -23.83ZM394.96 -42.38V-44.43H374.36Q365.47 -44.43 360.59 -40.92Q355.7 -37.4 355.7 -30.96Q355.7 -25.59 359.81 -22.41Q363.91 -19.24 370.94 -19.24Q381.97 -19.24 388.37 -25.54Q394.77 -31.84 394.96 -42.38Z"/><path fill-opacity="0.55" d="M437.44 -124.28H441.96V-113.41H445.34V-124.28H449.87V-127.4H437.44ZM451.43 -113.41H454.7V-123.29L458.97 -113.41H461.62L465.99 -123.29V-113.41H469.21V-127.4H464.53L460.42 -117.68L456.16 -127.4H451.43Z"/></g></svg>';
|
|
17673
17744
|
|
|
17674
17745
|
// src/renderers/native/chrome/AttributionMark.ts
|
|
17675
|
-
var ATTRIBUTION_URL = "https://
|
|
17746
|
+
var ATTRIBUTION_URL = "https://velacharts.dev/?utm_source=vela&utm_medium=attribution";
|
|
17676
17747
|
var STYLE_ID5 = "vela-attribution-styles";
|
|
17677
17748
|
var CSS = `
|
|
17678
17749
|
.vela-attribution {
|
|
17679
17750
|
text-decoration: none;
|
|
17680
17751
|
display: flex;
|
|
17681
17752
|
align-items: center;
|
|
17682
|
-
/*
|
|
17683
|
-
|
|
17684
|
-
|
|
17685
|
-
reads wrong because the symbol's ink hangs low and the wordmark descends. */
|
|
17686
|
-
gap: 4px;
|
|
17753
|
+
/* No gutter: the V is the wordmark's first letter, and the letters' viewBox starts
|
|
17754
|
+
where the V's ends, so the kit's own letter spacing comes with them. */
|
|
17755
|
+
gap: 0;
|
|
17687
17756
|
}
|
|
17688
17757
|
.vela-attribution .vela-attr-symbol {
|
|
17689
17758
|
flex: none;
|
|
@@ -17691,7 +17760,7 @@ var CSS = `
|
|
|
17691
17760
|
line-height: 0;
|
|
17692
17761
|
}
|
|
17693
17762
|
.vela-attribution .vela-attr-symbol svg {
|
|
17694
|
-
height:
|
|
17763
|
+
height: 24px;
|
|
17695
17764
|
width: auto;
|
|
17696
17765
|
display: block;
|
|
17697
17766
|
filter: drop-shadow(0 1px 2px var(--vela-attr-shadow, rgba(0,0,0,0.45)));
|
|
@@ -17702,15 +17771,13 @@ var CSS = `
|
|
|
17702
17771
|
opacity: 0;
|
|
17703
17772
|
display: flex;
|
|
17704
17773
|
align-items: center;
|
|
17705
|
-
/*
|
|
17706
|
-
position: relative;
|
|
17707
|
-
top: 3px;
|
|
17774
|
+
/* Same height and baseline as the V (one viewBox height), so no vertical offset. */
|
|
17708
17775
|
transform: translateX(-8px);
|
|
17709
17776
|
transition: max-width 0.3s ease, opacity 0.25s ease, transform 0.3s ease;
|
|
17710
17777
|
flex: none;
|
|
17711
17778
|
}
|
|
17712
17779
|
.vela-attribution .vela-attr-wordmark svg {
|
|
17713
|
-
height:
|
|
17780
|
+
height: 24px;
|
|
17714
17781
|
width: auto;
|
|
17715
17782
|
display: block;
|
|
17716
17783
|
filter: drop-shadow(0 1px 2px var(--vela-attr-shadow, rgba(0,0,0,0.45)));
|
|
@@ -17725,14 +17792,11 @@ var CSS = `
|
|
|
17725
17792
|
(data-layout): the workspace's single grid-wide mark lives OUTSIDE any renderer
|
|
17726
17793
|
container, so only the shell attribute reaches it. */
|
|
17727
17794
|
[data-vela-layout='mobile'] .vela-attribution .vela-attr-symbol svg,
|
|
17728
|
-
[data-layout='mobile'] .vela-attribution .vela-attr-symbol svg { height:
|
|
17795
|
+
[data-layout='mobile'] .vela-attribution .vela-attr-symbol svg { height: 20px; }
|
|
17729
17796
|
[data-vela-layout='mobile'] .vela-attribution .vela-attr-wordmark,
|
|
17730
|
-
[data-layout='mobile'] .vela-attribution .vela-attr-wordmark {
|
|
17731
|
-
top: 2px;
|
|
17732
|
-
transform: translateX(-6px);
|
|
17733
|
-
}
|
|
17797
|
+
[data-layout='mobile'] .vela-attribution .vela-attr-wordmark { transform: translateX(-6px); }
|
|
17734
17798
|
[data-vela-layout='mobile'] .vela-attribution .vela-attr-wordmark svg,
|
|
17735
|
-
[data-layout='mobile'] .vela-attribution .vela-attr-wordmark svg { height:
|
|
17799
|
+
[data-layout='mobile'] .vela-attribution .vela-attr-wordmark svg { height: 20px; }
|
|
17736
17800
|
[data-vela-layout='mobile'] .vela-attribution:hover .vela-attr-wordmark,
|
|
17737
17801
|
[data-layout='mobile'] .vela-attribution:hover .vela-attr-wordmark { transform: translateX(0); }
|
|
17738
17802
|
`;
|
|
@@ -17789,10 +17853,10 @@ function createAttributionMark(doc, background) {
|
|
|
17789
17853
|
const symbol = doc.createElement("span");
|
|
17790
17854
|
symbol.className = "vela-attr-symbol";
|
|
17791
17855
|
symbol.setAttribute("aria-hidden", "true");
|
|
17792
|
-
symbol.innerHTML =
|
|
17856
|
+
symbol.innerHTML = VELA_MARK_SVG;
|
|
17793
17857
|
const wordmark = doc.createElement("span");
|
|
17794
17858
|
wordmark.className = "vela-attr-wordmark";
|
|
17795
|
-
wordmark.innerHTML =
|
|
17859
|
+
wordmark.innerHTML = VELA_LETTERS_SVG;
|
|
17796
17860
|
a.append(symbol, wordmark);
|
|
17797
17861
|
return a;
|
|
17798
17862
|
}
|
|
@@ -21886,7 +21950,7 @@ var IndicatorHandleImpl = class {
|
|
|
21886
21950
|
this.controller.applyProps(this.id, values);
|
|
21887
21951
|
}
|
|
21888
21952
|
updateCode(source) {
|
|
21889
|
-
this.controller.updateCode(this.id, source);
|
|
21953
|
+
return this.controller.updateCode(this.id, source);
|
|
21890
21954
|
}
|
|
21891
21955
|
setVisible(visible) {
|
|
21892
21956
|
this.controller.setVisible(this.id, visible);
|
|
@@ -23701,20 +23765,26 @@ var EngineOrchestrator = class _EngineOrchestrator {
|
|
|
23701
23765
|
/**
|
|
23702
23766
|
* IndicatorController: replace a SCRIPT indicator's source in place (see
|
|
23703
23767
|
* {@link IndicatorHandle.updateCode}). Prepare-first: the running session keeps
|
|
23704
|
-
* computing until the new source has compiled
|
|
23705
|
-
*
|
|
23768
|
+
* computing until the new source has compiled; then the new code runs on TRIAL until
|
|
23769
|
+
* its first model lands, and a failure before that puts the previous code back.
|
|
23770
|
+
* Natives have no script — warn and leave them alone.
|
|
23706
23771
|
*/
|
|
23707
23772
|
updateCode(id, source) {
|
|
23708
23773
|
const record = this.registry.get(id);
|
|
23709
23774
|
const handle = this.handles.get(id);
|
|
23710
|
-
if (!record || !handle) return;
|
|
23775
|
+
if (!record || !handle) return Promise.resolve({ ok: false, error: new Error(`[vela] updateCode("${id}") \u2014 the indicator is no longer on the chart.`) });
|
|
23711
23776
|
if (record.native) {
|
|
23712
23777
|
console.warn(`[vela] updateCode("${id}") \u2014 a native indicator has no script to update.`);
|
|
23713
|
-
return;
|
|
23778
|
+
return Promise.resolve({ ok: false, error: new Error(`[vela] updateCode("${id}") \u2014 a native indicator has no script to update.`) });
|
|
23714
23779
|
}
|
|
23715
|
-
|
|
23716
|
-
record.
|
|
23717
|
-
|
|
23780
|
+
const busy = record.pendingSource !== void 0 || record.codeTrial !== void 0;
|
|
23781
|
+
if (!busy && source === record.source) return Promise.resolve({ ok: true, error: null });
|
|
23782
|
+
return new Promise((resolve) => {
|
|
23783
|
+
(record.codeWaiters ?? (record.codeWaiters = [])).push(resolve);
|
|
23784
|
+
if (record.pendingSource === source || record.pendingSource === void 0 && record.codeTrial && record.source === source) return;
|
|
23785
|
+
record.pendingSource = source;
|
|
23786
|
+
void this.swapSource(id, source, handle);
|
|
23787
|
+
});
|
|
23718
23788
|
}
|
|
23719
23789
|
async swapSource(id, source, handle) {
|
|
23720
23790
|
const engine = this.registry.get(id)?.engine ?? this.engineFor(this.registry.get(id)?.options?.language);
|
|
@@ -23725,26 +23795,41 @@ var EngineOrchestrator = class _EngineOrchestrator {
|
|
|
23725
23795
|
const record2 = this.registry.get(id);
|
|
23726
23796
|
if (record2?.pendingSource === source) {
|
|
23727
23797
|
record2.pendingSource = void 0;
|
|
23728
|
-
this.
|
|
23798
|
+
this.rejectCode(id, record2, handle, err);
|
|
23729
23799
|
}
|
|
23730
23800
|
return;
|
|
23731
23801
|
}
|
|
23732
23802
|
const record = this.registry.get(id);
|
|
23733
23803
|
if (!record || record.pendingSource !== source) return;
|
|
23734
23804
|
record.pendingSource = void 0;
|
|
23805
|
+
const previous = record.codeTrial?.previous ?? {
|
|
23806
|
+
source: record.source,
|
|
23807
|
+
engine: record.engine,
|
|
23808
|
+
prepared: record.prepared,
|
|
23809
|
+
inputValues: record.inputValues,
|
|
23810
|
+
propValues: record.propValues,
|
|
23811
|
+
inputs: [...handle.inputs],
|
|
23812
|
+
props: [...handle.props]
|
|
23813
|
+
};
|
|
23814
|
+
record.inputValues = valuesOnSchema(prepared.inputs, record.inputValues, record.prepared?.inputs);
|
|
23815
|
+
record.propValues = valuesOnSchema(prepared.props ?? [], record.propValues, record.prepared?.props);
|
|
23735
23816
|
record.source = source;
|
|
23736
23817
|
record.engine = engine;
|
|
23737
23818
|
record.prepared = prepared;
|
|
23738
23819
|
handle.setSource(source);
|
|
23739
|
-
record.inputValues = valuesOnSchema(prepared.inputs, record.inputValues);
|
|
23740
|
-
record.propValues = valuesOnSchema(prepared.props ?? [], record.propValues);
|
|
23741
23820
|
handle.setSchema(prepared.inputs);
|
|
23742
23821
|
handle.setPropsSchema(prepared.props ?? []);
|
|
23743
23822
|
record.session?.stop();
|
|
23744
23823
|
record.session = void 0;
|
|
23745
23824
|
record.pendingStructural = true;
|
|
23746
23825
|
record.pendingCause = "code";
|
|
23747
|
-
if (record.hidden)
|
|
23826
|
+
if (record.hidden) {
|
|
23827
|
+
record.codeTrial = void 0;
|
|
23828
|
+
if (record.renderHandle) this.renderer.setIndicatorInputs(record.renderHandle, record.inputValues, record.propValues);
|
|
23829
|
+
this.settleCode(record, { ok: true, error: null });
|
|
23830
|
+
return;
|
|
23831
|
+
}
|
|
23832
|
+
record.codeTrial = { previous };
|
|
23748
23833
|
if (record.renderHandle) {
|
|
23749
23834
|
this.renderer.setIndicatorInputs(record.renderHandle, record.inputValues, record.propValues);
|
|
23750
23835
|
this.setLoading(record, true);
|
|
@@ -23752,6 +23837,46 @@ var EngineOrchestrator = class _EngineOrchestrator {
|
|
|
23752
23837
|
this.mountLoadingPlaceholder(id, record);
|
|
23753
23838
|
}
|
|
23754
23839
|
this.executeIndicator(id, handle);
|
|
23840
|
+
if (this.bars.length === 0 && record.codeTrial) {
|
|
23841
|
+
record.codeTrial = void 0;
|
|
23842
|
+
this.settleCode(record, { ok: true, error: null });
|
|
23843
|
+
}
|
|
23844
|
+
}
|
|
23845
|
+
/** Resolve every `updateCode` caller waiting on this record's chain of edits. */
|
|
23846
|
+
settleCode(record, result) {
|
|
23847
|
+
const waiters = record.codeWaiters;
|
|
23848
|
+
record.codeWaiters = void 0;
|
|
23849
|
+
if (waiters) for (const resolve of waiters) resolve(result);
|
|
23850
|
+
}
|
|
23851
|
+
/**
|
|
23852
|
+
* An update failed — at prepare, or on trial before its first model. A trial puts the
|
|
23853
|
+
* previous code back (source, engine, prepared script, values, schema) and restarts it;
|
|
23854
|
+
* its visuals were never dropped, so the chart keeps painting throughout. Then the
|
|
23855
|
+
* failure reports the usual way and every waiting caller learns it.
|
|
23856
|
+
*/
|
|
23857
|
+
rejectCode(id, record, handle, err) {
|
|
23858
|
+
const trial = record.codeTrial;
|
|
23859
|
+
record.codeTrial = void 0;
|
|
23860
|
+
this.fail(id, handle, err);
|
|
23861
|
+
if (trial) {
|
|
23862
|
+
const p = trial.previous;
|
|
23863
|
+
record.session?.stop();
|
|
23864
|
+
record.session = void 0;
|
|
23865
|
+
record.source = p.source;
|
|
23866
|
+
record.engine = p.engine;
|
|
23867
|
+
record.prepared = p.prepared;
|
|
23868
|
+
record.inputValues = p.inputValues;
|
|
23869
|
+
record.propValues = p.propValues;
|
|
23870
|
+
handle.setSource(p.source);
|
|
23871
|
+
handle.setSchema(p.inputs);
|
|
23872
|
+
handle.setPropsSchema(p.props);
|
|
23873
|
+
record.pendingStructural = true;
|
|
23874
|
+
record.pendingCause = void 0;
|
|
23875
|
+
if (record.renderHandle) this.renderer.setIndicatorInputs(record.renderHandle, record.inputValues, record.propValues);
|
|
23876
|
+
if (!record.hidden) this.executeIndicator(id, handle);
|
|
23877
|
+
}
|
|
23878
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
23879
|
+
this.settleCode(record, { ok: false, error });
|
|
23755
23880
|
}
|
|
23756
23881
|
/** IndicatorController: tear down an indicator and (if now empty) its pane. */
|
|
23757
23882
|
/** Live handles of every indicator on the chart (script + native), insertion order. */
|
|
@@ -23766,6 +23891,7 @@ var EngineOrchestrator = class _EngineOrchestrator {
|
|
|
23766
23891
|
removeIndicator(id) {
|
|
23767
23892
|
const record = this.registry.remove(id);
|
|
23768
23893
|
if (record?.native?.type === "volume") this.volumeOptedOut = true;
|
|
23894
|
+
if (record) this.settleCode(record, { ok: false, error: new Error(`[vela] updateCode("${id}") \u2014 the indicator was removed.`) });
|
|
23769
23895
|
record?.session?.stop();
|
|
23770
23896
|
if (record?.native?.started) record.native.instance.stop();
|
|
23771
23897
|
this.handles.delete(id);
|
|
@@ -23793,6 +23919,10 @@ var EngineOrchestrator = class _EngineOrchestrator {
|
|
|
23793
23919
|
if (!visible) {
|
|
23794
23920
|
record.session?.stop();
|
|
23795
23921
|
record.session = void 0;
|
|
23922
|
+
if (record.codeTrial) {
|
|
23923
|
+
record.codeTrial = void 0;
|
|
23924
|
+
this.settleCode(record, { ok: true, error: null });
|
|
23925
|
+
}
|
|
23796
23926
|
if (record.native?.started) record.native.instance.suspend();
|
|
23797
23927
|
if (record.renderHandle) this.renderer.setIndicatorVisible?.(record.renderHandle, false);
|
|
23798
23928
|
else if (record.native) this.mountHiddenNativeRow(id, record);
|
|
@@ -23880,6 +24010,7 @@ var EngineOrchestrator = class _EngineOrchestrator {
|
|
|
23880
24010
|
this.viewportUnsub?.();
|
|
23881
24011
|
this.paneActionUnsub?.();
|
|
23882
24012
|
for (const record of this.registry.all()) {
|
|
24013
|
+
this.settleCode(record, { ok: false, error: new Error("[vela] updateCode \u2014 the chart was destroyed.") });
|
|
23883
24014
|
record.session?.stop();
|
|
23884
24015
|
if (record.native?.started) record.native.instance.stop();
|
|
23885
24016
|
}
|
|
@@ -23948,7 +24079,8 @@ var EngineOrchestrator = class _EngineOrchestrator {
|
|
|
23948
24079
|
const record = this.registry.get(id);
|
|
23949
24080
|
if (!record || !record.engine || !record.prepared || record.hidden) return;
|
|
23950
24081
|
const mode = this.config.live && !record.prepared.reactsToViewport && record.engine.capabilities.streaming ? "live" : "static";
|
|
23951
|
-
|
|
24082
|
+
const prepared = record.prepared;
|
|
24083
|
+
const session = record.engine.execute(
|
|
23952
24084
|
{
|
|
23953
24085
|
prepared: record.prepared,
|
|
23954
24086
|
market: this.market(),
|
|
@@ -23969,6 +24101,10 @@ var EngineOrchestrator = class _EngineOrchestrator {
|
|
|
23969
24101
|
const cause = record.pendingCause ?? "history";
|
|
23970
24102
|
if (!this.applyModel(id, model)) return;
|
|
23971
24103
|
record.pendingCause = void 0;
|
|
24104
|
+
if (record.codeTrial) {
|
|
24105
|
+
record.codeTrial = void 0;
|
|
24106
|
+
this.settleCode(record, { ok: true, error: null });
|
|
24107
|
+
}
|
|
23972
24108
|
this.emitContextChanged(id);
|
|
23973
24109
|
this.emitScriptRun(id, cause, first);
|
|
23974
24110
|
},
|
|
@@ -23979,9 +24115,17 @@ var EngineOrchestrator = class _EngineOrchestrator {
|
|
|
23979
24115
|
handle.emit("alert", { id: a.id, message: a.message, title: a.title, time: a.time });
|
|
23980
24116
|
},
|
|
23981
24117
|
onWarning: (w) => this.events.emit("warning", w),
|
|
23982
|
-
onError: (err) =>
|
|
24118
|
+
onError: (err) => {
|
|
24119
|
+
if (record.codeTrial) this.rejectCode(id, record, handle, err);
|
|
24120
|
+
else this.fail(id, handle, err);
|
|
24121
|
+
}
|
|
23983
24122
|
}
|
|
23984
24123
|
);
|
|
24124
|
+
if (record.prepared !== prepared) {
|
|
24125
|
+
session.stop();
|
|
24126
|
+
return;
|
|
24127
|
+
}
|
|
24128
|
+
record.session = session;
|
|
23985
24129
|
this.emitContextChanged(id);
|
|
23986
24130
|
}
|
|
23987
24131
|
/**
|
|
@@ -24482,7 +24626,7 @@ function yieldToPaint() {
|
|
|
24482
24626
|
}
|
|
24483
24627
|
return new Promise((resolve) => setTimeout(resolve, 0));
|
|
24484
24628
|
}
|
|
24485
|
-
function valuesOnSchema(schema, previous) {
|
|
24629
|
+
function valuesOnSchema(schema, previous, oldSchema = []) {
|
|
24486
24630
|
const out = {};
|
|
24487
24631
|
const declared = /* @__PURE__ */ new Set();
|
|
24488
24632
|
for (const s of schema) {
|
|
@@ -24490,9 +24634,22 @@ function valuesOnSchema(schema, previous) {
|
|
|
24490
24634
|
declared.add(s.key);
|
|
24491
24635
|
declared.add(s.title);
|
|
24492
24636
|
}
|
|
24493
|
-
|
|
24637
|
+
const oldDefaults = /* @__PURE__ */ new Map();
|
|
24638
|
+
for (const s of oldSchema) {
|
|
24639
|
+
oldDefaults.set(s.key, s.defval);
|
|
24640
|
+
if (!oldDefaults.has(s.title)) oldDefaults.set(s.title, s.defval);
|
|
24641
|
+
}
|
|
24642
|
+
for (const [k, v] of Object.entries(previous)) {
|
|
24643
|
+
if (!declared.has(k)) continue;
|
|
24644
|
+
if (oldDefaults.has(k) && sameInputValue(oldDefaults.get(k), v)) continue;
|
|
24645
|
+
out[k] = v;
|
|
24646
|
+
}
|
|
24494
24647
|
return out;
|
|
24495
24648
|
}
|
|
24649
|
+
function sameInputValue(a, b) {
|
|
24650
|
+
if (a === b) return true;
|
|
24651
|
+
return typeof a === "object" && a !== null && typeof b === "object" && b !== null && JSON.stringify(a) === JSON.stringify(b);
|
|
24652
|
+
}
|
|
24496
24653
|
function blankedModel(model) {
|
|
24497
24654
|
return {
|
|
24498
24655
|
...model,
|