@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
package/dist/index.cjs
CHANGED
|
@@ -238,7 +238,7 @@ var IndicatorHandleImpl = class {
|
|
|
238
238
|
this.controller.applyProps(this.id, values);
|
|
239
239
|
}
|
|
240
240
|
updateCode(source) {
|
|
241
|
-
this.controller.updateCode(this.id, source);
|
|
241
|
+
return this.controller.updateCode(this.id, source);
|
|
242
242
|
}
|
|
243
243
|
setVisible(visible) {
|
|
244
244
|
this.controller.setVisible(this.id, visible);
|
|
@@ -641,6 +641,7 @@ registerIcon("expand", S('<rect x="2.2" y="2.2" width="11.6" height="11.6" rx="1
|
|
|
641
641
|
registerIcon("plus", S('<path d="M8 2.8v10.4M2.8 8h10.4"/>'));
|
|
642
642
|
registerIcon("minus", S('<path d="M2.8 8h10.4"/>'));
|
|
643
643
|
registerIcon("maximize", S('<path d="M2.5 6V3a.5.5 0 0 1 .5-.5h3M10 2.5h3a.5.5 0 0 1 .5.5v3M13.5 10v3a.5.5 0 0 1-.5.5h-3M6 13.5H3a.5.5 0 0 1-.5-.5v-3"/>'));
|
|
644
|
+
registerIcon("restore", S('<path d="M6 2.5v3a.5.5 0 0 1-.5.5h-3M13.5 6h-3a.5.5 0 0 1-.5-.5v-3M10 13.5v-3a.5.5 0 0 1 .5-.5h3M2.5 10h3a.5.5 0 0 1 .5.5v3"/>'));
|
|
644
645
|
registerIcon("restore", S('<path d="M6.2 2.5v3.7H2.5M9.8 13.5V9.8h3.7M13.5 6.2H9.8V2.5M2.5 9.8h3.7v3.7"/>'));
|
|
645
646
|
registerIcon("star", S('<path d="M8 2.2l1.75 3.55 3.9.55-2.8 2.75.65 3.9L8 11.1l-3.5 1.85.65-3.9-2.8-2.75 3.9-.55z"/>'));
|
|
646
647
|
registerIcon("star-filled", S('<path d="M8 2.2l1.75 3.55 3.9.55-2.8 2.75.65 3.9L8 11.1l-3.5 1.85.65-3.9-2.8-2.75 3.9-.55z"/>', 'fill="currentColor"'));
|
|
@@ -3299,6 +3300,10 @@ var FibRatios = class extends Drawing {
|
|
|
3299
3300
|
|
|
3300
3301
|
// src/core/drawings/types/FibLevels.ts
|
|
3301
3302
|
var FibLevels = class extends FibRatios {
|
|
3303
|
+
/** Price of a level for the two anchor prices; subclasses override to change which anchor ratio 0 sits on. */
|
|
3304
|
+
levelPrice(ratio, p1, p2) {
|
|
3305
|
+
return p1 + ratio * (p2 - p1);
|
|
3306
|
+
}
|
|
3302
3307
|
/** Per-level pixel line + price for the ENABLED levels, spanning the anchors' time range. */
|
|
3303
3308
|
levelLines(proj) {
|
|
3304
3309
|
const a = this.anchors[0];
|
|
@@ -3308,11 +3313,10 @@ var FibLevels = class extends FibRatios {
|
|
|
3308
3313
|
const xb = proj.xOf(b.time);
|
|
3309
3314
|
const x1 = Math.min(xa, xb);
|
|
3310
3315
|
const x2 = Math.max(xa, xb);
|
|
3311
|
-
const delta = b.price - a.price;
|
|
3312
3316
|
const out = [];
|
|
3313
3317
|
for (const lv of this.levels) {
|
|
3314
3318
|
if (!lv.enabled) continue;
|
|
3315
|
-
const price =
|
|
3319
|
+
const price = this.levelPrice(lv.ratio, a.price, b.price);
|
|
3316
3320
|
const y = proj.yOf(price, this.paneId);
|
|
3317
3321
|
if (y == null) continue;
|
|
3318
3322
|
out.push({ ratio: lv.ratio, color: lv.color, label: lv.label, price, x1, x2, y });
|
|
@@ -3352,8 +3356,7 @@ var FibLevels = class extends FibRatios {
|
|
|
3352
3356
|
const a = this.anchors[0];
|
|
3353
3357
|
const b = this.anchors[1];
|
|
3354
3358
|
if (!a || !b) return null;
|
|
3355
|
-
const
|
|
3356
|
-
const prices = this.levels.filter((l) => l.enabled).map((l) => a.price + l.ratio * delta);
|
|
3359
|
+
const prices = this.levels.filter((l) => l.enabled).map((l) => this.levelPrice(l.ratio, a.price, b.price));
|
|
3357
3360
|
if (prices.length === 0) return null;
|
|
3358
3361
|
return { min: Math.min(...prices), max: Math.max(...prices) };
|
|
3359
3362
|
}
|
|
@@ -3439,13 +3442,24 @@ function cycleLevels(count, enabledCount = count) {
|
|
|
3439
3442
|
// src/core/drawings/types/FibRetracement.ts
|
|
3440
3443
|
var LEVELS = fibLevels([0, 0.236, 0.382, 0.5, 0.618, 0.786, 1]);
|
|
3441
3444
|
var FibRetracement = class extends FibLevels {
|
|
3442
|
-
constructor() {
|
|
3443
|
-
super(
|
|
3445
|
+
constructor(init) {
|
|
3446
|
+
super(init);
|
|
3444
3447
|
this.type = "fibretracement";
|
|
3448
|
+
if (this.reverse === void 0) this.reverse = false;
|
|
3445
3449
|
}
|
|
3446
3450
|
defaultLevels() {
|
|
3447
3451
|
return LEVELS;
|
|
3448
3452
|
}
|
|
3453
|
+
levelPrice(ratio, p1, p2) {
|
|
3454
|
+
return this.reverse ? p1 + ratio * (p2 - p1) : p2 + ratio * (p1 - p2);
|
|
3455
|
+
}
|
|
3456
|
+
writeProps() {
|
|
3457
|
+
return { ...super.writeProps(), reverse: this.reverse };
|
|
3458
|
+
}
|
|
3459
|
+
readProps(props) {
|
|
3460
|
+
super.readProps(props);
|
|
3461
|
+
this.reverse = typeof props.reverse === "boolean" ? props.reverse : true;
|
|
3462
|
+
}
|
|
3449
3463
|
};
|
|
3450
3464
|
|
|
3451
3465
|
// src/core/drawings/types/FibExtension.ts
|
|
@@ -9258,20 +9272,26 @@ var EngineOrchestrator = class _EngineOrchestrator {
|
|
|
9258
9272
|
/**
|
|
9259
9273
|
* IndicatorController: replace a SCRIPT indicator's source in place (see
|
|
9260
9274
|
* {@link IndicatorHandle.updateCode}). Prepare-first: the running session keeps
|
|
9261
|
-
* computing until the new source has compiled
|
|
9262
|
-
*
|
|
9275
|
+
* computing until the new source has compiled; then the new code runs on TRIAL until
|
|
9276
|
+
* its first model lands, and a failure before that puts the previous code back.
|
|
9277
|
+
* Natives have no script — warn and leave them alone.
|
|
9263
9278
|
*/
|
|
9264
9279
|
updateCode(id, source) {
|
|
9265
9280
|
const record = this.registry.get(id);
|
|
9266
9281
|
const handle = this.handles.get(id);
|
|
9267
|
-
if (!record || !handle) return;
|
|
9282
|
+
if (!record || !handle) return Promise.resolve({ ok: false, error: new Error(`[vela] updateCode("${id}") \u2014 the indicator is no longer on the chart.`) });
|
|
9268
9283
|
if (record.native) {
|
|
9269
9284
|
console.warn(`[vela] updateCode("${id}") \u2014 a native indicator has no script to update.`);
|
|
9270
|
-
return;
|
|
9285
|
+
return Promise.resolve({ ok: false, error: new Error(`[vela] updateCode("${id}") \u2014 a native indicator has no script to update.`) });
|
|
9271
9286
|
}
|
|
9272
|
-
|
|
9273
|
-
record.
|
|
9274
|
-
|
|
9287
|
+
const busy = record.pendingSource !== void 0 || record.codeTrial !== void 0;
|
|
9288
|
+
if (!busy && source === record.source) return Promise.resolve({ ok: true, error: null });
|
|
9289
|
+
return new Promise((resolve) => {
|
|
9290
|
+
(record.codeWaiters ?? (record.codeWaiters = [])).push(resolve);
|
|
9291
|
+
if (record.pendingSource === source || record.pendingSource === void 0 && record.codeTrial && record.source === source) return;
|
|
9292
|
+
record.pendingSource = source;
|
|
9293
|
+
void this.swapSource(id, source, handle);
|
|
9294
|
+
});
|
|
9275
9295
|
}
|
|
9276
9296
|
async swapSource(id, source, handle) {
|
|
9277
9297
|
const engine = this.registry.get(id)?.engine ?? this.engineFor(this.registry.get(id)?.options?.language);
|
|
@@ -9282,26 +9302,41 @@ var EngineOrchestrator = class _EngineOrchestrator {
|
|
|
9282
9302
|
const record2 = this.registry.get(id);
|
|
9283
9303
|
if (record2?.pendingSource === source) {
|
|
9284
9304
|
record2.pendingSource = void 0;
|
|
9285
|
-
this.
|
|
9305
|
+
this.rejectCode(id, record2, handle, err);
|
|
9286
9306
|
}
|
|
9287
9307
|
return;
|
|
9288
9308
|
}
|
|
9289
9309
|
const record = this.registry.get(id);
|
|
9290
9310
|
if (!record || record.pendingSource !== source) return;
|
|
9291
9311
|
record.pendingSource = void 0;
|
|
9312
|
+
const previous = record.codeTrial?.previous ?? {
|
|
9313
|
+
source: record.source,
|
|
9314
|
+
engine: record.engine,
|
|
9315
|
+
prepared: record.prepared,
|
|
9316
|
+
inputValues: record.inputValues,
|
|
9317
|
+
propValues: record.propValues,
|
|
9318
|
+
inputs: [...handle.inputs],
|
|
9319
|
+
props: [...handle.props]
|
|
9320
|
+
};
|
|
9321
|
+
record.inputValues = valuesOnSchema(prepared.inputs, record.inputValues, record.prepared?.inputs);
|
|
9322
|
+
record.propValues = valuesOnSchema(prepared.props ?? [], record.propValues, record.prepared?.props);
|
|
9292
9323
|
record.source = source;
|
|
9293
9324
|
record.engine = engine;
|
|
9294
9325
|
record.prepared = prepared;
|
|
9295
9326
|
handle.setSource(source);
|
|
9296
|
-
record.inputValues = valuesOnSchema(prepared.inputs, record.inputValues);
|
|
9297
|
-
record.propValues = valuesOnSchema(prepared.props ?? [], record.propValues);
|
|
9298
9327
|
handle.setSchema(prepared.inputs);
|
|
9299
9328
|
handle.setPropsSchema(prepared.props ?? []);
|
|
9300
9329
|
record.session?.stop();
|
|
9301
9330
|
record.session = void 0;
|
|
9302
9331
|
record.pendingStructural = true;
|
|
9303
9332
|
record.pendingCause = "code";
|
|
9304
|
-
if (record.hidden)
|
|
9333
|
+
if (record.hidden) {
|
|
9334
|
+
record.codeTrial = void 0;
|
|
9335
|
+
if (record.renderHandle) this.renderer.setIndicatorInputs(record.renderHandle, record.inputValues, record.propValues);
|
|
9336
|
+
this.settleCode(record, { ok: true, error: null });
|
|
9337
|
+
return;
|
|
9338
|
+
}
|
|
9339
|
+
record.codeTrial = { previous };
|
|
9305
9340
|
if (record.renderHandle) {
|
|
9306
9341
|
this.renderer.setIndicatorInputs(record.renderHandle, record.inputValues, record.propValues);
|
|
9307
9342
|
this.setLoading(record, true);
|
|
@@ -9309,6 +9344,46 @@ var EngineOrchestrator = class _EngineOrchestrator {
|
|
|
9309
9344
|
this.mountLoadingPlaceholder(id, record);
|
|
9310
9345
|
}
|
|
9311
9346
|
this.executeIndicator(id, handle);
|
|
9347
|
+
if (this.bars.length === 0 && record.codeTrial) {
|
|
9348
|
+
record.codeTrial = void 0;
|
|
9349
|
+
this.settleCode(record, { ok: true, error: null });
|
|
9350
|
+
}
|
|
9351
|
+
}
|
|
9352
|
+
/** Resolve every `updateCode` caller waiting on this record's chain of edits. */
|
|
9353
|
+
settleCode(record, result) {
|
|
9354
|
+
const waiters = record.codeWaiters;
|
|
9355
|
+
record.codeWaiters = void 0;
|
|
9356
|
+
if (waiters) for (const resolve of waiters) resolve(result);
|
|
9357
|
+
}
|
|
9358
|
+
/**
|
|
9359
|
+
* An update failed — at prepare, or on trial before its first model. A trial puts the
|
|
9360
|
+
* previous code back (source, engine, prepared script, values, schema) and restarts it;
|
|
9361
|
+
* its visuals were never dropped, so the chart keeps painting throughout. Then the
|
|
9362
|
+
* failure reports the usual way and every waiting caller learns it.
|
|
9363
|
+
*/
|
|
9364
|
+
rejectCode(id, record, handle, err) {
|
|
9365
|
+
const trial = record.codeTrial;
|
|
9366
|
+
record.codeTrial = void 0;
|
|
9367
|
+
this.fail(id, handle, err);
|
|
9368
|
+
if (trial) {
|
|
9369
|
+
const p = trial.previous;
|
|
9370
|
+
record.session?.stop();
|
|
9371
|
+
record.session = void 0;
|
|
9372
|
+
record.source = p.source;
|
|
9373
|
+
record.engine = p.engine;
|
|
9374
|
+
record.prepared = p.prepared;
|
|
9375
|
+
record.inputValues = p.inputValues;
|
|
9376
|
+
record.propValues = p.propValues;
|
|
9377
|
+
handle.setSource(p.source);
|
|
9378
|
+
handle.setSchema(p.inputs);
|
|
9379
|
+
handle.setPropsSchema(p.props);
|
|
9380
|
+
record.pendingStructural = true;
|
|
9381
|
+
record.pendingCause = void 0;
|
|
9382
|
+
if (record.renderHandle) this.renderer.setIndicatorInputs(record.renderHandle, record.inputValues, record.propValues);
|
|
9383
|
+
if (!record.hidden) this.executeIndicator(id, handle);
|
|
9384
|
+
}
|
|
9385
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
9386
|
+
this.settleCode(record, { ok: false, error });
|
|
9312
9387
|
}
|
|
9313
9388
|
/** IndicatorController: tear down an indicator and (if now empty) its pane. */
|
|
9314
9389
|
/** Live handles of every indicator on the chart (script + native), insertion order. */
|
|
@@ -9323,6 +9398,7 @@ var EngineOrchestrator = class _EngineOrchestrator {
|
|
|
9323
9398
|
removeIndicator(id) {
|
|
9324
9399
|
const record = this.registry.remove(id);
|
|
9325
9400
|
if (record?.native?.type === "volume") this.volumeOptedOut = true;
|
|
9401
|
+
if (record) this.settleCode(record, { ok: false, error: new Error(`[vela] updateCode("${id}") \u2014 the indicator was removed.`) });
|
|
9326
9402
|
record?.session?.stop();
|
|
9327
9403
|
if (record?.native?.started) record.native.instance.stop();
|
|
9328
9404
|
this.handles.delete(id);
|
|
@@ -9350,6 +9426,10 @@ var EngineOrchestrator = class _EngineOrchestrator {
|
|
|
9350
9426
|
if (!visible) {
|
|
9351
9427
|
record.session?.stop();
|
|
9352
9428
|
record.session = void 0;
|
|
9429
|
+
if (record.codeTrial) {
|
|
9430
|
+
record.codeTrial = void 0;
|
|
9431
|
+
this.settleCode(record, { ok: true, error: null });
|
|
9432
|
+
}
|
|
9353
9433
|
if (record.native?.started) record.native.instance.suspend();
|
|
9354
9434
|
if (record.renderHandle) this.renderer.setIndicatorVisible?.(record.renderHandle, false);
|
|
9355
9435
|
else if (record.native) this.mountHiddenNativeRow(id, record);
|
|
@@ -9437,6 +9517,7 @@ var EngineOrchestrator = class _EngineOrchestrator {
|
|
|
9437
9517
|
this.viewportUnsub?.();
|
|
9438
9518
|
this.paneActionUnsub?.();
|
|
9439
9519
|
for (const record of this.registry.all()) {
|
|
9520
|
+
this.settleCode(record, { ok: false, error: new Error("[vela] updateCode \u2014 the chart was destroyed.") });
|
|
9440
9521
|
record.session?.stop();
|
|
9441
9522
|
if (record.native?.started) record.native.instance.stop();
|
|
9442
9523
|
}
|
|
@@ -9505,7 +9586,8 @@ var EngineOrchestrator = class _EngineOrchestrator {
|
|
|
9505
9586
|
const record = this.registry.get(id);
|
|
9506
9587
|
if (!record || !record.engine || !record.prepared || record.hidden) return;
|
|
9507
9588
|
const mode = this.config.live && !record.prepared.reactsToViewport && record.engine.capabilities.streaming ? "live" : "static";
|
|
9508
|
-
|
|
9589
|
+
const prepared = record.prepared;
|
|
9590
|
+
const session = record.engine.execute(
|
|
9509
9591
|
{
|
|
9510
9592
|
prepared: record.prepared,
|
|
9511
9593
|
market: this.market(),
|
|
@@ -9526,6 +9608,10 @@ var EngineOrchestrator = class _EngineOrchestrator {
|
|
|
9526
9608
|
const cause = record.pendingCause ?? "history";
|
|
9527
9609
|
if (!this.applyModel(id, model)) return;
|
|
9528
9610
|
record.pendingCause = void 0;
|
|
9611
|
+
if (record.codeTrial) {
|
|
9612
|
+
record.codeTrial = void 0;
|
|
9613
|
+
this.settleCode(record, { ok: true, error: null });
|
|
9614
|
+
}
|
|
9529
9615
|
this.emitContextChanged(id);
|
|
9530
9616
|
this.emitScriptRun(id, cause, first);
|
|
9531
9617
|
},
|
|
@@ -9536,9 +9622,17 @@ var EngineOrchestrator = class _EngineOrchestrator {
|
|
|
9536
9622
|
handle.emit("alert", { id: a.id, message: a.message, title: a.title, time: a.time });
|
|
9537
9623
|
},
|
|
9538
9624
|
onWarning: (w) => this.events.emit("warning", w),
|
|
9539
|
-
onError: (err) =>
|
|
9625
|
+
onError: (err) => {
|
|
9626
|
+
if (record.codeTrial) this.rejectCode(id, record, handle, err);
|
|
9627
|
+
else this.fail(id, handle, err);
|
|
9628
|
+
}
|
|
9540
9629
|
}
|
|
9541
9630
|
);
|
|
9631
|
+
if (record.prepared !== prepared) {
|
|
9632
|
+
session.stop();
|
|
9633
|
+
return;
|
|
9634
|
+
}
|
|
9635
|
+
record.session = session;
|
|
9542
9636
|
this.emitContextChanged(id);
|
|
9543
9637
|
}
|
|
9544
9638
|
/**
|
|
@@ -10039,7 +10133,7 @@ function yieldToPaint() {
|
|
|
10039
10133
|
}
|
|
10040
10134
|
return new Promise((resolve) => setTimeout(resolve, 0));
|
|
10041
10135
|
}
|
|
10042
|
-
function valuesOnSchema(schema, previous) {
|
|
10136
|
+
function valuesOnSchema(schema, previous, oldSchema = []) {
|
|
10043
10137
|
const out = {};
|
|
10044
10138
|
const declared = /* @__PURE__ */ new Set();
|
|
10045
10139
|
for (const s of schema) {
|
|
@@ -10047,9 +10141,22 @@ function valuesOnSchema(schema, previous) {
|
|
|
10047
10141
|
declared.add(s.key);
|
|
10048
10142
|
declared.add(s.title);
|
|
10049
10143
|
}
|
|
10050
|
-
|
|
10144
|
+
const oldDefaults = /* @__PURE__ */ new Map();
|
|
10145
|
+
for (const s of oldSchema) {
|
|
10146
|
+
oldDefaults.set(s.key, s.defval);
|
|
10147
|
+
if (!oldDefaults.has(s.title)) oldDefaults.set(s.title, s.defval);
|
|
10148
|
+
}
|
|
10149
|
+
for (const [k, v] of Object.entries(previous)) {
|
|
10150
|
+
if (!declared.has(k)) continue;
|
|
10151
|
+
if (oldDefaults.has(k) && sameInputValue(oldDefaults.get(k), v)) continue;
|
|
10152
|
+
out[k] = v;
|
|
10153
|
+
}
|
|
10051
10154
|
return out;
|
|
10052
10155
|
}
|
|
10156
|
+
function sameInputValue(a, b) {
|
|
10157
|
+
if (a === b) return true;
|
|
10158
|
+
return typeof a === "object" && a !== null && typeof b === "object" && b !== null && JSON.stringify(a) === JSON.stringify(b);
|
|
10159
|
+
}
|
|
10053
10160
|
function blankedModel(model) {
|
|
10054
10161
|
return {
|
|
10055
10162
|
...model,
|
|
@@ -11693,6 +11800,17 @@ function iconEl(id, doc = document) {
|
|
|
11693
11800
|
if (svg) span.innerHTML = svg;
|
|
11694
11801
|
return span;
|
|
11695
11802
|
}
|
|
11803
|
+
|
|
11804
|
+
// src/ui/surface-events.ts
|
|
11805
|
+
var SURFACE_OPEN_EVENT = "vela:surface-open";
|
|
11806
|
+
var SURFACE_CLOSE_EVENT = "vela:surface-close";
|
|
11807
|
+
function announceSurface(el, open2, kind, trigger = null) {
|
|
11808
|
+
const View = el.ownerDocument.defaultView;
|
|
11809
|
+
if (!View) return;
|
|
11810
|
+
el.dispatchEvent(
|
|
11811
|
+
new View.CustomEvent(open2 ? SURFACE_OPEN_EVENT : SURFACE_CLOSE_EVENT, { bubbles: true, composed: true, detail: { kind, trigger } })
|
|
11812
|
+
);
|
|
11813
|
+
}
|
|
11696
11814
|
function menuController(opts) {
|
|
11697
11815
|
return {
|
|
11698
11816
|
machine: menu__namespace.machine,
|
|
@@ -11838,6 +11956,8 @@ var Surface = class _Surface {
|
|
|
11838
11956
|
/** Trigger rect captured when this level opened — the list stays put if the
|
|
11839
11957
|
* trigger then moves (favorite chips shifting the caret). */
|
|
11840
11958
|
this.pinnedAnchor = null;
|
|
11959
|
+
/** The open state last announced — see {@link announce}. */
|
|
11960
|
+
this.shown = false;
|
|
11841
11961
|
this.doc = doc;
|
|
11842
11962
|
this.host = opts.host;
|
|
11843
11963
|
this.onSelect = opts.onSelect;
|
|
@@ -11851,6 +11971,7 @@ var Surface = class _Surface {
|
|
|
11851
11971
|
this.positioner.appendChild(this.list);
|
|
11852
11972
|
this.host.appendChild(this.positioner);
|
|
11853
11973
|
const trigger = opts.trigger;
|
|
11974
|
+
this.opener = trigger ?? opts.opener ?? null;
|
|
11854
11975
|
this.ctrl = menuController({
|
|
11855
11976
|
items: [],
|
|
11856
11977
|
id: opts.id,
|
|
@@ -11872,15 +11993,21 @@ var Surface = class _Surface {
|
|
|
11872
11993
|
if (opts.triggerId && trigger) trigger.id = opts.triggerId;
|
|
11873
11994
|
this.handle = runMachine(this.ctrl.machine, this.ctrl.props, (service) => {
|
|
11874
11995
|
const api = this.ctrl.connect(service);
|
|
11996
|
+
if (this.shown && !api.open) this.announce(false);
|
|
11875
11997
|
if (trigger) vanilla.spreadProps(trigger, api.getTriggerProps(), this.mid);
|
|
11876
11998
|
vanilla.spreadProps(this.positioner, api.getPositionerProps(), this.mid);
|
|
11877
11999
|
vanilla.spreadProps(this.list, api.getContentProps(), this.mid);
|
|
11878
12000
|
this.project(api);
|
|
12001
|
+
if (api.open && !this.shown) this.announce(true);
|
|
11879
12002
|
});
|
|
11880
12003
|
}
|
|
11881
12004
|
get api() {
|
|
11882
12005
|
return this.ctrl.connect(this.handle.service);
|
|
11883
12006
|
}
|
|
12007
|
+
announce(open2) {
|
|
12008
|
+
this.shown = open2;
|
|
12009
|
+
announceSurface(this.list, open2, "menu", this.opener);
|
|
12010
|
+
}
|
|
11884
12011
|
setItems(items) {
|
|
11885
12012
|
this.items = items;
|
|
11886
12013
|
for (const sub2 of this.subs.values()) sub2.destroy();
|
|
@@ -11898,6 +12025,7 @@ var Surface = class _Surface {
|
|
|
11898
12025
|
for (const sub2 of this.subs.values()) sub2.destroy();
|
|
11899
12026
|
this.subs.clear();
|
|
11900
12027
|
this.handle.stop();
|
|
12028
|
+
if (this.shown) this.announce(false);
|
|
11901
12029
|
this.positioner.remove();
|
|
11902
12030
|
}
|
|
11903
12031
|
byId(id) {
|
|
@@ -11991,6 +12119,7 @@ var Surface = class _Surface {
|
|
|
11991
12119
|
const sub2 = new _Surface(doc, {
|
|
11992
12120
|
host: this.host,
|
|
11993
12121
|
placement: "right-start",
|
|
12122
|
+
opener: li,
|
|
11994
12123
|
onSelect: this.onSelect,
|
|
11995
12124
|
onFavorite: this.onFavorite,
|
|
11996
12125
|
checkmarks: this.checkmarks,
|
|
@@ -12210,16 +12339,21 @@ var Popover = class {
|
|
|
12210
12339
|
this.hide();
|
|
12211
12340
|
};
|
|
12212
12341
|
const onReflow = () => this.place();
|
|
12213
|
-
setTimeout(() =>
|
|
12342
|
+
setTimeout(() => {
|
|
12343
|
+
if (this.onOutside === onOutside) document.addEventListener("pointerdown", onOutside, true);
|
|
12344
|
+
}, 0);
|
|
12214
12345
|
document.addEventListener("keydown", onKey, true);
|
|
12215
12346
|
window.addEventListener("resize", onReflow, true);
|
|
12216
12347
|
document.addEventListener("scroll", onReflow, true);
|
|
12217
12348
|
this.onOutside = onOutside;
|
|
12218
12349
|
this.onKey = onKey;
|
|
12219
12350
|
this.onReflow = onReflow;
|
|
12351
|
+
announceSurface(this.el, true, "popover", this.trigger);
|
|
12220
12352
|
}
|
|
12221
12353
|
hide() {
|
|
12222
12354
|
if (!this.shown) return;
|
|
12355
|
+
this.shown = false;
|
|
12356
|
+
announceSurface(this.el, false, "popover", this.trigger);
|
|
12223
12357
|
if (this.onOutside) document.removeEventListener("pointerdown", this.onOutside, true);
|
|
12224
12358
|
if (this.onKey) document.removeEventListener("keydown", this.onKey, true);
|
|
12225
12359
|
if (this.onReflow) {
|
|
@@ -12239,7 +12373,6 @@ var Popover = class {
|
|
|
12239
12373
|
} else {
|
|
12240
12374
|
this.el.remove();
|
|
12241
12375
|
}
|
|
12242
|
-
this.shown = false;
|
|
12243
12376
|
if (open === this) open = null;
|
|
12244
12377
|
this.ctrl.onClose?.();
|
|
12245
12378
|
}
|
|
@@ -12940,6 +13073,8 @@ ${overlayScrollbarCss(".vela-dialog *")}
|
|
|
12940
13073
|
`;
|
|
12941
13074
|
var Dialog = class {
|
|
12942
13075
|
constructor(opts = {}) {
|
|
13076
|
+
this.opener = null;
|
|
13077
|
+
this.wasOpen = false;
|
|
12943
13078
|
const doc = (opts.host ?? document.body).ownerDocument;
|
|
12944
13079
|
injectStyles(DIALOG_STYLE_ID, DIALOG_CSS, doc);
|
|
12945
13080
|
const host = opts.host ?? doc.body;
|
|
@@ -13036,6 +13171,7 @@ var Dialog = class {
|
|
|
13036
13171
|
const mid = String(this.ctrl.props.id);
|
|
13037
13172
|
this.handle = runMachine(this.ctrl.machine, this.ctrl.props, (service) => {
|
|
13038
13173
|
const api = this.ctrl.connect(service);
|
|
13174
|
+
if (this.wasOpen && !api.open) this.announce(false);
|
|
13039
13175
|
vanilla.spreadProps(this.backdrop, api.getBackdropProps(), mid);
|
|
13040
13176
|
vanilla.spreadProps(this.positioner, api.getPositionerProps(), mid);
|
|
13041
13177
|
vanilla.spreadProps(this.panel, api.getContentProps(), mid);
|
|
@@ -13043,12 +13179,27 @@ var Dialog = class {
|
|
|
13043
13179
|
vanilla.spreadProps(close, api.getCloseTriggerProps(), mid);
|
|
13044
13180
|
this.backdrop.style.display = api.open ? "" : "none";
|
|
13045
13181
|
this.positioner.style.display = api.open ? "" : "none";
|
|
13182
|
+
if (api.open && !this.wasOpen) this.announce(true);
|
|
13183
|
+
if (this.wasOpen && !api.open) this.restoreOpener();
|
|
13184
|
+
this.wasOpen = api.open;
|
|
13046
13185
|
});
|
|
13047
13186
|
}
|
|
13187
|
+
/** Closing hands focus back to whatever opened it (Escape, the ✕, hide(), or a
|
|
13188
|
+
* teardown that outruns the machine's close notification). */
|
|
13189
|
+
restoreOpener() {
|
|
13190
|
+
const opener = this.opener;
|
|
13191
|
+
this.opener = null;
|
|
13192
|
+
if (opener?.isConnected) opener.focus({ preventScroll: true });
|
|
13193
|
+
}
|
|
13194
|
+
announce(open2) {
|
|
13195
|
+
const opener = this.opener === this.panel.ownerDocument.body ? null : this.opener;
|
|
13196
|
+
announceSurface(this.panel, open2, "dialog", opener);
|
|
13197
|
+
}
|
|
13048
13198
|
get open() {
|
|
13049
13199
|
return this.ctrl.connect(this.handle.service).open;
|
|
13050
13200
|
}
|
|
13051
13201
|
show() {
|
|
13202
|
+
this.opener = this.panel.ownerDocument.activeElement;
|
|
13052
13203
|
this.ctrl.connect(this.handle.service).setOpen(true);
|
|
13053
13204
|
}
|
|
13054
13205
|
hide() {
|
|
@@ -13063,6 +13214,11 @@ var Dialog = class {
|
|
|
13063
13214
|
destroy() {
|
|
13064
13215
|
if (this.open) this.hide();
|
|
13065
13216
|
this.handle.stop();
|
|
13217
|
+
if (this.wasOpen) {
|
|
13218
|
+
this.wasOpen = false;
|
|
13219
|
+
this.announce(false);
|
|
13220
|
+
}
|
|
13221
|
+
this.restoreOpener();
|
|
13066
13222
|
this.backdrop.remove();
|
|
13067
13223
|
this.positioner.remove();
|
|
13068
13224
|
}
|
|
@@ -14047,14 +14203,49 @@ function buildColorPicker(color, theme, onChange, options = {}) {
|
|
|
14047
14203
|
const knob = document.createElement("div");
|
|
14048
14204
|
knob.style.cssText = "position:absolute;top:50%;width:15px;height:15px;border-radius:50%;background:var(--vela-selected-bg);box-shadow:0 1px 3px rgba(0,0,0,0.55);transform:translate(-50%,-50%);pointer-events:none;";
|
|
14049
14205
|
track.appendChild(knob);
|
|
14050
|
-
const pctBox = document.createElement("
|
|
14051
|
-
pctBox.
|
|
14206
|
+
const pctBox = document.createElement("input");
|
|
14207
|
+
pctBox.type = "text";
|
|
14208
|
+
pctBox.inputMode = "numeric";
|
|
14209
|
+
pctBox.title = "Opacity (%)";
|
|
14210
|
+
pctBox.style.cssText = `width:46px;box-sizing:border-box;text-align:center;font:var(--vela-font-size-md) ${theme.fontFamily};color:var(--vela-fg);background:transparent;border:1px solid var(--vela-border);border-radius:5px;padding:3px 4px;outline:none;`;
|
|
14211
|
+
pctBox.addEventListener("focus", () => {
|
|
14212
|
+
pctBox.style.borderColor = "var(--vela-border-strong)";
|
|
14213
|
+
pctBox.select();
|
|
14214
|
+
});
|
|
14052
14215
|
opRow.append(track, pctBox);
|
|
14053
14216
|
const paintOpacity = () => {
|
|
14054
14217
|
track.style.background = `linear-gradient(to right, ${curHex}00, ${curHex}ff), ${CHECKER}`;
|
|
14055
14218
|
knob.style.left = `${curAlpha * 100}%`;
|
|
14056
|
-
pctBox.
|
|
14219
|
+
pctBox.value = `${Math.round(curAlpha * 100)}%`;
|
|
14057
14220
|
};
|
|
14221
|
+
const commitTyped = () => {
|
|
14222
|
+
pctBox.style.borderColor = "var(--vela-border)";
|
|
14223
|
+
const n = parseFloat(pctBox.value.replace("%", ""));
|
|
14224
|
+
if (Number.isFinite(n)) {
|
|
14225
|
+
const next = Math.max(0, Math.min(100, n)) / 100;
|
|
14226
|
+
if (Math.round(next * 100) !== Math.round(curAlpha * 100)) {
|
|
14227
|
+
curAlpha = next;
|
|
14228
|
+
paintOpacity();
|
|
14229
|
+
emit();
|
|
14230
|
+
return;
|
|
14231
|
+
}
|
|
14232
|
+
}
|
|
14233
|
+
paintOpacity();
|
|
14234
|
+
};
|
|
14235
|
+
pctBox.addEventListener("change", commitTyped);
|
|
14236
|
+
pctBox.addEventListener("blur", () => {
|
|
14237
|
+
pctBox.style.borderColor = "var(--vela-border)";
|
|
14238
|
+
paintOpacity();
|
|
14239
|
+
});
|
|
14240
|
+
pctBox.addEventListener("keydown", (e) => {
|
|
14241
|
+
if (e.key === "Escape") return;
|
|
14242
|
+
e.stopPropagation();
|
|
14243
|
+
if (e.key === "Enter") {
|
|
14244
|
+
e.preventDefault();
|
|
14245
|
+
commitTyped();
|
|
14246
|
+
pctBox.blur();
|
|
14247
|
+
}
|
|
14248
|
+
});
|
|
14058
14249
|
let dragging = false;
|
|
14059
14250
|
const onDrag = (clientX) => {
|
|
14060
14251
|
const r = track.getBoundingClientRect();
|
|
@@ -17197,15 +17388,23 @@ var Batch = class {
|
|
|
17197
17388
|
this.seg(x + w, y + h, x, y + h, lineWidth, c);
|
|
17198
17389
|
this.seg(x, y + h, x, y, lineWidth, c);
|
|
17199
17390
|
}
|
|
17200
|
-
/**
|
|
17391
|
+
/**
|
|
17392
|
+
* Filled circle (triangle fan), feathered like a line: the rim is padded by {@link AA_PAD} and
|
|
17393
|
+
* edgeDist runs from 0 at the center to the padded radius at the rim, with edgeHalf = r. The
|
|
17394
|
+
* distance grows linearly along each spoke, so the shader's line feather gives a round soft edge.
|
|
17395
|
+
*/
|
|
17201
17396
|
circle(cx, cy, r, c, segments = 16) {
|
|
17202
|
-
|
|
17397
|
+
const ext = r + AA_PAD;
|
|
17398
|
+
let px = cx + ext;
|
|
17203
17399
|
let py = cy;
|
|
17400
|
+
this.ensure(segments * 3);
|
|
17204
17401
|
for (let i = 1; i <= segments; i += 1) {
|
|
17205
17402
|
const a = i / segments * Math.PI * 2;
|
|
17206
|
-
const nx = cx + Math.cos(a) *
|
|
17207
|
-
const ny = cy + Math.sin(a) *
|
|
17208
|
-
this.
|
|
17403
|
+
const nx = cx + Math.cos(a) * ext;
|
|
17404
|
+
const ny = cy + Math.sin(a) * ext;
|
|
17405
|
+
this.v(cx, cy, c, 0, r);
|
|
17406
|
+
this.v(px, py, c, ext, r);
|
|
17407
|
+
this.v(nx, ny, c, ext, r);
|
|
17209
17408
|
px = nx;
|
|
17210
17409
|
py = ny;
|
|
17211
17410
|
}
|
|
@@ -17386,7 +17585,7 @@ var WebGL2Backend = class {
|
|
|
17386
17585
|
}
|
|
17387
17586
|
mount(canvas) {
|
|
17388
17587
|
this.canvas = canvas;
|
|
17389
|
-
this.gl = canvas.getContext("webgl2", { alpha: true, antialias:
|
|
17588
|
+
this.gl = canvas.getContext("webgl2", { alpha: true, antialias: false, depth: false, stencil: false, premultipliedAlpha: true });
|
|
17390
17589
|
if (!this.gl) return;
|
|
17391
17590
|
if (!this.initGL()) {
|
|
17392
17591
|
this.gl = null;
|
|
@@ -18645,6 +18844,12 @@ var InputController = class {
|
|
|
18645
18844
|
this.lastTapT = 0;
|
|
18646
18845
|
this.lastTapX = 0;
|
|
18647
18846
|
this.lastTapY = 0;
|
|
18847
|
+
// Whether the last two primary presses were claimed by the drawings layer. A double-click
|
|
18848
|
+
// is the last press plus the one before it; a tool-driven click pair must never fall through
|
|
18849
|
+
// to the pane maximize toggle, even when the tool disarmed itself between the two clicks
|
|
18850
|
+
// (a finished placement leaves plain cursor mode for the second click).
|
|
18851
|
+
this.lastPressDrawing = false;
|
|
18852
|
+
this.prevPressDrawing = false;
|
|
18648
18853
|
this.onTouchContextMenu = (e) => {
|
|
18649
18854
|
if (this.touches.size === 0) return;
|
|
18650
18855
|
if (!(e.target instanceof Node) || !this.el?.contains(e.target)) return;
|
|
@@ -18699,19 +18904,24 @@ var InputController = class {
|
|
|
18699
18904
|
this.moved = false;
|
|
18700
18905
|
this.startX = x;
|
|
18701
18906
|
this.startY = y;
|
|
18907
|
+
this.prevPressDrawing = this.lastPressDrawing;
|
|
18908
|
+
this.lastPressDrawing = false;
|
|
18702
18909
|
if (this.deps.drawingsClaim?.(x, y)) {
|
|
18703
18910
|
this.region = "drawing";
|
|
18911
|
+
this.lastPressDrawing = true;
|
|
18704
18912
|
this.deps.drawingsPointerDown?.(x, y, this.snapMode(e), e.shiftKey, e.ctrlKey || e.metaKey);
|
|
18705
18913
|
this.capture(e.pointerId);
|
|
18706
18914
|
return;
|
|
18707
18915
|
}
|
|
18708
18916
|
if (e.shiftKey && this.regionAt(x, y) === "data" && this.deps.drawingsMeasureStart?.(x, y, this.snapMode(e))) {
|
|
18709
18917
|
this.region = "drawing";
|
|
18918
|
+
this.lastPressDrawing = true;
|
|
18710
18919
|
this.capture(e.pointerId);
|
|
18711
18920
|
return;
|
|
18712
18921
|
}
|
|
18713
18922
|
if ((e.ctrlKey || e.metaKey) && this.regionAt(x, y) === "data" && this.deps.drawingsMarqueeStart?.(x, y)) {
|
|
18714
18923
|
this.region = "drawing";
|
|
18924
|
+
this.lastPressDrawing = true;
|
|
18715
18925
|
this.capture(e.pointerId);
|
|
18716
18926
|
return;
|
|
18717
18927
|
}
|
|
@@ -18827,7 +19037,7 @@ var InputController = class {
|
|
|
18827
19037
|
this.deps.drawingsPointerUp?.(x, y, this.snapMode(e));
|
|
18828
19038
|
} else if (tapRelease && this.region === "data") {
|
|
18829
19039
|
this.deps.onClick(x, y);
|
|
18830
|
-
} else if (this.dragging && this.region === "data") {
|
|
19040
|
+
} else if (this.dragging && this.region === "data" && wasTouch) {
|
|
18831
19041
|
const stale = e.timeStamp - this.lastT > FLING_STALE_MS;
|
|
18832
19042
|
if (!stale && Math.abs(this.vx) > FLING_MIN_SPEED) {
|
|
18833
19043
|
const pitch = this.deps.getCoords().pxPerBar();
|
|
@@ -19033,6 +19243,7 @@ var InputController = class {
|
|
|
19033
19243
|
if (region === "price") this.deps.resetPriceScale(x, y);
|
|
19034
19244
|
else if (region === "separator") this.deps.resetPaneSize(y);
|
|
19035
19245
|
else if (region === "time") this.deps.resetView();
|
|
19246
|
+
else if (this.lastPressDrawing || this.prevPressDrawing) return;
|
|
19036
19247
|
else this.deps.dataDblClick(x, y);
|
|
19037
19248
|
}
|
|
19038
19249
|
};
|
|
@@ -21198,6 +21409,7 @@ function timeTicks(fromMs, toMs, target = 8, offsetMs = 0) {
|
|
|
21198
21409
|
const step = pickStep(span / Math.max(1, target));
|
|
21199
21410
|
const zFrom = fromMs + offsetMs;
|
|
21200
21411
|
const zTo = toMs + offsetMs;
|
|
21412
|
+
if (step >= MONTH) return calendarTicks(zFrom, zTo, step >= YEAR ? 12 : step >= 3 * MONTH ? 3 : 1, offsetMs);
|
|
21201
21413
|
const first = Math.ceil(zFrom / step) * step;
|
|
21202
21414
|
const out = [];
|
|
21203
21415
|
for (let zt = first; zt <= zTo; zt += step) {
|
|
@@ -21228,6 +21440,18 @@ function timeTicks(fromMs, toMs, target = 8, offsetMs = 0) {
|
|
|
21228
21440
|
}
|
|
21229
21441
|
return out;
|
|
21230
21442
|
}
|
|
21443
|
+
function calendarTicks(zFrom, zTo, months, offsetMs) {
|
|
21444
|
+
const d0 = new Date(zFrom);
|
|
21445
|
+
let idx = d0.getUTCFullYear() * 12 + d0.getUTCMonth();
|
|
21446
|
+
if (Date.UTC(Math.floor(idx / 12), idx % 12, 1) < zFrom) idx += 1;
|
|
21447
|
+
idx = Math.ceil(idx / months) * months;
|
|
21448
|
+
const out = [];
|
|
21449
|
+
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)) {
|
|
21450
|
+
const label = months === 12 ? String(Math.floor(idx / 12)) : MONTHS[idx % 12];
|
|
21451
|
+
out.push({ time: zt - offsetMs, label, major: true });
|
|
21452
|
+
}
|
|
21453
|
+
return out;
|
|
21454
|
+
}
|
|
21231
21455
|
|
|
21232
21456
|
// src/renderers/native/chrome/countdown.ts
|
|
21233
21457
|
function countdownText(barOpen, barMs, now2) {
|
|
@@ -25269,6 +25493,12 @@ var DrawingInteraction = class {
|
|
|
25269
25493
|
activeDragId() {
|
|
25270
25494
|
return this.state.kind === "pressed" && this.state.moved ? this.state.id : null;
|
|
25271
25495
|
}
|
|
25496
|
+
/** The store drawings a live drag is moving — the pressed one and its riders — or none
|
|
25497
|
+
* before the drag passes the slop. A Ctrl-drag moves copies, so its sources stay put. */
|
|
25498
|
+
movingIds() {
|
|
25499
|
+
if (this.state.kind !== "pressed" || !this.state.moved || this.state.clones) return /* @__PURE__ */ new Set();
|
|
25500
|
+
return /* @__PURE__ */ new Set([this.state.id, ...this.state.riders.map((r) => r.id)]);
|
|
25501
|
+
}
|
|
25272
25502
|
/** The drawing under a press that has not been released yet (drag or click undecided), or null. */
|
|
25273
25503
|
pressedId() {
|
|
25274
25504
|
return this.state.kind === "pressed" ? this.state.id : null;
|
|
@@ -25927,6 +26157,17 @@ var DrawingSettingsDialog = class {
|
|
|
25927
26157
|
}
|
|
25928
26158
|
}));
|
|
25929
26159
|
}
|
|
26160
|
+
if (drawing instanceof FibRetracement) {
|
|
26161
|
+
const fib = drawing;
|
|
26162
|
+
grid.appendChild(fieldRow({
|
|
26163
|
+
label: "Reverse",
|
|
26164
|
+
bool: true,
|
|
26165
|
+
toggle: {
|
|
26166
|
+
checked: fib.reverse,
|
|
26167
|
+
onChange: (v) => actions.patch({ reverse: v })
|
|
26168
|
+
}
|
|
26169
|
+
}));
|
|
26170
|
+
}
|
|
25930
26171
|
levels.forEach((lv, i) => {
|
|
25931
26172
|
const row = document.createElement("div");
|
|
25932
26173
|
row.className = "vela-field-span";
|
|
@@ -27294,6 +27535,7 @@ var DrawingToolbar = class {
|
|
|
27294
27535
|
);
|
|
27295
27536
|
}
|
|
27296
27537
|
}
|
|
27538
|
+
announceSurface(fly, true, "menu", cell);
|
|
27297
27539
|
}
|
|
27298
27540
|
openMagnetFlyout() {
|
|
27299
27541
|
const cell = this.magnetCell;
|
|
@@ -27317,6 +27559,7 @@ var DrawingToolbar = class {
|
|
|
27317
27559
|
})
|
|
27318
27560
|
);
|
|
27319
27561
|
}
|
|
27562
|
+
announceSurface(fly, true, "menu", cell);
|
|
27320
27563
|
}
|
|
27321
27564
|
flyoutHeader(text) {
|
|
27322
27565
|
const t = this.theme;
|
|
@@ -27385,9 +27628,11 @@ var DrawingToolbar = class {
|
|
|
27385
27628
|
}
|
|
27386
27629
|
closeFlyout() {
|
|
27387
27630
|
this.starEls.clear();
|
|
27388
|
-
|
|
27389
|
-
|
|
27631
|
+
const fly = this.flyout;
|
|
27632
|
+
if (fly) {
|
|
27390
27633
|
this.flyout = null;
|
|
27634
|
+
announceSurface(fly, false, "menu", this.flyoutCell);
|
|
27635
|
+
fly.remove();
|
|
27391
27636
|
this.flyoutCell?.classList.remove("vela-open");
|
|
27392
27637
|
this.flyoutCell = null;
|
|
27393
27638
|
this.flyoutOwnerId = null;
|
|
@@ -27712,6 +27957,8 @@ var UserDrawingController = class {
|
|
|
27712
27957
|
this.drawings = [];
|
|
27713
27958
|
/** Ids painted on an interleave layer this frame — the top canvas paints only their handles. */
|
|
27714
27959
|
this.sliced = /* @__PURE__ */ new Set();
|
|
27960
|
+
/** Interleaved drawings mid-drag: painted on the top canvas, left out of their slice. */
|
|
27961
|
+
this.lifted = /* @__PURE__ */ new Set();
|
|
27715
27962
|
/** Cached slice canvases, keyed `paneId|beforeZ`, reused across frames to avoid churn. */
|
|
27716
27963
|
this.sliceCache = /* @__PURE__ */ new Map();
|
|
27717
27964
|
/** Series boundaries per pane as of the last `prepareSlices` — lets a repaint between data
|
|
@@ -27799,7 +28046,7 @@ var UserDrawingController = class {
|
|
|
27799
28046
|
selectedIds: () => this.selectedIds,
|
|
27800
28047
|
emit: (i) => this.emit(i),
|
|
27801
28048
|
changed: () => {
|
|
27802
|
-
this.
|
|
28049
|
+
this.syncLift();
|
|
27803
28050
|
this.render();
|
|
27804
28051
|
},
|
|
27805
28052
|
openSettings: (id, x, y) => this.openSettingsById(id, x, y),
|
|
@@ -28425,6 +28672,20 @@ var UserDrawingController = class {
|
|
|
28425
28672
|
/** A drawing that paints inside the series stack changed (content, not hover): its pixels
|
|
28426
28673
|
* live in the backend composite, so this layer alone can't show the change — ask for a
|
|
28427
28674
|
* data frame, which re-runs `prepareSlices` before the backend composites. */
|
|
28675
|
+
/** A drawing being dragged leaves its interleave slice for the top canvas, so each pointer
|
|
28676
|
+
* move repaints one 2D layer instead of re-rasterizing and re-uploading a plot-sized slice
|
|
28677
|
+
* texture through the data frame. The slices rebuild once as the drag starts and once as it
|
|
28678
|
+
* ends (release, cancel), when the lifted set changes. */
|
|
28679
|
+
syncLift() {
|
|
28680
|
+
const moving = this.interaction.movingIds();
|
|
28681
|
+
let same = moving.size === this.lifted.size;
|
|
28682
|
+
if (same) {
|
|
28683
|
+
for (const id of moving) if (!this.lifted.has(id)) same = false;
|
|
28684
|
+
}
|
|
28685
|
+
if (same) return;
|
|
28686
|
+
this.lifted = new Set(moving);
|
|
28687
|
+
this.invalidateSlices();
|
|
28688
|
+
}
|
|
28428
28689
|
invalidateSlices() {
|
|
28429
28690
|
if (this.sliced.size > 0 || this.drawings.some((d) => this.isInterleaved(d))) this.deps.requestDataPaint();
|
|
28430
28691
|
}
|
|
@@ -28443,7 +28704,7 @@ var UserDrawingController = class {
|
|
|
28443
28704
|
const theme = this.deps.theme();
|
|
28444
28705
|
const buckets = /* @__PURE__ */ new Map();
|
|
28445
28706
|
for (const d of this.drawings) {
|
|
28446
|
-
if (!d.visible) continue;
|
|
28707
|
+
if (!d.visible || this.lifted.has(d.id)) continue;
|
|
28447
28708
|
const beforeZ = sliceKeyFor(d.zIndex, this.lastBounds.get(d.paneId) ?? []);
|
|
28448
28709
|
if (beforeZ === null) continue;
|
|
28449
28710
|
const key = `${d.paneId}|${beforeZ}`;
|
|
@@ -28495,8 +28756,9 @@ var UserDrawingController = class {
|
|
|
28495
28756
|
mutedLabel: edited instanceof TextLabel ? edited.id : null
|
|
28496
28757
|
};
|
|
28497
28758
|
this.painter.seriesLook = this.deps.seriesLook();
|
|
28498
|
-
|
|
28499
|
-
this.painter.
|
|
28759
|
+
const onTop = (d) => !this.isInterleaved(d) || this.lifted.has(d.id);
|
|
28760
|
+
this.painter.paintAll(ctx, this.drawings.filter(onTop), proj, this.deps.theme(), targets);
|
|
28761
|
+
this.painter.paintHighlights(ctx, this.drawings.filter((d) => !onTop(d)), proj, handleIdsFor(targets));
|
|
28500
28762
|
const clones = this.interaction.dragClones();
|
|
28501
28763
|
if (clones) this.painter.paintAll(ctx, clones, proj, this.deps.theme(), { selected: new Set(clones.map((c) => c.id)) });
|
|
28502
28764
|
this.layoutTextEditor();
|
|
@@ -29773,23 +30035,21 @@ function stackLayers(entries, candleZ) {
|
|
|
29773
30035
|
return { below, above };
|
|
29774
30036
|
}
|
|
29775
30037
|
|
|
29776
|
-
// src/renderers/native/chrome/
|
|
29777
|
-
var
|
|
29778
|
-
var
|
|
30038
|
+
// src/renderers/native/chrome/vela-logos.ts
|
|
30039
|
+
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>';
|
|
30040
|
+
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>';
|
|
29779
30041
|
|
|
29780
30042
|
// src/renderers/native/chrome/AttributionMark.ts
|
|
29781
|
-
var ATTRIBUTION_URL = "https://
|
|
30043
|
+
var ATTRIBUTION_URL = "https://velacharts.dev/?utm_source=vela&utm_medium=attribution";
|
|
29782
30044
|
var STYLE_ID5 = "vela-attribution-styles";
|
|
29783
30045
|
var CSS2 = `
|
|
29784
30046
|
.vela-attribution {
|
|
29785
30047
|
text-decoration: none;
|
|
29786
30048
|
display: flex;
|
|
29787
30049
|
align-items: center;
|
|
29788
|
-
/*
|
|
29789
|
-
|
|
29790
|
-
|
|
29791
|
-
reads wrong because the symbol's ink hangs low and the wordmark descends. */
|
|
29792
|
-
gap: 4px;
|
|
30050
|
+
/* No gutter: the V is the wordmark's first letter, and the letters' viewBox starts
|
|
30051
|
+
where the V's ends, so the kit's own letter spacing comes with them. */
|
|
30052
|
+
gap: 0;
|
|
29793
30053
|
}
|
|
29794
30054
|
.vela-attribution .vela-attr-symbol {
|
|
29795
30055
|
flex: none;
|
|
@@ -29797,7 +30057,7 @@ var CSS2 = `
|
|
|
29797
30057
|
line-height: 0;
|
|
29798
30058
|
}
|
|
29799
30059
|
.vela-attribution .vela-attr-symbol svg {
|
|
29800
|
-
height:
|
|
30060
|
+
height: 24px;
|
|
29801
30061
|
width: auto;
|
|
29802
30062
|
display: block;
|
|
29803
30063
|
filter: drop-shadow(0 1px 2px var(--vela-attr-shadow, rgba(0,0,0,0.45)));
|
|
@@ -29808,15 +30068,13 @@ var CSS2 = `
|
|
|
29808
30068
|
opacity: 0;
|
|
29809
30069
|
display: flex;
|
|
29810
30070
|
align-items: center;
|
|
29811
|
-
/*
|
|
29812
|
-
position: relative;
|
|
29813
|
-
top: 3px;
|
|
30071
|
+
/* Same height and baseline as the V (one viewBox height), so no vertical offset. */
|
|
29814
30072
|
transform: translateX(-8px);
|
|
29815
30073
|
transition: max-width 0.3s ease, opacity 0.25s ease, transform 0.3s ease;
|
|
29816
30074
|
flex: none;
|
|
29817
30075
|
}
|
|
29818
30076
|
.vela-attribution .vela-attr-wordmark svg {
|
|
29819
|
-
height:
|
|
30077
|
+
height: 24px;
|
|
29820
30078
|
width: auto;
|
|
29821
30079
|
display: block;
|
|
29822
30080
|
filter: drop-shadow(0 1px 2px var(--vela-attr-shadow, rgba(0,0,0,0.45)));
|
|
@@ -29831,14 +30089,11 @@ var CSS2 = `
|
|
|
29831
30089
|
(data-layout): the workspace's single grid-wide mark lives OUTSIDE any renderer
|
|
29832
30090
|
container, so only the shell attribute reaches it. */
|
|
29833
30091
|
[data-vela-layout='mobile'] .vela-attribution .vela-attr-symbol svg,
|
|
29834
|
-
[data-layout='mobile'] .vela-attribution .vela-attr-symbol svg { height:
|
|
30092
|
+
[data-layout='mobile'] .vela-attribution .vela-attr-symbol svg { height: 20px; }
|
|
29835
30093
|
[data-vela-layout='mobile'] .vela-attribution .vela-attr-wordmark,
|
|
29836
|
-
[data-layout='mobile'] .vela-attribution .vela-attr-wordmark {
|
|
29837
|
-
top: 2px;
|
|
29838
|
-
transform: translateX(-6px);
|
|
29839
|
-
}
|
|
30094
|
+
[data-layout='mobile'] .vela-attribution .vela-attr-wordmark { transform: translateX(-6px); }
|
|
29840
30095
|
[data-vela-layout='mobile'] .vela-attribution .vela-attr-wordmark svg,
|
|
29841
|
-
[data-layout='mobile'] .vela-attribution .vela-attr-wordmark svg { height:
|
|
30096
|
+
[data-layout='mobile'] .vela-attribution .vela-attr-wordmark svg { height: 20px; }
|
|
29842
30097
|
[data-vela-layout='mobile'] .vela-attribution:hover .vela-attr-wordmark,
|
|
29843
30098
|
[data-layout='mobile'] .vela-attribution:hover .vela-attr-wordmark { transform: translateX(0); }
|
|
29844
30099
|
`;
|
|
@@ -29895,10 +30150,10 @@ function createAttributionMark(doc, background) {
|
|
|
29895
30150
|
const symbol = doc.createElement("span");
|
|
29896
30151
|
symbol.className = "vela-attr-symbol";
|
|
29897
30152
|
symbol.setAttribute("aria-hidden", "true");
|
|
29898
|
-
symbol.innerHTML =
|
|
30153
|
+
symbol.innerHTML = VELA_MARK_SVG;
|
|
29899
30154
|
const wordmark = doc.createElement("span");
|
|
29900
30155
|
wordmark.className = "vela-attr-wordmark";
|
|
29901
|
-
wordmark.innerHTML =
|
|
30156
|
+
wordmark.innerHTML = VELA_LETTERS_SVG;
|
|
29902
30157
|
a.append(symbol, wordmark);
|
|
29903
30158
|
return a;
|
|
29904
30159
|
}
|