@luxalgo/vela 0.6.15 → 0.6.17
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/README.md +12 -1
- package/dist/{DataProvider-XLdJB86x.d.ts → DataProvider-B-Jz59Rf.d.ts} +1 -1
- package/dist/{DataProvider-xH2VBcFT.d.cts → DataProvider-OfR3fXg9.d.cts} +1 -1
- package/dist/{chunk-6DPAYEGO.js → chunk-CAFCLMPF.js} +1 -0
- package/dist/chunk-FE6V2YAQ.js +1 -0
- package/dist/{chunk-32A7KHFM.js → chunk-IFJJPXSV.js} +8 -2
- package/dist/{chunk-7C7NWEXH.js → chunk-OSZDSH7F.js} +83 -59
- package/dist/{chunk-MWDNPGU3.js → chunk-T5Z5YUCF.js} +23 -16
- package/dist/{chunk-MWS4CUJL.js → chunk-XCBJU674.js} +2 -2
- package/dist/{chunk-J5QIR2Z3.js → chunk-YCD72KGK.js} +2543 -159
- package/dist/{contributions-x7iamlnd.d.cts → contributions-C3b0Sx5P.d.cts} +29 -13
- package/dist/{contributions-h5BzEiV2.d.ts → contributions-Swzz10fG.d.ts} +29 -13
- package/dist/index.cjs +2746 -355
- package/dist/index.d.cts +15 -6
- package/dist/index.d.ts +15 -6
- package/dist/index.js +5 -5
- package/dist/{options-bdSAtp7y.d.ts → options-CX1lSYWA.d.cts} +12 -2
- package/dist/{options-bdSAtp7y.d.cts → options-CX1lSYWA.d.ts} +12 -2
- package/dist/{plugin-2sJcf5mk.d.cts → plugin-BjnEE1zA.d.cts} +3 -3
- package/dist/{plugin-BLaNPh55.d.ts → plugin-mvddudqd.d.ts} +3 -3
- package/dist/plugin.cjs +1 -0
- package/dist/plugin.d.cts +4 -4
- package/dist/plugin.d.ts +4 -4
- package/dist/plugin.js +3 -3
- 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/{statusline-model--tH0VWCy.d.cts → statusline-model-D91cU2fF.d.cts} +3 -3
- package/dist/{statusline-model-CLpaO3Dl.d.ts → statusline-model-IURCya0H.d.ts} +3 -3
- package/dist/ui.cjs +23 -15
- package/dist/ui.d.cts +1 -1
- package/dist/ui.d.ts +1 -1
- package/dist/ui.js +3 -3
- package/dist/vela.global.js +2600 -209
- package/dist/vela.global.min.js +52 -55
- package/dist/widget.cjs +2663 -241
- package/dist/widget.d.cts +6 -6
- package/dist/widget.d.ts +6 -6
- package/dist/widget.js +7 -7
- package/dist/workspace.cjs +2663 -241
- package/dist/workspace.d.cts +25 -14
- package/dist/workspace.d.ts +25 -14
- package/dist/workspace.js +6 -6
- package/package.json +1 -1
- package/dist/chunk-H26BEHF4.js +0 -7
package/README.md
CHANGED
|
@@ -32,6 +32,10 @@ touching the rest.
|
|
|
32
32
|
|
|
33
33
|
## What's in the box
|
|
34
34
|
|
|
35
|
+
<p align="center">
|
|
36
|
+
<img src=".github/vela-layout.png" alt="Vela package layout" width="100%">
|
|
37
|
+
</p>
|
|
38
|
+
|
|
35
39
|
- **`@luxalgo/vela`**: the headless chart. Data model, engines, drawings, providers,
|
|
36
40
|
native renderer.
|
|
37
41
|
- **`@luxalgo/vela/workspace`**: the full chart app. One chart or a grid of them under
|
|
@@ -95,7 +99,14 @@ providers, to `window.Vela`.
|
|
|
95
99
|
|
|
96
100
|
## Indicators
|
|
97
101
|
|
|
98
|
-
Vela™
|
|
102
|
+
Vela™ ships **70+** built-in studies — moving averages, bands and channels, momentum
|
|
103
|
+
oscillators, trend and volatility measures, volume studies, and price-anchored
|
|
104
|
+
overlays such as VWAP, SuperTrend, and Pivot Points. They compute from the chart's
|
|
105
|
+
own bars (no scripting engine), and each one gets a legend row, a settings dialog,
|
|
106
|
+
and persistence across reloads. Volume and the visible-range volume profile sit
|
|
107
|
+
alongside them.
|
|
108
|
+
|
|
109
|
+
Custom scripts still run through pluggable engines. Vela™ **ships none**: install the
|
|
99
110
|
addon for the language you want, or write one against the public `ScriptingEngine` port.
|
|
100
111
|
Pine Script lives in [`@luxalgo/vela-pinets`](https://github.com/LuxAlgo/Vela-pinets)
|
|
101
112
|
(`npm i @luxalgo/vela-pinets pinets`), which is **AGPL-3.0** because the PineTS runtime it
|
|
@@ -151,6 +151,7 @@ registerIcon("star-filled", S('<path d="M8 2.2l1.75 3.55 3.9.55-2.8 2.75.65 3.9L
|
|
|
151
151
|
registerIcon("grip", S('<circle cx="6" cy="3.5" r="1"/><circle cx="10" cy="3.5" r="1"/><circle cx="6" cy="8" r="1"/><circle cx="10" cy="8" r="1"/><circle cx="6" cy="12.5" r="1"/><circle cx="10" cy="12.5" r="1"/>', 'fill="currentColor" stroke="none"'));
|
|
152
152
|
registerIcon("kebab", S('<circle cx="8" cy="3.2" r="1.2"/><circle cx="8" cy="8" r="1.2"/><circle cx="8" cy="12.8" r="1.2"/>', 'fill="currentColor" stroke="none"'));
|
|
153
153
|
registerIcon("burger", S('<path d="M2.5 4.5h11M2.5 8h11M2.5 11.5h11"/>'));
|
|
154
|
+
registerIcon("info", S('<path d="M8 7.4v4.4"/><circle cx="8" cy="4.6" r="0.9" fill="currentColor" stroke="none"/>'));
|
|
154
155
|
registerIcon("reset", S('<path d="M2 8a6 6 0 1 0 6-6 6.5 6.5 0 0 0-4.5 1.83L2 5.33"/><path d="M2 2v3.33h3.33"/>'));
|
|
155
156
|
registerIcon("pane-collapse", S('<path d="M2.6 9.4h4v4M13.4 6.6h-4v-4"/><path d="m9.4 6.6 4.2-4.2M2.4 13.6l4.2-4.2"/>'));
|
|
156
157
|
registerIcon("pane-expand", S('<path d="M9.8 2.4h3.8v3.8M6.2 13.6H2.4V9.8"/><path d="m13.6 2.4-4.4 4.4M2.4 13.6l4.4-4.4"/>'));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { svg24, NEUTRAL, BEARISH, WARNING, BULLISH, INFO, ACCENT_BRIGHT, VALID, INVALID, MARKER, ACCENT, injectStyles, iconEl } from './chunk-
|
|
1
|
+
import { svg24, NEUTRAL, BEARISH, WARNING, BULLISH, INFO, ACCENT_BRIGHT, VALID, INVALID, MARKER, ACCENT, injectStyles, iconEl } from './chunk-CAFCLMPF.js';
|
|
2
2
|
|
|
3
3
|
// src/core/native-indicators/NativeIndicator.ts
|
|
4
4
|
var REGISTRY = /* @__PURE__ */ new Map();
|
|
@@ -5890,6 +5890,12 @@ function rendererLayers() {
|
|
|
5890
5890
|
return [...registry2.values()];
|
|
5891
5891
|
}
|
|
5892
5892
|
|
|
5893
|
+
// src/core/model/identity.ts
|
|
5894
|
+
function stableSeriesId(parts) {
|
|
5895
|
+
const normTitle = parts.title.trim().toLowerCase().replace(/\s+/g, "-");
|
|
5896
|
+
return `${parts.instanceId}:${parts.kind}:${normTitle}#${parts.ordinal}`;
|
|
5897
|
+
}
|
|
5898
|
+
|
|
5893
5899
|
// src/widget/topbar-composition.ts
|
|
5894
5900
|
var TOPBAR_BUILTIN_IDS = ["symbol", "timeframes", "style", "layout", "indicators", "actions", "undo-redo", "alerts", "panels", "screenshot"];
|
|
5895
5901
|
var TOPBAR_DEFAULT_LEFT = ["symbol", "timeframes", "style", "layout", "indicators", "actions", "undo-redo"];
|
|
@@ -6359,4 +6365,4 @@ var SidePanel = class {
|
|
|
6359
6365
|
}
|
|
6360
6366
|
};
|
|
6361
6367
|
|
|
6362
|
-
export { AnchoredVwap, ArrowMark, Callout, CalloutBase, Comment, DEDEKIND_CURVATURE_OPTIONS, DEFAULT_DRAWING_COLOR, DEFAULT_PANEL_MAX_WIDTH, DEFAULT_PANEL_MIN_WIDTH, DEFAULT_PANEL_ORDER, DEFAULT_PANEL_WIDTH, DIRECTION_OPTIONS, DedekindTessellation, Drawing, FibRatios, FibSpiral, FixedRangeVolumeProfile, GANN_SQUARE_ARCS, GLYPH_OPTIONS, GannSquare, GlyphStamp, LINE_STYLE_OPTIONS, MACH_NUMBER_OPTIONS, MACH_WAVE_COUNT_OPTIONS, MAGNIFIER_TIMEFRAME_OPTIONS, MachFigure, Magnifier, MeasureBox, Note, OVERRIDABLE_TOPBAR_IDS, PatternDrawing, PositionTool, PriceLabel, PriceNote, RadialFib, RegressionChannel, STAMP_SIZE_OPTIONS, SegmentDrawing, SidePanel, Signpost, TEXT_SIZE_OPTIONS, TOPBAR_BUILTIN_IDS, TOPBAR_DEFAULT_LEFT, TOPBAR_DEFAULT_RIGHT, TextLabel, chartType, chartTypes, clampPanelWidth, createDrawing, deserializeDrawing, drawingTypes, foldBaseModulation, formatDuration, getDrawingType, getNativeIndicator, inputDeltas, inputVisible, legendActions, legendActionsProviderFor, legendCallouts, legendCalloutsProviderFor, lineSegmentIntersection, magnifierTimeframeLabel, nativeIndicatorDescriptors, nativeIndicatorTypes, normalizeSettingsRow, pinnedTopbarActionIds, registerChartType, registerDefaultEngine, registerDrawingType, registerLegendAction, registerLegendCallout, registerNativeIndicator, registerRendererDefaults, registerRendererLayer, registerSidePanel, registerStatePersistence, registerSymbolRanking, registerWidgetAction, registerWidgetAttachment, rendererDefaults, rendererLayers, resetDrawingSettings, resolveEngines, resolveTopbarComposition, settingsRowValueKeys, settingsRowVisible, sidePanels, statePersistenceHandlers, symbolRanking, tickerModifierIds, topbarActionOverride, topbarHas, unregisterChartType, unregisterDefaultEngine, unregisterLegendAction, unregisterLegendCallout, unregisterNativeIndicator, unregisterRendererDefaults, unregisterRendererLayer, unregisterSidePanel, unregisterStatePersistence, unregisterWidgetAction, unregisterWidgetAttachment, widgetActions, widgetAttachments };
|
|
6368
|
+
export { AnchoredVwap, ArrowMark, Callout, CalloutBase, Comment, DEDEKIND_CURVATURE_OPTIONS, DEFAULT_DRAWING_COLOR, DEFAULT_PANEL_MAX_WIDTH, DEFAULT_PANEL_MIN_WIDTH, DEFAULT_PANEL_ORDER, DEFAULT_PANEL_WIDTH, DIRECTION_OPTIONS, DedekindTessellation, Drawing, FibRatios, FibSpiral, FixedRangeVolumeProfile, GANN_SQUARE_ARCS, GLYPH_OPTIONS, GannSquare, GlyphStamp, LINE_STYLE_OPTIONS, MACH_NUMBER_OPTIONS, MACH_WAVE_COUNT_OPTIONS, MAGNIFIER_TIMEFRAME_OPTIONS, MachFigure, Magnifier, MeasureBox, Note, OVERRIDABLE_TOPBAR_IDS, PatternDrawing, PositionTool, PriceLabel, PriceNote, RadialFib, RegressionChannel, STAMP_SIZE_OPTIONS, SegmentDrawing, SidePanel, Signpost, TEXT_SIZE_OPTIONS, TOPBAR_BUILTIN_IDS, TOPBAR_DEFAULT_LEFT, TOPBAR_DEFAULT_RIGHT, TextLabel, chartType, chartTypes, clampPanelWidth, createDrawing, deserializeDrawing, drawingTypes, foldBaseModulation, formatDuration, getDrawingType, getNativeIndicator, inputDeltas, inputVisible, legendActions, legendActionsProviderFor, legendCallouts, legendCalloutsProviderFor, lineSegmentIntersection, magnifierTimeframeLabel, nativeIndicatorDescriptors, nativeIndicatorTypes, normalizeSettingsRow, pinnedTopbarActionIds, registerChartType, registerDefaultEngine, registerDrawingType, registerLegendAction, registerLegendCallout, registerNativeIndicator, registerRendererDefaults, registerRendererLayer, registerSidePanel, registerStatePersistence, registerSymbolRanking, registerWidgetAction, registerWidgetAttachment, rendererDefaults, rendererLayers, resetDrawingSettings, resolveEngines, resolveTopbarComposition, settingsRowValueKeys, settingsRowVisible, sidePanels, stableSeriesId, statePersistenceHandlers, symbolRanking, tickerModifierIds, topbarActionOverride, topbarHas, unregisterChartType, unregisterDefaultEngine, unregisterLegendAction, unregisterLegendCallout, unregisterNativeIndicator, unregisterRendererDefaults, unregisterRendererLayer, unregisterSidePanel, unregisterStatePersistence, unregisterWidgetAction, unregisterWidgetAttachment, widgetActions, widgetAttachments };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { parseSymbol, priceStyleIds, BUILTIN_PRICE_STYLES, tzButtonLabel, TIMEZONES, normalizeTimezone, tzMenuLabel, isGroupRow, defaultMemberOf, groupKeyOf, groupMembers, LEGEND_AT_TOP_ATTR, Vela, TypedEventBus, MultiProviderFeed, registerBuiltinChartTypes, resolveTheme, buildToolbar, createCustomMark, createAttributionMark, DrawingToolbar, applyAttributionMarkTheme, sharedBarStore, timeframeToMs } from './chunk-
|
|
2
|
-
import { chartType, resolveTopbarComposition, topbarActionOverride, TOPBAR_BUILTIN_IDS, widgetActions, SidePanel, sidePanels, DEFAULT_PANEL_ORDER, symbolRanking, resolveEngines, legendActionsProviderFor, legendCalloutsProviderFor, statePersistenceHandlers, topbarHas, rendererDefaults, widgetAttachments, getDrawingType, inputDeltas } from './chunk-
|
|
3
|
-
import { Tooltip, KeymapManager, isEditableTarget, Drawer } from './chunk-
|
|
4
|
-
import { Menu, Dialog, CalloutBubble, applyPlotOverlayTokens, ensureUIHost } from './chunk-
|
|
5
|
-
import { registerIcon, svg16, injectStyles, iconEl, iconMarkup, iconAt, SESSION_OFF, SESSION_POST, SESSION_PRE, icon, categoricalColor } from './chunk-
|
|
1
|
+
import { parseSymbol, priceStyleIds, BUILTIN_PRICE_STYLES, tzButtonLabel, TIMEZONES, normalizeTimezone, tzMenuLabel, isGroupRow, defaultMemberOf, groupKeyOf, groupMembers, LEGEND_AT_TOP_ATTR, normalizeSession, Vela, TypedEventBus, MultiProviderFeed, registerBuiltinChartTypes, resolveTheme, buildToolbar, createCustomMark, createAttributionMark, DrawingToolbar, applyAttributionMarkTheme, sharedBarStore, timeframeToMs } from './chunk-YCD72KGK.js';
|
|
2
|
+
import { chartType, resolveTopbarComposition, topbarActionOverride, TOPBAR_BUILTIN_IDS, widgetActions, SidePanel, sidePanels, DEFAULT_PANEL_ORDER, symbolRanking, resolveEngines, legendActionsProviderFor, legendCalloutsProviderFor, statePersistenceHandlers, topbarHas, rendererDefaults, widgetAttachments, getDrawingType, inputDeltas } from './chunk-IFJJPXSV.js';
|
|
3
|
+
import { Tooltip, KeymapManager, isEditableTarget, Drawer } from './chunk-XCBJU674.js';
|
|
4
|
+
import { Menu, Dialog, CalloutBubble, applyPlotOverlayTokens, ensureUIHost } from './chunk-T5Z5YUCF.js';
|
|
5
|
+
import { registerIcon, svg16, injectStyles, iconEl, iconMarkup, iconAt, SESSION_OFF, SESSION_POST, SESSION_PRE, icon, categoricalColor } from './chunk-CAFCLMPF.js';
|
|
6
6
|
import { baseOf } from './chunk-W4EJWLEO.js';
|
|
7
7
|
|
|
8
8
|
// src/widget/timeframe.ts
|
|
@@ -2999,17 +2999,12 @@ function filterSymbols(list, query, limit = 100, top = TOP_TICKERS) {
|
|
|
2999
2999
|
}
|
|
3000
3000
|
var STYLE_ID6 = "vela-widget-symbolpicker";
|
|
3001
3001
|
var CSS6 = `
|
|
3002
|
-
/*
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
z-index: 1;
|
|
3009
|
-
background: var(--vela-surface);
|
|
3010
|
-
margin: calc(-1 * var(--vela-space-4)) calc(-1 * var(--vela-space-4)) 0;
|
|
3011
|
-
padding: var(--vela-space-4) var(--vela-space-4) 0;
|
|
3012
|
-
}
|
|
3002
|
+
/* The dialog body is flush (a flex column): search + market tabs are a fixed head
|
|
3003
|
+
and the result list is the ONLY scroller, in both layouts. A sticky head over a
|
|
3004
|
+
scrolling padded body is not an option \u2014 browsers pin sticky boxes to the
|
|
3005
|
+
scroller's content box, so the head lands one padding below the top and covers
|
|
3006
|
+
the first row. */
|
|
3007
|
+
.vela-sp-head { flex: none; padding: var(--vela-space-4) var(--vela-space-4) 0; }
|
|
3013
3008
|
.vela-sp-searchrow {
|
|
3014
3009
|
display: flex;
|
|
3015
3010
|
align-items: center;
|
|
@@ -3034,12 +3029,13 @@ var CSS6 = `
|
|
|
3034
3029
|
.vela-sp-input::placeholder { text-transform: none; }
|
|
3035
3030
|
.vela-sp-tabs { display: flex; gap: 14px; margin: 12px 2px 0; border-bottom: 1px solid var(--vela-border); padding-bottom: 8px; }
|
|
3036
3031
|
/* Mobile (fullscreen dialog): the asset-class strip scrolls sideways instead of
|
|
3037
|
-
overflowing the body, and the result list stops capping itself \u2014
|
|
3038
|
-
the
|
|
3032
|
+
overflowing the body, and the result list stops capping itself \u2014 it fills the
|
|
3033
|
+
rest of the screen. The bottom inset (+ safe area) is the kit's: every mobile
|
|
3034
|
+
dialog body carries it, flush or not, so the list adds none of its own. */
|
|
3039
3035
|
[data-layout='mobile'] .vela-sp-tabs { overflow-x: auto; scrollbar-width: none; gap: 6px; }
|
|
3040
3036
|
[data-layout='mobile'] .vela-sp-tabs::-webkit-scrollbar { display: none; }
|
|
3041
3037
|
[data-layout='mobile'] .vela-sp-tab { flex: none; padding: 7px 10px; }
|
|
3042
|
-
[data-layout='mobile'] .vela-sp-list { max-height: none; }
|
|
3038
|
+
[data-layout='mobile'] .vela-sp-list { flex: 1 1 auto; max-height: none; margin-bottom: 0; }
|
|
3043
3039
|
.vela-sp-tab {
|
|
3044
3040
|
all: unset;
|
|
3045
3041
|
padding: 3px 10px;
|
|
@@ -3051,7 +3047,12 @@ var CSS6 = `
|
|
|
3051
3047
|
}
|
|
3052
3048
|
.vela-sp-tab:hover { color: var(--vela-fg); }
|
|
3053
3049
|
.vela-sp-tab[data-active] { background: var(--vela-selected-bg); color: var(--vela-selected-fg); }
|
|
3054
|
-
.vela-sp-list {
|
|
3050
|
+
.vela-sp-list {
|
|
3051
|
+
min-height: 0;
|
|
3052
|
+
margin: var(--vela-space-2) var(--vela-space-4) var(--vela-space-4);
|
|
3053
|
+
max-height: 46vh;
|
|
3054
|
+
overflow: auto;
|
|
3055
|
+
}
|
|
3055
3056
|
.vela-sp-list::-webkit-scrollbar { width: 8px; }
|
|
3056
3057
|
.vela-sp-list::-webkit-scrollbar-thumb {
|
|
3057
3058
|
background: var(--vela-scroll);
|
|
@@ -3144,8 +3145,8 @@ var SymbolPicker = class {
|
|
|
3144
3145
|
searchRow.append(iconEl("search", doc), this.input);
|
|
3145
3146
|
this.tabs = doc.createElement("div");
|
|
3146
3147
|
this.tabs.className = "vela-sp-tabs";
|
|
3147
|
-
const
|
|
3148
|
-
|
|
3148
|
+
const head = doc.createElement("div");
|
|
3149
|
+
head.className = "vela-sp-head";
|
|
3149
3150
|
for (const t of ["All", "Stocks", "ETFs", "Crypto", "Futures", "Forex", "Commodities"]) {
|
|
3150
3151
|
const b = doc.createElement("button");
|
|
3151
3152
|
b.className = "vela-sp-tab";
|
|
@@ -3159,7 +3160,7 @@ var SymbolPicker = class {
|
|
|
3159
3160
|
});
|
|
3160
3161
|
this.tabs.appendChild(b);
|
|
3161
3162
|
}
|
|
3162
|
-
|
|
3163
|
+
head.append(searchRow, this.tabs);
|
|
3163
3164
|
this.list = doc.createElement("div");
|
|
3164
3165
|
this.list.className = "vela-sp-list";
|
|
3165
3166
|
this.list.addEventListener("scroll", () => {
|
|
@@ -3172,7 +3173,8 @@ var SymbolPicker = class {
|
|
|
3172
3173
|
title: "Symbol Search",
|
|
3173
3174
|
host: opts.host,
|
|
3174
3175
|
closeOnInteractOutside: true,
|
|
3175
|
-
|
|
3176
|
+
flush: true,
|
|
3177
|
+
content: (body) => body.append(head, this.list),
|
|
3176
3178
|
onOpenChange: (open) => {
|
|
3177
3179
|
if (open) {
|
|
3178
3180
|
this.input.value = this.seed.toUpperCase();
|
|
@@ -4824,9 +4826,6 @@ var ChartContextMenu = class {
|
|
|
4824
4826
|
}
|
|
4825
4827
|
};
|
|
4826
4828
|
|
|
4827
|
-
// src/core/options.ts
|
|
4828
|
-
var normalizeSession = (v) => v === "regular" || v === "extended" ? v : void 0;
|
|
4829
|
-
|
|
4830
4829
|
// src/widget/session-shading.ts
|
|
4831
4830
|
var DAY_MS = 864e5;
|
|
4832
4831
|
var MINUTE_MS = 6e4;
|
|
@@ -5482,8 +5481,8 @@ var ChartCell = class {
|
|
|
5482
5481
|
/** The volume auto-add rides the cell's first candles (`load:end`); until then the
|
|
5483
5482
|
* registry can't show it and the dehydrated ledger reports the INTENT instead. */
|
|
5484
5483
|
this.volumeMayBePending = true;
|
|
5485
|
-
/** Sync mirror of the chart's
|
|
5486
|
-
*
|
|
5484
|
+
/** Sync mirror of the chart's native instances (id + type) — the removal handler
|
|
5485
|
+
* looks the removed id up here to learn which type an undo must re-add. */
|
|
5487
5486
|
this.presentNatives = [];
|
|
5488
5487
|
this.rangeBars = 0;
|
|
5489
5488
|
this.pendingRange = null;
|
|
@@ -5655,15 +5654,18 @@ var ChartCell = class {
|
|
|
5655
5654
|
redo: () => this.dropInstance(snapshot)
|
|
5656
5655
|
});
|
|
5657
5656
|
} else {
|
|
5658
|
-
const
|
|
5659
|
-
|
|
5657
|
+
const gone = this.presentNatives.find((n) => n.id === id2);
|
|
5658
|
+
if (gone) {
|
|
5659
|
+
const { type } = gone;
|
|
5660
|
+
let revived = null;
|
|
5660
5661
|
this.history.push({
|
|
5661
5662
|
undo: () => {
|
|
5662
|
-
this.inner?.addNativeIndicator(type);
|
|
5663
|
+
revived = this.inner?.addNativeIndicator(type) ?? null;
|
|
5663
5664
|
this.refreshNativeCatalog();
|
|
5664
5665
|
},
|
|
5665
5666
|
redo: () => {
|
|
5666
|
-
|
|
5667
|
+
revived?.remove();
|
|
5668
|
+
revived = null;
|
|
5667
5669
|
this.refreshNativeCatalog();
|
|
5668
5670
|
}
|
|
5669
5671
|
});
|
|
@@ -5968,9 +5970,9 @@ var ChartCell = class {
|
|
|
5968
5970
|
const live = this.inner?.renderer.get("priceStyle");
|
|
5969
5971
|
return typeof live === "string" ? live : this.state.priceStyle ?? "candles";
|
|
5970
5972
|
}
|
|
5971
|
-
/** Manifest instances +
|
|
5973
|
+
/** Manifest instances + native instances — the topbar indicator count. */
|
|
5972
5974
|
get indicatorCount() {
|
|
5973
|
-
return this.instances.length + this.
|
|
5975
|
+
return this.instances.length + (this.inner ? this.nativeHandles().length : this.presentNatives.length);
|
|
5974
5976
|
}
|
|
5975
5977
|
/** Switch this cell's market in place (the chart instance survives). The projection
|
|
5976
5978
|
* is OPTIMISTIC — labels and chrome show the pick before the bars load; it follows
|
|
@@ -6102,13 +6104,15 @@ var ChartCell = class {
|
|
|
6102
6104
|
if (!chart) return;
|
|
6103
6105
|
this.volumeIntent = led.natives.includes("volume");
|
|
6104
6106
|
this.history.silently(() => {
|
|
6105
|
-
const
|
|
6106
|
-
for (const type of led.natives)
|
|
6107
|
-
|
|
6108
|
-
|
|
6109
|
-
|
|
6110
|
-
if (
|
|
6107
|
+
const owed = /* @__PURE__ */ new Map();
|
|
6108
|
+
for (const type of led.natives) owed.set(type, (owed.get(type) ?? 0) + 1);
|
|
6109
|
+
for (const h of this.nativeHandles()) {
|
|
6110
|
+
const type = h.nativeType;
|
|
6111
|
+
const n = owed.get(type) ?? 0;
|
|
6112
|
+
if (n > 0) owed.set(type, n - 1);
|
|
6113
|
+
else h.remove();
|
|
6111
6114
|
}
|
|
6115
|
+
for (const [type, n] of owed) for (let i = 0; i < n; i++) chart.addNativeIndicator(type);
|
|
6112
6116
|
for (const it of [...this.instances]) this.dropInstance(it);
|
|
6113
6117
|
if (this.manifest.length > 0) {
|
|
6114
6118
|
for (const item of led.manifest) {
|
|
@@ -6126,34 +6130,42 @@ var ChartCell = class {
|
|
|
6126
6130
|
this.syncPresentNatives();
|
|
6127
6131
|
this.refreshNativeCatalog();
|
|
6128
6132
|
}
|
|
6129
|
-
/** The picker
|
|
6133
|
+
/** The supported natives in picker order: A→Z by title — registration order follows
|
|
6134
|
+
* the catalog's families, which is meaningless to the reader. This is the library
|
|
6135
|
+
* index space the picker hands back, so `libraryRows` and `addFromLibrary` MUST both
|
|
6136
|
+
* read it — indexing the unsorted catalog on add would land on a different study. */
|
|
6137
|
+
supportedNatives() {
|
|
6138
|
+
return this.nativeCatalog.filter((n) => n.supported).sort((a, b) => a.title.localeCompare(b.title, "en", { sensitivity: "base" }));
|
|
6139
|
+
}
|
|
6140
|
+
/** The picker's library rows: supported natives first (see {@link supportedNatives}),
|
|
6141
|
+
* then the manifest in the host's own order. */
|
|
6130
6142
|
libraryRows() {
|
|
6131
6143
|
return [
|
|
6132
|
-
...this.
|
|
6144
|
+
...this.supportedNatives().map((n) => ({ name: n.title, category: "Vela", native: true, nativeType: n.type, beta: n.beta })),
|
|
6133
6145
|
...this.manifest.map((e) => ({ name: e.name, language: e.language, category: e.category }))
|
|
6134
6146
|
];
|
|
6135
6147
|
}
|
|
6136
|
-
/** The picker's on-chart rows:
|
|
6148
|
+
/** The picker's on-chart rows: native instances first, then live script instances. */
|
|
6137
6149
|
onChartRows() {
|
|
6138
6150
|
return [
|
|
6139
|
-
...this.
|
|
6151
|
+
...this.nativeHandles().map((h) => ({ name: h.title, native: true, nativeType: h.nativeType })),
|
|
6140
6152
|
...this.instances.map((it) => ({ name: it.entry.name, language: it.entry.language }))
|
|
6141
6153
|
];
|
|
6142
6154
|
}
|
|
6143
6155
|
/** Add by picker LIBRARY index (natives precede the manifest — mirrors libraryRows). */
|
|
6144
6156
|
addFromLibrary(index) {
|
|
6145
|
-
const natives = this.
|
|
6157
|
+
const natives = this.supportedNatives();
|
|
6146
6158
|
if (index < natives.length) this.addNative(natives[index].type);
|
|
6147
6159
|
else {
|
|
6148
6160
|
const entry = this.manifest[index - natives.length];
|
|
6149
6161
|
if (entry) this.addManifestInstance(entry);
|
|
6150
6162
|
}
|
|
6151
6163
|
}
|
|
6152
|
-
/** Remove by picker ON-CHART index (
|
|
6164
|
+
/** Remove by picker ON-CHART index (native instances precede script instances — mirrors onChartRows). */
|
|
6153
6165
|
removeFromChart(index) {
|
|
6154
|
-
const
|
|
6155
|
-
if (index <
|
|
6156
|
-
else this.removeInstance(index -
|
|
6166
|
+
const natives = this.nativeHandles();
|
|
6167
|
+
if (index < natives.length) this.removeNative(natives[index]);
|
|
6168
|
+
else this.removeInstance(index - natives.length);
|
|
6157
6169
|
}
|
|
6158
6170
|
/**
|
|
6159
6171
|
* Add a script indicator through the PUBLIC seam (`ctx.addIndicator`) — same undo/
|
|
@@ -6213,30 +6225,42 @@ var ChartCell = class {
|
|
|
6213
6225
|
it.handle = null;
|
|
6214
6226
|
this.deps.onIndicatorsChanged(this.id);
|
|
6215
6227
|
}
|
|
6216
|
-
/** Add a native indicator
|
|
6228
|
+
/** Add a native indicator. A multi-instance type gets a fresh instance every time; a
|
|
6229
|
+
* single-instance type already on the chart hands back its existing one — nothing
|
|
6230
|
+
* changed, so nothing enters the undo timeline. */
|
|
6217
6231
|
addNative(type) {
|
|
6218
|
-
this.inner
|
|
6232
|
+
const chart = this.inner;
|
|
6233
|
+
if (!chart) return;
|
|
6234
|
+
const before = new Set(chart.indicators().map((h) => h.id));
|
|
6235
|
+
let added = chart.addNativeIndicator(type);
|
|
6219
6236
|
this.syncPresentNatives();
|
|
6220
6237
|
this.refreshNativeCatalog();
|
|
6238
|
+
if (before.has(added.id)) return;
|
|
6221
6239
|
this.history.push({
|
|
6222
6240
|
undo: () => {
|
|
6223
|
-
|
|
6241
|
+
added?.remove();
|
|
6242
|
+
added = null;
|
|
6224
6243
|
this.refreshNativeCatalog();
|
|
6225
6244
|
},
|
|
6226
6245
|
redo: () => {
|
|
6227
|
-
this.inner?.addNativeIndicator(type);
|
|
6246
|
+
added = this.inner?.addNativeIndicator(type) ?? null;
|
|
6228
6247
|
this.refreshNativeCatalog();
|
|
6229
6248
|
}
|
|
6230
6249
|
});
|
|
6231
6250
|
}
|
|
6232
|
-
removeNative(
|
|
6233
|
-
|
|
6251
|
+
removeNative(handle) {
|
|
6252
|
+
handle.remove();
|
|
6234
6253
|
this.refreshNativeCatalog();
|
|
6235
6254
|
}
|
|
6236
|
-
/**
|
|
6237
|
-
*
|
|
6255
|
+
/** The chart's native instances, insertion order — the picker's on-chart rows and
|
|
6256
|
+
* the removal index space (script instances follow them). */
|
|
6257
|
+
nativeHandles() {
|
|
6258
|
+
return this.inner?.indicators().filter((h) => h.nativeType !== void 0) ?? [];
|
|
6259
|
+
}
|
|
6260
|
+
/** Sync mirror of the chart's native instances — the removal handler looks the
|
|
6261
|
+
* removed id up here (the registry has already forgotten it) to record its type. */
|
|
6238
6262
|
syncPresentNatives() {
|
|
6239
|
-
this.presentNatives = this.
|
|
6263
|
+
this.presentNatives = this.nativeHandles().map((h) => ({ id: h.id, type: h.nativeType }));
|
|
6240
6264
|
}
|
|
6241
6265
|
/** Refresh the native catalog (supported/present flags) for this cell's market. */
|
|
6242
6266
|
refreshNativeCatalog() {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { overlayScrollbarCss, injectStyles, isDarkColor, mix, HIGHLIGHT, ACCENT_BRIGHT, ACCENT, withAlpha, iconAt, iconEl, BULLISH, BEARISH, WARNING, NEUTRAL } from './chunk-
|
|
1
|
+
import { overlayScrollbarCss, injectStyles, isDarkColor, mix, HIGHLIGHT, ACCENT_BRIGHT, ACCENT, withAlpha, iconAt, iconEl, BULLISH, BEARISH, WARNING, NEUTRAL } from './chunk-CAFCLMPF.js';
|
|
2
2
|
import { VanillaMachine, normalizeProps, spreadProps } from '@zag-js/vanilla';
|
|
3
3
|
export { normalizeProps, spreadProps } from '@zag-js/vanilla';
|
|
4
4
|
import * as menu from '@zag-js/menu';
|
|
@@ -2185,8 +2185,21 @@ function buildColorPicker(color, theme, onChange) {
|
|
|
2185
2185
|
};
|
|
2186
2186
|
const recentRow = document.createElement("div");
|
|
2187
2187
|
recentRow.style.cssText = "display:flex;align-items:center;gap:5px;flex-wrap:wrap;border-top:1px solid var(--vela-border);padding-top:9px;";
|
|
2188
|
+
const recentSwatches = document.createElement("div");
|
|
2189
|
+
recentSwatches.style.cssText = "display:contents;";
|
|
2190
|
+
const add = document.createElement("label");
|
|
2191
|
+
add.style.cssText = `width:17px;height:17px;border-radius:var(--vela-radius-sm);border:1px dashed var(--vela-border-strong);cursor:pointer;display:flex;align-items:center;justify-content:center;color:${theme.textColor};font:14px ${theme.fontFamily};position:relative;`;
|
|
2192
|
+
add.textContent = "+";
|
|
2193
|
+
const customInput = document.createElement("input");
|
|
2194
|
+
customInput.type = "color";
|
|
2195
|
+
customInput.value = curHex;
|
|
2196
|
+
customInput.style.cssText = "position:absolute;inset:0;opacity:0;cursor:pointer;";
|
|
2197
|
+
customInput.addEventListener("input", () => previewHex(customInput.value));
|
|
2198
|
+
customInput.addEventListener("change", () => pickHex(customInput.value, true));
|
|
2199
|
+
add.appendChild(customInput);
|
|
2200
|
+
recentRow.append(recentSwatches, add);
|
|
2188
2201
|
const renderRecents = () => {
|
|
2189
|
-
|
|
2202
|
+
recentSwatches.replaceChildren();
|
|
2190
2203
|
for (const c of recents) {
|
|
2191
2204
|
const sw = document.createElement("button");
|
|
2192
2205
|
sw.type = "button";
|
|
@@ -2195,18 +2208,8 @@ function buildColorPicker(color, theme, onChange) {
|
|
|
2195
2208
|
e.stopPropagation();
|
|
2196
2209
|
pickHex(c);
|
|
2197
2210
|
});
|
|
2198
|
-
|
|
2211
|
+
recentSwatches.appendChild(sw);
|
|
2199
2212
|
}
|
|
2200
|
-
const add = document.createElement("label");
|
|
2201
|
-
add.style.cssText = `width:17px;height:17px;border-radius:var(--vela-radius-sm);border:1px dashed var(--vela-border-strong);cursor:pointer;display:flex;align-items:center;justify-content:center;color:${theme.textColor};font:14px ${theme.fontFamily};position:relative;`;
|
|
2202
|
-
add.textContent = "+";
|
|
2203
|
-
const input = document.createElement("input");
|
|
2204
|
-
input.type = "color";
|
|
2205
|
-
input.value = curHex;
|
|
2206
|
-
input.style.cssText = "position:absolute;inset:0;opacity:0;cursor:pointer;";
|
|
2207
|
-
input.addEventListener("input", () => pickHex(input.value, true));
|
|
2208
|
-
add.appendChild(input);
|
|
2209
|
-
recentRow.appendChild(add);
|
|
2210
2213
|
};
|
|
2211
2214
|
const opLabel = document.createElement("div");
|
|
2212
2215
|
opLabel.textContent = "Opacity";
|
|
@@ -2246,14 +2249,18 @@ function buildColorPicker(color, theme, onChange) {
|
|
|
2246
2249
|
function emit() {
|
|
2247
2250
|
onChange(combineColor(curHex, curAlpha));
|
|
2248
2251
|
}
|
|
2249
|
-
function
|
|
2252
|
+
function previewHex(hex) {
|
|
2250
2253
|
curHex = splitColor(hex).hex6;
|
|
2251
|
-
addRecent(curHex);
|
|
2252
2254
|
paintSelection();
|
|
2253
2255
|
paintOpacity();
|
|
2254
|
-
if (custom) renderRecents();
|
|
2255
2256
|
emit();
|
|
2256
2257
|
}
|
|
2258
|
+
function pickHex(hex, custom = false) {
|
|
2259
|
+
previewHex(hex);
|
|
2260
|
+
addRecent(curHex);
|
|
2261
|
+
customInput.value = curHex;
|
|
2262
|
+
if (custom) renderRecents();
|
|
2263
|
+
}
|
|
2257
2264
|
renderRecents();
|
|
2258
2265
|
paintSelection();
|
|
2259
2266
|
paintOpacity();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { normalizeProps, nextUid, runMachine, spreadProps } from './chunk-
|
|
2
|
-
import { injectStyles } from './chunk-
|
|
1
|
+
import { normalizeProps, nextUid, runMachine, spreadProps } from './chunk-T5Z5YUCF.js';
|
|
2
|
+
import { injectStyles } from './chunk-CAFCLMPF.js';
|
|
3
3
|
import * as tooltip from '@zag-js/tooltip';
|
|
4
4
|
import * as dialog from '@zag-js/dialog';
|
|
5
5
|
|