@luxalgo/vela 0.5.0

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 (61) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +28 -0
  3. package/README.md +135 -0
  4. package/dist/DataProvider-DKNDHpNv.d.cts +134 -0
  5. package/dist/DataProvider-Dzd-Erlk.d.ts +134 -0
  6. package/dist/chunk-7UFX5ZIG.js +5976 -0
  7. package/dist/chunk-GYD2THPV.js +252 -0
  8. package/dist/chunk-KCCZNKH7.js +19137 -0
  9. package/dist/chunk-KM6LHB3Y.js +76 -0
  10. package/dist/chunk-OVQKKXLZ.js +3978 -0
  11. package/dist/chunk-Q3XQHLIH.js +7 -0
  12. package/dist/chunk-RHIDOUFL.js +698 -0
  13. package/dist/contributions-hX3EUyjG.d.ts +1528 -0
  14. package/dist/contributions-o1GRKPI_.d.cts +1528 -0
  15. package/dist/history-Dzxz-MQj.d.ts +298 -0
  16. package/dist/history-LJkz4-sS.d.cts +298 -0
  17. package/dist/icons-BZYbJXSV.d.cts +10 -0
  18. package/dist/icons-BZYbJXSV.d.ts +10 -0
  19. package/dist/index.cjs +25294 -0
  20. package/dist/index.d.cts +1189 -0
  21. package/dist/index.d.ts +1189 -0
  22. package/dist/index.js +5 -0
  23. package/dist/keymap-CGOz5F5f.d.cts +64 -0
  24. package/dist/keymap-CGOz5F5f.d.ts +64 -0
  25. package/dist/options-Q-576hIi.d.cts +1545 -0
  26. package/dist/options-Q-576hIi.d.ts +1545 -0
  27. package/dist/plugin-D94muTV-.d.cts +405 -0
  28. package/dist/plugin-aGUD1epn.d.ts +405 -0
  29. package/dist/plugin.cjs +5967 -0
  30. package/dist/plugin.d.cts +7 -0
  31. package/dist/plugin.d.ts +7 -0
  32. package/dist/plugin.js +3 -0
  33. package/dist/providers/binance.cjs +390 -0
  34. package/dist/providers/binance.d.cts +62 -0
  35. package/dist/providers/binance.d.ts +62 -0
  36. package/dist/providers/binance.js +388 -0
  37. package/dist/providers/coinbase.cjs +462 -0
  38. package/dist/providers/coinbase.d.cts +59 -0
  39. package/dist/providers/coinbase.d.ts +59 -0
  40. package/dist/providers/coinbase.js +460 -0
  41. package/dist/providers/hyperliquid.cjs +361 -0
  42. package/dist/providers/hyperliquid.d.cts +54 -0
  43. package/dist/providers/hyperliquid.d.ts +54 -0
  44. package/dist/providers/hyperliquid.js +359 -0
  45. package/dist/side-panel-CT9ZwIGz.d.cts +63 -0
  46. package/dist/side-panel-CT9ZwIGz.d.ts +63 -0
  47. package/dist/ui.cjs +1030 -0
  48. package/dist/ui.d.cts +188 -0
  49. package/dist/ui.d.ts +188 -0
  50. package/dist/ui.js +3 -0
  51. package/dist/vela.global.js +26509 -0
  52. package/dist/vela.global.min.js +230 -0
  53. package/dist/widget.cjs +31178 -0
  54. package/dist/widget.d.cts +799 -0
  55. package/dist/widget.d.ts +799 -0
  56. package/dist/widget.js +1060 -0
  57. package/dist/workspace.cjs +31692 -0
  58. package/dist/workspace.d.cts +579 -0
  59. package/dist/workspace.d.ts +579 -0
  60. package/dist/workspace.js +1694 -0
  61. package/package.json +95 -0
@@ -0,0 +1,1545 @@
1
+ /**
2
+ * Canonical time in Vela: Unix epoch **milliseconds**.
3
+ *
4
+ * This matches JS `Date` and the bar `openTime` every provider and scripting
5
+ * engine speaks. Each renderer converts to its own unit at its boundary (a
6
+ * second-based adapter divides by 1000).
7
+ */
8
+ type Millis = number;
9
+
10
+ /** A single price bar. `time` is the bar's open time in epoch ms. */
11
+ interface OHLCV {
12
+ time: Millis;
13
+ open: number;
14
+ high: number;
15
+ low: number;
16
+ close: number;
17
+ volume?: number;
18
+ }
19
+
20
+ /** Value-series kinds drawn as a connected/point series. */
21
+ type LineLikeKind = 'line' | 'area' | 'step' | 'histogram' | 'columns' | 'circles' | 'cross';
22
+ /**
23
+ * All renderable series kinds. NOTE: `fill`, `background`, and `hline` are
24
+ * intentionally NOT series kinds — they are modeled as overlays on a pane
25
+ * (see scene.ts), and `barcolor` is a recolor of the price candles, not a
26
+ * series.
27
+ */
28
+ type SeriesKind = LineLikeKind | 'candle' | 'bar' | 'markers';
29
+ type LineStyle = 'solid' | 'dashed' | 'dotted';
30
+ /** A single point of a value series. `value: null` marks a gap (whitespace). */
31
+ interface SeriesPoint {
32
+ time: Millis;
33
+ value: number | null;
34
+ /** Per-point color override (e.g. `plot(x, color = cond ? c1 : c2)`). */
35
+ color?: string;
36
+ }
37
+ interface LineLikeStyle {
38
+ color: string;
39
+ width: number;
40
+ lineStyle: LineStyle;
41
+ /** Baseline for histogram/area; ignored by the line family. */
42
+ base?: number;
43
+ }
44
+ interface CandleStyle {
45
+ up: string;
46
+ down: string;
47
+ wickUp?: string;
48
+ wickDown?: string;
49
+ borderUp?: string;
50
+ borderDown?: string;
51
+ }
52
+ /** Per-bar plotcandle/plotbar override (body / wick / border colours). */
53
+ interface CandleBarColor {
54
+ color?: string;
55
+ wickColor?: string;
56
+ borderColor?: string;
57
+ }
58
+ interface MarkerPoint {
59
+ time: Millis;
60
+ position: 'aboveBar' | 'belowBar' | 'inBar';
61
+ /** Neutral shape token (e.g. 'arrowUp', 'circle', 'square'); mapped per renderer. */
62
+ shape: string;
63
+ color: string;
64
+ text?: string;
65
+ size?: 'tiny' | 'small' | 'normal' | 'large' | 'huge';
66
+ }
67
+ interface SeriesBase {
68
+ /** Content-addressed, stable across re-runs of identical source (see identity.ts). */
69
+ id: string;
70
+ title: string;
71
+ /** Pane this series belongs to; resolved by the orchestrator. */
72
+ paneId: string;
73
+ /** Declared draw-order intent; the renderer owns final z-ordering. */
74
+ zOrder?: number;
75
+ visible?: boolean;
76
+ }
77
+ interface LineLikeSeries extends SeriesBase {
78
+ kind: LineLikeKind;
79
+ points: SeriesPoint[];
80
+ style: LineLikeStyle;
81
+ }
82
+ interface CandleSeries extends SeriesBase {
83
+ kind: 'candle' | 'bar';
84
+ bars: OHLCV[];
85
+ style?: Partial<CandleStyle>;
86
+ /** Per-bar plotcandle/plotbar colours, aligned to `bars` by index (null ≡ use defaults). */
87
+ barColors?: Array<CandleBarColor | null>;
88
+ }
89
+ interface MarkerSeries extends SeriesBase {
90
+ kind: 'markers';
91
+ markers: MarkerPoint[];
92
+ }
93
+ type SeriesSpec = LineLikeSeries | CandleSeries | MarkerSeries;
94
+
95
+ /**
96
+ * Renderer-neutral models for Pine drawing objects (`line.new`, `box.new`, …).
97
+ * Coordinates are kept in their Pine form, tagged by {@link DrawingXLoc}: the
98
+ * renderer converts a bar index or epoch-ms time to a pixel via the time scale.
99
+ */
100
+ /** How a drawing's x-coordinates are interpreted (Pine `xloc`). */
101
+ type DrawingXLoc = 'bar_index' | 'bar_time';
102
+ /** Pine `extend`: which side(s) the drawing runs out to the chart edge. */
103
+ type DrawingExtend = 'none' | 'left' | 'right' | 'both';
104
+ type BoxTextSize = 'auto' | 'tiny' | 'small' | 'normal' | 'large' | 'huge';
105
+ type BoxHAlign = 'left' | 'center' | 'right';
106
+ type BoxVAlign = 'top' | 'center' | 'bottom';
107
+ type BoxFontFamily = 'default' | 'monospace';
108
+ /**
109
+ * A Pine `line.new(...)`. `x1/x2` are bar indices (xloc `bar_index`) or epoch ms
110
+ * (xloc `bar_time`); `y1/y2` are prices.
111
+ */
112
+ interface DrawingLine {
113
+ id: string;
114
+ paneId: string;
115
+ xloc: DrawingXLoc;
116
+ x1: number;
117
+ y1: number;
118
+ x2: number;
119
+ y2: number;
120
+ extend: DrawingExtend;
121
+ /** Stroke color. `undefined` → use the renderer's default foreground color. */
122
+ color?: string;
123
+ /** `na` color → the line exists but is not stroked (e.g. a linefill anchor). */
124
+ invisible: boolean;
125
+ /** Pine line width in px (uncapped, unlike a series `lineWidth`). */
126
+ width: number;
127
+ style: LineStyle;
128
+ /** Arrowhead at the first point (`style_arrow_left` / `style_arrow_both`). */
129
+ arrowLeft: boolean;
130
+ /** Arrowhead at the second point (`style_arrow_right` / `style_arrow_both`). */
131
+ arrowRight: boolean;
132
+ /** `force_overlay` → render on the price pane regardless of the indicator's pane. */
133
+ overlay?: boolean;
134
+ }
135
+ /** A Pine `box.new(...)`. `left/right` follow `xloc`; `top/bottom` are prices. */
136
+ interface DrawingBox {
137
+ id: string;
138
+ paneId: string;
139
+ xloc: DrawingXLoc;
140
+ left: number;
141
+ top: number;
142
+ right: number;
143
+ bottom: number;
144
+ extend: DrawingExtend;
145
+ /** Fill color (may carry alpha). `undefined` → no fill (`na`). */
146
+ bgColor?: string;
147
+ /** Border color. `undefined` → no border (`na`). */
148
+ borderColor?: string;
149
+ borderWidth: number;
150
+ borderStyle: LineStyle;
151
+ /** Box text. `undefined`/empty → no text drawn. */
152
+ text?: string;
153
+ /** Text color. `undefined` → auto-contrast against the fill. */
154
+ textColor?: string;
155
+ textSize: BoxTextSize;
156
+ hAlign: BoxHAlign;
157
+ vAlign: BoxVAlign;
158
+ /** `text.wrap_auto` → wrap to the box width; otherwise single line per `\n`. */
159
+ wrap: boolean;
160
+ fontFamily: BoxFontFamily;
161
+ bold: boolean;
162
+ italic: boolean;
163
+ /** `force_overlay` → render on the price pane regardless of the indicator's pane. */
164
+ overlay?: boolean;
165
+ }
166
+ /** Pine `label.style_*` (the bubble/pointer variants and the point-marker shapes). */
167
+ type LabelStyle = 'label_up' | 'label_down' | 'label_left' | 'label_right' | 'label_center' | 'label_lower_left' | 'label_lower_right' | 'label_upper_left' | 'label_upper_right' | 'circle' | 'square' | 'diamond' | 'flag' | 'arrowup' | 'arrowdown' | 'triangleup' | 'triangledown' | 'cross' | 'xcross' | 'text_outline' | 'none';
168
+ /**
169
+ * Where a label/marker anchors vertically. Pine `yloc` (price/abovebar/belowbar)
170
+ * plus the `plotshape` pane-relative `location.top`/`location.bottom`.
171
+ */
172
+ type LabelYLoc = 'price' | 'abovebar' | 'belowbar' | 'top' | 'bottom';
173
+ /** A Pine `label.new(...)`. `x` follows `xloc`; `y` is a price (used when yloc='price'). */
174
+ interface DrawingLabel {
175
+ id: string;
176
+ paneId: string;
177
+ xloc: DrawingXLoc;
178
+ x: number;
179
+ y: number;
180
+ yloc: LabelYLoc;
181
+ text?: string;
182
+ style: LabelStyle;
183
+ /** Bubble / marker color. `undefined` → renderer default. */
184
+ color?: string;
185
+ textColor?: string;
186
+ size: BoxTextSize;
187
+ textAlign: BoxHAlign;
188
+ tooltip?: string;
189
+ fontFamily: BoxFontFamily;
190
+ /** na bubble/marker color → render text only (no bubble/shape fill). */
191
+ noFill?: boolean;
192
+ /** `force_overlay` → render on the price pane regardless of the indicator's pane. */
193
+ overlay?: boolean;
194
+ }
195
+ /** One vertex of a polyline (Pine `chart.point`). `x` follows `xloc`; `price` is y. */
196
+ interface PolylinePoint {
197
+ xloc: DrawingXLoc;
198
+ x: number;
199
+ price: number;
200
+ }
201
+ /** A Pine `polyline.new(...)` — a multi-point path, optionally curved and/or closed. */
202
+ interface DrawingPolyline {
203
+ id: string;
204
+ paneId: string;
205
+ points: PolylinePoint[];
206
+ curved: boolean;
207
+ closed: boolean;
208
+ /** Stroke color. `undefined` → no stroke. */
209
+ lineColor?: string;
210
+ /** Fill color (closed paths). `undefined` → no fill. */
211
+ fillColor?: string;
212
+ lineWidth: number;
213
+ lineStyle: LineStyle;
214
+ /** Arrowheads at segment starts/ends (`line.style_arrow_*`). */
215
+ arrowLeft: boolean;
216
+ arrowRight: boolean;
217
+ /** `force_overlay` → render on the price pane regardless of the indicator's pane. */
218
+ overlay?: boolean;
219
+ }
220
+ /** A Pine `linefill.new(line1, line2, color)` — the band between two lines. */
221
+ interface DrawingLinefill {
222
+ id: string;
223
+ paneId: string;
224
+ line1: DrawingLine;
225
+ line2: DrawingLine;
226
+ /** Fill color. `undefined` → nothing drawn. */
227
+ color?: string;
228
+ /** `force_overlay` → render on the price pane regardless of the indicator's pane. */
229
+ overlay?: boolean;
230
+ }
231
+ /** Pine `position.*` — which chart corner/edge a table anchors to. */
232
+ type TablePosition = 'top_left' | 'top_center' | 'top_right' | 'middle_left' | 'middle_center' | 'middle_right' | 'bottom_left' | 'bottom_center' | 'bottom_right';
233
+ /** One `table.cell(...)`. */
234
+ interface TableCell {
235
+ text?: string;
236
+ textColor?: string;
237
+ bgColor?: string;
238
+ hAlign: BoxHAlign;
239
+ vAlign: BoxVAlign;
240
+ textSize: BoxTextSize;
241
+ fontFamily: BoxFontFamily;
242
+ tooltip?: string;
243
+ bold: boolean;
244
+ italic: boolean;
245
+ /** A non-origin cell absorbed by a `table.merge_cells` region → not rendered. */
246
+ merged?: boolean;
247
+ }
248
+ /** A `table.merge_cells` region (inclusive, in column/row coordinates). */
249
+ interface TableMerge {
250
+ startCol: number;
251
+ startRow: number;
252
+ endCol: number;
253
+ endRow: number;
254
+ }
255
+ /** A Pine `table.new(...)` — a DOM-overlay grid anchored to a chart corner. */
256
+ interface DrawingTable {
257
+ id: string;
258
+ paneId: string;
259
+ position: TablePosition;
260
+ columns: number;
261
+ rows: number;
262
+ bgColor?: string;
263
+ frameColor?: string;
264
+ frameWidth: number;
265
+ borderColor?: string;
266
+ borderWidth: number;
267
+ /** Row-major: `cells[row][col]`; entries may be null (empty cell). */
268
+ cells: Array<Array<TableCell | null>>;
269
+ /** Merged-cell regions (`table.merge_cells`); origin spans, others are dropped. */
270
+ merges: TableMerge[];
271
+ }
272
+
273
+ type PaneKind = 'price' | 'study';
274
+ interface Pane {
275
+ id: string;
276
+ kind: PaneKind;
277
+ /** Display order, top-to-bottom; the price pane is conventionally order 0. */
278
+ order: number;
279
+ /** Relative height weight among panes (the renderer normalizes). */
280
+ heightWeight?: number;
281
+ title?: string;
282
+ }
283
+ /** One bar's vertical gradient stop for a gradient `fill()` (color@price). */
284
+ interface FillGradientStop {
285
+ topValue: number;
286
+ bottomValue: number;
287
+ topColor: string;
288
+ bottomColor: string;
289
+ }
290
+ /** A band fill between two value series (Pine `fill(plot1, plot2, ...)`). */
291
+ interface Fill {
292
+ id: string;
293
+ paneId: string;
294
+ /** RESOLVED series ids (the orchestrator resolves Pine plot refs to ids). */
295
+ fromSeriesId: string;
296
+ toSeriesId: string;
297
+ /** Flat band color (no per-bar variation). */
298
+ color?: string;
299
+ /** Per-bar solid color (conditional fills), aligned to the anchor points by index. */
300
+ colors?: Array<string | null>;
301
+ /** Per-bar vertical gradient (gradient-fill overload), aligned by index. */
302
+ gradient?: Array<FillGradientStop | null>;
303
+ }
304
+ /** A vertical background tint over a time span (Pine `bgcolor()` / session bands). */
305
+ interface Background {
306
+ id: string;
307
+ paneId: string;
308
+ /** Inclusive start, epoch ms. */
309
+ from: Millis;
310
+ /** Exclusive end, epoch ms. */
311
+ to: Millis;
312
+ color: string;
313
+ }
314
+ /** A horizontal price line (Pine `hline()`). */
315
+ interface PriceLine {
316
+ id: string;
317
+ paneId: string;
318
+ price: number;
319
+ color?: string;
320
+ lineStyle?: LineStyle;
321
+ width?: number;
322
+ title?: string;
323
+ }
324
+ /**
325
+ * The renderer-neutral, full description of what to draw. In the engine-owned
326
+ * design the orchestrator usually drives the renderer per-indicator
327
+ * (`mountIndicator`), but `Scene` is the conceptual aggregate the reconciler
328
+ * diffs against.
329
+ */
330
+ interface Scene {
331
+ bars: OHLCV[];
332
+ panes: Pane[];
333
+ series: SeriesSpec[];
334
+ fills: Fill[];
335
+ backgrounds: Background[];
336
+ priceLines: PriceLine[];
337
+ lines?: DrawingLine[];
338
+ boxes?: DrawingBox[];
339
+ labels?: DrawingLabel[];
340
+ polylines?: DrawingPolyline[];
341
+ linefills?: DrawingLinefill[];
342
+ tables?: DrawingTable[];
343
+ }
344
+
345
+ /**
346
+ * One order execution of a strategy indicator — the unit painted on the chart as a
347
+ * trade marker (direction arrow + optional label/quantity text + a tick at the exact
348
+ * fill price). Executions anchor to their FILL bar and always render on the PRICE
349
+ * pane, whatever pane the indicator's plots landed on: a fill price only means
350
+ * something on the price scale.
351
+ */
352
+ interface TradeExecution {
353
+ /** Fill bar (bar open time, epoch ms) — the bar the marker unit anchors to. */
354
+ time: Millis;
355
+ /** Exact fill price — anchors the price tick on the bar's edge. */
356
+ price: number;
357
+ /** A buy paints an up arrow below the bar; a sell a down arrow above it. */
358
+ side: 'buy' | 'sell';
359
+ /**
360
+ * Entries paint a plain arrow in the position side's entry color; exits paint a
361
+ * capped arrow (a bar between tip and price bar) in the shared exit color.
362
+ */
363
+ kind: 'entry' | 'exit';
364
+ /** Text line next to the arrow — the order id, or its comment when one was given. */
365
+ label?: string;
366
+ /** Filled quantity (magnitude); painted signed (`+` for buys, `-` for sells). */
367
+ qty?: number;
368
+ /** Shared by the executions of one round-trip (an entry and its exits). */
369
+ tradeId?: string;
370
+ }
371
+
372
+ /**
373
+ * Renderer-neutral indicator input schema — Vela's own shape, owned here so no
374
+ * scripting language's own input model leaks into core (each engine maps its
375
+ * declarations onto this at its boundary). Drives the renderer's settings dialog
376
+ * (the gear settings UI).
377
+ */
378
+ type InputType = 'int' | 'float' | 'bool' | 'string' | 'source' | 'color' | 'price' | 'time' | 'session' | 'timeframe' | 'symbol' | 'text_area';
379
+ type InputValue = number | string | boolean;
380
+ /**
381
+ * Host-provided symbol picker for the settings dialog's `input.symbol` control. Called when the
382
+ * user activates the field: the host opens its own symbol-selection UI (e.g. the app's ticker
383
+ * menu) seeded with the `current` symbol, and reports the chosen one back through `onPick`. When
384
+ * no picker is wired, `input.symbol` falls back to a plain text field.
385
+ */
386
+ type SymbolPickerFn = (current: string, onPick: (symbol: string) => void) => void;
387
+ interface InputSchema {
388
+ /** Stable key used by `setInput()` — the engine's own variable id, falling back to `title`. */
389
+ key: string;
390
+ /** Display label shown in the settings dialog. */
391
+ title: string;
392
+ type: InputType;
393
+ defval: InputValue;
394
+ min?: number;
395
+ max?: number;
396
+ step?: number;
397
+ /** Choices for a dropdown (`input.string(..., options=[...])`). */
398
+ options?: readonly string[];
399
+ /** Grouping label for the dialog layout. */
400
+ group?: string;
401
+ /** Inline grouping label (controls placed on one row). */
402
+ inline?: string;
403
+ tooltip?: string;
404
+ }
405
+
406
+ /** Declaration metadata from the Pine `indicator()` / `strategy()` call. */
407
+ interface IndicatorMeta {
408
+ title: string;
409
+ shorttitle?: string;
410
+ overlay: boolean;
411
+ precision?: number;
412
+ format?: string;
413
+ }
414
+ /** Where an indicator's plots are placed. */
415
+ type PaneHint = 'price' | 'new';
416
+ /**
417
+ * Everything one `addIndicator()` produces — the unit the orchestrator mounts
418
+ * on the renderer. Renderer-neutral.
419
+ */
420
+ interface IndicatorModel {
421
+ /** Per-instance id (stable). */
422
+ id: string;
423
+ title: string;
424
+ overlay: boolean;
425
+ paneHint: PaneHint;
426
+ /**
427
+ * Marks a NATIVE indicator (core-computed, no Pine engine) and its type (e.g. `'volume'`,
428
+ * `'volume'`). Absent ⇒ an ordinary Pine indicator. Drives native-only legend styling
429
+ * (distinct title color) + list ordering (native indicators pin to the top).
430
+ */
431
+ native?: {
432
+ type: string;
433
+ };
434
+ /** Resolved pane id, filled in by the orchestrator after routing. */
435
+ paneId?: string;
436
+ /**
437
+ * When true, this indicator renders on its OWN price scale within its pane (a
438
+ * dedicated axis column to the right of the pane's scale), independent of the
439
+ * pane's master scale — set when the indicator is merged into a pane it does not
440
+ * own. Absent/false ⇒ it shares the pane's scale (the norm; script overlays like
441
+ * a moving average keep sharing the price scale).
442
+ */
443
+ ownScale?: boolean;
444
+ /**
445
+ * Chart time (epoch ms) of the execution's FIRST bar. Index-aligned payloads —
446
+ * dense series point/bar arrays and `bar_index` drawing coordinates — count from
447
+ * this bar, so a renderer aligns them to the chart via the offset of this time in
448
+ * its bar array. Absent ⇒ the model spans the whole chart (offset 0, the norm);
449
+ * set by engines that ran over a SUFFIX of the bars (e.g. mid-backfill).
450
+ */
451
+ anchorTime?: Millis;
452
+ series: SeriesSpec[];
453
+ fills: Fill[];
454
+ backgrounds: Background[];
455
+ priceLines: PriceLine[];
456
+ /** Pine `line.new(...)` drawings (optional; absent ≡ none). */
457
+ lines?: DrawingLine[];
458
+ /** Pine `box.new(...)` drawings (optional; absent ≡ none). */
459
+ boxes?: DrawingBox[];
460
+ /** Pine `label.new(...)` drawings (optional; absent ≡ none). */
461
+ labels?: DrawingLabel[];
462
+ /** Pine `polyline.new(...)` drawings (optional; absent ≡ none). */
463
+ polylines?: DrawingPolyline[];
464
+ /** Pine `linefill.new(...)` fills (optional; absent ≡ none). */
465
+ linefills?: DrawingLinefill[];
466
+ /** Pine `table.new(...)` DOM overlays (optional; absent ≡ none). */
467
+ tables?: DrawingTable[];
468
+ /** Pine `barcolor(...)` per-bar candle recolor (time→color; absent/empty ≡ none). */
469
+ barColors?: Array<{
470
+ time: Millis;
471
+ color: string;
472
+ }>;
473
+ /** Strategy order executions, painted as trade markers on the PRICE pane (optional; absent ≡ none). */
474
+ trades?: TradeExecution[];
475
+ /** Input schema parsed from the Pine source (drives the renderer's settings dialog). */
476
+ inputs: InputSchema[];
477
+ /** Current input values (defaults merged with any user/add-time overrides). */
478
+ inputValues: Record<string, InputValue>;
479
+ }
480
+
481
+ interface DirtyRange {
482
+ from: Millis;
483
+ to: Millis;
484
+ }
485
+ /** Per-series changed tail in a value patch. */
486
+ type SeriesValueDelta = {
487
+ seriesId: string;
488
+ kind: 'points';
489
+ points: SeriesPoint[];
490
+ } | {
491
+ seriesId: string;
492
+ kind: 'bars';
493
+ bars: OHLCV[];
494
+ } | {
495
+ seriesId: string;
496
+ kind: 'markers';
497
+ markers: MarkerPoint[];
498
+ };
499
+ /**
500
+ * Value-only update to existing series — legal as an in-place renderer update
501
+ * (the renderer chooses `update()` vs `setData(tail)` by time comparison).
502
+ */
503
+ interface ValuePatch {
504
+ kind: 'value';
505
+ indicatorId: string;
506
+ dirty: DirtyRange;
507
+ /**
508
+ * The emitting run's anchor (see `IndicatorModel.anchorTime`): a re-run over a
509
+ * DIFFERENT bar window arrives as a value patch, so the anchor must travel with
510
+ * it for index-aligned rendering to re-derive its offset. `null` states the run
511
+ * spanned the WHOLE chart and clears any previous anchor — an omitted key cannot,
512
+ * so a model that once had an anchor would otherwise keep that stale offset.
513
+ */
514
+ anchorTime?: Millis | null;
515
+ series: SeriesValueDelta[];
516
+ /**
517
+ * Full drawing snapshots for this tick. Pine drawing containers are emitted
518
+ * as a small, capped, already-final set each run, so live updates replace
519
+ * the whole set rather than diffing. Absent ≡ unchanged/none.
520
+ */
521
+ lines?: DrawingLine[];
522
+ boxes?: DrawingBox[];
523
+ labels?: DrawingLabel[];
524
+ polylines?: DrawingPolyline[];
525
+ linefills?: DrawingLinefill[];
526
+ tables?: DrawingTable[];
527
+ /** Trade executions follow the same full-snapshot-per-tick pattern as the drawings. */
528
+ trades?: TradeExecution[];
529
+ }
530
+ /**
531
+ * Structural change — series added/removed/kind-changed, or panes changed.
532
+ * Forces a remount of the affected series (a series' kind is fixed at creation
533
+ * in most backends).
534
+ */
535
+ interface SchemaPatch {
536
+ kind: 'schema';
537
+ indicatorId: string;
538
+ added: SeriesSpec[];
539
+ removed: string[];
540
+ changed: Array<{
541
+ seriesId: string;
542
+ reason: 'kind' | 'pane';
543
+ }>;
544
+ }
545
+ type ScenePatch = ValuePatch | SchemaPatch;
546
+
547
+ /** A function that detaches a previously-registered subscription. */
548
+ type Unsubscribe = () => void;
549
+
550
+ /**
551
+ * Geometry seam for user drawings. A drawing stores its anchors in DATA space
552
+ * ({@link DrawingPoint}); every pixel it needs is resolved on demand through a
553
+ * {@link Projector} the renderer supplies. The model never stores pixels, so a
554
+ * drawing survives reload, pan/zoom, bar-prepend, and timezone changes — the
555
+ * same invariant Pine drawings get from `xloc:'bar_time'`.
556
+ */
557
+ /** A drawing anchor in DATA space (epoch-ms time + data-space price). */
558
+ interface DrawingPoint {
559
+ /** Epoch ms — resolved to a fractional logical bar index by the time scale. */
560
+ time: number;
561
+ /** Data-space price (not normalized, not pane-relative). */
562
+ price: number;
563
+ }
564
+ /** Axes a handle is free to move along — drives drag constraints + handle generation. */
565
+ type FreeAxis = 'both' | 'x' | 'y' | 'none';
566
+ /**
567
+ * Magnet (snap-to-candle) strength. `off` never snaps; `strong` always snaps the
568
+ * anchor to the nearest bar/OHLC; `weak` snaps only when the candle point is within
569
+ * a small pixel radius of the cursor (so you can place freely between candles).
570
+ * Holding Ctrl/Cmd is a momentary `strong` override regardless of the sticky mode.
571
+ */
572
+ type SnapMode = 'off' | 'weak' | 'strong';
573
+ /**
574
+ * The renderer-supplied data→pixel transform. The native renderer builds it from
575
+ * its {@link CoordinateSystem} (`xOf = timeToX`, `yOf = priceToY` against the
576
+ * pane's live scale + bounds); any other renderer can build the same from its own
577
+ * coordinate closures. Defined in core so the model depends only on the interface.
578
+ */
579
+ interface Projector {
580
+ /** Pixel x for an epoch-ms time (extrapolates past either edge). */
581
+ xOf(time: number): number;
582
+ /** Pixel y for a price on a pane; `null` when the pane is gone. */
583
+ yOf(price: number, paneId: string): number | null;
584
+ /** Inverse — pixel → data point on a pane (used on create/drag commit). */
585
+ pxToPoint(x: number, y: number, paneId: string): DrawingPoint;
586
+ /** Which pane owns a pixel y, or `null` outside every pane. */
587
+ paneIdAtY(y: number): string | null;
588
+ /**
589
+ * A pane's vertical pixel extent, or `null` when the pane is gone. `height` is 0 while
590
+ * the pane is hidden (collapsed to a legend strip, or zeroed by another pane's maximize) —
591
+ * painters clip each drawing to this rect so panes stay visually separated; optional.
592
+ */
593
+ paneRect?(paneId: string): {
594
+ top: number;
595
+ height: number;
596
+ } | null;
597
+ /** Approximate whole bars between two times (for measurement labels); optional. */
598
+ barsBetween?(t1: number, t2: number): number;
599
+ /**
600
+ * OHLC(V) bars whose time falls within `[from, to]` (inclusive), in ascending time —
601
+ * the data a statistical drawing (e.g. a regression channel or anchored VWAP) fits
602
+ * against. `volume` is optional (some feeds omit it). Optional itself: renderers without
603
+ * series access (or with user-drawings disabled) may omit the method, and such drawings
604
+ * then degrade gracefully to an anchor-only fallback.
605
+ */
606
+ barsInRange?(from: number, to: number): ReadonlyArray<{
607
+ time: number;
608
+ open: number;
609
+ high: number;
610
+ low: number;
611
+ close: number;
612
+ volume?: number;
613
+ }>;
614
+ /** Plot width in media px (excludes the right price-axis strip). */
615
+ readonly width: number;
616
+ /** Plot height in media px (excludes the bottom time-axis strip). */
617
+ readonly height: number;
618
+ }
619
+
620
+ /**
621
+ * The cosmetic payload shared by every drawing (the "settings" a user edits).
622
+ * Reuses the Pine {@link LineStyle} so dash patterns resolve through the same
623
+ * `dashPattern()` helper the renderer already uses.
624
+ */
625
+ interface DrawingStyle {
626
+ lineColor: string;
627
+ lineWidth: number;
628
+ lineStyle: LineStyle;
629
+ /** Fill (box / closed path); `undefined` ⇒ no fill. */
630
+ fillColor?: string;
631
+ /** Fill opacity 0..1 (applied over `fillColor`). */
632
+ fillOpacity?: number;
633
+ arrowLeft?: boolean;
634
+ arrowRight?: boolean;
635
+ }
636
+ /** A drawing's editable text/annotation block. */
637
+ interface DrawingText {
638
+ value: string;
639
+ /** `undefined` ⇒ auto-contrast against the fill/background. */
640
+ color?: string;
641
+ size: 'tiny' | 'small' | 'normal' | 'large' | 'huge' | 'auto';
642
+ hAlign: 'left' | 'center' | 'right';
643
+ vAlign: 'top' | 'center' | 'bottom';
644
+ bold?: boolean;
645
+ italic?: boolean;
646
+ }
647
+
648
+ /**
649
+ * A data-driven settings schema. Each {@link SettingsField} names a dot-path into
650
+ * a drawing (`'style.lineColor'`, `'text.value'`) plus a control `kind`, so the
651
+ * renderer's settings popup builds controls generically — adding a new drawing
652
+ * type is a schema entry, not new UI code.
653
+ */
654
+ type FieldKind = 'color' | 'number' | 'select' | 'lineStyle' | 'boolean' | 'text' | 'opacity';
655
+ interface SettingsField {
656
+ /** Dot-path into the drawing, e.g. `'style.lineColor'`, `'text.value'`, `'locked'`. */
657
+ path: string;
658
+ label: string;
659
+ kind: FieldKind;
660
+ /** number/opacity bounds. */
661
+ min?: number;
662
+ max?: number;
663
+ step?: number;
664
+ /** select options. */
665
+ options?: ReadonlyArray<{
666
+ value: string;
667
+ label: string;
668
+ }>;
669
+ /** Cosmetic grouping in the popup. */
670
+ group?: 'line' | 'fill' | 'text' | 'behavior';
671
+ }
672
+ interface SettingsSchema {
673
+ fields: SettingsField[];
674
+ /**
675
+ * The text **is** the drawing (a text label, a note, a callout) rather than an optional label on
676
+ * a shape. The settings popup then puts the text controls — color, size, bold, italic — on the
677
+ * bar itself instead of tucking them under the text field.
678
+ */
679
+ textIsContent?: boolean;
680
+ }
681
+
682
+ /**
683
+ * The interactive user-drawing types. The lean-core set ships first; new types
684
+ * (fibs/patterns) extend the union + register a class — no base/port change.
685
+ */
686
+ type DrawingTypeKey = 'trendline' | 'hline' | 'ray' | 'extendedline' | 'vline' | 'hray' | 'crossline' | 'infoline' | 'trendangle' | 'box' | 'text' | 'note' | 'pricenote' | 'comment' | 'pricelabel' | 'signpost' | 'parallelchannel' | 'disjointchannel' | 'flattopbottom' | 'regressionchannel' | 'anchoredvwap' | 'fixedrangevp' | 'pitchfork' | 'schiffpitchfork' | 'modifiedschiffpitchfork' | 'insidepitchfork' | 'arrow' | 'callout' | 'ellipse' | 'triangle' | 'polyline' | 'freehand' | 'highlighter' | 'circle' | 'rotatedrect' | 'path' | 'arc' | 'curve' | 'arrowmarkup' | 'arrowmarkdown' | 'flagmark' | 'iconstamp' | 'fibretracement' | 'fibextension' | 'fibextensiontrend' | 'fibfan' | 'fibtimezones' | 'fibchannel' | 'fibspeedfan' | 'trendfibtime' | 'fibcircles' | 'fibarcs' | 'fibwedge' | 'fibspiral' | 'gannfan' | 'gannbox' | 'gannsquare' | 'dedekind' | 'sonic' | 'supersonic' | 'goldensonic' | 'goldensupersonic' | 'datepricerange' | 'position' | 'xabcd' | 'abcd' | 'elliottimpulse' | 'elliottcorrection' | 'headshoulders' | 'gartley' | 'bat' | 'butterfly' | 'crab' | 'shark' | 'cypher';
687
+ /** One anchor's role + which axes its handle may move along. */
688
+ interface AnchorSlot {
689
+ role: string;
690
+ free: FreeAxis;
691
+ }
692
+ /**
693
+ * The plain-JSON shape of one drawing — the ONLY representation that crosses the
694
+ * renderer port and the persistence boundary. A {@link Drawing} (rich behavior)
695
+ * serializes to/from this; the renderer never sees a class instance.
696
+ */
697
+ interface SerializedDrawing {
698
+ id: string;
699
+ type: DrawingTypeKey;
700
+ paneId: string;
701
+ /** time+price anchors — the single source of geometry truth. */
702
+ anchors: DrawingPoint[];
703
+ style: DrawingStyle;
704
+ text?: DrawingText;
705
+ locked: boolean;
706
+ visible: boolean;
707
+ /** Draw-order key. On a renderer with `drawingDepth` it shares ONE space with the pane's
708
+ * series — the candles and each indicator carry z keys of their own — so a drawing can sit
709
+ * anywhere in the stack, under the candles or between two indicators included. */
710
+ zIndex: number;
711
+ createdAt: number;
712
+ /** Per-type extras (e.g. box `extend`) — keeps the base closed. */
713
+ props?: Record<string, unknown>;
714
+ }
715
+ /**
716
+ * The parent of every user drawing. Owns the shared state + settings/serialization
717
+ * (the "everything inherits from a parent object" intent), and declares the
718
+ * geometry behaviors as PURE functions of `(anchors, Projector)` so the whole
719
+ * hierarchy stays renderer-neutral and serializable.
720
+ */
721
+ declare abstract class Drawing {
722
+ readonly id: string;
723
+ abstract readonly type: DrawingTypeKey;
724
+ paneId: string;
725
+ /** DATA-space anchors (time+price). The only geometry the model stores. */
726
+ anchors: DrawingPoint[];
727
+ style: DrawingStyle;
728
+ text?: DrawingText;
729
+ locked: boolean;
730
+ visible: boolean;
731
+ zIndex: number;
732
+ readonly createdAt: number;
733
+ constructor(init: Partial<SerializedDrawing> & {
734
+ paneId: string;
735
+ });
736
+ /** Fallback id counter — used only when no id is supplied (store assigns real ids). */
737
+ private static seq;
738
+ abstract anchorSchema(): {
739
+ min: number;
740
+ max: number;
741
+ slots: AnchorSlot[];
742
+ };
743
+ /** True once enough anchors exist to be a real shape. */
744
+ isComplete(): boolean;
745
+ /**
746
+ * How the tool is placed: `'click'` (click each anchor; a variable-count tool —
747
+ * `max > min` — keeps adding until a finish gesture), `'drag'` (press at the first
748
+ * corner, drag, release at the second — the press-drag-release idiom for boxes/ranges/positions),
749
+ * or `'freehand'` (press, drag to capture a path, release). Drives the state machine.
750
+ */
751
+ placementMode(): 'click' | 'drag' | 'freehand';
752
+ /**
753
+ * Hook run once after interactive placement finishes, before the `create` intent —
754
+ * lets a type finalize its anchors against the live projector (e.g. a position deriving
755
+ * its stop/target/width in pixel space so a bare click drops a default-sized box).
756
+ * Default: no-op.
757
+ */
758
+ onPlaced(_proj: Projector): void;
759
+ /**
760
+ * After a single handle (anchor `index`) is dragged, re-impose any cross-anchor invariant —
761
+ * e.g. a position keeps its stop and target on opposite sides of the entry, flipping the
762
+ * non-dragged side across the entry when a drag would put them on the same side. Default: no-op.
763
+ */
764
+ constrainHandleDrag(_index: number): void;
765
+ /**
766
+ * Apply a whole-body drag — translate the original anchors by (dt, dp) in data space.
767
+ * Default moves every anchor together; a type can pin some (e.g. a callout keeps its
768
+ * pointer tip fixed and moves only the box).
769
+ */
770
+ translateBody(dt: number, dp: number, orig: DrawingPoint[]): DrawingPoint[];
771
+ /** Is the pixel (px,py) on this drawing's body, within `tol` px? */
772
+ abstract hitTest(px: number, py: number, proj: Projector, tol: number): boolean;
773
+ /** Index of the grabbed handle, or -1 for the body. */
774
+ abstract hitHandle(px: number, py: number, proj: Projector, tol: number): number;
775
+ /** Pixel positions of the draggable handles (for painting + hit-test). */
776
+ abstract handlePoints(proj: Projector): Array<[number, number]>;
777
+ /** Tight pixel bounds (selection box), or null when unresolvable. */
778
+ abstract bounds(proj: Projector): {
779
+ x: number;
780
+ y: number;
781
+ w: number;
782
+ h: number;
783
+ } | null;
784
+ /** Visible price span on its pane — folded into autoscale. */
785
+ abstract priceRange(): {
786
+ min: number;
787
+ max: number;
788
+ } | null;
789
+ /**
790
+ * Time span (epoch ms) the drawing occupies, for visible-range culling. Default
791
+ * is the anchor extent; a full-width drawing (e.g. a horizontal line) overrides
792
+ * to `null` meaning "all time" so it never culls.
793
+ */
794
+ timeExtent(): {
795
+ min: number;
796
+ max: number;
797
+ } | null;
798
+ abstract schema(): SettingsSchema;
799
+ /**
800
+ * Editable per-level config for a rich "gear" settings panel (Fibonacci levels):
801
+ * each entry's `color` / `enabled` / `label` is mutated via a `levels.<i>.<field>`
802
+ * settings path. Simple drawings return null (no gear).
803
+ */
804
+ editableLevels(): Array<{
805
+ ratio: number;
806
+ color: string;
807
+ enabled: boolean;
808
+ label?: string;
809
+ }> | null;
810
+ /** Apply a `{ 'dot.path': value }` patch (the popup emits these). */
811
+ applySettings(patch: Record<string, unknown>): void;
812
+ /** Re-read per-type extras (props) onto this instance — used by the store on an edit. */
813
+ applyProps(props: Record<string, unknown>): void;
814
+ serialize(): SerializedDrawing;
815
+ /** Per-type extras to serialize into `props` (override in subclasses). */
816
+ protected writeProps(): Record<string, unknown> | undefined;
817
+ /** Read per-type extras from a `props` bag (override in subclasses). */
818
+ protected readProps(_props: Record<string, unknown>): void;
819
+ }
820
+
821
+ /**
822
+ * Inert, renderer-neutral toolbar data. The core builds it from the type registry;
823
+ * the renderer paints a vertical bar where each {@link ToolGroup} is one button with
824
+ * a flyout listing its {@link ToolDefinition}s. One tool is armed
825
+ * at a time across all groups.
826
+ */
827
+ interface ToolDefinition {
828
+ type: DrawingTypeKey;
829
+ label: string;
830
+ /** Inline SVG markup (no DOM). */
831
+ icon: string;
832
+ }
833
+ /** A labelled subsection inside a toolbar group's flyout (e.g. "Fibonacci" within Fibonacci & Gann). */
834
+ interface ToolSection {
835
+ label: string;
836
+ tools: ToolDefinition[];
837
+ }
838
+ interface ToolGroup {
839
+ id: string;
840
+ label: string;
841
+ tools: ToolDefinition[];
842
+ /** When set, the flyout renders non-clickable headers between sections. */
843
+ sections?: ToolSection[];
844
+ }
845
+ interface ToolbarDefinition {
846
+ groups: ToolGroup[];
847
+ }
848
+ /** A developer-supplied explicit group (just type keys; the registry fills the rest). */
849
+ interface ToolbarGroupConfig {
850
+ id: string;
851
+ label: string;
852
+ tools: DrawingTypeKey[];
853
+ }
854
+ /** Public `options.drawings` shape. `true` = default toolbar; object = customize. */
855
+ type DrawingsOption = boolean | {
856
+ toolbar?: boolean;
857
+ tools?: DrawingTypeKey[];
858
+ groups?: ToolbarGroupConfig[];
859
+ };
860
+ /** The default toolbar — every registered type, grouped into the canonical seven-button layout. */
861
+ declare function defaultToolbar(): ToolbarDefinition;
862
+ /**
863
+ * Resolve `options.drawings` into a concrete toolbar definition + initial visibility.
864
+ * Default (undefined) ⇒ toolbar VISIBLE; `false` ⇒ subsystem available but toolbar hidden
865
+ * (headless use still works via `chart.drawings.add(...)`); object ⇒ `toolbar ?? true`.
866
+ */
867
+ declare function buildToolbar(option: DrawingsOption | undefined): {
868
+ definition: ToolbarDefinition;
869
+ visible: boolean;
870
+ };
871
+
872
+ /**
873
+ * The renderer-local drawing MODES beyond an armed tool: the transient measure ruler,
874
+ * the eraser, or none. Mutually exclusive with each other and with any armed tool —
875
+ * the renderer owns that exclusion; the core mirrors the outcome (see the `mode`
876
+ * intent) so external UIs (a shared workspace toolbar) can reflect and drive it.
877
+ */
878
+ type DrawingMode = 'measure' | 'eraser' | null;
879
+ /**
880
+ * Renderer→core INTENT. The renderer proposes a change from a user gesture; the
881
+ * core {@link DrawingController} decides, mutates the store (the source of truth),
882
+ * re-syncs, and emits a `drawing:*` event. A single discriminated union (vs one
883
+ * callback per kind) because every arm routes to the same destination.
884
+ */
885
+ type DrawingIntent = {
886
+ kind: 'arm';
887
+ type: DrawingTypeKey | null;
888
+ } | {
889
+ kind: 'create';
890
+ doc: SerializedDrawing;
891
+ } | {
892
+ kind: 'edit';
893
+ doc: SerializedDrawing;
894
+ } | {
895
+ kind: 'edit-many';
896
+ docs: SerializedDrawing[];
897
+ } | {
898
+ kind: 'select';
899
+ ids: string[];
900
+ additive?: boolean;
901
+ } | {
902
+ kind: 'delete';
903
+ ids: string[];
904
+ } | {
905
+ kind: 'reorder';
906
+ id: string;
907
+ to: 'front' | 'back';
908
+ } | {
909
+ kind: 'settings';
910
+ id: string;
911
+ } | {
912
+ kind: 'tool-finished';
913
+ type: DrawingTypeKey;
914
+ } | {
915
+ kind: 'favorite';
916
+ type: DrawingTypeKey;
917
+ on: boolean;
918
+ } | {
919
+ kind: 'snap-mode';
920
+ mode: SnapMode;
921
+ }
922
+ /** Stay-in-drawing-mode toggled in-chart — when on, finishing a drawing leaves the
923
+ * tool armed instead of reverting to the pointer. */
924
+ | {
925
+ kind: 'stay-mode';
926
+ on: boolean;
927
+ } | {
928
+ kind: 'mode';
929
+ mode: DrawingMode;
930
+ } | {
931
+ kind: 'undo';
932
+ } | {
933
+ kind: 'redo';
934
+ } | {
935
+ kind: 'duplicate';
936
+ ids: string[];
937
+ } | {
938
+ kind: 'copy';
939
+ ids: string[];
940
+ } | {
941
+ kind: 'paste';
942
+ };
943
+ /**
944
+ * The interactive user-drawings surface a renderer optionally implements. Present
945
+ * iff `capabilities.userDrawings`. Commands flow down; one intent channel flows up.
946
+ * Only plain {@link SerializedDrawing}/{@link ToolbarDefinition} data crosses — no
947
+ * backend types, mirroring the rest of {@link IChartRenderer}.
948
+ */
949
+ interface IDrawingsRendererPort {
950
+ /** Hand the renderer the inert toolbar definition to RENDER (groups/tools/icons). */
951
+ setToolbar(def: ToolbarDefinition): void;
952
+ /** Show or hide the on-chart drawing toolbar. */
953
+ showToolbar(visible: boolean): void;
954
+ /** Push the authoritative snapshot down; the renderer re-projects + repaints. */
955
+ syncDrawings(docs: readonly SerializedDrawing[]): void;
956
+ /** Arm/disarm a tool (`null` = selection/idle, pan resumes). `lastStyle` is the
957
+ * tool's last-used style (if any) so the placement preview matches what will be
958
+ * committed, rather than falling back to the type default. */
959
+ setActiveTool(type: DrawingTypeKey | null, lastStyle?: SerializedDrawing['style']): void;
960
+ /** Reflect which drawings are selected (drives handle painting); `[]` = none. */
961
+ setSelection(ids: readonly string[]): void;
962
+ /** Push the FAVORITE tool set (flyout stars + any favorites-driven UI). Optional —
963
+ * favorites still work headless without a renderer reflection. */
964
+ setFavorites?(types: readonly DrawingTypeKey[]): void;
965
+ /** Push per-tool shortcut hints — PRE-FORMATTED display strings (e.g. `'Alt+T'`)
966
+ * shown beside the tools in the toolbar flyouts. The host owns the keymap and the
967
+ * platform formatting; the renderer only displays. Optional. */
968
+ setToolShortcuts?(map: Readonly<Partial<Record<DrawingTypeKey, string>>>): void;
969
+ /** Set the sticky magnet snap mode (off/weak/strong). Optional — a renderer without
970
+ * a magnet omits it; the in-chart toolbar reflects the pushed value. */
971
+ setSnapMode?(mode: SnapMode): void;
972
+ /** Set stay-in-drawing-mode (tools remain armed after each placement). Optional —
973
+ * the in-chart toolbar reflects the pushed value. */
974
+ setStayMode?(on: boolean): void;
975
+ /** Enter/exit a renderer-local mode (measure ruler / eraser; `null` exits). The
976
+ * renderer keeps owning the mutual exclusion (with armed tools too) and reports
977
+ * every actual change back through the `mode` intent. Optional. */
978
+ setMode?(mode: DrawingMode): void;
979
+ /** Open a drawing's settings popup (selecting it too) — the programmatic twin of a click on it. */
980
+ openSettings(id: string): void;
981
+ /**
982
+ * The pane's SERIES stack in z terms, for renderers whose drawings share one draw-order
983
+ * space with the series (`drawingDepth`): the extremes ("bring to front" beats `front`,
984
+ * "send to back" undercuts `back`) and the candles' own key (`price`, absent on a study
985
+ * pane) — a new drawing starts just under it. Optional — without it drawings order only
986
+ * among themselves, on a layer of their own.
987
+ */
988
+ stackRange?(paneId: string): {
989
+ front: number;
990
+ back: number;
991
+ price?: number;
992
+ };
993
+ /** The one channel up — create/edit/select/delete/settings/tool-finished. */
994
+ onDrawingIntent(cb: (intent: DrawingIntent) => void): Unsubscribe;
995
+ }
996
+
997
+ /** What a rendering backend supports — drives graceful degradation + warnings. */
998
+ interface RendererCapabilities {
999
+ panes: boolean;
1000
+ /**
1001
+ * Full pane management: moving/merging an indicator between panes (with its own
1002
+ * scale column), reordering panes, and pane collapse/maximize. A renderer without
1003
+ * it keeps one-pane-per-indicator behavior; `chart.panes` mutations warn + no-op.
1004
+ */
1005
+ paneManagement: boolean;
1006
+ fills: 'native' | 'primitive' | 'unsupported';
1007
+ bgcolor: 'native' | 'primitive' | 'unsupported';
1008
+ hline: 'native' | 'primitive' | 'unsupported';
1009
+ markers: boolean;
1010
+ barcolor: 'native' | 'approximated' | 'unsupported';
1011
+ perPointColor: boolean;
1012
+ /** Pine drawing objects (line/box/label/polyline/linefill) via custom primitives. */
1013
+ drawings: boolean;
1014
+ /** Interactive USER drawing tools (toolbar + hit-test + handles). Distinct from `drawings`. */
1015
+ userDrawings: boolean;
1016
+ /** Whether user drawings share ONE draw-order space with the pane's series — a drawing's
1017
+ * `zIndex` then places it anywhere in the stack: over everything, under the candles, or
1018
+ * between two indicators. Absent/false: every drawing paints in front, `zIndex` orders
1019
+ * only the drawings among themselves, and a host UI should not offer depth slots. */
1020
+ drawingDepth?: boolean;
1021
+ /** Pine `table.new` dashboards via a DOM overlay. */
1022
+ tables: boolean;
1023
+ /** Strategy trade markers (`IndicatorModel.trades`): order-fill arrows + labels + price
1024
+ * ticks on the price pane, plus the `tradeMarkers` display feature. Absent/false ⇒ the
1025
+ * channel is carried through mounts/patches but never painted. */
1026
+ trades?: boolean;
1027
+ /** Whether the renderer provides the in-chart inputs/settings UI. */
1028
+ inputsUI: boolean;
1029
+ }
1030
+ /** Opaque handle to a mounted indicator, returned by `mountIndicator()`. */
1031
+ interface IndicatorRenderHandle {
1032
+ readonly id: string;
1033
+ }
1034
+ /** An indicator's live status, shown in its legend row. */
1035
+ type IndicatorStatus = 'idle' | 'loading' | 'live';
1036
+ /**
1037
+ * One host-contributed legend-row action, as the renderer consumes it: pure data plus a
1038
+ * thunk. The shell resolves the plugin descriptor (its `when` gate, the context, the
1039
+ * indicator info) BEFORE it reaches the renderer, so the renderer stays ignorant of the
1040
+ * plugin layer — it just paints an icon button and calls `run` on click.
1041
+ */
1042
+ interface LegendActionView {
1043
+ id: string;
1044
+ /** Icon id in the core icon registry (`registerIcon`). */
1045
+ icon: string;
1046
+ tooltip: string;
1047
+ run(): void;
1048
+ }
1049
+ /** OHLCV of the price bar under the crosshair (the "data window" source). */
1050
+ interface CrosshairOHLC {
1051
+ time: Millis;
1052
+ open: number;
1053
+ high: number;
1054
+ low: number;
1055
+ close: number;
1056
+ volume?: number;
1057
+ }
1058
+ interface CrosshairEvent {
1059
+ time: Millis | null;
1060
+ price: number | null;
1061
+ /** Value at the crosshair per series, keyed by stable series id. */
1062
+ values: ReadonlyMap<string, number>;
1063
+ /** The hovered price bar's OHLCV (null when the cursor is off any bar). */
1064
+ ohlc: CrosshairOHLC | null;
1065
+ }
1066
+ interface ClickEvent {
1067
+ time: Millis | null;
1068
+ price: number | null;
1069
+ }
1070
+ /** One indicator plot's readout line in the data window. */
1071
+ interface DataWindowRow {
1072
+ label: string;
1073
+ value: string;
1074
+ color: string;
1075
+ }
1076
+ /** The OHLCV block of a data-window readout, formatted on the price pane's scale. */
1077
+ interface DataWindowOHLC {
1078
+ o: string;
1079
+ h: string;
1080
+ l: string;
1081
+ c: string;
1082
+ vol?: string;
1083
+ /** Close ≥ open → tint the values with the up color, else the down color. */
1084
+ up: boolean;
1085
+ }
1086
+ /** One indicator's readout: its title plus a row per plot. */
1087
+ interface DataWindowGroup {
1088
+ name: string;
1089
+ rows: DataWindowRow[];
1090
+ }
1091
+ /**
1092
+ * A data-window snapshot — the bar's timestamp split into date + time, its OHLCV, and one
1093
+ * group per indicator. Every value arrives pre-formatted on the scale of the pane it belongs
1094
+ * to, so a host panel lays the readout out without doing any numeric formatting itself.
1095
+ */
1096
+ interface DataWindowReadout {
1097
+ /** Bar date, pre-formatted (e.g. `2026-07-03`); empty when there is no bar. */
1098
+ date: string;
1099
+ /** Bar time of day, pre-formatted `HH:MM`; empty when there is no bar. */
1100
+ time: string;
1101
+ ohlc: DataWindowOHLC | null;
1102
+ groups: DataWindowGroup[];
1103
+ }
1104
+ /** Raised by the renderer when the user edits an input in the settings dialog. */
1105
+ interface InputChangeEvent {
1106
+ indicatorId: string;
1107
+ key: string;
1108
+ value: InputValue;
1109
+ }
1110
+ interface VisibleRange {
1111
+ from: Millis;
1112
+ to: Millis;
1113
+ }
1114
+ /** A user-initiated pane action reported by the renderer (hover buttons / double-clicks). */
1115
+ type PaneAction = {
1116
+ type: 'move';
1117
+ paneId: string;
1118
+ dir: 'up' | 'down';
1119
+ } | {
1120
+ type: 'remove';
1121
+ paneId: string;
1122
+ } | {
1123
+ type: 'collapse';
1124
+ paneId: string;
1125
+ collapsed: boolean;
1126
+ } | {
1127
+ type: 'maximize';
1128
+ paneId: string;
1129
+ maximized: boolean;
1130
+ };
1131
+ /**
1132
+ * The rendering backend abstraction. No backend (e.g. lightweight-charts) types
1133
+ * cross this boundary — that is what makes the renderer swappable. The only MVP
1134
+ * implementation is `src/renderers/lightweight-charts/LwcRenderer.ts`.
1135
+ */
1136
+ interface IChartRenderer {
1137
+ readonly capabilities: RendererCapabilities;
1138
+ /** Stable identity of this renderer (e.g. `'native'`, `'lwc'`) — the warn label and `chart.renderer.name`. */
1139
+ readonly name: string;
1140
+ /** Feature keys this renderer can get/set at runtime via `chart.renderer.set` / `.get`. */
1141
+ readonly features: readonly string[];
1142
+ /** Apply a supported feature live (the caller has already checked `features`); repaints as needed. */
1143
+ applyFeature(key: string, value: unknown): void;
1144
+ /** Read a feature's current value (`undefined` if unsupported). */
1145
+ readFeature(key: string): unknown;
1146
+ mount(container: HTMLElement, theme: VelaTheme): void;
1147
+ setTheme(theme: VelaTheme): void;
1148
+ resize(): void;
1149
+ destroy(): void;
1150
+ /**
1151
+ * Replace all price bars. By default re-frames the view (a fresh series). Pass
1152
+ * `{ preserveView: true }` to keep the current viewport — used when extending the
1153
+ * same series in place (e.g. swapping a quick preview for the full history) so
1154
+ * candles don't jump.
1155
+ */
1156
+ setBars(bars: OHLCV[], opts?: {
1157
+ preserveView?: boolean;
1158
+ }): void;
1159
+ /** Append a new bar or replace the forming (last) bar, decided by time. */
1160
+ updateBar(bar: OHLCV): void;
1161
+ /**
1162
+ * Set the active symbol's tick size (e.g. `0.01`) so the price axis renders the
1163
+ * instrument's true precision. Passed as soon as symbol metadata resolves; `undefined`
1164
+ * (or absent) ⇒ the renderer falls back to its zoom-derived decimals. Optional.
1165
+ */
1166
+ setPricePrecision?(mintick: number | undefined): void;
1167
+ /**
1168
+ * Push a bespoke NATIVE-LAYER render payload, keyed by layer `type`. Visuals that aren't
1169
+ * ordinary series/fills draw through a dedicated renderer layer instead of the model; this is
1170
+ * the channel. Producers are native indicators (`'volume'`, `'vpvr'` — layer config) and core
1171
+ * data engines behind a price style (a plugin chart type pushing per-bar secondary data
1172
+ * through its own channel). Optional: a renderer without the
1173
+ * layers omits it.
1174
+ */
1175
+ setNativeData?(type: string, data: unknown): void;
1176
+ /**
1177
+ * Reflect an indicator's live status in its legend row: `'loading'` (a fetch is in flight —
1178
+ * spinner), `'live'` (live-updating — a distinct pulse), or `'idle'` (nothing). Optional.
1179
+ */
1180
+ setIndicatorStatus?(handle: IndicatorRenderHandle, status: IndicatorStatus): void;
1181
+ /**
1182
+ * A market load is in flight with NO bars painted yet — the first load, or a
1183
+ * symbol/timeframe switch (the host clears the old series first). Renderers may show a
1184
+ * subtle loading affordance, and must hide any content that does NOT ride the bar series
1185
+ * (corner-anchored tables); bar-mapped content vanishes with the cleared series on its
1186
+ * own. The host turns the flag off with the first series it hands over (or when a load
1187
+ * fails or parks) — the core also mirrors this state to plugins as `load:start`/`load:end`.
1188
+ * Optional.
1189
+ */
1190
+ setLoading?(loading: boolean): void;
1191
+ ensurePane(pane: Pane): void;
1192
+ removePane(id: string): void;
1193
+ /**
1194
+ * Move a mounted indicator to another pane (merge/unmerge). `ownScale` gives the
1195
+ * indicator its own scale column within the target pane, rescaled so its visible
1196
+ * extent lines up with the pane's; omitted/false shares the pane scale. Present iff
1197
+ * `capabilities.paneManagement`.
1198
+ */
1199
+ setIndicatorPane?(handle: IndicatorRenderHandle, paneId: string, opts?: {
1200
+ ownScale?: boolean;
1201
+ }): void;
1202
+ /** Set the top-to-bottom pane display order (an array of pane ids). */
1203
+ orderPanes?(orderedIds: string[]): void;
1204
+ /** Collapse a pane to a thin strip (legend + expand button) or restore it. */
1205
+ setPaneCollapsed?(paneId: string, collapsed: boolean): void;
1206
+ /** Maximize one pane to fill the plot, or restore the previous split (`null`). */
1207
+ setPaneMaximized?(paneId: string | null): void;
1208
+ /**
1209
+ * The renderer reports a user-initiated pane action (from a pane hover button or a
1210
+ * double-click). The host/core reflects it: `'remove'` tears down the pane's
1211
+ * indicators; the rest are already applied by the renderer and just keep core's
1212
+ * `chart.panes` view in sync. Present iff `capabilities.paneManagement`.
1213
+ */
1214
+ onPaneAction?(cb: (action: PaneAction) => void): Unsubscribe;
1215
+ /**
1216
+ * The renderer reports a user request to move/merge an indicator to another pane, made
1217
+ * from its own in-chart UI (the legend "Move to" menu or a legend-row drag). Core routes
1218
+ * it through `moveIndicator`. Present iff `capabilities.paneManagement`.
1219
+ */
1220
+ onMoveIndicator?(cb: (id: string, target: MoveTarget) => void): Unsubscribe;
1221
+ /** Mount an indicator's series + its in-chart legend/settings UI. */
1222
+ mountIndicator(model: IndicatorModel): IndicatorRenderHandle;
1223
+ updateIndicator(handle: IndicatorRenderHandle, patch: ScenePatch): void;
1224
+ removeIndicator(handle: IndicatorRenderHandle): void;
1225
+ /** Reflect a programmatic input change in the renderer's settings UI. */
1226
+ setIndicatorInputs(handle: IndicatorRenderHandle, values: Record<string, InputValue>): void;
1227
+ /**
1228
+ * Supply a symbol picker so the settings dialog's `input.symbol` control opens the host's own
1229
+ * ticker-selection UI (the host wires this). Optional — without it, `input.symbol` is a plain
1230
+ * text field. Pass `null` to detach.
1231
+ */
1232
+ setSymbolPicker?(picker: SymbolPickerFn | null): void;
1233
+ /**
1234
+ * Supply the HOST-CONTRIBUTED actions of each legend row (the shells wire the plugin
1235
+ * registry through this — see `registerLegendAction`). The provider is called per row,
1236
+ * lazily, so `when()` gates and late registrations resolve at render time; calling this
1237
+ * again replaces the provider AND re-projects the rows already on screen. Optional — a
1238
+ * renderer without it simply never shows contributed legend actions.
1239
+ */
1240
+ setLegendActions?(provider: ((indicatorId: string) => LegendActionView[]) | null): void;
1241
+ /**
1242
+ * Hide (`false`) or show (`true`) a mounted indicator's visuals while keeping its legend row
1243
+ * (marked hidden). Optional — a renderer that can't suppress an indicator omits it (and the
1244
+ * core's hide still works for resource suspension; only the in-chart legend eye is unavailable).
1245
+ * On show the core re-mounts the indicator, so this need only drop the visuals + flag the row.
1246
+ */
1247
+ setIndicatorVisible?(handle: IndicatorRenderHandle, visible: boolean): void;
1248
+ /**
1249
+ * The renderer tells core when the base price style changes — from ANY source (the
1250
+ * `priceStyle` feature, the in-chart settings dialog, an applied config template).
1251
+ * Display state stays renderer-owned; the core listens because some styles carry a
1252
+ * DATA requirement (a plugin style may need its data engine running). Optional —
1253
+ * a renderer without runtime style switching omits it.
1254
+ */
1255
+ onPriceStyleChange?(cb: (style: PriceStyle) => void): Unsubscribe;
1256
+ /** The renderer tells core when the user edits an input in-chart. */
1257
+ onInputChange(cb: (e: InputChangeEvent) => void): Unsubscribe;
1258
+ /** The renderer tells core when the user removes an indicator in-chart (the legend ✕). */
1259
+ onRemoveIndicator(cb: (id: string) => void): Unsubscribe;
1260
+ /** The renderer tells core when the user toggles an indicator's visibility in-chart (the legend eye). */
1261
+ onToggleIndicatorVisible?(cb: (id: string, visible: boolean) => void): Unsubscribe;
1262
+ onCrosshairMove(cb: (e: CrosshairEvent) => void): Unsubscribe;
1263
+ onClick(cb: (e: ClickEvent) => void): Unsubscribe;
1264
+ /**
1265
+ * Display an EXTERNAL crosshair at a data-space position — a ghost marker driven by
1266
+ * another chart (multi-chart crosshair sync), not by this chart's own pointer.
1267
+ * `time` is epoch-ms (`null` clears); `price` optionally adds the horizontal line
1268
+ * when the caller knows the scales are comparable (same-symbol groups). The ghost
1269
+ * must NEVER re-emit `onCrosshairMove` — that one-way rule is what makes the sync
1270
+ * loop-free. OPTIONAL — detect by presence (`RendererControl.supportsExternalCrosshair`);
1271
+ * a renderer without the seam simply never shows foreign crosshairs.
1272
+ */
1273
+ setExternalCrosshair?(time: Millis | null, price?: number | null): void;
1274
+ /**
1275
+ * A pre-formatted readout of the bar under the crosshair — or of the latest bar when the
1276
+ * cursor is off the plot, so the snapshot is always useful. Pull it on crosshair movement
1277
+ * to drive a host data-window panel. Optional: a renderer that tracks no hovered bar omits
1278
+ * it (`RendererControl.dataWindowReadout()` then returns null).
1279
+ */
1280
+ getDataWindowReadout?(): DataWindowReadout;
1281
+ getVisibleRange(): VisibleRange | null;
1282
+ setVisibleRange(range: VisibleRange): void;
1283
+ /**
1284
+ * Pan by a fraction of the visible width at constant zoom (positive ⇒ toward the
1285
+ * latest bars), behaving exactly like a pointer drag: same pan limits (including the
1286
+ * bounded whitespace past the newest bar), eased if the renderer animates pans.
1287
+ * OPTIONAL — without it the core falls back to an instant `setVisibleRange` shift.
1288
+ */
1289
+ panBy?(fraction: number): void;
1290
+ onViewportChange(cb: (range: VisibleRange) => void): Unsubscribe;
1291
+ /**
1292
+ * Export the current chart as a PNG data URL (optional — a renderer that can't
1293
+ * rasterize its surface omits it). DOM overlays may not be included.
1294
+ */
1295
+ screenshot?(): string | null;
1296
+ /**
1297
+ * Snapshot the renderer's full cosmetic configuration as a serializable,
1298
+ * versioned document — for persistence (templates, saved user settings).
1299
+ * Optional: a renderer without a rich config omits it. The returned value is
1300
+ * plain JSON; its concrete shape is renderer-defined.
1301
+ */
1302
+ getConfig?(): unknown;
1303
+ /**
1304
+ * Apply a (possibly partial) config document produced by `getConfig()`.
1305
+ * Implementations validate untrusted input and ignore unknown/malformed fields,
1306
+ * repainting with no indicator re-run.
1307
+ */
1308
+ applyConfig?(config: unknown): void;
1309
+ /**
1310
+ * The renderer's cosmetic config changed via {@link applyConfig} — the in-chart
1311
+ * settings dialog commits through it, so this is how host chrome mirroring a config
1312
+ * value (a bottom-bar timezone, a persisted template) learns about in-chart edits.
1313
+ * Re-pull {@link getConfig} / `readFeature` for the new values. Optional — paired
1314
+ * with `applyConfig`.
1315
+ */
1316
+ onConfigChanged?(cb: () => void): Unsubscribe;
1317
+ /**
1318
+ * The renderer reports a user request to switch the APP THEME, made from its own
1319
+ * in-chart UI (the settings dialog's Canvas → Theme row). The core owns the
1320
+ * canonical theme: it resolves the name, calls {@link setTheme}, and emits
1321
+ * `theme:changed` so host chrome follows. Optional — a renderer without an
1322
+ * in-chart theme control omits it.
1323
+ */
1324
+ onThemeSelect?(cb: (theme: ThemeName) => void): Unsubscribe;
1325
+ /**
1326
+ * Move keyboard focus onto the chart's interactive surface (the element its keyboard
1327
+ * shortcuts key off). Optional — a host UI calls it after its own controls steal focus
1328
+ * (e.g. a shared workspace toolbar click) so chart/drawing keys keep working.
1329
+ */
1330
+ focus?(): void;
1331
+ /**
1332
+ * Close any in-chart dialogs the renderer owns (the indicator settings dialog, the
1333
+ * chart-settings gear dialog). Optional — used by a host to keep its own dialogs mutually
1334
+ * exclusive with the renderer's. A no-op when nothing is open.
1335
+ */
1336
+ closeDialogs?(): void;
1337
+ /**
1338
+ * Open (or toggle) the renderer's own settings dialog, when it has one. `section` names
1339
+ * the tab to land on (matched against the dialog's section titles, unknown ones ignored);
1340
+ * with a section an already-open dialog switches tab rather than closing.
1341
+ */
1342
+ openSettingsDialog?(section?: string): void;
1343
+ /** A chart type's SDK settings changed (dialog edit / applyConfig) — the core forwards
1344
+ * them to the type's data engine. */
1345
+ onChartTypeSettingsChange?(cb: (typeId: string, values: Record<string, unknown>) => void): Unsubscribe;
1346
+ /** Host-app settings tabs (callback rows) shown by the renderer's settings dialog. */
1347
+ setSettingsSections?(sections: ReadonlyArray<{
1348
+ title: string;
1349
+ rows: readonly unknown[];
1350
+ }>): void;
1351
+ /**
1352
+ * Interactive user-drawings surface. Present iff `capabilities.userDrawings`.
1353
+ * The core `DrawingController` drives it (commands down) and listens for
1354
+ * intents (up); a renderer without drawing tools simply omits it.
1355
+ */
1356
+ readonly userDrawingsPort?: IDrawingsRendererPort;
1357
+ }
1358
+
1359
+ /** A named visible-range shortcut, resolved against the loaded bars. */
1360
+ type VisibleRangePreset = '1D' | '1W' | '1M' | '3M' | '6M' | '1Y' | '5Y' | 'YTD' | 'ALL';
1361
+
1362
+ /** A registered data-provider name (any string; matched case-insensitively). */
1363
+ type ProviderName = string;
1364
+ /** How the chart obtains its candles. */
1365
+ interface MarketConfig {
1366
+ /** The market's symbol. A bare ticker (`'BTCUSDT'`) resolves against the registered
1367
+ * providers in DECLARATION order (first one whose index lists it); an
1368
+ * `EXCHANGE:` prefix (`'coinbase:BTC-USD'`, case-insensitive) pins the venue. */
1369
+ symbol?: string;
1370
+ timeframe?: string;
1371
+ bars?: number;
1372
+ /**
1373
+ * The window to frame on the FIRST paint — a preset name (`'1D'`, `'YTD'`, …) or an
1374
+ * explicit `{from, to}`. Set it when the initial view is known up front (a range
1375
+ * chip, a shared link): the chart then loads the depth in ONE pass and paints the
1376
+ * requested window straight away, instead of flashing its fast recent-bars preview
1377
+ * and re-framing a moment later.
1378
+ */
1379
+ visibleRange?: VisibleRangePreset | VisibleRange;
1380
+ /** Offline bars instead of a provider; when set, no network fetch happens. */
1381
+ data?: OHLCV[];
1382
+ }
1383
+ /**
1384
+ * One in-place market switch — the argument of `chart.setMarket(next)`. Only the fields
1385
+ * given change; the rest of the market keeps its current value. `data` switches to
1386
+ * offline bars (and giving `symbol`/`provider` WITHOUT `data` drops a previous offline
1387
+ * dataset — back to the provider path). `visibleRange` frames the FIRST paint of the
1388
+ * new market (a range chip switching timeframe + depth + window in one call).
1389
+ */
1390
+ interface MarketSwitch {
1391
+ /** Bare ticker (provider resolved by declaration order) or `EXCHANGE:`-prefixed. */
1392
+ symbol?: string;
1393
+ timeframe?: string;
1394
+ bars?: number;
1395
+ data?: OHLCV[];
1396
+ visibleRange?: VisibleRangePreset | VisibleRange;
1397
+ }
1398
+ /**
1399
+ * The chart's current market identity — `chart.market`, the read counterpart of
1400
+ * `setMarket`. A SNAPSHOT of the requested market (mutating it changes nothing): it
1401
+ * reflects a switch as soon as `setMarket` is called, not when the load lands — the
1402
+ * "what is this chart showing/loading right now" answer. `offline` is true when the
1403
+ * chart runs on an inline `data` array instead of a provider.
1404
+ */
1405
+ interface MarketSnapshot {
1406
+ symbol?: string;
1407
+ /** The venue the symbol PINS (its `EXCHANGE:` prefix, lower-cased) — undefined for a
1408
+ * bare symbol. The venue that actually served it: `chart.data.resolve(symbol)`. */
1409
+ provider?: ProviderName;
1410
+ timeframe?: string;
1411
+ bars?: number;
1412
+ offline: boolean;
1413
+ }
1414
+ interface VelaTheme {
1415
+ background: string;
1416
+ textColor: string;
1417
+ gridColor: string;
1418
+ borderColor: string;
1419
+ upColor: string;
1420
+ downColor: string;
1421
+ fontFamily: string;
1422
+ }
1423
+ type ThemeName = 'dark' | 'light';
1424
+ /** A renderer **class** — Vela instantiates it with the resolved display options.
1425
+ * Built-in default: `NativeRenderer`.
1426
+ * from `'vela/renderers/lwc'` and pass it as `options.renderer`. */
1427
+ type RendererConstructor = new (opts?: RendererDisplayOptions) => IChartRenderer;
1428
+ interface VelaOptions extends MarketConfig {
1429
+ /** false = static history; true = history + live forming candle. */
1430
+ live?: boolean;
1431
+ theme?: ThemeName | VelaTheme;
1432
+ height?: number | string;
1433
+ /** Rendering backend as a renderer **class** that Vela instantiates (with the
1434
+ * resolved display options). Omit for the built-in native renderer (default); for
1435
+ **/
1436
+ renderer?: RendererConstructor;
1437
+ /** Scripting language used when `addIndicator` doesn't specify one. Default `'pine'`
1438
+ * (or the first injected engine's language). */
1439
+ defaultLanguage?: string;
1440
+ /** Show the dashed line + axis label at the latest price (default true). */
1441
+ currentPriceLine?: boolean;
1442
+ /** Use a logarithmic price scale on the price pane (default false). */
1443
+ logScale?: boolean;
1444
+ /** Native geometry backend: `'auto'` (WebGL2 if available, else canvas2d),
1445
+ * or force `'canvas2d'` / `'webgl2'`. Native renderer only. */
1446
+ nativeBackend?: NativeBackend;
1447
+ /** Native-renderer animations. `true`/`false` toggles all; an object configures
1448
+ * each independently. Default: eased **zoom on**, inertial **pan on but snappy**
1449
+ * (short glide). Set `{ pan: false }` for an instant pan with no momentum. */
1450
+ animations?: boolean | AnimationConfig;
1451
+ /** Neon glow/bloom intensity for line series (0 = off, ~0.6 = strong). WebGL2 only
1452
+ * — the canvas2d backend ignores it. Default 0. */
1453
+ glow?: number;
1454
+ /** Bullish candle body/wick color (native renderer). Defaults to the palette's bullish green. */
1455
+ upColor?: string;
1456
+ /** Bearish candle body/wick color (native renderer). Defaults to the palette's bearish red. */
1457
+ downColor?: string;
1458
+ /** How the base price series is drawn (native renderer): candlestick / OHLC bars /
1459
+ * line / area / baseline. Default `'candles'`. */
1460
+ priceStyle?: PriceStyle;
1461
+ /** Interactive user drawings (native renderer). Default: toolbar VISIBLE with the
1462
+ * default tool set. `false` hides the toolbar (the `chart.drawings` API still works
1463
+ * headlessly); an object picks tools (`{ tools: [...] }`) or defines groups
1464
+ * (`{ groups: [...] }`) and toggles the toolbar (`{ toolbar: false }`). */
1465
+ drawings?: DrawingsOption;
1466
+ /** The built-in volume indicator: per-bar volume columns anchored to the bottom of the
1467
+ * price pane, on their own scale (they never affect the price autoscale). Added
1468
+ * automatically on chart creation (native renderer) — pass `false` to opt out. */
1469
+ volume?: boolean;
1470
+ }
1471
+ /** Per-feature native-renderer animation toggles. */
1472
+ interface AnimationConfig {
1473
+ /** Eased cursor-anchored wheel-zoom (+ gliding autoscale while zooming). Default true. */
1474
+ zoom?: boolean;
1475
+ /** Inertial/kinetic pan — a short snappy glide after a drag-release. Default true. */
1476
+ pan?: boolean;
1477
+ }
1478
+ /** Native geometry-layer backend selection. */
1479
+ type NativeBackend = 'auto' | 'canvas2d' | 'webgl2';
1480
+ /** How the base price series is drawn on the price pane (native renderer).
1481
+ * A plugin chart type (registered via `vela/plugin`) adds its own id to this union
1482
+ * volume-at-price (plus a right-edge visible-range profile); it needs the
1483
+ * provider+symbol to expose trade data — without it, plain candles render.
1484
+ * `'heikinashi'` draws Heikin Ashi candles: a 1:1 display transform of the raw
1485
+ * bars applied at the core's bar seam, so indicators compute on the same
1486
+ * smoothed values the chart shows (raw data stays untouched underneath). */
1487
+ /** Built-in styles plus any id registered through the chart-type SDK (`registerChartType`). */
1488
+ type PriceStyle = 'candles' | 'bars' | 'line' | 'area' | 'baseline' | 'heikinashi' | (string & {});
1489
+ /** Display options passed to a renderer at construction. */
1490
+ interface RendererDisplayOptions {
1491
+ currentPriceLine: boolean;
1492
+ logScale: boolean;
1493
+ nativeBackend: NativeBackend;
1494
+ animZoom: boolean;
1495
+ animPan: boolean;
1496
+ glow: number;
1497
+ upColor: string;
1498
+ downColor: string;
1499
+ priceStyle: PriceStyle;
1500
+ }
1501
+ /**
1502
+ * Where to move an indicator (via `handle.moveTo(...)`):
1503
+ * - `'price'` — merge into the main price pane (on its own scale unless it's a
1504
+ * price-unit overlay).
1505
+ * - `{ pane: id }` — merge into an existing pane (identified by `Pane.id`).
1506
+ * - `{ newPane: {...} }` — create a fresh pane, optionally placed relative to an
1507
+ * existing one (`before`/`after` its pane id); default is a new pane at the bottom.
1508
+ */
1509
+ type MoveTarget = 'price' | {
1510
+ pane: string;
1511
+ } | {
1512
+ newPane: {
1513
+ before?: string;
1514
+ after?: string;
1515
+ } | true;
1516
+ };
1517
+ /** A pane and the indicators it holds — a `chart.panes.list()` entry. */
1518
+ interface PaneInfo {
1519
+ id: string;
1520
+ kind: 'price' | 'study';
1521
+ /** Display order, top-to-bottom (0 = topmost, the price pane). */
1522
+ order: number;
1523
+ collapsed: boolean;
1524
+ maximized: boolean;
1525
+ indicators: Array<{
1526
+ id: string;
1527
+ title: string;
1528
+ ownScale: boolean;
1529
+ }>;
1530
+ }
1531
+ /** Options for `chart.addIndicator(source, options?)`. */
1532
+ interface AddIndicatorOptions {
1533
+ /** Which registered engine runs this script (by language id). Default: the chart's `defaultLanguage`. */
1534
+ language?: string;
1535
+ /** Input overrides, keyed by input title or varId. */
1536
+ inputs?: Record<string, InputValue>;
1537
+ /** Force overlay-vs-pane placement (default: read from `indicator(overlay=…)`). */
1538
+ overlay?: boolean;
1539
+ /** Explicit pane placement. */
1540
+ pane?: 'price' | 'new';
1541
+ /** Display title override. */
1542
+ title?: string;
1543
+ }
1544
+
1545
+ export { type DrawingLinefill as $, type AddIndicatorOptions as A, type Background as B, type CrosshairEvent as C, Drawing as D, type CandleBarColor as E, type CandleSeries as F, type CandleStyle as G, type DataWindowGroup as H, type IChartRenderer as I, type DataWindowOHLC as J, type DataWindowRow as K, type LineStyle as L, type MarketConfig as M, type NativeBackend as N, type OHLCV as O, type PriceStyle as P, type DirtyRange as Q, type RendererCapabilities as R, type SerializedDrawing as S, type ThemeName as T, type Unsubscribe as U, type VisibleRangePreset as V, type DrawingBox as W, type DrawingExtend as X, type DrawingIntent as Y, type DrawingLabel as Z, type DrawingLine as _, type VisibleRange as a, type DrawingMode as a0, type DrawingPoint as a1, type DrawingPolyline as a2, type DrawingStyle as a3, type DrawingTable as a4, type DrawingText as a5, type DrawingXLoc as a6, type DrawingsOption as a7, type Fill as a8, type FillGradientStop as a9, type SettingsSchema as aA, type TableCell as aB, type TableMerge as aC, type TablePosition as aD, type ToolbarGroupConfig as aE, type TradeExecution as aF, type ValuePatch as aG, buildToolbar as aH, defaultToolbar as aI, type PaneInfo as aJ, type IndicatorMeta as aa, type InputSchema as ab, type InputType as ac, type LabelStyle as ad, type LabelYLoc as ae, type LineLikeKind as af, type LineLikeSeries as ag, type LineLikeStyle as ah, type MarkerPoint as ai, type MarkerSeries as aj, type MarketSnapshot as ak, type MarketSwitch as al, type PaneHint as am, type PaneKind as an, type PolylinePoint as ao, type PriceLine as ap, type Projector as aq, type ProviderName as ar, type RendererConstructor as as, type Scene as at, type SchemaPatch as au, type SeriesKind as av, type SeriesPoint as aw, type SeriesSpec as ax, type SeriesValueDelta as ay, type SettingsField as az, type VelaOptions as b, type VelaTheme as c, type RendererDisplayOptions as d, type IndicatorRenderHandle as e, type IndicatorStatus as f, type Pane as g, type PaneAction as h, type MoveTarget as i, type IndicatorModel as j, type ScenePatch as k, type InputValue as l, type SymbolPickerFn as m, type LegendActionView as n, type InputChangeEvent as o, type ClickEvent as p, type DataWindowReadout as q, type IDrawingsRendererPort as r, type Millis as s, type SnapMode as t, type DrawingTypeKey as u, type ToolbarDefinition as v, type BoxFontFamily as w, type BoxHAlign as x, type BoxTextSize as y, type BoxVAlign as z };