hyperprop-charting-library 0.1.138 → 0.1.140
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/dist/hyperprop-charting-library.cjs +641 -50
- package/dist/hyperprop-charting-library.d.ts +131 -1
- package/dist/hyperprop-charting-library.js +641 -50
- package/dist/index.cjs +641 -50
- package/dist/index.d.cts +131 -1
- package/dist/index.d.ts +131 -1
- package/dist/index.js +641 -50
- package/docs/API.md +106 -0
- package/package.json +1 -1
package/docs/API.md
CHANGED
|
@@ -568,6 +568,9 @@ an up measurement, red for down.
|
|
|
568
568
|
- `cancelDrawing(): boolean` — abort an in-progress multi-click drawing (between the first click and the final point, e.g. a half-drawn trendline/ray/fib). Returns `true` if a draft was cancelled. Wire it to Escape.
|
|
569
569
|
- Hold **Shift** while drawing or dragging an endpoint of a `trendline`/`ray`/`arrow` to constrain it to the nearest 0/45/90° angle (e.g. a perfectly horizontal line).
|
|
570
570
|
- `setMagnetMode(mode): void` / `getMagnetMode()` — magnet/snap for all drawing tools. `"none"` off, `"weak"` snaps to a candle's OHLC only when the cursor is near a value, `"strong"` always snaps to the nearest OHLC of the bar under the cursor. Holding Cmd/Ctrl while drawing/dragging forces strong snapping regardless of the mode.
|
|
571
|
+
- `setDatafeed(datafeed: ChartDatafeed | null): Promise<void>` — attach a pull-based data source with lazy history; see "Datafeed" below
|
|
572
|
+
- `onLongPress(handler: ((event: ChartLongPressEvent) => void) | null): void` — touch press-and-hold inspection
|
|
573
|
+
- `setCompareSeries(series: CompareSeriesOptions[]): void` / `addCompareSeries(series)` / `removeCompareSeries(id)` / `getCompareSeries()` — overlay other instruments on the main pane; see "Compare overlays" below
|
|
571
574
|
- `setPriceScale(options: { mode?: "linear" | "log" | "percent"; inverted?: boolean }): void` / `getPriceScale()` — price-scale modes for the main pane (TradingView-style). `"log"` maps prices through log10 (wide ranges get 1/2/5-per-decade axis marks). `"percent"` keeps the linear mapping but relabels the axis (ticks, last-price/PDC/H/L/bid/ask tags and the crosshair) as % change from the first visible bar's close, updating as you pan. `inverted: true` flips the axis top-to-bottom. All viewport state stays in plain price space, so switching modes never moves your zoom, and drawings/orders/indicators follow automatically. Indicator panes keep their own scales. Included in `saveState()` as `priceScale`.
|
|
572
575
|
- `setActiveDrawingTool(tool: DrawingToolType | null): void` (`DrawingToolType` = `"horizontal-line" | "vertical-line" | "trendline" | "ray" | "fib-retracement" | "fib-extension" | "long-position" | "short-position" | "price-range" | "rectangle" | "text" | "note" | "parallel-channel" | "ellipse" | "arrow" | "brush" | "callout" | "measure"`)
|
|
573
576
|
- `getActiveDrawingTool(): DrawingToolType | null`
|
|
@@ -610,6 +613,109 @@ link.click();
|
|
|
610
613
|
|
|
611
614
|
---
|
|
612
615
|
|
|
616
|
+
## Datafeed (optional, pull-based)
|
|
617
|
+
|
|
618
|
+
By default the host pushes bars in with `setData`/`upsertBar`. Attach a
|
|
619
|
+
datafeed instead and the chart pulls what it needs — including older history
|
|
620
|
+
as the user scrolls left, which every host otherwise hand-rolls as infinite
|
|
621
|
+
scroll. The shape follows TradingView's datafeed closely enough to port an
|
|
622
|
+
existing adapter.
|
|
623
|
+
|
|
624
|
+
```ts
|
|
625
|
+
await chart.setDatafeed({
|
|
626
|
+
onReady: async () => { /* optional, awaited once before the first getBars */ },
|
|
627
|
+
getBars: async ({ fromMs, toMs, countBack, firstRequest }) => {
|
|
628
|
+
// countBack is authoritative; fromMs is a hint derived from bar spacing.
|
|
629
|
+
return fetchBars({ symbol, to: toMs, limit: countBack });
|
|
630
|
+
},
|
|
631
|
+
subscribeBars: (onBar) => {
|
|
632
|
+
const socket = openStream(symbol, onBar);
|
|
633
|
+
return () => socket.close(); // teardown, called on replace/destroy
|
|
634
|
+
},
|
|
635
|
+
onError: (error, request) => report(error, request),
|
|
636
|
+
});
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
- The chart loads `initialVisibleBars × 3` bars, then calls `subscribeBars` and
|
|
640
|
+
upserts every streamed bar.
|
|
641
|
+
- **Lazy history**: when the viewport comes within
|
|
642
|
+
`datafeedOptions.prefetchThresholdBars` (default 150) of the oldest loaded
|
|
643
|
+
bar, the chart requests the next `chunkBars` (default 1500) and merges them,
|
|
644
|
+
re-anchoring on time so the view doesn't jump. A `cooldownMs` (default 1200)
|
|
645
|
+
keeps a fast scroll from stampeding the backend.
|
|
646
|
+
- **Return an empty array to mean "no more history"** — the chart stops asking
|
|
647
|
+
until a new datafeed is attached.
|
|
648
|
+
- `setData`/`upsertBar` keep working while a datafeed is attached, so hosts can
|
|
649
|
+
migrate one surface at a time. `setDatafeed(null)` detaches and unsubscribes.
|
|
650
|
+
|
|
651
|
+
## Touch
|
|
652
|
+
|
|
653
|
+
Touch input gets its own ergonomics, configured with `touch` in `ChartOptions`:
|
|
654
|
+
|
|
655
|
+
- **Bigger targets.** Every drawing, handle and pane-divider tolerance is
|
|
656
|
+
multiplied by `hitToleranceScale` (default 2.2) while the last input was
|
|
657
|
+
touch or pen, so a line you can grab within 7px with a mouse is grabbable
|
|
658
|
+
within ~15px with a finger. Mouse precision is untouched, and the mode
|
|
659
|
+
flips back the moment a mouse moves.
|
|
660
|
+
- **Press-and-hold to inspect.** Holding still on the plot for
|
|
661
|
+
`longPressMs` (default 400) puts the crosshair on that bar and draws an OHLC
|
|
662
|
+
tooltip (time, O/H/L/C, change with %, volume) offset clear of the fingertip.
|
|
663
|
+
The finger then *scrubs* — it moves the reading instead of panning the chart
|
|
664
|
+
— until it lifts, which clears both. Turn the built-in tooltip off with
|
|
665
|
+
`longPressTooltip: false`; subscribe with `onLongPress(handler)` to drive
|
|
666
|
+
your own UI (the event carries the bar, price, index and client coords, and
|
|
667
|
+
`scrubbing` distinguishes the initial press from the drag that follows).
|
|
668
|
+
|
|
669
|
+
## Compare overlays (multi-series)
|
|
670
|
+
|
|
671
|
+
Overlay other instruments on the main pane. The host owns the data (it already
|
|
672
|
+
has a datafeed); the chart aligns each series to the main bars by timestamp and
|
|
673
|
+
draws it.
|
|
674
|
+
|
|
675
|
+
```ts
|
|
676
|
+
chart.setCompareSeries([
|
|
677
|
+
{ id: "NQ", label: "NQ1!", data: nqBars, color: "#22d3ee" },
|
|
678
|
+
{ id: "BTC", label: "BTCUSD", data: btcBars, color: "#a855f7", style: "area" },
|
|
679
|
+
]);
|
|
680
|
+
```
|
|
681
|
+
|
|
682
|
+
- **Alignment** is by timestamp, computed once per data change (a merge walk,
|
|
683
|
+
not a search per bar), so different session hours and holidays are fine — the
|
|
684
|
+
last known value carries forward across gaps, and bars before a compared
|
|
685
|
+
instrument starts are simply not drawn.
|
|
686
|
+
- **`scale`** defaults to `"percent"`: both instruments are normalised to their
|
|
687
|
+
first visible bar, so a $180 index and a $60,000 coin can be compared by
|
|
688
|
+
shape. It re-anchors as you pan, exactly like TradingView. Use `"price"` to
|
|
689
|
+
plot raw values on the main scale (only sensible for related instruments).
|
|
690
|
+
- **Autoscale** includes compare series unless `includeInAutoScale: false`.
|
|
691
|
+
- Each series gets a colored tag in the price gutter showing its own % move
|
|
692
|
+
(or value in price mode); tags stack instead of overlapping, and drop the
|
|
693
|
+
label when the gutter is too narrow.
|
|
694
|
+
- Compare data is **not** in `saveState()` — it can be megabytes and the host
|
|
695
|
+
re-fetches it anyway. Persist the symbol list yourself and re-supply data on
|
|
696
|
+
load.
|
|
697
|
+
|
|
698
|
+
## Deep zoom-out (viewport downsampling)
|
|
699
|
+
|
|
700
|
+
Once bars are narrower than `downsampling.thresholdPx` (default 1.5px), several
|
|
701
|
+
bars share a pixel column, and drawing each one separately is wasted work. The
|
|
702
|
+
chart aggregates each column into one min/max bucket, so path operations scale
|
|
703
|
+
with the chart's width rather than the number of bars. Extremes are preserved
|
|
704
|
+
exactly — a one-bar spike still reaches full height — because the bucket keeps
|
|
705
|
+
the true high and low rather than sampling. Candle and bar styles converge to a
|
|
706
|
+
single colored high-low column (the body is sub-pixel at that density anyway);
|
|
707
|
+
line/area/baseline keep a min/max envelope so the shape of the move survives.
|
|
708
|
+
|
|
709
|
+
Measured on the playground benchmark (50,000 bars, 120Hz display):
|
|
710
|
+
|
|
711
|
+
| Scenario | Per-bar (before) | Downsampled |
|
|
712
|
+
| --- | --- | --- |
|
|
713
|
+
| zoom 100 ↔ 20k bars | 21.3ms avg, 49.8ms p95, 47fps, 53 slow frames | 8.3ms avg, 10.3ms p95, 120fps, 0 slow frames |
|
|
714
|
+
| deep zoom-out, 50k bars | 52.7ms avg, 58.8ms p95, 19fps, 240 slow frames | 8.3ms avg, 10.2ms p95, 120fps, 0 slow frames |
|
|
715
|
+
|
|
716
|
+
Turn it off with `downsampling: { enabled: false }`, or tune when it kicks in
|
|
717
|
+
with `thresholdPx`.
|
|
718
|
+
|
|
613
719
|
## Context menus, selection toolbars and keyboard
|
|
614
720
|
|
|
615
721
|
Three pieces of chrome that every host previously rebuilt by hand. The chart
|