acttrader-charts 1.3.0-beta.16 → 1.3.0-beta.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -378,6 +378,88 @@ chart.on('orderLineMoved', ({ label, fromTimestamp, toTimestamp, data }) => {
378
378
 
379
379
  ---
380
380
 
381
+ ### Trade action bar — `features.tradeActionBar`
382
+
383
+ With the flag on, the floating trade button opens a segmented bar at the clicked
384
+ price instead of the two-row Buy/Sell popup:
385
+
386
+ ```
387
+ Alert | Pending | SL | TP | TSL | ×
388
+ ```
389
+
390
+ - No price readout — the axis already shows the price at that point.
391
+ - **Alert** calls `onAddAlert(price)`. The chip is only rendered when that callback is set.
392
+ - **Pending** opens a sub-menu just above the bar — an `Above · 1.17586` / `Below · …`
393
+ header, then the two orders that make sense at that price (`Buy Limit` / `Sell Stop`
394
+ below the market, `Sell Limit` / `Buy Stop` above), each with its `@ price`. Picking a
395
+ row creates the draft order exactly as before and closes both.
396
+ - **SL / TP / TSL** emit `bulkLevelsRequested` with `{ kind, price }` and close the
397
+ bar — the host opens its Bulk Levels dialog pre-focused on that kind. The chart
398
+ never calls a broker.
399
+ - **×**, a click elsewhere, Escape, TFC off and `dismissAllUI()` all close it.
400
+
401
+ Chip labels and the × tooltip live under `labels.trade` (`actionAlert`, `actionPending`,
402
+ `actionSl`, `actionTp`, `actionTsl`, `actionCloseTitle`).
403
+
404
+ ### On-chart P/L pill — `features.pnlPill`
405
+
406
+ A floating summary of the open positions on the chart, for the trader who wants
407
+ the total without opening the positions panel:
408
+
409
+ ```
410
+ ⋮⋮ 3 POS +72.65 USD | ◎ ✕
411
+ ```
412
+
413
+ - **`3 POS`** — how many position levels are on the chart. Pending orders,
414
+ position-style entry orders (`entryPriceEditable`) and an unconfirmed draft
415
+ are not counted.
416
+ - **`+72.65 USD`** — the sum of the numeric `pnl` those levels carry, i.e. the
417
+ `pnlKey` column you pass to `setLevels`. The chart computes no money itself;
418
+ while no position has a `pnl` yet the pill shows `—`. Profit is drawn in the
419
+ buy colour, loss in the sell colour.
420
+ - **Click the body** (the grip, the count or the amount) to fan every position
421
+ badge out on the chart — clustered levels expand, and TFC is switched on if it
422
+ was off — with an accent ring on the pill while they are shown. Click again to
423
+ collapse.
424
+ - **◎** (the same target glyph as the Bulk Levels dialog header) emits
425
+ `bulkLevelsRequested` with `source: 'pill'` and a `null` price, so your Bulk Levels
426
+ dialog opens pre-scoped to every open position on the symbol. Tooltip:
427
+ "Set SL · TP · TSL on all N {symbol} positions".
428
+ - **✕** (amber) emits `pnlPillCloseAll` with every counted position. Your app
429
+ confirms and closes them; the chart never calls a broker.
430
+
431
+ The pill sits top-right of the plot, clear of the price axis. Drag it anywhere
432
+ inside the plot; double-click puts it back. It hides itself while the chart has
433
+ no positions and follows the chart theme. Every element sits on one shared row
434
+ height, and the grip and both buttons have fixed widths, so a long or negative
435
+ amount never shifts or squeezes them.
436
+
437
+ With the feature on, the header (advanced toolbar and default top bar) also gets a
438
+ **P/L** switch — wallet icon, `P/L`, the same 24px `rounded-sm` button tinted while the
439
+ pill is shown. It hides or shows the pill on the user's say-so, wins over the position
440
+ count, and emits `pnlPillToggle` so you can persist the choice; `pnlPill.visible` seeds
441
+ it and `setPnlPillVisible()` drives it from code.
442
+
443
+ ```ts
444
+ const chart = new ChartEngine({
445
+ container,
446
+ features: { pnlPill: true },
447
+ pnlPill: { currency: 'USD' }, // → "+72.65 USD"; or format: (pnl) => myMoney(pnl)
448
+ });
449
+
450
+ chart.setLevels(positions, 'TradeID', 'Price', 'position', 'pnl', 'pnlText');
451
+
452
+ chart.on('pnlPillCloseAll', async ({ count, pnl, data }) => {
453
+ if (!(await confirmDialog(`Close all ${count} positions?`))) return;
454
+ for (const row of data) closeTrade(row);
455
+ });
456
+ ```
457
+
458
+ Labels live under `labels.pnlPill`: `positionsAbbrev` (`'POS'`), `showPositionsTitle`,
459
+ `hidePositionsTitle`, `bulkLevelsTitle`, `closeAllTitle` — titles may
460
+ use `{symbol}` and `{count}`. The maths behind the pill is exported as
461
+ `summarisePositionLevels(levels, draftLabel?)` and `formatPnlPillValue(pnl, currency?)`.
462
+
381
463
  ## Default Configuration
382
464
 
383
465
  ### `ChartConfig`
@@ -392,7 +474,8 @@ chart.on('orderLineMoved', ({ label, fromTimestamp, toTimestamp, data }) => {
392
474
  | `hideHeader` | | `false` | Hide only the chart header (TopBar / AdvancedToolbar / CompactToolbar, per `headerLayout`). Bottom bar, left drawing tools, and on-canvas overlays remain on their own flags. Drive the chart from your own UI via `setTimeframe(tf)`, `setSeries(type)`, `addIndicatorByName(name)`, `removeIndicator(name)` |
393
475
  | `showDrawingTools` | | `true` | Show drawing toolbar and pencil button |
394
476
  | `showFullscreenButton` | | `true` | Show the fullscreen toggle button in the top bar. Set to `false` to hide it entirely. Mobile wrappers (Android / iOS) default this to `false` |
395
- | `timeframe` | | `"1D"` | Initial timeframe |
477
+ | `timeframe` | | `"1D"` | Initial timeframe. Values: `1m` `3m` `4m` `5m` `10m` `15m` `30m` `1h` `2h` `4h` `8h` `1D` `1W` `1M`; `3m` / `4m` / `10m` / `30m` are requested from `dataLoader` as `3min` / `4min` / `10min` / `30min`. If your API lacks them, point `aggregateFrom` at a finer interval it does serve, e.g. `{ '3m': '1m', '4m': '1m', '10m': '5m', '30m': '15m' }` — the chart merges the candles |
478
+ | `timeframes` | | classic set | Timeframes offered in the header, in order: the advanced row's pills, the classic dropdown, and the rest of the reference header's ⌄ menu after its six fixed pills. Omit to keep `1m 5m 15m 1h 4h 1D 1W` (row) / `… 30m 2h 8h 1M` (dropdown, ⌄), so the newer minute timeframes only appear for hosts that list them |
396
479
  | `duration` | | — | Initial active duration button |
397
480
  | `symbol` | | — | Symbol name shown in the top bar |
398
481
  | `features` | | `{}` | Opt-in feature gates. See [Feature flags](#feature-flags) |
@@ -434,12 +517,18 @@ chart.on('orderLineMoved', ({ label, fromTimestamp, toTimestamp, data }) => {
434
517
  | `showPriceAxisCountdown` | | `false` | Show candle countdown timer on the right price axis, just below the live price tag. Honours `candleCountdownTimeframes`. Toggleable from the Settings dialog (Appearance tab). |
435
518
  | `maxSubPanes` | | `3` | Max simultaneous oscillator sub-panes |
436
519
  | `tradeDisplayFilter` | | `"all"` | Which TFC levels are visible: `"all"` · `"positions"` · `"orders"` · `"none"` |
520
+ | `pnlPill` | | — | `{ currency?, format?, visible? }` for the on-chart P/L pill — currency code appended to the amount, or your own formatter. Only read when `features.pnlPill` is on |
437
521
  | `positionRenderStyle` | | auto | Force position render style: `"line"` or `"dot"` |
438
522
  | `hideLevelConfirmCancel` | | `false` | Hide on-canvas ✓/✗ confirm-cancel buttons for TFC level edits |
439
523
  | `deselectActiveOnOutsideClick` | | `false` | When `true`, clicking/tapping anywhere outside a selected trade level dismisses it (reverting any pending edits, mirroring ✗ Cancel). Default `false` keeps the level active so incidental clicks — price-axis resize, taps outside the QTY input — don't drop an in-progress edit. The level can still be dismissed via ✓/✗, tapping the level again, or `setLevels()` removing it |
440
524
  | `showTradeLevelsAlways` | | `false` | Always render SL/TP bracket lines + price pills, even when the parent level is not hovered or selected. The close (×) button stays hover-only so the chart isn't cluttered. Toggleable from the Settings dialog (Trading tab). Persisted in `localStorage`. |
441
525
  | `tradeLevelButtonScale` | | `1` | Multiplier for trade-level Confirm/Cancel/Edit/Close button radii and gaps. Scales visuals **and** hit/drag areas together — raise it on touch devices for larger tap targets. Clamped to `[1, 3]`. Also settable at runtime via `chart.setTradeLevelButtonScale(scale)` |
526
+ | `tradeLevelBadgeScale` | | `1` | Shrinks the on-chart position / order tag — font, padding, grip, ✎ × buttons and their hit areas together. `0.6` is about half the default area. Clamped `[0.5, 1]` |
527
+ | `tradeLevelBadgeAnchor` | | `"auto"` | `"left"` homes the tag at the plot's left edge like an axis label, whatever the open price or time anchor, so it never covers candles until the trader drags it. With `features.orderLineTimeDrag` the tag stays draggable along the time axis and the drop is remembered as before |
442
528
  | `tfcEnabled` | | `true` | Enable the TFC toggle button in the top bar. When `false`, TFC is completely disabled — the toggle button is hidden and all trade levels, draft orders, and the floating trade button are suppressed |
529
+ | `crosshairEnabled` | | `true` | Draw the mouse crosshair. `false` hides it **and** the floating "place order at this price" button that rides on its horizontal line, ignores mirrored `setCrosshair()` calls and keeps the mobile long-press crosshair from arming. Trade levels, drawings and TFC are unaffected. Runtime: `chart.setCrosshairEnabled(enabled)` |
530
+ | `enableCrosshairToggle` | | `false` | Crosshair on/off switch in the header (advanced toolbar and default top bar): the reference 24px `rounded-sm` button, tinted while on. Clicking it calls `setCrosshairEnabled()` and emits `crosshairToggle` so the host can persist the choice |
531
+ | `headerOverflowMenu` | | `false` | Advanced header only: the reference Hanko header. A 32px bar with six lowercase timeframe pills (`1m 5m 15m 1h 4h 1d`) and a ⌄ for the rest, then crosshair · P/L · Layout (grid icon) · ⋯ · fullscreen at 24px. Draw, Chart type, Indicators, Compare, Snapshot and Chart settings fold into the ⋯ menu; each keeps its behaviour |
443
532
  | `features.orderLineTimeDrag` | | `false` | Enable **horizontal (time-axis) order-line dragging**. A level with `timeDraggable: true` can have its info-box badge dragged left/right to re-anchor the order to a different candle — **price stays locked**. Emits `orderLineMoved` on release. Off by default; intended to be enabled per broker (e.g. Hankotrade) by the host app |
444
533
  | `orderLineDragSnap` | | `true` | When horizontal dragging is enabled, snap the badge to the nearest candle on release. Set `false` to keep the exact released time |
445
534
  | `orderLineAnchorPersistence` | | `true` | When horizontal dragging is enabled, remember where each badge was dropped in `localStorage` (key `finchart.orderLineTimeAnchors`, keyed by level label) so it comes back to the same candle after a reload. A persisted anchor overrides the level's `timestamp` until the badge is dragged again. Set `false` to persist anchors yourself |
@@ -526,6 +615,8 @@ const chart = new ChartEngine({
526
615
  |---|---|---|
527
616
  | `enableForecasting` | `false` | The reworked drawing tools, as one switch — see below |
528
617
  | `orderLineTimeDrag` | `false` | Horizontal (time-axis) order-line dragging — see [Horizontal order-line dragging](#horizontal-time-axis-order-line-dragging) |
618
+ | `pnlPill` | `false` | Floating on-chart P/L pill — count and summed P/L of the positions on the chart — see [On-chart P/L pill](#on-chart-pl-pill--featurespnlpill) |
619
+ | `tradeActionBar` | `false` | The trade button opens a segmented `Alert · Pending · SL · TP · TSL · ×` bar at the clicked price instead of the two-row Buy/Sell popup — see [Trade action bar](#trade-action-bar--featurestradeactionbar) |
529
620
 
530
621
  `enableForecasting` turns on three things together:
531
622
 
@@ -606,7 +697,7 @@ import { DEFAULT_UI_CONFIG } from 'acttrader-charts';
606
697
 
607
698
  | Component key | Configurable properties |
608
699
  |---|---|
609
- | `drawingToolbar` | `iconBtnSize`, `iconFontSize`, `iconFontFamily`, `flyoutLabelFontSize`, `flyoutLabelFontFamily`, `shortcutFontSize`, `soonBadgeFontSize`, `flyoutHeadingFontSize`, `flyoutHeadingLetterSpacing`, `scrollBtnHeight`, `scrollBtnFontSize`, `barPadding`, `btnGap` |
700
+ | `drawingToolbar` | `iconBtnSize`, `iconFontSize`, `iconFontFamily`, `flyoutLabelFontSize`, `flyoutLabelFontFamily`, `shortcutFontSize`, `soonBadgeFontSize`, `flyoutHeadingFontSize`, `flyoutHeadingLetterSpacing`, `scrollBtnHeight`, `scrollBtnFontSize`, `barPadding`, `btnGap`, `modernIcons`, `actionsButtonIcon` (`'default'` \| `'lock'` — lock glyph on the Actions button, for hosts that relabel Lock All as "Save Charts") |
610
701
  | `topBar` | `height`, `dropBtnFontSize`, `dropBtnFontFamily`, `drawBtnSize`, `drawBtnIconFontSize`, `iconBtnSize`, `mobileIconBtnSize`, `mobileDrawBtnIconSize`, `flyoutRowFontSize`, `flyoutRowFontFamily`, `flyoutCategoryFontSize`, `flyoutCategoryLetterSpacing`, `flyoutCheckFontSize`, `streamDotSize` |
611
702
  | `bottomBar` | `height`, `btnFontSize`, `btnFontFamily` |
612
703
  | `priceAxis` | `fontSize`, `fontFamily` |
@@ -684,6 +775,11 @@ new ChartEngine({
684
775
  | `topBar.series` | `area` | `'Area'` | |
685
776
  | `topBar` | `indicatorsBtn` | `'Indicators'` | Indicators button (no active) |
686
777
  | `topBar` | `indicatorsBtnActive` | `'Indicators ({count})'` | `{count}` replaced at runtime |
778
+ | `topBar` | `disableCrosshairTitle` | `'Disable crosshair'` | Header crosshair switch tooltip while on (`enableCrosshairToggle`) |
779
+ | `topBar` | `enableCrosshairTitle` | `'Enable crosshair'` | Header crosshair switch tooltip while off |
780
+ | `topBar` | `pnlPillBtn` | `'P/L'` | Header P/L pill switch label (`features.pnlPill`) |
781
+ | `topBar` | `hidePnlPillTitle` | `'Hide P/L pill for {symbol}'` | P/L switch tooltip while the pill is shown |
782
+ | `topBar` | `showPnlPillTitle` | `'Show P/L pill for {symbol}'` | P/L switch tooltip while the pill is hidden |
687
783
  | `topBar` | `toggleDrawingTitle` | `'Toggle Drawing Tools'` | Toolbar toggle tooltip |
688
784
  | `topBar` | `toggleFullscreenTitle` | `'Toggle Fullscreen'` | Fullscreen button tooltip |
689
785
  | `topBar` | `exitFullscreenTitle` | `'Exit Fullscreen'` | |
@@ -726,6 +822,14 @@ new ChartEngine({
726
822
  | `trade` | `market` | `'Market'` | |
727
823
  | `trade` | `qty` | `'Qty'` | Draft order qty input label |
728
824
  | `trade` | `placeOrderTitle` | `'Place order at this price'` | Trade button tooltip |
825
+ | `trade` | `actionAlert` … `actionTsl` | `'Alert'`, `'Pending'`, `'SL'`, `'TP'`, `'TSL'` | Trade action bar chips (`features.tradeActionBar`) |
826
+ | `trade` | `actionCloseTitle` | `'Close'` | Trade action bar × tooltip |
827
+ | `trade` | `directionAbove`, `directionBelow` | `'Above'`, `'Below'` | Pending sub-menu header — side of the market the clicked price is on |
828
+ | `pnlPill` | `positionsAbbrev` | `'POS'` | On-chart P/L pill — word after the count (`3 POS`), shown uppercase |
829
+ | `pnlPill` | `showPositionsTitle` | `'Show positions on chart · drag handle to move · double-click to reset'` | Pill tooltip while collapsed — a body click fans the positions out |
830
+ | `pnlPill` | `hidePositionsTitle` | `'Hide positions on chart · drag handle to move · double-click to reset'` | Pill tooltip while fanned out |
831
+ | `pnlPill` | `bulkLevelsTitle` | `'Set SL · TP · TSL on all {count} {symbol} positions'` | ◎ tooltip — opens the host's Bulk Levels dialog |
832
+ | `pnlPill` | `closeAllTitle` | `'Close all {symbol} positions'` | Amber ✕ tooltip; `{symbol}` and `{count}` are filled in |
729
833
  | `dialogs.settings` | `title` | `'Chart Settings'` | Dialog title |
730
834
  | `dialogs.settings` | `tfcSection` | `'Trade from Charts'` | Section heading |
731
835
  | `dialogs.settings` | `showLabel` | `'Show'` | Radio group label |
@@ -858,6 +962,7 @@ chart.cancelCurrentEdit(): this // cancel the active draft order or any in-pro
858
962
  chart.addLevelBracket(label: string, bracketType: 'sl' | 'tp'): this // auto-place a SL or TP bracket at a default offset; emits tradeLevelBracketActivated with the computed price
859
963
  chart.setDraftBracketPnl(bracketType: 'sl' | 'tp', pnlText: string | null): this // set estimated P&L text on the active bracket host — the draft order while drafting, or the currently selected existing pending order / position while modifying; pass null to clear
860
964
  chart.setTfcActive(enabled: boolean): this // toggle TFC on/off at runtime; hides/shows all trade levels, draft orders, and floating trade button; fires tfcToggle event
965
+ chart.setPnlPillVisible(visible: boolean): this // show/hide the on-chart P/L pill (features.pnlPill) — what the header's P/L switch does; emits pnlPillToggle
861
966
  ```
862
967
 
863
968
  > **Staging semantics for `updateLevelMainPrice` / `updateLevelBracket`.** Calls to these methods register the change in the chart's pending-edit buffer (the same buffer chart-initiated drags use), so the edit stays visible even when the host app keeps pushing fresh server state via `setLevels` (e.g. per-tick PnL refreshes). When the server echoes back the new price in a later `setLevels` call, the staged edit is auto-released (mobile, i.e. `hideLevelConfirmCancel: true`). If a panel closes without submitting, call `cancelLevelEdit(label)` or `cancelCurrentEdit()` to drop the staged edit — otherwise it will keep overriding server state on the chart.
@@ -866,8 +971,14 @@ chart.setTfcActive(enabled: boolean): this // toggle TFC on/off at runtime; hi
866
971
 
867
972
  ```ts
868
973
  chart.setOrderLots(lots: number): void // update default qty at runtime
974
+ chart.setCrosshairEnabled(enabled: boolean): this // off hides the crosshair AND this button — it rides on the crosshair line, so it has no place once the line is gone
869
975
  ```
870
976
 
977
+ The button follows the crosshair's horizontal line, so it is only ever shown while the
978
+ crosshair is (`crosshairEnabled`, default `true`). Hosts with a crosshair on/off control
979
+ should call `setCrosshairEnabled()` rather than painting the crosshair transparent — the
980
+ latter leaves the button riding an invisible line.
981
+
871
982
  ### Viewport
872
983
 
873
984
  ```ts
@@ -1216,6 +1327,10 @@ chart.on('tradeLevelEditCancelled', ({ label, type, isFullscreen }) => {}); // E
1216
1327
  chart.on('draftInitiated', ({ side, price, orderType, isFullscreen }) => {}); // new draft order shown — open buy/sell form
1217
1328
  chart.on('draftCancelled', ({ label, isFullscreen }) => {}); // draft order dismissed without confirming
1218
1329
  chart.on('tfcToggle', ({ enabled }) => {}); // TFC toggled on or off via top bar button or setTfcActive()
1330
+ chart.on('crosshairToggle', ({ enabled }) => {}); // crosshair switched on or off — header switch (enableCrosshairToggle) or setCrosshairEnabled(); persist it here
1331
+ chart.on('pnlPillCloseAll', ({ count, pnl, labels, data, isFullscreen }) => {}); // the on-chart P/L pill's ✕ — close these positions (features.pnlPill)
1332
+ chart.on('pnlPillToggle', ({ visible }) => {}); // the header's P/L switch showed or hid the pill — persist it here (features.pnlPill)
1333
+ chart.on('bulkLevelsRequested', ({ kind, price, source, isFullscreen }) => {}); // action-bar chip (price) or the P/L pill's ◎ (price null) — open your Bulk Levels dialog for `kind`
1219
1334
  chart.on('tradeLevelDragEnd', ({ label, type, newPrice, data }) => {}); // deprecated — use tradeLevelEdit
1220
1335
  chart.on('tradeLevelBracketDrag', ({ label, bracketType, newPrice, data }) => {}); // deprecated
1221
1336
 
@@ -89,6 +89,15 @@ interface DrawingToolbarUiConfig {
89
89
  * Default: `false` (original icons, unchanged for all existing consumers).
90
90
  */
91
91
  modernIcons?: boolean;
92
+ /**
93
+ * Glyph on the toolbar's Actions button — the one that opens Undo / Redo /
94
+ * Delete / Clear / Hide / Lock All. `'lock'` uses the same lock as the Lock
95
+ * All action, so the button reads as the place where drawings get locked and
96
+ * saved (the Hanko reference; pair it with a `labels.drawingToolbar.actions.lockAll`
97
+ * override such as "Save Charts"). Default `'default'`: the classic ⋯, or the
98
+ * Lucide pointer when `modernIcons` is on — unchanged for existing consumers.
99
+ */
100
+ actionsButtonIcon?: 'default' | 'lock';
92
101
  }
93
102
  interface TopBarUiConfig {
94
103
  /** Height of the top bar strip */
@@ -243,6 +252,16 @@ interface TopBarLabels {
243
252
  settingsTitle: string;
244
253
  /** Tooltip on the TFC (Trade from Charts) toggle button. */
245
254
  tfcToggleTitle: string;
255
+ /** Crosshair switch tooltip while the crosshair is on (`enableCrosshairToggle`). */
256
+ disableCrosshairTitle: string;
257
+ /** Crosshair switch tooltip while the crosshair is off. */
258
+ enableCrosshairTitle: string;
259
+ /** Header P/L pill switch label (`features.pnlPill`). */
260
+ pnlPillBtn: string;
261
+ /** P/L pill switch tooltip while the pill is shown. `{symbol}` is filled in. */
262
+ hidePnlPillTitle: string;
263
+ /** P/L pill switch tooltip while the pill is hidden. */
264
+ showPnlPillTitle: string;
246
265
  }
247
266
  interface BottomBarLabels {
248
267
  /** Duration selector button labels. */
@@ -316,6 +335,16 @@ interface TradeLabels {
316
335
  qty: string;
317
336
  /** Tooltip on the floating trade button (⊕). */
318
337
  placeOrderTitle: string;
338
+ /** Trade action bar (`features.tradeActionBar`) chips — Alert · Pending · SL · TP · TSL — and its × tooltip. */
339
+ actionAlert: string;
340
+ actionPending: string;
341
+ actionSl: string;
342
+ actionTp: string;
343
+ actionTsl: string;
344
+ actionCloseTitle: string;
345
+ /** Pending sub-menu header: which side of the market the clicked price is on. */
346
+ directionAbove: string;
347
+ directionBelow: string;
319
348
  }
320
349
  interface DialogLabels {
321
350
  /** Chart Settings dialog. */
@@ -363,6 +392,19 @@ interface ChartMiscLabels {
363
392
  * are active. Use `{count}` as a placeholder for the count. */
364
393
  nIndicators: string;
365
394
  }
395
+ /** On-chart P/L pill (`features.pnlPill`). Titles may use `{symbol}` and `{count}`. */
396
+ interface PnlPillLabels {
397
+ /** Short word after the count — `3 POS`. Rendered uppercase. */
398
+ positionsAbbrev: string;
399
+ /** Pill tooltip while the positions are collapsed — a click on the body fans them out. */
400
+ showPositionsTitle: string;
401
+ /** Pill tooltip while the positions are fanned out. */
402
+ hidePositionsTitle: string;
403
+ /** ◎ tooltip — it opens the host's Bulk Levels dialog. `{count}` and `{symbol}` are filled in. */
404
+ bulkLevelsTitle: string;
405
+ /** Amber ✕ tooltip. */
406
+ closeAllTitle: string;
407
+ }
366
408
  interface ChartLabels {
367
409
  topBar: TopBarLabels;
368
410
  bottomBar: BottomBarLabels;
@@ -371,6 +413,7 @@ interface ChartLabels {
371
413
  trade: TradeLabels;
372
414
  dialogs: DialogLabels;
373
415
  chart: ChartMiscLabels;
416
+ pnlPill: PnlPillLabels;
374
417
  }
375
418
  declare const DEFAULT_LABELS: ChartLabels;
376
419
  /**
@@ -582,7 +625,7 @@ interface PriceRange {
582
625
  }
583
626
  type SeriesType = "candlestick" | "hollow" | "line" | "area" | "ohlc" | "heikinashi" | "volumecandles" | "linemarkers" | "step" | "hlcarea" | "baseline" | "columns" | "highlow";
584
627
  type Theme = "dark" | "light";
585
- type Timeframe = "1m" | "5m" | "15m" | "30m" | "1h" | "2h" | "4h" | "8h" | "1D" | "1W" | "1M";
628
+ type Timeframe = "1m" | "3m" | "4m" | "5m" | "10m" | "15m" | "30m" | "1h" | "2h" | "4h" | "8h" | "1D" | "1W" | "1M";
586
629
  type Duration = "1D" | "5D" | "1M" | "3M" | "6M" | "1Y" | "5Y" | "All";
587
630
  interface Padding {
588
631
  top: number;
@@ -672,6 +715,23 @@ interface AccountSpec {
672
715
  /** Percent of the account risked per trade. Default `1`. */
673
716
  riskPercent?: number;
674
717
  }
718
+ /**
719
+ * Text options for the on-chart P/L pill (`features.pnlPill`). The chart sums the
720
+ * numeric `pnl` each position level carries (`setLevels`' `pnlKey`); these only
721
+ * decide how that total is written.
722
+ */
723
+ interface PnlPillConfig {
724
+ /** Currency code the default formatter appends after a space — `+72.65 USD`. Omit for none. */
725
+ currency?: string;
726
+ /** Replaces the default `+72.65 USD` formatter. Receives the summed P/L. */
727
+ format?: (pnl: number) => string;
728
+ /**
729
+ * Whether the pill starts shown. The header's P/L switch (rendered with the
730
+ * feature) and `setPnlPillVisible()` change it at runtime; `pnlPillToggle`
731
+ * reports the change so a host can persist it. Default: true.
732
+ */
733
+ visible?: boolean;
734
+ }
675
735
  interface ChartConfig {
676
736
  container: HTMLElement;
677
737
  theme?: Theme;
@@ -1082,6 +1142,22 @@ interface ChartConfig {
1082
1142
  * Clamped to `[1, 3]`. Default: `1`.
1083
1143
  */
1084
1144
  tradeLevelButtonScale?: number;
1145
+ /**
1146
+ * Shrinks the main-level info box — the on-chart position / order tag with its P/L,
1147
+ * side, lots and ✎ × buttons. Font, padding, row height, grip and buttons scale
1148
+ * together, hit areas included; `0.6` is roughly half the area of the default tag.
1149
+ * SL/TP bracket pills are unaffected. Clamped to `[0.5, 1]`. Default: `1`.
1150
+ */
1151
+ tradeLevelBadgeScale?: number;
1152
+ /**
1153
+ * Where the main-level info box sits horizontally. `'auto'` (default): centred on the
1154
+ * chart, or over the level's time anchor with `features.orderLineTimeDrag`. `'left'`:
1155
+ * the tag's home is the plot's left edge, like an axis label, whatever the open price
1156
+ * or time — so it never covers the candles until the trader decides otherwise. With
1157
+ * `features.orderLineTimeDrag` a `timeDraggable` tag can still be dragged along the
1158
+ * time axis, and the drop is remembered exactly as before. Default: `'auto'`.
1159
+ */
1160
+ tradeLevelBadgeAnchor?: 'auto' | 'left';
1085
1161
  /**
1086
1162
  * What the SL/TP bracket pills show.
1087
1163
  *
@@ -1132,7 +1208,10 @@ interface ChartConfig {
1132
1208
  * (preferred for branded designs that still want a link affordance)
1133
1209
  */
1134
1210
  symbolNameDecoration?: 'underline' | 'none' | 'hover';
1135
- /** Called when the user clicks "Add alert" in the trade popover. Omit to hide the alert row. */
1211
+ /**
1212
+ * Called with the clicked price when the user picks **Alert** on the trade
1213
+ * action bar (`features.tradeActionBar`). Omit to leave the Alert chip out.
1214
+ */
1136
1215
  onAddAlert?: (price: number) => void;
1137
1216
  /**
1138
1217
  * Header layout variant. Default `'simple'`.
@@ -1203,6 +1282,32 @@ interface ChartConfig {
1203
1282
  * (a one-time `console.warn` is logged at init).
1204
1283
  */
1205
1284
  enableSnapshot?: boolean;
1285
+ /**
1286
+ * Put a crosshair on/off switch in the header (advanced toolbar and default
1287
+ * top bar). Clicking it calls `setCrosshairEnabled()`, so the crosshair and
1288
+ * the floating "place order at this price" button go together, and emits
1289
+ * `crosshairToggle` for the host to persist the choice. Starts from
1290
+ * `crosshairEnabled`. Default: false.
1291
+ */
1292
+ enableCrosshairToggle?: boolean;
1293
+ /**
1294
+ * Advanced header only (`headerLayout: 'advanced'`): fold Indicators, Compare,
1295
+ * Snapshot and Chart settings into one ⋯ menu at the right end of the bar, and
1296
+ * make the Layout button icon-only, so the right cluster stays short next to
1297
+ * the crosshair and P/L switches. Each folded item keeps its behaviour — the
1298
+ * Indicators entry opens the same searchable list. Default: false.
1299
+ */
1300
+ headerOverflowMenu?: boolean;
1301
+ /** Currency code and formatter for the on-chart P/L pill — see `features.pnlPill`. */
1302
+ pnlPill?: PnlPillConfig;
1303
+ /**
1304
+ * Timeframes offered in the header, in this order — the advanced toolbar's pill row,
1305
+ * the classic top bar's dropdown, and the compact header's ⌄ menu (its six fixed pills
1306
+ * come first; the rest of this list fills the menu). Omit to keep the classic set, so
1307
+ * `3m` / `4m` / `10m` / `30m` only appear for hosts that list them. Every value must be
1308
+ * a `Timeframe` the chart can load or aggregate (see `aggregateFrom`).
1309
+ */
1310
+ timeframes?: Timeframe[];
1206
1311
  /**
1207
1312
  * Opt-in feature flags. All flags default to `false` / disabled so existing
1208
1313
  * consumers are completely unaffected when this field is omitted.
@@ -1243,6 +1348,27 @@ interface ChartConfig {
1243
1348
  * pips on both the position tools and the ruler come from `instrument`.
1244
1349
  */
1245
1350
  enableForecasting?: boolean;
1351
+ /**
1352
+ * Floating on-chart P/L pill — `⋮⋮ 3 POS +72.65 USD | ◎ ✕` — summarising the
1353
+ * open positions passed through `setLevels`: their count and the sum of the
1354
+ * numeric `pnl` each carries (the chart computes no money of its own).
1355
+ * A click on the body fans every position badge out on the chart (clustered
1356
+ * levels expand, TFC is switched on if needed) and lights the accent ring;
1357
+ * click again to collapse. Draggable within the plot, double-click puts it
1358
+ * back top-right. ◎ emits `bulkLevelsRequested` for the host's Bulk Levels dialog; the amber ✕ emits `pnlPillCloseAll` and the host closes the
1359
+ * positions. Hidden while there are no positions. Text is shaped by
1360
+ * top-level `pnlPill`. Default: false.
1361
+ */
1362
+ pnlPill?: boolean;
1363
+ /**
1364
+ * Replace the two-row pending-order popup that the trade button opens with a
1365
+ * segmented action bar at the clicked price — `Alert | Pending | SL | TP | TSL | ×`,
1366
+ * no price readout (the axis shows it). Alert calls `onAddAlert` (chip only
1367
+ * shown when that is set); Pending opens the Buy/Sell Limit/Stop list as a
1368
+ * sub-menu above the bar; SL / TP / TSL emit `bulkLevelsRequested` for the
1369
+ * host's Bulk Levels dialog. Default: false.
1370
+ */
1371
+ tradeActionBar?: boolean;
1246
1372
  };
1247
1373
  /**
1248
1374
  * Fetches historical OHLC bars for a compare symbol. When provided, the
@@ -1306,6 +1432,16 @@ interface ChartConfig {
1306
1432
  * allowing the user to enable/disable TFC at runtime.
1307
1433
  */
1308
1434
  tfcEnabled?: boolean;
1435
+ /**
1436
+ * Draw the mouse crosshair and, with it, the floating "place order at this
1437
+ * price" button that rides along its horizontal line. `false` hides both: no
1438
+ * crosshair lines or axis readouts, `crosshair` events carry `null`, mirrored
1439
+ * `setCrosshair()` calls are ignored, the mobile long-press crosshair does not
1440
+ * arm, and the trade button stays hidden until the crosshair is enabled again.
1441
+ * Trade levels, drawings and the TFC state are unaffected. Runtime toggle:
1442
+ * `setCrosshairEnabled()`. Default: true.
1443
+ */
1444
+ crosshairEnabled?: boolean;
1309
1445
  /**
1310
1446
  * Snap a horizontally-dragged order line to the nearest candle on drag release.
1311
1447
  * Only relevant when `features.orderLineTimeDrag` is enabled. When `false`, the badge
@@ -1739,6 +1875,40 @@ type ChartEventMap = {
1739
1875
  tfcToggle: {
1740
1876
  enabled: boolean;
1741
1877
  };
1878
+ /** Crosshair switched on or off — via the header switch (`enableCrosshairToggle`) or `setCrosshairEnabled()`. */
1879
+ crosshairToggle: {
1880
+ enabled: boolean;
1881
+ };
1882
+ /** The P/L pill was shown or hidden — via the header's P/L switch or `setPnlPillVisible()` (`features.pnlPill`). */
1883
+ pnlPillToggle: {
1884
+ visible: boolean;
1885
+ };
1886
+ /**
1887
+ * Open the host's Bulk Levels dialog — one SL / TP / TSL for every open position of
1888
+ * the symbol. From the trade action bar (`source: 'actionBar'`) `kind` is the chip
1889
+ * clicked and `price` the clicked price; from the P/L pill's ◎ (`source: 'pill'`)
1890
+ * `kind` is `'sl'` and `price` is `null` — no level was clicked, so the dialog opens
1891
+ * with an empty price. The chart never calls a broker.
1892
+ */
1893
+ bulkLevelsRequested: {
1894
+ kind: 'sl' | 'tp' | 'tsl';
1895
+ price: number | null;
1896
+ isFullscreen: boolean;
1897
+ source: 'actionBar' | 'pill';
1898
+ };
1899
+ /**
1900
+ * The on-chart P/L pill's ✕ (`features.pnlPill`). Carries every position the pill
1901
+ * counted — the host closes them; the chart never calls a broker. `pnl` is the
1902
+ * summed P/L, or null when no position carried one. `data` are the rows given to
1903
+ * `setLevels`, in the same order as `labels`.
1904
+ */
1905
+ pnlPillCloseAll: {
1906
+ count: number;
1907
+ pnl: number | null;
1908
+ labels: string[];
1909
+ data: unknown[];
1910
+ isFullscreen: boolean;
1911
+ };
1742
1912
  /** Emitted whenever any dismissible UI (flyout, modal, dropdown, popover) opens or closes.
1743
1913
  * Hosts (native wrappers, PWAs) listen to track whether a back button / gesture should
1744
1914
  * dismiss chart UI vs. navigate. Pair with `dismissAllUI()` to wire platform back events. */
@@ -2158,4 +2328,4 @@ declare class MACD implements IIndicator {
2158
2328
  render(ctx: CanvasRenderingContext2D, results: IndicatorResult[], scale: ScaleManager, viewport: Viewport, paneHeight: number, rangeOverride?: PriceRange): void;
2159
2329
  }
2160
2330
 
2161
- export { type DeepPartial$1 as $, type AccountSpec as A, BollingerBands as B, type ChartConfig as C, type Duration as D, type CrosshairPosition as E, type CrosshairUiConfig as F, DARK_THEME as G, DEFAULT_BOTTOM_BAR_CONFIG as H, type IIndicator as I, DEFAULT_CROSSHAIR_CONFIG as J, DEFAULT_DRAWING_TOOLBAR_CONFIG as K, type LayoutSyncState as L, DEFAULT_INDICATOR_OVERLAY_CONFIG as M, DEFAULT_LABELS as N, type OHLCVBar as O, type PriceRange as P, DEFAULT_LAYOUT_SYNC as Q, type ResolvedInstrument as R, type SeriesType as S, type Timeframe as T, DEFAULT_PRICE_AXIS_CONFIG as U, type Viewport as V, DEFAULT_TIME_AXIS_CONFIG as W, DEFAULT_TOP_BAR_CONFIG as X, DEFAULT_TRADE_BUTTON_CONFIG as Y, DEFAULT_UI_CONFIG as Z, type DataLoaderParams as _, type IndicatorParams as a, type DeepPartialChartTheme as a0, type DialogLabels as a1, type DrawingToolbarColors as a2, type DrawingToolbarLabels as a3, type DrawingToolbarUiConfig as a4, EMA as a5, type IndicatorOverlayColors as a6, type IndicatorOverlayUiConfig as a7, type IndicatorResult as a8, type IndicatorStateEntry as a9, type TradeLevelColors as aA, type TradePanelColors as aB, type UiConfig as aC, deepMergeTheme as aD, formatDuration as aE, formatVolume as aF, getAllPresets as aG, getCustomPresets as aH, getPreset as aI, inferPipSize as aJ, registerCustomPreset as aK, resolveCssVarsInTheme as aL, resolveInstrument as aM, resolveLabels as aN, resolveUiConfig as aO, toMoney as aP, toPips as aQ, unregisterCustomPreset as aR, type PriceSource as aS, LAYOUT_PRESETS as aa, LIGHT_THEME as ab, type LayoutPreset as ac, MACD as ad, type OhlcLabels as ae, type OrderSubmit as af, PRESETS_BY_COUNT as ag, PRESET_COUNTS as ah, PRESET_LABEL as ai, type Padding as aj, type PendingOrderLevel as ak, type PositionLevel as al, type PositionRenderStyle as am, type PriceAxisUiConfig as an, RSI as ao, SMA as ap, type Theme as aq, type ThemeOverrides as ar, type TimeAxisUiConfig as as, type TopBarColors as at, type TopBarLabels as au, type TopBarUiConfig as av, type TradeButtonUiConfig as aw, type TradeDisplayFilter as ax, type TradeLabels as ay, type TradeLevel as az, type ChartEventMap as b, type ChartState as c, type InstrumentSpec as d, type DrawingToolType as e, type IDrawing as f, type AnyDrawingStyle as g, type IWebSocketAdapter as h, type TradeLevelType as i, type ChartTheme as j, type AnyLevel as k, type DrawingPoint as l, ScaleManager as m, type DrawingHandle as n, type DrawingRenderContext as o, type SerializedDrawing as p, type Tick as q, type StreamStatus as r, type ActiveIndicatorState as s, type BottomBarColors as t, type BottomBarLabels as u, type BottomBarUiConfig as v, type CanvasColorSettings as w, type ChartLabels as x, type ChartMiscLabels as y, type ChartThemeUi as z };
2331
+ export { type DataLoaderParams as $, type AccountSpec as A, BollingerBands as B, type ChartConfig as C, type Duration as D, type ChartThemeUi as E, type CrosshairPosition as F, type CrosshairUiConfig as G, DARK_THEME as H, type IIndicator as I, DEFAULT_BOTTOM_BAR_CONFIG as J, DEFAULT_CROSSHAIR_CONFIG as K, type LayoutSyncState as L, DEFAULT_DRAWING_TOOLBAR_CONFIG as M, DEFAULT_INDICATOR_OVERLAY_CONFIG as N, type OHLCVBar as O, type PositionLevel as P, DEFAULT_LABELS as Q, type ResolvedInstrument as R, type SeriesType as S, type Timeframe as T, DEFAULT_LAYOUT_SYNC as U, type Viewport as V, DEFAULT_PRICE_AXIS_CONFIG as W, DEFAULT_TIME_AXIS_CONFIG as X, DEFAULT_TOP_BAR_CONFIG as Y, DEFAULT_TRADE_BUTTON_CONFIG as Z, DEFAULT_UI_CONFIG as _, type IndicatorParams as a, type DeepPartial$1 as a0, type DeepPartialChartTheme as a1, type DialogLabels as a2, type DrawingToolbarColors as a3, type DrawingToolbarLabels as a4, type DrawingToolbarUiConfig as a5, EMA as a6, type IndicatorOverlayColors as a7, type IndicatorOverlayUiConfig as a8, type IndicatorResult as a9, type TradeLabels as aA, type TradeLevel as aB, type TradeLevelColors as aC, type TradePanelColors as aD, type UiConfig as aE, deepMergeTheme as aF, formatDuration as aG, formatVolume as aH, getAllPresets as aI, getCustomPresets as aJ, getPreset as aK, inferPipSize as aL, registerCustomPreset as aM, resolveCssVarsInTheme as aN, resolveInstrument as aO, resolveLabels as aP, resolveUiConfig as aQ, toMoney as aR, toPips as aS, unregisterCustomPreset as aT, type PriceSource as aU, type IndicatorStateEntry as aa, LAYOUT_PRESETS as ab, LIGHT_THEME as ac, type LayoutPreset as ad, MACD as ae, type OhlcLabels as af, type OrderSubmit as ag, PRESETS_BY_COUNT as ah, PRESET_COUNTS as ai, PRESET_LABEL as aj, type Padding as ak, type PendingOrderLevel as al, type PnlPillConfig as am, type PnlPillLabels as an, type PositionRenderStyle as ao, type PriceAxisUiConfig as ap, RSI as aq, SMA as ar, type Theme as as, type ThemeOverrides as at, type TimeAxisUiConfig as au, type TopBarColors as av, type TopBarLabels as aw, type TopBarUiConfig as ax, type TradeButtonUiConfig as ay, type TradeDisplayFilter as az, type ChartEventMap as b, type ChartState as c, type InstrumentSpec as d, type DrawingToolType as e, type IDrawing as f, type AnyDrawingStyle as g, type IWebSocketAdapter as h, type TradeLevelType as i, type ChartTheme as j, type AnyLevel as k, type DrawingPoint as l, ScaleManager as m, type PriceRange as n, type DrawingHandle as o, type DrawingRenderContext as p, type SerializedDrawing as q, type Tick as r, type StreamStatus as s, type ActiveIndicatorState as t, type BottomBarColors as u, type BottomBarLabels as v, type BottomBarUiConfig as w, type CanvasColorSettings as x, type ChartLabels as y, type ChartMiscLabels as z };