@luxalgo/vela 0.6.6 → 0.6.8

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.
Files changed (43) hide show
  1. package/dist/{DataProvider-JJq7M2it.d.ts → DataProvider-BSLlBpB9.d.ts} +10 -0
  2. package/dist/{DataProvider-DDUYw2qP.d.cts → DataProvider-BsQM2WNH.d.cts} +10 -0
  3. package/dist/{chunk-OEUGUXL7.js → chunk-L3I2CCYO.js} +49 -1
  4. package/dist/{chunk-TMXK2SJR.js → chunk-N7LGMKCE.js} +523 -142
  5. package/dist/{chunk-JQFO2WMU.js → chunk-SQETIBFU.js} +83 -9
  6. package/dist/chunk-W4EJWLEO.js +12 -0
  7. package/dist/{contributions-BqCIsbaP.d.ts → contributions-DLLdV9jD.d.ts} +59 -3
  8. package/dist/{contributions-DNMqrAuw.d.cts → contributions-Vw-Hm58R.d.cts} +59 -3
  9. package/dist/index.cjs +110 -8
  10. package/dist/index.d.cts +8 -4
  11. package/dist/index.d.ts +8 -4
  12. package/dist/index.js +2 -2
  13. package/dist/{plugin-CN8U2__Q.d.cts → plugin-BnJgjLAy.d.cts} +2 -2
  14. package/dist/{plugin-WnvNNJOp.d.ts → plugin-CC7rBrOY.d.ts} +2 -2
  15. package/dist/plugin.cjs +28 -0
  16. package/dist/plugin.d.cts +3 -3
  17. package/dist/plugin.d.ts +3 -3
  18. package/dist/plugin.js +1 -1
  19. package/dist/providers/binance.cjs +16 -0
  20. package/dist/providers/binance.d.cts +4 -1
  21. package/dist/providers/binance.d.ts +4 -1
  22. package/dist/providers/binance.js +7 -0
  23. package/dist/providers/coinbase.cjs +16 -0
  24. package/dist/providers/coinbase.d.cts +4 -1
  25. package/dist/providers/coinbase.d.ts +4 -1
  26. package/dist/providers/coinbase.js +7 -0
  27. package/dist/providers/hyperliquid.cjs +16 -0
  28. package/dist/providers/hyperliquid.d.cts +4 -1
  29. package/dist/providers/hyperliquid.d.ts +4 -1
  30. package/dist/providers/hyperliquid.js +7 -0
  31. package/dist/{bottombar-COnL2Sk4.d.ts → statusline-CGkB2EOo.d.ts} +137 -8
  32. package/dist/{bottombar-DeDXbF_K.d.cts → statusline-DqzBqy42.d.cts} +137 -8
  33. package/dist/vela.global.js +136 -8
  34. package/dist/vela.global.min.js +42 -42
  35. package/dist/widget.cjs +667 -148
  36. package/dist/widget.d.cts +50 -81
  37. package/dist/widget.d.ts +50 -81
  38. package/dist/widget.js +5 -4
  39. package/dist/workspace.cjs +613 -150
  40. package/dist/workspace.d.cts +62 -9
  41. package/dist/workspace.d.ts +62 -9
  42. package/dist/workspace.js +4 -3
  43. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import { deserializeDrawing, chartTypes, rendererLayers, foldBaseModulation, registerChartType, rendererDefaults, getDrawingType, settingsRowVisible, normalizeSettingsRow, TextLabel, Callout, resetDrawingSettings, registerNativeIndicator, chartType, getNativeIndicator, nativeIndicatorDescriptors, drawingTypes, settingsRowValueKeys, formatDuration, RegressionChannel, FixedRangeVolumeProfile, SegmentDrawing, ArrowMark, GlyphStamp, RadialFib, FibSpiral, DedekindTessellation, MachFigure, GannSquare, FibRatios, MeasureBox, PositionTool, AnchoredVwap, PatternDrawing, Comment, PriceNote, Signpost, Note, PriceLabel, GANN_SQUARE_ARCS, lineSegmentIntersection, DEFAULT_DRAWING_COLOR, GLYPH_OPTIONS, STAMP_SIZE_OPTIONS, LINE_STYLE_OPTIONS, DEDEKIND_CURVATURE_OPTIONS, MACH_NUMBER_OPTIONS, MACH_WAVE_COUNT_OPTIONS, TEXT_SIZE_OPTIONS, createDrawing, inputVisible, tickerModifierIds, CalloutBase, DIRECTION_OPTIONS } from './chunk-OEUGUXL7.js';
1
+ import { deserializeDrawing, chartTypes, rendererLayers, foldBaseModulation, registerChartType, rendererDefaults, getDrawingType, settingsRowVisible, normalizeSettingsRow, TextLabel, Callout, resetDrawingSettings, registerNativeIndicator, chartType, getNativeIndicator, nativeIndicatorDescriptors, drawingTypes, settingsRowValueKeys, formatDuration, RegressionChannel, FixedRangeVolumeProfile, SegmentDrawing, ArrowMark, GlyphStamp, RadialFib, FibSpiral, DedekindTessellation, MachFigure, GannSquare, FibRatios, MeasureBox, PositionTool, AnchoredVwap, PatternDrawing, Comment, PriceNote, Signpost, Note, PriceLabel, GANN_SQUARE_ARCS, lineSegmentIntersection, DEFAULT_DRAWING_COLOR, GLYPH_OPTIONS, STAMP_SIZE_OPTIONS, LINE_STYLE_OPTIONS, DEDEKIND_CURVATURE_OPTIONS, MACH_NUMBER_OPTIONS, MACH_WAVE_COUNT_OPTIONS, TEXT_SIZE_OPTIONS, createDrawing, inputVisible, tickerModifierIds, CalloutBase, DIRECTION_OPTIONS } from './chunk-L3I2CCYO.js';
2
2
  import { themeTokens, Dialog, closeOpenPopovers, closeWidthPopover, fieldSection, buildFieldControl, fieldSeparator, fieldGrid, fieldRow, blendOver, splitColor, Menu, TextArea, Popover, NumberInput, buildColorPicker, isPopoverOpen, eventDismissedPopover, toggleSelectList, openPopoverTrigger, fieldGridColumns, FIELD_GAP_PX, STATIC_TOKENS } from './chunk-OICPLNU7.js';
3
3
  import { icon, iconAt, withAlpha, WARNING, ACCENT, NEUTRAL, BEARISH, BULLISH, isDarkColor, SERIES_LINE, SLATE, CROSSHAIR, TRADE_EXIT, TRADE_SHORT, TRADE_LONG, overlayScrollbarCss, SLATE_DEEP, VALID, INVALID, FIELD_FOCUS_CSS, FIELD_FOCUS_RING, svg24, svg24Solid } from './chunk-PN5KWFZ4.js';
4
4
 
@@ -865,6 +865,28 @@ var ProviderRegistry = class {
865
865
  const d = this.entries.get(resolved.provider)?.byTicker?.get(normTicker(resolved.ticker));
866
866
  return `${d?.prefix ?? resolved.provider}:${d?.ticker ?? resolved.ticker}`;
867
867
  }
868
+ /** The icon URL for a DESCRIPTOR — routed to its OWNING provider's resolver (the
869
+ * provider owns the knowledge of where its asset class's icons live). A missing
870
+ * provider, an absent resolver, or a resolver that throws all mean "no icon" —
871
+ * the shells' initials badge takes over, never an error. */
872
+ symbolIconOf(d) {
873
+ const name = d.provider ? normName(d.provider) : [...this.entries.keys()][0];
874
+ const entry = name !== void 0 ? this.entries.get(name) : void 0;
875
+ try {
876
+ return entry?.provider.resolveSymbolIcon?.(d) ?? void 0;
877
+ } catch {
878
+ return void 0;
879
+ }
880
+ }
881
+ /** The icon URL for a raw SYMBOL string (the statusline/object-tree path): resolve
882
+ * to the owning provider, find its descriptor, route to the resolver. Before the
883
+ * index settles (or for a lenient sole-provider resolution) a minimal synthetic
884
+ * descriptor is offered — crypto resolvers can answer from the ticker alone. */
885
+ symbolIcon(resolved) {
886
+ if (!resolved) return void 0;
887
+ const d = this.entries.get(resolved.provider)?.byTicker?.get(normTicker(resolved.ticker));
888
+ return this.symbolIconOf({ ...d ?? { ticker: resolved.ticker }, provider: d?.provider ?? resolved.provider });
889
+ }
868
890
  /** Indexed symbols for one provider (or all, concatenated) — for autocomplete. */
869
891
  symbolsOf(rawName) {
870
892
  if (rawName != null) return this.entries.get(normName(rawName))?.descriptors ?? [];
@@ -1107,6 +1129,14 @@ var MultiProviderFeed = class {
1107
1129
  providerInstance(name) {
1108
1130
  return this.registry.get(name);
1109
1131
  }
1132
+ /** The icon URL for a DESCRIPTOR — its owning provider's `resolveSymbolIcon` (picker rows). */
1133
+ symbolIconOf(d) {
1134
+ return this.registry.symbolIconOf(d);
1135
+ }
1136
+ /** The icon URL for a raw SYMBOL string — resolve, then route (statusline, object tree). */
1137
+ symbolIcon(raw) {
1138
+ return this.registry.symbolIcon(this.resolveSymbol(raw));
1139
+ }
1110
1140
  symbols(name) {
1111
1141
  return this.registry.symbolsOf(name);
1112
1142
  }
@@ -1333,6 +1363,12 @@ var DataControl = class {
1333
1363
  symbols(provider) {
1334
1364
  return this.registry?.symbols(provider) ?? [];
1335
1365
  }
1366
+ /** The icon URL for `symbol` — its owning provider's `resolveSymbolIcon`, routed
1367
+ * through resolution. Undefined while unresolvable, when the provider declares no
1368
+ * resolver, or on a custom `deps.dataFeed` — the shells then show initials. */
1369
+ symbolIcon(symbol) {
1370
+ return this.registry?.symbolIcon(symbol);
1371
+ }
1336
1372
  /** Per-symbol metadata (Pine `syminfo.*`), resolved through the owning provider. */
1337
1373
  symbolInfo(symbol) {
1338
1374
  return this.registry?.symbolInfoFor(symbol) ?? Promise.resolve(void 0);
@@ -2917,12 +2953,16 @@ var IndicatorInputsDialog = class {
2917
2953
  closeOnEscape: false,
2918
2954
  footer: (foot) => {
2919
2955
  foot.append(
2956
+ this.resetAction(),
2920
2957
  this.dialogButton("Cancel", false, () => this.revertAndClose()),
2921
2958
  this.dialogButton("Ok", true, () => this.close())
2922
2959
  );
2923
2960
  },
2961
+ // Stale-guard: destroying a dialog fires its machine's onOpenChange(false)
2962
+ // asynchronously — after a reset rebuild that notification must not close
2963
+ // the replacement dialog.
2924
2964
  onOpenChange: (open) => {
2925
- if (!open) this.close();
2965
+ if (!open && this.uiDialog === ui) this.close();
2926
2966
  }
2927
2967
  });
2928
2968
  applyChromeTokens(ui.panel, t);
@@ -3053,6 +3093,30 @@ var IndicatorInputsDialog = class {
3053
3093
  }
3054
3094
  this.close();
3055
3095
  }
3096
+ /** The footer's reset button — same chip as Cancel, pinned to the LEFT edge
3097
+ * (`margin-right:auto` against the footer's flex-end keeps Cancel/Ok right). */
3098
+ resetAction() {
3099
+ const b = this.dialogButton("Reset defaults", false, () => this.resetToDefaults());
3100
+ b.style.marginRight = "auto";
3101
+ return b;
3102
+ }
3103
+ /** Restore every input to its declared default (re-running the indicator), then
3104
+ * re-open the form so each control re-reads the restored values — the same
3105
+ * rebuild-after-reset move as the chart-settings dialog. The open-time snapshot
3106
+ * survives the rebuild, so Cancel after a reset still reverts the whole session. */
3107
+ resetToDefaults() {
3108
+ const row = this.row;
3109
+ if (!row) return;
3110
+ const snap = this.snapshot;
3111
+ for (const inp of row.inputs) {
3112
+ if (row.values[inp.key] !== inp.defval) {
3113
+ row.values[inp.key] = inp.defval;
3114
+ this.host.onChange?.({ indicatorId: row.id, key: inp.key, value: inp.defval });
3115
+ }
3116
+ }
3117
+ this.open(row);
3118
+ if (snap) this.snapshot = snap;
3119
+ }
3056
3120
  /** Write one edit through: store it, notify the host, and re-apply the `when` gates. */
3057
3121
  commit(row, key, value) {
3058
3122
  row.values[key] = value;
@@ -14769,6 +14833,11 @@ function resizeSplit(split, dyTotal, minPx = MIN_PANE_PX) {
14769
14833
  }
14770
14834
 
14771
14835
  // src/renderers/native/backdrop/BackdropRenderer.ts
14836
+ function clipHighlightRect(x1, x2, left, right) {
14837
+ const x = Math.max(left, x1);
14838
+ const end = Math.min(right, x2);
14839
+ return end > x ? { x, width: end - x } : null;
14840
+ }
14772
14841
  var BackdropRenderer = class {
14773
14842
  constructor() {
14774
14843
  this.canvas = null;
@@ -14801,17 +14870,22 @@ var BackdropRenderer = class {
14801
14870
  /** Renderer-owned session highlight bands: full-height (all panes), behind the grid.
14802
14871
  * Session-zone washes (pre/post-market) paint first, host highlights on top. */
14803
14872
  drawHighlights(ctx, scene, coords) {
14804
- const bands = [...scene.sessionHighlightBands(), ...scene.highlights];
14805
- if (bands.length === 0) return;
14873
+ const sessions = scene.sessionHighlightBands();
14874
+ if (sessions.length > 0) {
14875
+ const left = Math.max(0, coords.logicalToX(-0.5));
14876
+ const right = Math.min(coords.width, coords.logicalToX(coords.barCount - 0.5));
14877
+ this.drawHighlightSet(ctx, sessions, coords, left, right);
14878
+ }
14879
+ this.drawHighlightSet(ctx, scene.highlights, coords, 0, coords.width);
14880
+ }
14881
+ drawHighlightSet(ctx, bands, coords, left, right) {
14806
14882
  for (const band of bands) {
14807
14883
  const x1 = coords.timeToX(band.from);
14808
14884
  const x2 = coords.timeToX(band.to);
14809
- if (x2 < 0 || x1 > coords.width || x2 <= x1) continue;
14810
- const cx = Math.max(0, x1);
14811
- const cw = Math.min(coords.width, x2) - cx;
14812
- if (cw <= 0) continue;
14885
+ const rect = clipHighlightRect(x1, x2, left, right);
14886
+ if (!rect) continue;
14813
14887
  ctx.fillStyle = band.color;
14814
- ctx.fillRect(cx, 0, cw, coords.height);
14888
+ ctx.fillRect(rect.x, 0, rect.width, coords.height);
14815
14889
  }
14816
14890
  }
14817
14891
  // ── grid ── vert/horz gate on `scene.showGrid` AND their own per-axis visibility
@@ -0,0 +1,12 @@
1
+ // src/data/symbol-base.ts
2
+ function baseOf(d) {
3
+ const fromDesc = d.description?.split("/")[0]?.trim();
4
+ if (fromDesc) return fromDesc.replace(/\s+Perpetual$/i, "");
5
+ return d.ticker.replace(/[-_/]?(USDT|USDC|USD1|USDS|BUSD|USD|EUR|PERP)$/i, "") || d.ticker;
6
+ }
7
+ function ledgerCryptoIconUrl(base) {
8
+ const key = base.trim().toUpperCase();
9
+ return key ? `https://crypto-icons.ledger.com/${encodeURIComponent(key)}.png` : void 0;
10
+ }
11
+
12
+ export { baseOf, ledgerCryptoIconUrl };
@@ -1,5 +1,5 @@
1
1
  import { t as Millis, ae as InputSchema, ac as IndicatorMeta, P as PriceStyle, O as OHLCV, m as InputValue, k as IndicatorModel, j as MoveTarget, aq as PaneAxis, aD as SeriesSpec, aa as Fill, B as Background, av as PriceLine, a0 as DrawingLine, Y as DrawingBox, $ as DrawingLabel, a4 as DrawingPolyline, a1 as DrawingLinefill, a6 as DrawingTable, g as IndicatorStatus, a as VisibleRange, c as VelaTheme, S as SerializedDrawing, v as DrawingTypeKey, u as SnapMode, a2 as DrawingMode, I as IChartRenderer, R as RendererCapabilities, o as LegendActionView, U as Unsubscribe, C as CrosshairEvent, A as AxisLongPressEvent, r as DataWindowReadout, n as SymbolPickerFn, aR as PaneInfo, a9 as DrawingsOption, D as Drawing, b as VelaOptions, x as AddIndicatorOptions, ap as MarketSwitch, ao as MarketSnapshot, V as VisibleRangePreset, T as ThemeName } from './options-BaVTMXaO.js';
2
- import { S as SymbolInfo, B as BarRange, M as MarketDataFeed, D as DataProvider, P as ProviderInfo, a as SymbolDescriptor, b as ProviderCapabilities } from './DataProvider-JJq7M2it.js';
2
+ import { S as SymbolInfo, B as BarRange, M as MarketDataFeed, D as DataProvider, P as ProviderInfo, a as SymbolDescriptor, b as ProviderCapabilities } from './DataProvider-BSLlBpB9.js';
3
3
 
4
4
  /**
5
5
  * A strategy's broker state at ONE bar — the flat summary a host reads while a script
@@ -361,6 +361,10 @@ declare class DataControl {
361
361
  providerInstance(name: string): DataProvider | undefined;
362
362
  /** Indexed symbols for one provider (or all) — for autocomplete. */
363
363
  symbols(provider?: string): SymbolDescriptor[];
364
+ /** The icon URL for `symbol` — its owning provider's `resolveSymbolIcon`, routed
365
+ * through resolution. Undefined while unresolvable, when the provider declares no
366
+ * resolver, or on a custom `deps.dataFeed` — the shells then show initials. */
367
+ symbolIcon(symbol: string): string | undefined;
364
368
  /** Per-symbol metadata (Pine `syminfo.*`), resolved through the owning provider. */
365
369
  symbolInfo(symbol: string): Promise<SymbolInfo | undefined>;
366
370
  /**
@@ -1435,6 +1439,10 @@ interface WidgetContext {
1435
1439
  * a shell may replace its chart instance, and a captured one would be destroyed.
1436
1440
  * (Symbol and timeframe switches are applied IN PLACE — the instance survives them.) */
1437
1441
  chart: Vela;
1442
+ /** LIVE getters, like `chart` — they resolve the ACTIVE cell's market at every
1443
+ * read, so an attachment that holds its mount context keeps reading the truth
1444
+ * after a symbol/timeframe switch. Read them at the point of use; never copy
1445
+ * them into long-lived state. */
1438
1446
  symbol: string;
1439
1447
  timeframe: string;
1440
1448
  priceStyle: string;
@@ -1481,9 +1489,18 @@ interface WidgetActionDescriptor {
1481
1489
  /** Stable id — re-registering an id replaces it. */
1482
1490
  id: string;
1483
1491
  target: WidgetActionTarget;
1492
+ /** Always required, even icon-only: it is the button's aria-label and tooltip, the
1493
+ * mobile drawer row's text, and the context-menu item's label. */
1484
1494
  label: string;
1485
1495
  /** Icon id from the `vela/ui` icon registry (register yours with `registerIcon`). */
1486
1496
  icon?: string;
1497
+ /** Topbar only: render the DESKTOP button icon-only, like the built-in tools — the
1498
+ * `label` moves to the aria-label and a kit tooltip instead of button text (mobile
1499
+ * surfaces keep their text). The right cluster gets the native 32px tool look; the
1500
+ * left cluster keeps the primary chrome, minus the text. Requires `icon` — without
1501
+ * one the flag is ignored (with a console warning) and the label renders. The piece
1502
+ * that makes a `'screenshot'` slot override pixel-faithful to the native button. */
1503
+ iconOnly?: boolean;
1487
1504
  /** Sort key within the contributed group (ascending; default 0). */
1488
1505
  order?: number;
1489
1506
  /** Topbar only: which cluster the button joins. `'right'` (default) is the
@@ -1577,7 +1594,24 @@ declare function registerSidePanel(desc: SidePanelDescriptor): () => void;
1577
1594
  declare function unregisterSidePanel(id: string): void;
1578
1595
  /** Every registered side panel, `order`-sorted (registration order breaks ties). */
1579
1596
  declare function sidePanels(): SidePanelDescriptor[];
1580
- /** Register (or replace) a widget action. Widgets read the registry live. */
1597
+ /** The built-in topbar slots a contributed action may TAKE OVER by registering under
1598
+ * their id — the "simple button" slots. The composites (symbol, timeframes, style,
1599
+ * layout, undo-redo, alerts, panels) are stateful controls the shell pushes state
1600
+ * into; a plain `{label, icon, run}` descriptor cannot stand in for them. */
1601
+ declare const OVERRIDABLE_TOPBAR_IDS: readonly ["indicators", "screenshot"];
1602
+ /**
1603
+ * The action OVERRIDING a built-in topbar slot, if one is registered — an action whose
1604
+ * `id` IS the built-in id. An override takes the slot's WHOLE surface: the desktop
1605
+ * button (at the slot's position), the mobile counterpart, and the keyboard chord all
1606
+ * route to `run`, and the native machinery behind the slot (the built-in indicator
1607
+ * picker) is not constructed. Shells resolve this at construction — register at import
1608
+ * time, like every contribution.
1609
+ */
1610
+ declare function topbarActionOverride(id: string): WidgetActionDescriptor | undefined;
1611
+ /** Register (or replace) a widget action. Widgets read the registry live.
1612
+ * Registering under a RESERVED built-in topbar id (`'indicators'`, `'screenshot'`)
1613
+ * OVERRIDES that slot — see {@link topbarActionOverride}. Built-in ids that are
1614
+ * stateful composites cannot be overridden and the registration is refused. */
1581
1615
  declare function registerWidgetAction(desc: WidgetActionDescriptor): () => void;
1582
1616
  declare function unregisterWidgetAction(id: string): void;
1583
1617
  /** Actions for one target, `order`-sorted, `when`-filtered when a context is given. */
@@ -1669,6 +1703,28 @@ declare function unregisterStatePersistence(key: string): void;
1669
1703
  declare function statePersistenceHandlers<S extends StatePersistenceHandler['scope']>(scope: S): Array<Extract<StatePersistenceHandler, {
1670
1704
  scope: S;
1671
1705
  }>>;
1706
+ /**
1707
+ * Reorder the symbol picker's AGGREGATED pool — every source combined, exactly what
1708
+ * the search dialog displays. Called when the pool changes (a provider's index lands
1709
+ * or refreshes), NOT per keystroke: the picker caches the result. May be async (a
1710
+ * server-fetched top list) — the picker shows the current order and refreshes when
1711
+ * the promise resolves.
1712
+ *
1713
+ * The returned list may INJECT descriptors absent from the pool (they must carry
1714
+ * their `provider` and be genuinely servable, or selecting them parks the load) and
1715
+ * may OMIT entries (hiding them). The picker dedupes by venue+ticker, FIRST
1716
+ * occurrence winning — injecting at the head fixes both position and display data.
1717
+ *
1718
+ * While a ranking is registered, the picker's built-in empty-query pin (the hardcoded
1719
+ * majors) stands down: the head of YOUR list is the dialog's opening screen. Under a
1720
+ * typed query the relevance tiers still lead — the ranking orders within each tier.
1721
+ */
1722
+ type SymbolRankingHook = (pool: SymbolDescriptor[]) => SymbolDescriptor[] | Promise<SymbolDescriptor[]>;
1723
+ /** Register (or replace — ONE ranking at a time, last wins) the symbol ranking.
1724
+ * Returns an unregister disposer. Register at import time, like every contribution. */
1725
+ declare function registerSymbolRanking(hook: SymbolRankingHook): () => void;
1726
+ /** The registered ranking, if any — what the shells' symbol picker consults. */
1727
+ declare function symbolRanking(): SymbolRankingHook | undefined;
1672
1728
  /** Makes ONE engine instance for ONE chart — engines hold per-chart sessions (and
1673
1729
  * possibly a worker), so the shell calls the factory per chart build, never shares. */
1674
1730
  type EngineFactory = () => ScriptingEngine;
@@ -1686,4 +1742,4 @@ declare function unregisterDefaultEngine(language: string): void;
1686
1742
  * language. The shell layers (widget, workspace cell) register exactly this result. */
1687
1743
  declare function resolveEngines(overrides?: Record<string, EngineFactory>): Record<string, EngineFactory>;
1688
1744
 
1689
- export { type WidgetAttachment as $, type SidePanelButton as A, type BarsChangeReason as B, type CellStateContext as C, type DrawingsDocument as D, type ExternalIndicatorEntry as E, type FetchSeries as F, type SidePanelDescriptor as G, type SidePanelHandle as H, type IndicatorHandle as I, type SidePanelHeader as J, type StatePersistenceHandler as K, type LegendActionDescriptor as L, type StrategyFill as M, type NativeIndicator as N, type StrategyState as O, type ParsedSymbol as P, type StrategyTrade as Q, type Resolved as R, type ScriptingEngine as S, TypedEventBus as T, type VelaDeps as U, Vela as V, type WidgetContext as W, type VelaEventMap as X, type VisibleBarRange as Y, type WidgetActionDescriptor as Z, type WidgetActionTarget as _, type ScriptRun as a, getNativeIndicator as a0, legendActions as a1, nativeIndicatorDescriptors as a2, nativeIndicatorTypes as a3, registerDefaultEngine as a4, registerLegendAction as a5, registerNativeIndicator as a6, registerSidePanel as a7, registerStatePersistence as a8, registerWidgetAction as a9, registerWidgetAttachment as aa, resolveEngines as ab, sidePanels as ac, statePersistenceHandlers as ad, unregisterDefaultEngine as ae, unregisterLegendAction as af, unregisterNativeIndicator as ag, unregisterSidePanel as ah, unregisterStatePersistence as ai, unregisterWidgetAction as aj, unregisterWidgetAttachment as ak, widgetActions as al, widgetAttachments as am, DEFAULT_PANEL_ORDER as an, type ContextSelect as b, DataControl as c, DrawingsControl as d, type EngineAlert as e, type EngineCapabilities as f, type EngineContextSnapshot as g, type EngineFactory as h, type EngineWarning as i, type ExecutionHandlers as j, type ExecutionMarket as k, type ExecutionRequest as l, type ExecutionSession as m, type IndicatorEventMap as n, type IndicatorSummary as o, type LegendIndicatorInfo as p, type NativeIndicatorContext as q, type NativeIndicatorDescriptor as r, type NativeIndicatorInfo as s, type NativeIndicatorOutput as t, type PreparedScript as u, RendererControl as v, type RunIndicatorResult as w, type SceneInspection as x, type ScriptRunCause as y, type ScriptRunResult as z };
1745
+ export { type WidgetActionDescriptor as $, type SidePanelButton as A, type BarsChangeReason as B, type CellStateContext as C, type DrawingsDocument as D, type ExternalIndicatorEntry as E, type FetchSeries as F, type SidePanelDescriptor as G, type SidePanelHandle as H, type IndicatorHandle as I, type SidePanelHeader as J, type StatePersistenceHandler as K, type LegendActionDescriptor as L, type StrategyFill as M, type NativeIndicator as N, OVERRIDABLE_TOPBAR_IDS as O, type ParsedSymbol as P, type StrategyState as Q, type Resolved as R, type ScriptingEngine as S, type StrategyTrade as T, type SymbolRankingHook as U, Vela as V, type WidgetContext as W, TypedEventBus as X, type VelaDeps as Y, type VelaEventMap as Z, type VisibleBarRange as _, type ScriptRun as a, type WidgetActionTarget as a0, type WidgetAttachment as a1, getNativeIndicator as a2, legendActions as a3, nativeIndicatorDescriptors as a4, nativeIndicatorTypes as a5, registerDefaultEngine as a6, registerLegendAction as a7, registerNativeIndicator as a8, registerSidePanel as a9, registerStatePersistence as aa, registerSymbolRanking as ab, registerWidgetAction as ac, registerWidgetAttachment as ad, resolveEngines as ae, sidePanels as af, statePersistenceHandlers as ag, symbolRanking as ah, topbarActionOverride as ai, unregisterDefaultEngine as aj, unregisterLegendAction as ak, unregisterNativeIndicator as al, unregisterSidePanel as am, unregisterStatePersistence as an, unregisterWidgetAction as ao, unregisterWidgetAttachment as ap, widgetActions as aq, widgetAttachments as ar, DEFAULT_PANEL_ORDER as as, type ContextSelect as b, DataControl as c, DrawingsControl as d, type EngineAlert as e, type EngineCapabilities as f, type EngineContextSnapshot as g, type EngineFactory as h, type EngineWarning as i, type ExecutionHandlers as j, type ExecutionMarket as k, type ExecutionRequest as l, type ExecutionSession as m, type IndicatorEventMap as n, type IndicatorSummary as o, type LegendIndicatorInfo as p, type NativeIndicatorContext as q, type NativeIndicatorDescriptor as r, type NativeIndicatorInfo as s, type NativeIndicatorOutput as t, type PreparedScript as u, RendererControl as v, type RunIndicatorResult as w, type SceneInspection as x, type ScriptRunCause as y, type ScriptRunResult as z };
@@ -1,5 +1,5 @@
1
1
  import { t as Millis, ae as InputSchema, ac as IndicatorMeta, P as PriceStyle, O as OHLCV, m as InputValue, k as IndicatorModel, j as MoveTarget, aq as PaneAxis, aD as SeriesSpec, aa as Fill, B as Background, av as PriceLine, a0 as DrawingLine, Y as DrawingBox, $ as DrawingLabel, a4 as DrawingPolyline, a1 as DrawingLinefill, a6 as DrawingTable, g as IndicatorStatus, a as VisibleRange, c as VelaTheme, S as SerializedDrawing, v as DrawingTypeKey, u as SnapMode, a2 as DrawingMode, I as IChartRenderer, R as RendererCapabilities, o as LegendActionView, U as Unsubscribe, C as CrosshairEvent, A as AxisLongPressEvent, r as DataWindowReadout, n as SymbolPickerFn, aR as PaneInfo, a9 as DrawingsOption, D as Drawing, b as VelaOptions, x as AddIndicatorOptions, ap as MarketSwitch, ao as MarketSnapshot, V as VisibleRangePreset, T as ThemeName } from './options-BaVTMXaO.cjs';
2
- import { S as SymbolInfo, B as BarRange, M as MarketDataFeed, D as DataProvider, P as ProviderInfo, a as SymbolDescriptor, b as ProviderCapabilities } from './DataProvider-DDUYw2qP.cjs';
2
+ import { S as SymbolInfo, B as BarRange, M as MarketDataFeed, D as DataProvider, P as ProviderInfo, a as SymbolDescriptor, b as ProviderCapabilities } from './DataProvider-BsQM2WNH.cjs';
3
3
 
4
4
  /**
5
5
  * A strategy's broker state at ONE bar — the flat summary a host reads while a script
@@ -361,6 +361,10 @@ declare class DataControl {
361
361
  providerInstance(name: string): DataProvider | undefined;
362
362
  /** Indexed symbols for one provider (or all) — for autocomplete. */
363
363
  symbols(provider?: string): SymbolDescriptor[];
364
+ /** The icon URL for `symbol` — its owning provider's `resolveSymbolIcon`, routed
365
+ * through resolution. Undefined while unresolvable, when the provider declares no
366
+ * resolver, or on a custom `deps.dataFeed` — the shells then show initials. */
367
+ symbolIcon(symbol: string): string | undefined;
364
368
  /** Per-symbol metadata (Pine `syminfo.*`), resolved through the owning provider. */
365
369
  symbolInfo(symbol: string): Promise<SymbolInfo | undefined>;
366
370
  /**
@@ -1435,6 +1439,10 @@ interface WidgetContext {
1435
1439
  * a shell may replace its chart instance, and a captured one would be destroyed.
1436
1440
  * (Symbol and timeframe switches are applied IN PLACE — the instance survives them.) */
1437
1441
  chart: Vela;
1442
+ /** LIVE getters, like `chart` — they resolve the ACTIVE cell's market at every
1443
+ * read, so an attachment that holds its mount context keeps reading the truth
1444
+ * after a symbol/timeframe switch. Read them at the point of use; never copy
1445
+ * them into long-lived state. */
1438
1446
  symbol: string;
1439
1447
  timeframe: string;
1440
1448
  priceStyle: string;
@@ -1481,9 +1489,18 @@ interface WidgetActionDescriptor {
1481
1489
  /** Stable id — re-registering an id replaces it. */
1482
1490
  id: string;
1483
1491
  target: WidgetActionTarget;
1492
+ /** Always required, even icon-only: it is the button's aria-label and tooltip, the
1493
+ * mobile drawer row's text, and the context-menu item's label. */
1484
1494
  label: string;
1485
1495
  /** Icon id from the `vela/ui` icon registry (register yours with `registerIcon`). */
1486
1496
  icon?: string;
1497
+ /** Topbar only: render the DESKTOP button icon-only, like the built-in tools — the
1498
+ * `label` moves to the aria-label and a kit tooltip instead of button text (mobile
1499
+ * surfaces keep their text). The right cluster gets the native 32px tool look; the
1500
+ * left cluster keeps the primary chrome, minus the text. Requires `icon` — without
1501
+ * one the flag is ignored (with a console warning) and the label renders. The piece
1502
+ * that makes a `'screenshot'` slot override pixel-faithful to the native button. */
1503
+ iconOnly?: boolean;
1487
1504
  /** Sort key within the contributed group (ascending; default 0). */
1488
1505
  order?: number;
1489
1506
  /** Topbar only: which cluster the button joins. `'right'` (default) is the
@@ -1577,7 +1594,24 @@ declare function registerSidePanel(desc: SidePanelDescriptor): () => void;
1577
1594
  declare function unregisterSidePanel(id: string): void;
1578
1595
  /** Every registered side panel, `order`-sorted (registration order breaks ties). */
1579
1596
  declare function sidePanels(): SidePanelDescriptor[];
1580
- /** Register (or replace) a widget action. Widgets read the registry live. */
1597
+ /** The built-in topbar slots a contributed action may TAKE OVER by registering under
1598
+ * their id — the "simple button" slots. The composites (symbol, timeframes, style,
1599
+ * layout, undo-redo, alerts, panels) are stateful controls the shell pushes state
1600
+ * into; a plain `{label, icon, run}` descriptor cannot stand in for them. */
1601
+ declare const OVERRIDABLE_TOPBAR_IDS: readonly ["indicators", "screenshot"];
1602
+ /**
1603
+ * The action OVERRIDING a built-in topbar slot, if one is registered — an action whose
1604
+ * `id` IS the built-in id. An override takes the slot's WHOLE surface: the desktop
1605
+ * button (at the slot's position), the mobile counterpart, and the keyboard chord all
1606
+ * route to `run`, and the native machinery behind the slot (the built-in indicator
1607
+ * picker) is not constructed. Shells resolve this at construction — register at import
1608
+ * time, like every contribution.
1609
+ */
1610
+ declare function topbarActionOverride(id: string): WidgetActionDescriptor | undefined;
1611
+ /** Register (or replace) a widget action. Widgets read the registry live.
1612
+ * Registering under a RESERVED built-in topbar id (`'indicators'`, `'screenshot'`)
1613
+ * OVERRIDES that slot — see {@link topbarActionOverride}. Built-in ids that are
1614
+ * stateful composites cannot be overridden and the registration is refused. */
1581
1615
  declare function registerWidgetAction(desc: WidgetActionDescriptor): () => void;
1582
1616
  declare function unregisterWidgetAction(id: string): void;
1583
1617
  /** Actions for one target, `order`-sorted, `when`-filtered when a context is given. */
@@ -1669,6 +1703,28 @@ declare function unregisterStatePersistence(key: string): void;
1669
1703
  declare function statePersistenceHandlers<S extends StatePersistenceHandler['scope']>(scope: S): Array<Extract<StatePersistenceHandler, {
1670
1704
  scope: S;
1671
1705
  }>>;
1706
+ /**
1707
+ * Reorder the symbol picker's AGGREGATED pool — every source combined, exactly what
1708
+ * the search dialog displays. Called when the pool changes (a provider's index lands
1709
+ * or refreshes), NOT per keystroke: the picker caches the result. May be async (a
1710
+ * server-fetched top list) — the picker shows the current order and refreshes when
1711
+ * the promise resolves.
1712
+ *
1713
+ * The returned list may INJECT descriptors absent from the pool (they must carry
1714
+ * their `provider` and be genuinely servable, or selecting them parks the load) and
1715
+ * may OMIT entries (hiding them). The picker dedupes by venue+ticker, FIRST
1716
+ * occurrence winning — injecting at the head fixes both position and display data.
1717
+ *
1718
+ * While a ranking is registered, the picker's built-in empty-query pin (the hardcoded
1719
+ * majors) stands down: the head of YOUR list is the dialog's opening screen. Under a
1720
+ * typed query the relevance tiers still lead — the ranking orders within each tier.
1721
+ */
1722
+ type SymbolRankingHook = (pool: SymbolDescriptor[]) => SymbolDescriptor[] | Promise<SymbolDescriptor[]>;
1723
+ /** Register (or replace — ONE ranking at a time, last wins) the symbol ranking.
1724
+ * Returns an unregister disposer. Register at import time, like every contribution. */
1725
+ declare function registerSymbolRanking(hook: SymbolRankingHook): () => void;
1726
+ /** The registered ranking, if any — what the shells' symbol picker consults. */
1727
+ declare function symbolRanking(): SymbolRankingHook | undefined;
1672
1728
  /** Makes ONE engine instance for ONE chart — engines hold per-chart sessions (and
1673
1729
  * possibly a worker), so the shell calls the factory per chart build, never shares. */
1674
1730
  type EngineFactory = () => ScriptingEngine;
@@ -1686,4 +1742,4 @@ declare function unregisterDefaultEngine(language: string): void;
1686
1742
  * language. The shell layers (widget, workspace cell) register exactly this result. */
1687
1743
  declare function resolveEngines(overrides?: Record<string, EngineFactory>): Record<string, EngineFactory>;
1688
1744
 
1689
- export { type WidgetAttachment as $, type SidePanelButton as A, type BarsChangeReason as B, type CellStateContext as C, type DrawingsDocument as D, type ExternalIndicatorEntry as E, type FetchSeries as F, type SidePanelDescriptor as G, type SidePanelHandle as H, type IndicatorHandle as I, type SidePanelHeader as J, type StatePersistenceHandler as K, type LegendActionDescriptor as L, type StrategyFill as M, type NativeIndicator as N, type StrategyState as O, type ParsedSymbol as P, type StrategyTrade as Q, type Resolved as R, type ScriptingEngine as S, TypedEventBus as T, type VelaDeps as U, Vela as V, type WidgetContext as W, type VelaEventMap as X, type VisibleBarRange as Y, type WidgetActionDescriptor as Z, type WidgetActionTarget as _, type ScriptRun as a, getNativeIndicator as a0, legendActions as a1, nativeIndicatorDescriptors as a2, nativeIndicatorTypes as a3, registerDefaultEngine as a4, registerLegendAction as a5, registerNativeIndicator as a6, registerSidePanel as a7, registerStatePersistence as a8, registerWidgetAction as a9, registerWidgetAttachment as aa, resolveEngines as ab, sidePanels as ac, statePersistenceHandlers as ad, unregisterDefaultEngine as ae, unregisterLegendAction as af, unregisterNativeIndicator as ag, unregisterSidePanel as ah, unregisterStatePersistence as ai, unregisterWidgetAction as aj, unregisterWidgetAttachment as ak, widgetActions as al, widgetAttachments as am, DEFAULT_PANEL_ORDER as an, type ContextSelect as b, DataControl as c, DrawingsControl as d, type EngineAlert as e, type EngineCapabilities as f, type EngineContextSnapshot as g, type EngineFactory as h, type EngineWarning as i, type ExecutionHandlers as j, type ExecutionMarket as k, type ExecutionRequest as l, type ExecutionSession as m, type IndicatorEventMap as n, type IndicatorSummary as o, type LegendIndicatorInfo as p, type NativeIndicatorContext as q, type NativeIndicatorDescriptor as r, type NativeIndicatorInfo as s, type NativeIndicatorOutput as t, type PreparedScript as u, RendererControl as v, type RunIndicatorResult as w, type SceneInspection as x, type ScriptRunCause as y, type ScriptRunResult as z };
1745
+ export { type WidgetActionDescriptor as $, type SidePanelButton as A, type BarsChangeReason as B, type CellStateContext as C, type DrawingsDocument as D, type ExternalIndicatorEntry as E, type FetchSeries as F, type SidePanelDescriptor as G, type SidePanelHandle as H, type IndicatorHandle as I, type SidePanelHeader as J, type StatePersistenceHandler as K, type LegendActionDescriptor as L, type StrategyFill as M, type NativeIndicator as N, OVERRIDABLE_TOPBAR_IDS as O, type ParsedSymbol as P, type StrategyState as Q, type Resolved as R, type ScriptingEngine as S, type StrategyTrade as T, type SymbolRankingHook as U, Vela as V, type WidgetContext as W, TypedEventBus as X, type VelaDeps as Y, type VelaEventMap as Z, type VisibleBarRange as _, type ScriptRun as a, type WidgetActionTarget as a0, type WidgetAttachment as a1, getNativeIndicator as a2, legendActions as a3, nativeIndicatorDescriptors as a4, nativeIndicatorTypes as a5, registerDefaultEngine as a6, registerLegendAction as a7, registerNativeIndicator as a8, registerSidePanel as a9, registerStatePersistence as aa, registerSymbolRanking as ab, registerWidgetAction as ac, registerWidgetAttachment as ad, resolveEngines as ae, sidePanels as af, statePersistenceHandlers as ag, symbolRanking as ah, topbarActionOverride as ai, unregisterDefaultEngine as aj, unregisterLegendAction as ak, unregisterNativeIndicator as al, unregisterSidePanel as am, unregisterStatePersistence as an, unregisterWidgetAction as ao, unregisterWidgetAttachment as ap, widgetActions as aq, widgetAttachments as ar, DEFAULT_PANEL_ORDER as as, type ContextSelect as b, DataControl as c, DrawingsControl as d, type EngineAlert as e, type EngineCapabilities as f, type EngineContextSnapshot as g, type EngineFactory as h, type EngineWarning as i, type ExecutionHandlers as j, type ExecutionMarket as k, type ExecutionRequest as l, type ExecutionSession as m, type IndicatorEventMap as n, type IndicatorSummary as o, type LegendIndicatorInfo as p, type NativeIndicatorContext as q, type NativeIndicatorDescriptor as r, type NativeIndicatorInfo as s, type NativeIndicatorOutput as t, type PreparedScript as u, RendererControl as v, type RunIndicatorResult as w, type SceneInspection as x, type ScriptRunCause as y, type ScriptRunResult as z };
package/dist/index.cjs CHANGED
@@ -7091,6 +7091,28 @@ var ProviderRegistry = class {
7091
7091
  const d = this.entries.get(resolved.provider)?.byTicker?.get(normTicker(resolved.ticker));
7092
7092
  return `${d?.prefix ?? resolved.provider}:${d?.ticker ?? resolved.ticker}`;
7093
7093
  }
7094
+ /** The icon URL for a DESCRIPTOR — routed to its OWNING provider's resolver (the
7095
+ * provider owns the knowledge of where its asset class's icons live). A missing
7096
+ * provider, an absent resolver, or a resolver that throws all mean "no icon" —
7097
+ * the shells' initials badge takes over, never an error. */
7098
+ symbolIconOf(d) {
7099
+ const name = d.provider ? normName(d.provider) : [...this.entries.keys()][0];
7100
+ const entry = name !== void 0 ? this.entries.get(name) : void 0;
7101
+ try {
7102
+ return entry?.provider.resolveSymbolIcon?.(d) ?? void 0;
7103
+ } catch {
7104
+ return void 0;
7105
+ }
7106
+ }
7107
+ /** The icon URL for a raw SYMBOL string (the statusline/object-tree path): resolve
7108
+ * to the owning provider, find its descriptor, route to the resolver. Before the
7109
+ * index settles (or for a lenient sole-provider resolution) a minimal synthetic
7110
+ * descriptor is offered — crypto resolvers can answer from the ticker alone. */
7111
+ symbolIcon(resolved) {
7112
+ if (!resolved) return void 0;
7113
+ const d = this.entries.get(resolved.provider)?.byTicker?.get(normTicker(resolved.ticker));
7114
+ return this.symbolIconOf({ ...d ?? { ticker: resolved.ticker }, provider: d?.provider ?? resolved.provider });
7115
+ }
7094
7116
  /** Indexed symbols for one provider (or all, concatenated) — for autocomplete. */
7095
7117
  symbolsOf(rawName) {
7096
7118
  if (rawName != null) return this.entries.get(normName(rawName))?.descriptors ?? [];
@@ -9311,6 +9333,14 @@ var MultiProviderFeed = class {
9311
9333
  providerInstance(name) {
9312
9334
  return this.registry.get(name);
9313
9335
  }
9336
+ /** The icon URL for a DESCRIPTOR — its owning provider's `resolveSymbolIcon` (picker rows). */
9337
+ symbolIconOf(d) {
9338
+ return this.registry.symbolIconOf(d);
9339
+ }
9340
+ /** The icon URL for a raw SYMBOL string — resolve, then route (statusline, object tree). */
9341
+ symbolIcon(raw) {
9342
+ return this.registry.symbolIcon(this.resolveSymbol(raw));
9343
+ }
9314
9344
  symbols(name) {
9315
9345
  return this.registry.symbolsOf(name);
9316
9346
  }
@@ -9537,6 +9567,12 @@ var DataControl = class {
9537
9567
  symbols(provider) {
9538
9568
  return this.registry?.symbols(provider) ?? [];
9539
9569
  }
9570
+ /** The icon URL for `symbol` — its owning provider's `resolveSymbolIcon`, routed
9571
+ * through resolution. Undefined while unresolvable, when the provider declares no
9572
+ * resolver, or on a custom `deps.dataFeed` — the shells then show initials. */
9573
+ symbolIcon(symbol) {
9574
+ return this.registry?.symbolIcon(symbol);
9575
+ }
9540
9576
  /** Per-symbol metadata (Pine `syminfo.*`), resolved through the owning provider. */
9541
9577
  symbolInfo(symbol) {
9542
9578
  return this.registry?.symbolInfoFor(symbol) ?? Promise.resolve(void 0);
@@ -12564,12 +12600,16 @@ var IndicatorInputsDialog = class {
12564
12600
  closeOnEscape: false,
12565
12601
  footer: (foot) => {
12566
12602
  foot.append(
12603
+ this.resetAction(),
12567
12604
  this.dialogButton("Cancel", false, () => this.revertAndClose()),
12568
12605
  this.dialogButton("Ok", true, () => this.close())
12569
12606
  );
12570
12607
  },
12608
+ // Stale-guard: destroying a dialog fires its machine's onOpenChange(false)
12609
+ // asynchronously — after a reset rebuild that notification must not close
12610
+ // the replacement dialog.
12571
12611
  onOpenChange: (open2) => {
12572
- if (!open2) this.close();
12612
+ if (!open2 && this.uiDialog === ui) this.close();
12573
12613
  }
12574
12614
  });
12575
12615
  applyChromeTokens(ui.panel, t);
@@ -12700,6 +12740,30 @@ var IndicatorInputsDialog = class {
12700
12740
  }
12701
12741
  this.close();
12702
12742
  }
12743
+ /** The footer's reset button — same chip as Cancel, pinned to the LEFT edge
12744
+ * (`margin-right:auto` against the footer's flex-end keeps Cancel/Ok right). */
12745
+ resetAction() {
12746
+ const b = this.dialogButton("Reset defaults", false, () => this.resetToDefaults());
12747
+ b.style.marginRight = "auto";
12748
+ return b;
12749
+ }
12750
+ /** Restore every input to its declared default (re-running the indicator), then
12751
+ * re-open the form so each control re-reads the restored values — the same
12752
+ * rebuild-after-reset move as the chart-settings dialog. The open-time snapshot
12753
+ * survives the rebuild, so Cancel after a reset still reverts the whole session. */
12754
+ resetToDefaults() {
12755
+ const row = this.row;
12756
+ if (!row) return;
12757
+ const snap = this.snapshot;
12758
+ for (const inp of row.inputs) {
12759
+ if (row.values[inp.key] !== inp.defval) {
12760
+ row.values[inp.key] = inp.defval;
12761
+ this.host.onChange?.({ indicatorId: row.id, key: inp.key, value: inp.defval });
12762
+ }
12763
+ }
12764
+ this.open(row);
12765
+ if (snap) this.snapshot = snap;
12766
+ }
12703
12767
  /** Write one edit through: store it, notify the host, and re-apply the `when` gates. */
12704
12768
  commit(row, key, value) {
12705
12769
  row.values[key] = value;
@@ -25130,6 +25194,11 @@ function resizeSplit(split, dyTotal, minPx = MIN_PANE_PX) {
25130
25194
  }
25131
25195
 
25132
25196
  // src/renderers/native/backdrop/BackdropRenderer.ts
25197
+ function clipHighlightRect(x1, x2, left, right) {
25198
+ const x = Math.max(left, x1);
25199
+ const end = Math.min(right, x2);
25200
+ return end > x ? { x, width: end - x } : null;
25201
+ }
25133
25202
  var BackdropRenderer = class {
25134
25203
  constructor() {
25135
25204
  this.canvas = null;
@@ -25162,17 +25231,22 @@ var BackdropRenderer = class {
25162
25231
  /** Renderer-owned session highlight bands: full-height (all panes), behind the grid.
25163
25232
  * Session-zone washes (pre/post-market) paint first, host highlights on top. */
25164
25233
  drawHighlights(ctx, scene, coords) {
25165
- const bands = [...scene.sessionHighlightBands(), ...scene.highlights];
25166
- if (bands.length === 0) return;
25234
+ const sessions = scene.sessionHighlightBands();
25235
+ if (sessions.length > 0) {
25236
+ const left = Math.max(0, coords.logicalToX(-0.5));
25237
+ const right = Math.min(coords.width, coords.logicalToX(coords.barCount - 0.5));
25238
+ this.drawHighlightSet(ctx, sessions, coords, left, right);
25239
+ }
25240
+ this.drawHighlightSet(ctx, scene.highlights, coords, 0, coords.width);
25241
+ }
25242
+ drawHighlightSet(ctx, bands, coords, left, right) {
25167
25243
  for (const band of bands) {
25168
25244
  const x1 = coords.timeToX(band.from);
25169
25245
  const x2 = coords.timeToX(band.to);
25170
- if (x2 < 0 || x1 > coords.width || x2 <= x1) continue;
25171
- const cx = Math.max(0, x1);
25172
- const cw = Math.min(coords.width, x2) - cx;
25173
- if (cw <= 0) continue;
25246
+ const rect = clipHighlightRect(x1, x2, left, right);
25247
+ if (!rect) continue;
25174
25248
  ctx.fillStyle = band.color;
25175
- ctx.fillRect(cx, 0, cw, coords.height);
25249
+ ctx.fillRect(rect.x, 0, rect.width, coords.height);
25176
25250
  }
25177
25251
  }
25178
25252
  // ── grid ── vert/horz gate on `scene.showGrid` AND their own per-axis visibility
@@ -29588,6 +29662,9 @@ function resolveElement(container) {
29588
29662
  return element;
29589
29663
  }
29590
29664
 
29665
+ // src/widget/topbar-composition.ts
29666
+ var TOPBAR_BUILTIN_IDS = ["symbol", "timeframes", "style", "layout", "indicators", "actions", "undo-redo", "alerts", "panels", "screenshot"];
29667
+
29591
29668
  // src/widget/contributions.ts
29592
29669
  var registry4 = /* @__PURE__ */ new Map();
29593
29670
  var attachments = /* @__PURE__ */ new Map();
@@ -29617,7 +29694,18 @@ function unregisterSidePanel(id) {
29617
29694
  function sidePanels() {
29618
29695
  return [...panels.values()].sort((a, b) => (a.order ?? DEFAULT_PANEL_ORDER) - (b.order ?? DEFAULT_PANEL_ORDER));
29619
29696
  }
29697
+ var OVERRIDABLE_TOPBAR_IDS = ["indicators", "screenshot"];
29698
+ var overridableSet = new Set(OVERRIDABLE_TOPBAR_IDS);
29699
+ var builtinTopbarSet = new Set(TOPBAR_BUILTIN_IDS);
29700
+ function topbarActionOverride(id) {
29701
+ if (!overridableSet.has(id)) return void 0;
29702
+ return registry4.get(id);
29703
+ }
29620
29704
  function registerWidgetAction(desc) {
29705
+ if (builtinTopbarSet.has(desc.id) && !overridableSet.has(desc.id)) {
29706
+ console.warn(`[vela] widget action "${desc.id}": this built-in topbar slot is a stateful control and cannot be overridden \u2014 ignored. Overridable slots: ${OVERRIDABLE_TOPBAR_IDS.join(", ")}.`);
29707
+ return () => void 0;
29708
+ }
29621
29709
  registry4.set(desc.id, desc);
29622
29710
  return () => {
29623
29711
  if (registry4.get(desc.id) === desc) registry4.delete(desc.id);
@@ -29657,6 +29745,16 @@ function unregisterStatePersistence(key) {
29657
29745
  function statePersistenceHandlers(scope) {
29658
29746
  return [...stateHandlers.values()].filter((h) => h.scope === scope);
29659
29747
  }
29748
+ var symbolRankingHook;
29749
+ function registerSymbolRanking(hook) {
29750
+ symbolRankingHook = hook;
29751
+ return () => {
29752
+ if (symbolRankingHook === hook) symbolRankingHook = void 0;
29753
+ };
29754
+ }
29755
+ function symbolRanking() {
29756
+ return symbolRankingHook;
29757
+ }
29660
29758
  var defaultEngines = /* @__PURE__ */ new Map();
29661
29759
  function registerDefaultEngine(language, make) {
29662
29760
  defaultEngines.set(language, make);
@@ -29713,6 +29811,7 @@ exports.MARKER = MARKER;
29713
29811
  exports.MultiProviderFeed = MultiProviderFeed;
29714
29812
  exports.NEUTRAL = NEUTRAL;
29715
29813
  exports.NativeRenderer = NativeRenderer;
29814
+ exports.OVERRIDABLE_TOPBAR_IDS = OVERRIDABLE_TOPBAR_IDS;
29716
29815
  exports.RendererControl = RendererControl;
29717
29816
  exports.SERIES_LINE = SERIES_LINE;
29718
29817
  exports.SESSION_OFF = SESSION_OFF;
@@ -29754,6 +29853,7 @@ exports.registerRendererDefaults = registerRendererDefaults;
29754
29853
  exports.registerRendererLayer = registerRendererLayer;
29755
29854
  exports.registerSidePanel = registerSidePanel;
29756
29855
  exports.registerStatePersistence = registerStatePersistence;
29856
+ exports.registerSymbolRanking = registerSymbolRanking;
29757
29857
  exports.registerWidgetAction = registerWidgetAction;
29758
29858
  exports.registerWidgetAttachment = registerWidgetAttachment;
29759
29859
  exports.rendererDefaults = rendererDefaults;
@@ -29765,8 +29865,10 @@ exports.sharedBarStore = sharedBarStore;
29765
29865
  exports.sidePanels = sidePanels;
29766
29866
  exports.stableSeriesId = stableSeriesId;
29767
29867
  exports.statePersistenceHandlers = statePersistenceHandlers;
29868
+ exports.symbolRanking = symbolRanking;
29768
29869
  exports.tickerModifierIds = tickerModifierIds;
29769
29870
  exports.timeframeToMs = timeframeToMs;
29871
+ exports.topbarActionOverride = topbarActionOverride;
29770
29872
  exports.unregisterChartType = unregisterChartType;
29771
29873
  exports.unregisterDefaultEngine = unregisterDefaultEngine;
29772
29874
  exports.unregisterLegendAction = unregisterLegendAction;