@funnest/charts 0.6.17 → 0.6.19

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/chart.d.ts CHANGED
@@ -99,6 +99,8 @@ export interface ChartEvents {
99
99
  canRedo: boolean;
100
100
  };
101
101
  comparesChange: CompareInfo[];
102
+ /** App rows in the legend (addLegendItem) were added, changed or removed. */
103
+ legendItemsChange: readonly LegendItem[];
102
104
  replayChange: ReplayStatus;
103
105
  /**
104
106
  * Right-click on the chart (mouse only). While anything listens, the browser's own menu is
@@ -123,6 +125,26 @@ export interface ChartPaneLayout {
123
125
  top: number;
124
126
  height: number;
125
127
  }
128
+ /**
129
+ * A row an app puts in the chart's legend for something it draws itself (a liquidation map, an
130
+ * order-book heatmap, a line from its own data), so people can hide, configure or remove it
131
+ * right where they see the indicators.
132
+ */
133
+ export interface LegendItemOptions {
134
+ name: string;
135
+ /** Starts shown. Default true. */
136
+ visible?: boolean;
137
+ /** 👁 hides / shows it: the app stops / resumes drawing. No eye without it. */
138
+ onToggle?(visible: boolean): void;
139
+ /** ⚙ opens the app's own settings for it. */
140
+ onSettings?(): void;
141
+ /** × turns it off (the app removes its drawing and this row). */
142
+ onRemove?(): void;
143
+ }
144
+ export interface LegendItem extends LegendItemOptions {
145
+ id: string;
146
+ visible: boolean;
147
+ }
126
148
  export interface IndicatorLegendItem {
127
149
  id: string;
128
150
  type: IndicatorType;
@@ -168,6 +190,8 @@ export declare class Chart {
168
190
  private readonly cleanups;
169
191
  private readonly drawings;
170
192
  private readonly overlays;
193
+ private legendExtras;
194
+ private legendSeq;
171
195
  private readonly trading;
172
196
  private readonly tradingSync;
173
197
  private tooltipKey;
@@ -413,6 +437,18 @@ export declare class Chart {
413
437
  addOrderLine(options: OrderLineOptions): LineHandle<OrderLineOptions>;
414
438
  /** Price alert line (dotted, gray, "알림" label). Pass `onMove` to make it draggable and `onCancel` for an ×. */
415
439
  addAlertLine(options: AlertLineOptions): LineHandle<AlertLineOptions>;
440
+ /**
441
+ * Adds a row to the legend for something the app draws (see LegendItemOptions). `update()`
442
+ * changes its name or state; `remove()` takes the row away (the app removes its drawing).
443
+ */
444
+ addLegendItem(options: LegendItemOptions): {
445
+ update(patch: Partial<LegendItemOptions>): void;
446
+ remove(): void;
447
+ };
448
+ /** The app's legend rows, in the order they were added. */
449
+ get legendItems(): readonly LegendItem[];
450
+ /** The legend's 👁 on an app row: tells the app (onToggle) and remembers the state. */
451
+ setLegendItemVisible(id: string, visible: boolean): void;
416
452
  /**
417
453
  * Paints `overlay` on the price pane every frame (see ChartOverlay). `redraw()` asks for a
418
454
  * new frame after its data changed; `remove()` takes it off.
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { Chart, createChart, fallbackResolution } from './chart';
2
2
  export { CHART_THEMES, DEFAULT_CHART_SETTINGS, matchChartTheme, parseChartState } from './settings';
3
3
  export type { ChartSettings, ChartState, ChartThemeColors, ChartThemePreset } from './settings';
4
- export type { ChartContextMenu, ChartEvents, ChartLayout, ChartOptions, ChartPaneLayout, CompareInfo, IndicatorLegendItem, ReplayStatus } from './chart';
4
+ export type { ChartContextMenu, ChartEvents, ChartLayout, ChartOptions, ChartPaneLayout, CompareInfo, IndicatorLegendItem, LegendItem, LegendItemOptions, ReplayStatus } from './chart';
5
5
  export type { PriceScaleMode } from './model/price-scale';
6
6
  export type { CrosshairInfo, PaneId } from './render/renderer';
7
7
  export type { Locale } from './model/time-format';
package/dist/index.js CHANGED
@@ -2412,6 +2412,25 @@ function drawMain(layer, m) {
2412
2412
  }
2413
2413
  }
2414
2414
  if (f.settings.gridVertical) for (const tick of f.timeTicks) p.vLine(tick.x, 0, f.panesHeight, pal.grid);
2415
+ const o = m.objects;
2416
+ const rc = { painter: p, coords: o.coords, palette: pal };
2417
+ const runOverlay = (overlay) => {
2418
+ ctx.save();
2419
+ try {
2420
+ overlay.render(rc);
2421
+ } catch (error) {
2422
+ console.error("[fnc] overlay", error);
2423
+ }
2424
+ ctx.restore();
2425
+ };
2426
+ if (o.overlays.some((x) => x.layer === "below")) {
2427
+ ctx.save();
2428
+ ctx.beginPath();
2429
+ ctx.rect(0, main.top, f.plotWidth, main.height);
2430
+ ctx.clip();
2431
+ for (const overlay of o.overlays) if (overlay.layer === "below") runOverlay(overlay);
2432
+ ctx.restore();
2433
+ }
2415
2434
  const hasBars = f.range.to >= f.range.from;
2416
2435
  if (hasBars) {
2417
2436
  ctx.save();
@@ -2451,17 +2470,7 @@ function drawMain(layer, m) {
2451
2470
  ctx.beginPath();
2452
2471
  ctx.rect(0, main.top, f.plotWidth, main.height);
2453
2472
  ctx.clip();
2454
- const o = m.objects;
2455
- const rc = { painter: p, coords: o.coords, palette: pal };
2456
- for (const overlay of o.overlays) {
2457
- ctx.save();
2458
- try {
2459
- overlay.render(rc);
2460
- } catch (error) {
2461
- console.error("[fnc] overlay", error);
2462
- }
2463
- ctx.restore();
2464
- }
2473
+ for (const overlay of o.overlays) if (overlay.layer !== "below") runOverlay(overlay);
2465
2474
  o.trading.render(rc, m.bars, o.barIndexAt, (i) => m.timeScale.indexToX(i), o.tradingLabels, badges);
2466
2475
  o.drawings.render(rc, badges, m.bars, o.barIndexAt);
2467
2476
  ctx.restore();
@@ -2802,6 +2811,8 @@ var Chart = class {
2802
2811
  cleanups = [];
2803
2812
  drawings;
2804
2813
  overlays = [];
2814
+ legendExtras = [];
2815
+ legendSeq = 0;
2805
2816
  trading;
2806
2817
  tradingSync;
2807
2818
  tooltipKey = null;
@@ -3778,6 +3789,38 @@ var Chart = class {
3778
3789
  addAlertLine(options) {
3779
3790
  return this.trading.addAlert(options);
3780
3791
  }
3792
+ /**
3793
+ * Adds a row to the legend for something the app draws (see LegendItemOptions). `update()`
3794
+ * changes its name or state; `remove()` takes the row away (the app removes its drawing).
3795
+ */
3796
+ addLegendItem(options) {
3797
+ const item = { ...options, id: `legend-${++this.legendSeq}`, visible: options.visible ?? true };
3798
+ this.legendExtras = [...this.legendExtras, item];
3799
+ this.emitter.emit("legendItemsChange", this.legendExtras);
3800
+ return {
3801
+ update: (patch) => {
3802
+ this.legendExtras = this.legendExtras.map((x) => x.id === item.id ? { ...x, ...patch, visible: patch.visible ?? x.visible } : x);
3803
+ this.emitter.emit("legendItemsChange", this.legendExtras);
3804
+ },
3805
+ remove: () => {
3806
+ if (!this.legendExtras.some((x) => x.id === item.id)) return;
3807
+ this.legendExtras = this.legendExtras.filter((x) => x.id !== item.id);
3808
+ this.emitter.emit("legendItemsChange", this.legendExtras);
3809
+ }
3810
+ };
3811
+ }
3812
+ /** The app's legend rows, in the order they were added. */
3813
+ get legendItems() {
3814
+ return this.legendExtras;
3815
+ }
3816
+ /** The legend's 👁 on an app row: tells the app (onToggle) and remembers the state. */
3817
+ setLegendItemVisible(id, visible) {
3818
+ const item = this.legendExtras.find((x) => x.id === id);
3819
+ if (!item || item.visible === visible) return;
3820
+ this.legendExtras = this.legendExtras.map((x) => x.id === id ? { ...x, visible } : x);
3821
+ item.onToggle?.(visible);
3822
+ this.emitter.emit("legendItemsChange", this.legendExtras);
3823
+ }
3781
3824
  /**
3782
3825
  * Paints `overlay` on the price pane every frame (see ChartOverlay). `redraw()` asks for a
3783
3826
  * new frame after its data changed; `remove()` takes it off.
@@ -29,6 +29,11 @@ export interface ObjectRenderContext {
29
29
  */
30
30
  export interface ChartOverlay {
31
31
  render(rc: ObjectRenderContext): void;
32
+ /**
33
+ * 'below': painted right after the grid, under the candles and indicators (an order-book
34
+ * heatmap, session shading). Default 'above'.
35
+ */
36
+ layer?: 'above' | 'below';
32
37
  }
33
38
  export type ObjectHit = {
34
39
  kind: 'drawing';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@funnest/charts",
3
- "version": "0.6.17",
3
+ "version": "0.6.19",
4
4
  "description": "Canvas charting engine for financial charts",
5
5
  "keywords": [
6
6
  "chart",