@luxalgo/vela 0.6.6 → 0.6.7

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/{bottombar-COnL2Sk4.d.ts → bottombar-Br4rzx_R.d.ts} +52 -6
  4. package/dist/{bottombar-DeDXbF_K.d.cts → bottombar-Div5zibZ.d.cts} +52 -6
  5. package/dist/{chunk-JQFO2WMU.js → chunk-6WFKTAT4.js} +37 -1
  6. package/dist/{chunk-OEUGUXL7.js → chunk-L3I2CCYO.js} +49 -1
  7. package/dist/chunk-W4EJWLEO.js +12 -0
  8. package/dist/{chunk-TMXK2SJR.js → chunk-WVP4XV5A.js} +221 -65
  9. package/dist/{contributions-DNMqrAuw.d.cts → contributions-Hv4_cOJo.d.cts} +46 -3
  10. package/dist/{contributions-BqCIsbaP.d.ts → contributions-Z12BrWCy.d.ts} +46 -3
  11. package/dist/index.cjs +64 -0
  12. package/dist/index.d.cts +8 -4
  13. package/dist/index.d.ts +8 -4
  14. package/dist/index.js +2 -2
  15. package/dist/{plugin-WnvNNJOp.d.ts → plugin-9koBjc5H.d.ts} +2 -2
  16. package/dist/{plugin-CN8U2__Q.d.cts → plugin-BXhDHTYn.d.cts} +2 -2
  17. package/dist/plugin.cjs +28 -0
  18. package/dist/plugin.d.cts +3 -3
  19. package/dist/plugin.d.ts +3 -3
  20. package/dist/plugin.js +1 -1
  21. package/dist/providers/binance.cjs +16 -0
  22. package/dist/providers/binance.d.cts +4 -1
  23. package/dist/providers/binance.d.ts +4 -1
  24. package/dist/providers/binance.js +7 -0
  25. package/dist/providers/coinbase.cjs +16 -0
  26. package/dist/providers/coinbase.d.cts +4 -1
  27. package/dist/providers/coinbase.d.ts +4 -1
  28. package/dist/providers/coinbase.js +7 -0
  29. package/dist/providers/hyperliquid.cjs +16 -0
  30. package/dist/providers/hyperliquid.d.cts +4 -1
  31. package/dist/providers/hyperliquid.d.ts +4 -1
  32. package/dist/providers/hyperliquid.js +7 -0
  33. package/dist/vela.global.js +90 -0
  34. package/dist/vela.global.min.js +42 -42
  35. package/dist/widget.cjs +319 -63
  36. package/dist/widget.d.cts +52 -10
  37. package/dist/widget.d.ts +52 -10
  38. package/dist/widget.js +5 -4
  39. package/dist/workspace.cjs +265 -65
  40. package/dist/workspace.d.cts +13 -4
  41. package/dist/workspace.d.ts +13 -4
  42. package/dist/workspace.js +4 -3
  43. package/package.json +1 -1
@@ -131,6 +131,16 @@ interface DataProvider {
131
131
  listSymbols?(): Promise<SymbolDescriptor[]>;
132
132
  /** Per-symbol metadata for engine `syminfo.*`. Absent ⇒ the engine synthesizes a fallback. */
133
133
  getSymbolInfo?(ticker: string): Promise<SymbolInfo | undefined>;
134
+ /**
135
+ * The icon URL for one of THIS provider's symbols — the provider owns the knowledge
136
+ * of where its asset class's icons live (a crypto CDN, a self-hosted store), the
137
+ * shells own the rendering (round badge, colored-initials fallback). Called lazily,
138
+ * per RENDERED row — never per index build — so it must be cheap and synchronous.
139
+ * `undefined` ⇒ no icon (the initials badge shows). Absent ⇒ same. The URL must be
140
+ * CORS-clean (`Access-Control-Allow-Origin`) or drawing it taints the canvas and
141
+ * breaks the PNG export — a load error falls back to initials either way.
142
+ */
143
+ resolveSymbolIcon?(symbol: SymbolDescriptor): string | undefined;
134
144
  /**
135
145
  * Open a true live stream for `ticker`/`timeframe`. Each call to `onBar` delivers
136
146
  * the forming candle (or a freshly-closed one). Returns an unsubscribe fn. Absent
@@ -131,6 +131,16 @@ interface DataProvider {
131
131
  listSymbols?(): Promise<SymbolDescriptor[]>;
132
132
  /** Per-symbol metadata for engine `syminfo.*`. Absent ⇒ the engine synthesizes a fallback. */
133
133
  getSymbolInfo?(ticker: string): Promise<SymbolInfo | undefined>;
134
+ /**
135
+ * The icon URL for one of THIS provider's symbols — the provider owns the knowledge
136
+ * of where its asset class's icons live (a crypto CDN, a self-hosted store), the
137
+ * shells own the rendering (round badge, colored-initials fallback). Called lazily,
138
+ * per RENDERED row — never per index build — so it must be cheap and synchronous.
139
+ * `undefined` ⇒ no icon (the initials badge shows). Absent ⇒ same. The URL must be
140
+ * CORS-clean (`Access-Control-Allow-Origin`) or drawing it taints the canvas and
141
+ * breaks the PNG export — a load error falls back to initials either way.
142
+ */
143
+ resolveSymbolIcon?(symbol: SymbolDescriptor): string | undefined;
134
144
  /**
135
145
  * Open a true live stream for `ticker`/`timeframe`. Each call to `onBar` delivers
136
146
  * the forming candle (or a freshly-closed one). Returns an unsubscribe fn. Absent
@@ -1,5 +1,5 @@
1
- import { D as DataProvider } from './DataProvider-JJq7M2it.js';
2
- import { S as ScriptingEngine, V as Vela } from './contributions-BqCIsbaP.js';
1
+ import { D as DataProvider } from './DataProvider-BSLlBpB9.js';
2
+ import { S as ScriptingEngine, V as Vela } from './contributions-Z12BrWCy.js';
3
3
  import { V as VisibleRangePreset } from './options-BaVTMXaO.js';
4
4
 
5
5
  /** The linkable dimensions. `crosshair` mirrors the pointer time onto same-group
@@ -172,6 +172,37 @@ type WidgetStorage = VelaStorage;
172
172
  */
173
173
  declare function localStorageAdapter(storageKey?: string): WidgetStorage;
174
174
 
175
+ /** The host-facing option: visible entries per side, in render order. An undeclared
176
+ * side falls back to its default list. */
177
+ interface TopbarComposition {
178
+ left?: readonly string[];
179
+ right?: readonly string[];
180
+ }
181
+ /** The built-in entry vocabulary (everything else in a list is a contributed-action id).
182
+ * `'layout'` renders only on multi-chart shells and `'indicators'` only while an
183
+ * indicator surface exists — the built-in picker (the deprecated `indicatorPicker:
184
+ * false` still removes it) or a slot OVERRIDE replacing it — so listing them is
185
+ * necessary but not sufficient. */
186
+ declare const TOPBAR_BUILTIN_IDS: readonly ["symbol", "timeframes", "style", "layout", "indicators", "actions", "undo-redo", "alerts", "panels", "screenshot"];
187
+ /** The default left side — the current shell composition, verbatim. */
188
+ declare const TOPBAR_DEFAULT_LEFT: readonly string[];
189
+ /** The default right side (the `margin-left: auto` cluster). */
190
+ declare const TOPBAR_DEFAULT_RIGHT: readonly string[];
191
+ /** A composition with both sides resolved (defaults applied, duplicates dropped). */
192
+ interface ResolvedTopbarComposition {
193
+ left: string[];
194
+ right: string[];
195
+ }
196
+ /** Resolve the host option: absent side ⇒ its default list; a duplicated id keeps its
197
+ * FIRST occurrence (left before right) so an entry never renders twice. `'actions'`
198
+ * is the exception — it is a flow SLOT each side legitimately owns (the defaults
199
+ * carry one on both), so it dedupes per side only. */
200
+ declare function resolveTopbarComposition(opt?: TopbarComposition): ResolvedTopbarComposition;
201
+ /** Whether an entry id is visible anywhere in the resolved composition. */
202
+ declare function topbarHas(comp: ResolvedTopbarComposition, id: string): boolean;
203
+ /** The non-built-in entries — contributed-action ids PINNED to a list position. */
204
+ declare function pinnedTopbarActionIds(comp: ResolvedTopbarComposition): string[];
205
+
175
206
  /** What a shell (widget or workspace) accepts BEYOND the chart options themselves. */
176
207
  interface VelaShellOptions {
177
208
  /** Provider factories, keyed by provider name. The shell owns the call cycle: the
@@ -197,10 +228,25 @@ interface VelaShellOptions {
197
228
  statusline?: boolean;
198
229
  watermark?: boolean;
199
230
  bottombar?: boolean;
231
+ /** Declarative topbar composition: `{ left, right }` lists of the VISIBLE entries,
232
+ * in render order — built-in ids (`'symbol'`, `'timeframes'`, `'style'`,
233
+ * `'layout'`, `'indicators'`, `'actions'`, `'undo-redo'`, `'alerts'`, `'panels'`,
234
+ * `'screenshot'`) and/or contributed-action ids (naming one PINS it there,
235
+ * overriding its `align`/`order`; `'actions'` is where the unlisted ones flow).
236
+ * An undeclared side keeps its default. An explicit list is that side's complete
237
+ * contract — it also FREEZES it: chrome a future release adds will not appear.
238
+ * Hiding a built-in removes its mobile entry and keyboard chord too (`mod+alt+S`
239
+ * for `'screenshot'`); Ctrl+Z / Ctrl+Y stay — they belong to editing, not to the
240
+ * `'undo-redo'` buttons. */
241
+ topbar?: TopbarComposition;
200
242
  /** The built-in indicator picker's entry points — the topbar button, the mobile-bar
201
- * item, and the `/` shortcut. `false` removes them, for hosts that replace the
202
- * picker with their own indicator UI (e.g. a contributed topbar action opening a
203
- * custom dialog). The `indicators` manifest still resolves and auto-adds. */
243
+ * item, and the `/` shortcut. `false` removes them. The `indicators` manifest
244
+ * still resolves and auto-adds.
245
+ * @deprecated Removed in 0.7.0. To HIDE the built-in surface, omit `'indicators'`
246
+ * from `topbar.left` (same effect: no button, no mobile stop, no `/`, no dialog).
247
+ * To REPLACE it, a plugin registers its action under the id `'indicators'`
248
+ * (`registerWidgetAction`) — the override takes the slot's whole surface and
249
+ * needs no shell option at all. */
204
250
  indicatorPicker?: boolean;
205
251
  /** Chrome size class. `'auto'` (default) follows the CONTAINER width plus a
206
252
  * coarse-pointer heuristic; `'mobile'` / `'desktop'` pin it. Mobile swaps the
@@ -315,4 +361,4 @@ declare class Bottombar {
315
361
  private tick;
316
362
  }
317
363
 
318
- export { Bottombar as B, type CellState as C, type IndicatorLoader as I, type PanelsState as P, type ResolvedIndicator as R, type SyncSetting as S, type TrackSizes as T, type VelaStorage as V, WidgetHistory as W, type RangePreset as a, type VelaShellOptions as b, type SyncOptions as c, type SyncKind as d, type WorkspaceState as e, type ChartState as f, decodeState as g, encodeState as h, type BottombarOptions as i, type IndicatorManifest as j, type IndicatorManifestEntry as k, RANGE_PRESETS as l, type WidgetStorage as m, localStorageAdapter as n, resolveIndicators as r, sanitizeState as s };
364
+ export { Bottombar as B, type CellState as C, type IndicatorLoader as I, type PanelsState as P, type ResolvedIndicator as R, type SyncSetting as S, type TrackSizes as T, type VelaStorage as V, WidgetHistory as W, type RangePreset as a, type VelaShellOptions as b, type SyncOptions as c, type SyncKind as d, type WorkspaceState as e, type ChartState as f, decodeState as g, encodeState as h, type TopbarComposition as i, type BottombarOptions as j, type IndicatorManifest as k, type IndicatorManifestEntry as l, RANGE_PRESETS as m, type ResolvedTopbarComposition as n, TOPBAR_BUILTIN_IDS as o, TOPBAR_DEFAULT_LEFT as p, TOPBAR_DEFAULT_RIGHT as q, type WidgetStorage as r, sanitizeState as s, localStorageAdapter as t, pinnedTopbarActionIds as u, resolveIndicators as v, resolveTopbarComposition as w, topbarHas as x };
@@ -1,5 +1,5 @@
1
- import { D as DataProvider } from './DataProvider-DDUYw2qP.cjs';
2
- import { S as ScriptingEngine, V as Vela } from './contributions-DNMqrAuw.cjs';
1
+ import { D as DataProvider } from './DataProvider-BsQM2WNH.cjs';
2
+ import { S as ScriptingEngine, V as Vela } from './contributions-Hv4_cOJo.cjs';
3
3
  import { V as VisibleRangePreset } from './options-BaVTMXaO.cjs';
4
4
 
5
5
  /** The linkable dimensions. `crosshair` mirrors the pointer time onto same-group
@@ -172,6 +172,37 @@ type WidgetStorage = VelaStorage;
172
172
  */
173
173
  declare function localStorageAdapter(storageKey?: string): WidgetStorage;
174
174
 
175
+ /** The host-facing option: visible entries per side, in render order. An undeclared
176
+ * side falls back to its default list. */
177
+ interface TopbarComposition {
178
+ left?: readonly string[];
179
+ right?: readonly string[];
180
+ }
181
+ /** The built-in entry vocabulary (everything else in a list is a contributed-action id).
182
+ * `'layout'` renders only on multi-chart shells and `'indicators'` only while an
183
+ * indicator surface exists — the built-in picker (the deprecated `indicatorPicker:
184
+ * false` still removes it) or a slot OVERRIDE replacing it — so listing them is
185
+ * necessary but not sufficient. */
186
+ declare const TOPBAR_BUILTIN_IDS: readonly ["symbol", "timeframes", "style", "layout", "indicators", "actions", "undo-redo", "alerts", "panels", "screenshot"];
187
+ /** The default left side — the current shell composition, verbatim. */
188
+ declare const TOPBAR_DEFAULT_LEFT: readonly string[];
189
+ /** The default right side (the `margin-left: auto` cluster). */
190
+ declare const TOPBAR_DEFAULT_RIGHT: readonly string[];
191
+ /** A composition with both sides resolved (defaults applied, duplicates dropped). */
192
+ interface ResolvedTopbarComposition {
193
+ left: string[];
194
+ right: string[];
195
+ }
196
+ /** Resolve the host option: absent side ⇒ its default list; a duplicated id keeps its
197
+ * FIRST occurrence (left before right) so an entry never renders twice. `'actions'`
198
+ * is the exception — it is a flow SLOT each side legitimately owns (the defaults
199
+ * carry one on both), so it dedupes per side only. */
200
+ declare function resolveTopbarComposition(opt?: TopbarComposition): ResolvedTopbarComposition;
201
+ /** Whether an entry id is visible anywhere in the resolved composition. */
202
+ declare function topbarHas(comp: ResolvedTopbarComposition, id: string): boolean;
203
+ /** The non-built-in entries — contributed-action ids PINNED to a list position. */
204
+ declare function pinnedTopbarActionIds(comp: ResolvedTopbarComposition): string[];
205
+
175
206
  /** What a shell (widget or workspace) accepts BEYOND the chart options themselves. */
176
207
  interface VelaShellOptions {
177
208
  /** Provider factories, keyed by provider name. The shell owns the call cycle: the
@@ -197,10 +228,25 @@ interface VelaShellOptions {
197
228
  statusline?: boolean;
198
229
  watermark?: boolean;
199
230
  bottombar?: boolean;
231
+ /** Declarative topbar composition: `{ left, right }` lists of the VISIBLE entries,
232
+ * in render order — built-in ids (`'symbol'`, `'timeframes'`, `'style'`,
233
+ * `'layout'`, `'indicators'`, `'actions'`, `'undo-redo'`, `'alerts'`, `'panels'`,
234
+ * `'screenshot'`) and/or contributed-action ids (naming one PINS it there,
235
+ * overriding its `align`/`order`; `'actions'` is where the unlisted ones flow).
236
+ * An undeclared side keeps its default. An explicit list is that side's complete
237
+ * contract — it also FREEZES it: chrome a future release adds will not appear.
238
+ * Hiding a built-in removes its mobile entry and keyboard chord too (`mod+alt+S`
239
+ * for `'screenshot'`); Ctrl+Z / Ctrl+Y stay — they belong to editing, not to the
240
+ * `'undo-redo'` buttons. */
241
+ topbar?: TopbarComposition;
200
242
  /** The built-in indicator picker's entry points — the topbar button, the mobile-bar
201
- * item, and the `/` shortcut. `false` removes them, for hosts that replace the
202
- * picker with their own indicator UI (e.g. a contributed topbar action opening a
203
- * custom dialog). The `indicators` manifest still resolves and auto-adds. */
243
+ * item, and the `/` shortcut. `false` removes them. The `indicators` manifest
244
+ * still resolves and auto-adds.
245
+ * @deprecated Removed in 0.7.0. To HIDE the built-in surface, omit `'indicators'`
246
+ * from `topbar.left` (same effect: no button, no mobile stop, no `/`, no dialog).
247
+ * To REPLACE it, a plugin registers its action under the id `'indicators'`
248
+ * (`registerWidgetAction`) — the override takes the slot's whole surface and
249
+ * needs no shell option at all. */
204
250
  indicatorPicker?: boolean;
205
251
  /** Chrome size class. `'auto'` (default) follows the CONTAINER width plus a
206
252
  * coarse-pointer heuristic; `'mobile'` / `'desktop'` pin it. Mobile swaps the
@@ -315,4 +361,4 @@ declare class Bottombar {
315
361
  private tick;
316
362
  }
317
363
 
318
- export { Bottombar as B, type CellState as C, type IndicatorLoader as I, type PanelsState as P, type ResolvedIndicator as R, type SyncSetting as S, type TrackSizes as T, type VelaStorage as V, WidgetHistory as W, type RangePreset as a, type VelaShellOptions as b, type SyncOptions as c, type SyncKind as d, type WorkspaceState as e, type ChartState as f, decodeState as g, encodeState as h, type BottombarOptions as i, type IndicatorManifest as j, type IndicatorManifestEntry as k, RANGE_PRESETS as l, type WidgetStorage as m, localStorageAdapter as n, resolveIndicators as r, sanitizeState as s };
364
+ export { Bottombar as B, type CellState as C, type IndicatorLoader as I, type PanelsState as P, type ResolvedIndicator as R, type SyncSetting as S, type TrackSizes as T, type VelaStorage as V, WidgetHistory as W, type RangePreset as a, type VelaShellOptions as b, type SyncOptions as c, type SyncKind as d, type WorkspaceState as e, type ChartState as f, decodeState as g, encodeState as h, type TopbarComposition as i, type BottombarOptions as j, type IndicatorManifest as k, type IndicatorManifestEntry as l, RANGE_PRESETS as m, type ResolvedTopbarComposition as n, TOPBAR_BUILTIN_IDS as o, TOPBAR_DEFAULT_LEFT as p, TOPBAR_DEFAULT_RIGHT as q, type WidgetStorage as r, sanitizeState as s, localStorageAdapter as t, pinnedTopbarActionIds as u, resolveIndicators as v, resolveTopbarComposition as w, topbarHas as x };
@@ -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);
@@ -5761,6 +5761,33 @@ function rendererLayers() {
5761
5761
  return [...registry2.values()];
5762
5762
  }
5763
5763
 
5764
+ // src/widget/topbar-composition.ts
5765
+ var TOPBAR_BUILTIN_IDS = ["symbol", "timeframes", "style", "layout", "indicators", "actions", "undo-redo", "alerts", "panels", "screenshot"];
5766
+ var TOPBAR_DEFAULT_LEFT = ["symbol", "timeframes", "style", "layout", "indicators", "actions", "undo-redo"];
5767
+ var TOPBAR_DEFAULT_RIGHT = ["actions", "alerts", "panels", "screenshot"];
5768
+ function resolveTopbarComposition(opt) {
5769
+ const seen = /* @__PURE__ */ new Set();
5770
+ const take = (list) => {
5771
+ const out = [];
5772
+ const local = /* @__PURE__ */ new Set();
5773
+ for (const id of list) {
5774
+ if (!id || local.has(id) || id !== "actions" && seen.has(id)) continue;
5775
+ local.add(id);
5776
+ seen.add(id);
5777
+ out.push(id);
5778
+ }
5779
+ return out;
5780
+ };
5781
+ return { left: take(opt?.left ?? TOPBAR_DEFAULT_LEFT), right: take(opt?.right ?? TOPBAR_DEFAULT_RIGHT) };
5782
+ }
5783
+ function topbarHas(comp, id) {
5784
+ return comp.left.includes(id) || comp.right.includes(id);
5785
+ }
5786
+ function pinnedTopbarActionIds(comp) {
5787
+ const builtin = new Set(TOPBAR_BUILTIN_IDS);
5788
+ return [...comp.left, ...comp.right].filter((id) => !builtin.has(id));
5789
+ }
5790
+
5764
5791
  // src/widget/contributions.ts
5765
5792
  var registry3 = /* @__PURE__ */ new Map();
5766
5793
  var attachments = /* @__PURE__ */ new Map();
@@ -5790,7 +5817,18 @@ function unregisterSidePanel(id) {
5790
5817
  function sidePanels() {
5791
5818
  return [...panels.values()].sort((a, b) => (a.order ?? DEFAULT_PANEL_ORDER) - (b.order ?? DEFAULT_PANEL_ORDER));
5792
5819
  }
5820
+ var OVERRIDABLE_TOPBAR_IDS = ["indicators", "screenshot"];
5821
+ var overridableSet = new Set(OVERRIDABLE_TOPBAR_IDS);
5822
+ var builtinTopbarSet = new Set(TOPBAR_BUILTIN_IDS);
5823
+ function topbarActionOverride(id) {
5824
+ if (!overridableSet.has(id)) return void 0;
5825
+ return registry3.get(id);
5826
+ }
5793
5827
  function registerWidgetAction(desc) {
5828
+ if (builtinTopbarSet.has(desc.id) && !overridableSet.has(desc.id)) {
5829
+ 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(", ")}.`);
5830
+ return () => void 0;
5831
+ }
5794
5832
  registry3.set(desc.id, desc);
5795
5833
  return () => {
5796
5834
  if (registry3.get(desc.id) === desc) registry3.delete(desc.id);
@@ -5838,6 +5876,16 @@ function unregisterStatePersistence(key) {
5838
5876
  function statePersistenceHandlers(scope) {
5839
5877
  return [...stateHandlers.values()].filter((h) => h.scope === scope);
5840
5878
  }
5879
+ var symbolRankingHook;
5880
+ function registerSymbolRanking(hook) {
5881
+ symbolRankingHook = hook;
5882
+ return () => {
5883
+ if (symbolRankingHook === hook) symbolRankingHook = void 0;
5884
+ };
5885
+ }
5886
+ function symbolRanking() {
5887
+ return symbolRankingHook;
5888
+ }
5841
5889
  var defaultEngines = /* @__PURE__ */ new Map();
5842
5890
  function registerDefaultEngine(language, make) {
5843
5891
  defaultEngines.set(language, make);
@@ -6065,4 +6113,4 @@ var SidePanel = class {
6065
6113
  }
6066
6114
  };
6067
6115
 
6068
- 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, MachFigure, MeasureBox, Note, PatternDrawing, PositionTool, PriceLabel, PriceNote, RadialFib, RegressionChannel, STAMP_SIZE_OPTIONS, SegmentDrawing, SidePanel, Signpost, TEXT_SIZE_OPTIONS, TextLabel, chartType, chartTypes, clampPanelWidth, createDrawing, deserializeDrawing, drawingTypes, foldBaseModulation, formatDuration, getDrawingType, getNativeIndicator, inputVisible, legendActions, legendActionsProviderFor, lineSegmentIntersection, nativeIndicatorDescriptors, nativeIndicatorTypes, normalizeSettingsRow, registerChartType, registerDefaultEngine, registerDrawingType, registerLegendAction, registerNativeIndicator, registerRendererDefaults, registerRendererLayer, registerSidePanel, registerStatePersistence, registerWidgetAction, registerWidgetAttachment, rendererDefaults, rendererLayers, resetDrawingSettings, resolveEngines, settingsRowValueKeys, settingsRowVisible, sidePanels, statePersistenceHandlers, tickerModifierIds, unregisterChartType, unregisterDefaultEngine, unregisterLegendAction, unregisterNativeIndicator, unregisterRendererDefaults, unregisterRendererLayer, unregisterSidePanel, unregisterStatePersistence, unregisterWidgetAction, unregisterWidgetAttachment, widgetActions, widgetAttachments };
6116
+ 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, MachFigure, 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, inputVisible, legendActions, legendActionsProviderFor, lineSegmentIntersection, nativeIndicatorDescriptors, nativeIndicatorTypes, normalizeSettingsRow, pinnedTopbarActionIds, registerChartType, registerDefaultEngine, registerDrawingType, registerLegendAction, registerNativeIndicator, registerRendererDefaults, registerRendererLayer, registerSidePanel, registerStatePersistence, registerSymbolRanking, registerWidgetAction, registerWidgetAttachment, rendererDefaults, rendererLayers, resetDrawingSettings, resolveEngines, resolveTopbarComposition, settingsRowValueKeys, settingsRowVisible, sidePanels, statePersistenceHandlers, symbolRanking, tickerModifierIds, topbarActionOverride, topbarHas, unregisterChartType, unregisterDefaultEngine, unregisterLegendAction, unregisterNativeIndicator, unregisterRendererDefaults, unregisterRendererLayer, unregisterSidePanel, unregisterStatePersistence, unregisterWidgetAction, unregisterWidgetAttachment, widgetActions, widgetAttachments };
@@ -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 };