@funnest/charts 0.6.2 → 0.6.4

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
@@ -209,6 +209,14 @@ export declare class Chart {
209
209
  private connectionState;
210
210
  private readonly displayTimezone;
211
211
  private loadingHistory;
212
+ /**
213
+ * Bumped by every data replacement (setData) and history request: a page answers only if it
214
+ * is still the latest request for the bars on screen. (The load token alone isn't enough — a
215
+ * page requested while setSymbol() awaits carries the new token but the old symbol's bars.)
216
+ */
217
+ private historyRequest;
218
+ /** setSymbol() is between its request and setData(). */
219
+ private symbolLoading;
212
220
  private noMoreHistory;
213
221
  private historyRequestedFor;
214
222
  private countdownLabel;
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { Chart, createChart, fallbackResolution } from './chart';
2
- export { DEFAULT_CHART_SETTINGS, parseChartState } from './settings';
3
- export type { ChartSettings, ChartState } from './settings';
2
+ export { CHART_THEMES, DEFAULT_CHART_SETTINGS, matchChartTheme, parseChartState } from './settings';
3
+ export type { ChartSettings, ChartState, ChartThemeColors, ChartThemePreset } from './settings';
4
4
  export type { ChartContextMenu, ChartEvents, ChartLayout, ChartOptions, ChartPaneLayout, CompareInfo, IndicatorLegendItem, ReplayStatus } from './chart';
5
5
  export type { PriceScaleMode } from './model/price-scale';
6
6
  export type { CrosshairInfo, PaneId } from './render/renderer';
package/dist/index.js CHANGED
@@ -1793,6 +1793,41 @@ function snapToOhlc(bar, y, priceToY) {
1793
1793
  }
1794
1794
 
1795
1795
  // src/settings.ts
1796
+ var FOLLOW = { upColor: null, downColor: null, background: null, gridColor: null, textColor: null };
1797
+ var CHART_THEMES = [
1798
+ { id: "default", name: { ko: "\uAE30\uBCF8", en: "Default" }, colors: FOLLOW },
1799
+ { id: "global", name: { ko: "\uCD08\uB85D\xB7\uBE68\uAC15", en: "Green \xB7 Red" }, colors: { ...FOLLOW, upColor: "#26A69A", downColor: "#EF5350" } },
1800
+ {
1801
+ id: "midnight",
1802
+ name: { ko: "\uBBF8\uB4DC\uB098\uC787", en: "Midnight" },
1803
+ colors: { upColor: "#2EBD85", downColor: "#F6465D", background: "#0E1117", gridColor: "#1A1F29", textColor: "#C9D1D9" }
1804
+ },
1805
+ {
1806
+ id: "navy",
1807
+ name: { ko: "\uB525 \uB124\uC774\uBE44", en: "Deep navy" },
1808
+ colors: { upColor: "#FF5A5F", downColor: "#4C8DFF", background: "#0F1A2E", gridColor: "#1B2A44", textColor: "#C8D3E6" }
1809
+ },
1810
+ {
1811
+ id: "mono",
1812
+ name: { ko: "\uBAA8\uB178", en: "Mono" },
1813
+ colors: { upColor: "#E4E4E7", downColor: "#6B6B75", background: "#121214", gridColor: "#1F1F23", textColor: "#D4D4D8" }
1814
+ },
1815
+ {
1816
+ id: "paper",
1817
+ name: { ko: "\uD398\uC774\uD37C", en: "Paper" },
1818
+ colors: { upColor: "#F04452", downColor: "#3182F6", background: "#FFFFFF", gridColor: "#F0F2F5", textColor: "#333D4B" }
1819
+ },
1820
+ {
1821
+ id: "sepia",
1822
+ name: { ko: "\uC138\uD53C\uC544", en: "Sepia" },
1823
+ colors: { upColor: "#C2410C", downColor: "#2F6690", background: "#F6F0E4", gridColor: "#E9DFCB", textColor: "#4A3F33" }
1824
+ }
1825
+ ];
1826
+ function matchChartTheme(settings) {
1827
+ const keys = Object.keys(FOLLOW);
1828
+ const same = (a, b) => (a ?? "").toLowerCase() === (b ?? "").toLowerCase();
1829
+ return CHART_THEMES.find((t) => keys.every((k) => same(t.colors[k], settings[k])));
1830
+ }
1796
1831
  var DEFAULT_CHART_SETTINGS = {
1797
1832
  highLowMarkers: true,
1798
1833
  lastPriceLine: true,
@@ -1803,7 +1838,10 @@ var DEFAULT_CHART_SETTINGS = {
1803
1838
  priceScale: "normal",
1804
1839
  countdown: true,
1805
1840
  upColor: null,
1806
- downColor: null
1841
+ downColor: null,
1842
+ background: null,
1843
+ gridColor: null,
1844
+ textColor: null
1807
1845
  };
1808
1846
  var CHART_TYPES = ["candles", "line", "area"];
1809
1847
  function parseChartState(input) {
@@ -2684,6 +2722,14 @@ var Chart = class {
2684
2722
  connectionState = null;
2685
2723
  displayTimezone;
2686
2724
  loadingHistory = false;
2725
+ /**
2726
+ * Bumped by every data replacement (setData) and history request: a page answers only if it
2727
+ * is still the latest request for the bars on screen. (The load token alone isn't enough — a
2728
+ * page requested while setSymbol() awaits carries the new token but the old symbol's bars.)
2729
+ */
2730
+ historyRequest = 0;
2731
+ /** setSymbol() is between its request and setData(). */
2732
+ symbolLoading = false;
2687
2733
  noMoreHistory = false;
2688
2734
  historyRequestedFor = Number.NaN;
2689
2735
  countdownLabel = null;
@@ -2765,6 +2811,8 @@ var Chart = class {
2765
2811
  this.volumeScale.autoScale = true;
2766
2812
  this.noMoreHistory = false;
2767
2813
  this.historyRequestedFor = Number.NaN;
2814
+ this.historyRequest++;
2815
+ this.loadingHistory = false;
2768
2816
  this.dataVersion++;
2769
2817
  this.invalidate();
2770
2818
  }
@@ -2817,6 +2865,7 @@ var Chart = class {
2817
2865
  this.quoteSymbol = null;
2818
2866
  }
2819
2867
  this.emitter.emit("loadingChange", true);
2868
+ this.symbolLoading = true;
2820
2869
  let info;
2821
2870
  let result;
2822
2871
  try {
@@ -2831,7 +2880,10 @@ var Chart = class {
2831
2880
  });
2832
2881
  if (token !== this.loadToken) return;
2833
2882
  } finally {
2834
- if (token === this.loadToken) this.emitter.emit("loadingChange", false);
2883
+ if (token === this.loadToken) {
2884
+ this.symbolLoading = false;
2885
+ this.emitter.emit("loadingChange", false);
2886
+ }
2835
2887
  }
2836
2888
  const previous = this.symbol?.symbol ?? "";
2837
2889
  if (previous !== info.symbol) {
@@ -3994,14 +4046,16 @@ var Chart = class {
3994
4046
  }
3995
4047
  resolvePalette() {
3996
4048
  const t = this.theme;
4049
+ const s = this.settingsValue;
3997
4050
  const c = (v) => this.colors.color(v);
4051
+ const muted = s.textColor && /^#[0-9a-f]{6}$/i.test(s.textColor) ? `${s.textColor}99` : null;
3998
4052
  return {
3999
- background: c(t.background),
4000
- text: c(t.text),
4001
- textSecondary: c(t.textSecondary),
4002
- grid: c(t.grid),
4003
- border: c(t.border),
4004
- crosshair: c(t.crosshair),
4053
+ background: c(s.background ?? t.background),
4054
+ text: c(s.textColor ?? t.text),
4055
+ textSecondary: c(muted ?? t.textSecondary),
4056
+ grid: c(s.gridColor ?? t.grid),
4057
+ border: c(s.gridColor ?? t.border),
4058
+ crosshair: c(muted ?? t.crosshair),
4005
4059
  up: c(this.settingsValue.upColor ?? t.up),
4006
4060
  down: c(this.settingsValue.downColor ?? t.down),
4007
4061
  accent: c(t.accent)
@@ -4036,6 +4090,7 @@ var Chart = class {
4036
4090
  requestHistory() {
4037
4091
  const oldest = this.store.first();
4038
4092
  if (!oldest || this.loadingHistory || this.noMoreHistory || oldest.time === this.historyRequestedFor) return;
4093
+ if (this.symbolLoading) return;
4039
4094
  this.historyRequestedFor = oldest.time;
4040
4095
  const feed = this.datafeed;
4041
4096
  if (!feed || !this.symbol || !this.resolution) {
@@ -4043,6 +4098,8 @@ var Chart = class {
4043
4098
  return;
4044
4099
  }
4045
4100
  const token = this.loadToken;
4101
+ const request = ++this.historyRequest;
4102
+ const current = () => token === this.loadToken && request === this.historyRequest;
4046
4103
  this.loadingHistory = true;
4047
4104
  const to = oldest.time - 1;
4048
4105
  feed.getBars(this.symbol, this.resolution, {
@@ -4050,13 +4107,13 @@ var Chart = class {
4050
4107
  to,
4051
4108
  countBack: this.historyBatchSize
4052
4109
  }).then((result) => {
4053
- if (token !== this.loadToken) return;
4110
+ if (!current()) return;
4054
4111
  this.prependData(result.bars, { noMoreData: result.noMoreData || result.bars.length === 0 });
4055
4112
  const first = this.store.first();
4056
4113
  if (first) void this.tradingSync.loadOlder(first.time);
4057
4114
  for (const entry of this.compares.values()) void this.loadOlderCompare(entry);
4058
4115
  }).catch((error) => this.emitter.emit("error", error)).finally(() => {
4059
- if (token === this.loadToken) this.loadingHistory = false;
4116
+ if (current()) this.loadingHistory = false;
4060
4117
  });
4061
4118
  }
4062
4119
  // ── Crosshair ──────────────────────────────────────────────────────
@@ -4497,6 +4554,7 @@ function combineDatafeeds(feeds) {
4497
4554
  }
4498
4555
  export {
4499
4556
  BUILTIN_DRAWINGS,
4557
+ CHART_THEMES,
4500
4558
  Chart,
4501
4559
  DEFAULT_CHART_SETTINGS,
4502
4560
  FIB_LEVELS,
@@ -4522,6 +4580,7 @@ export {
4522
4580
  lightTheme,
4523
4581
  maLines,
4524
4582
  macd,
4583
+ matchChartTheme,
4525
4584
  monitorLatency,
4526
4585
  parseChartState,
4527
4586
  priceSource,
@@ -22,7 +22,28 @@ export interface ChartSettings {
22
22
  /** Up/down candle colors; null follows the theme. */
23
23
  upColor: string | null;
24
24
  downColor: string | null;
25
+ /** Chart canvas colors (a theme from CHART_THEMES or your own); null follows the theme. `textColor` must be #rrggbb. */
26
+ background: string | null;
27
+ gridColor: string | null;
28
+ textColor: string | null;
25
29
  }
30
+ /** The settings a chart theme sets. */
31
+ export type ChartThemeColors = Pick<ChartSettings, 'upColor' | 'downColor' | 'background' | 'gridColor' | 'textColor'>;
32
+ export interface ChartThemePreset {
33
+ id: string;
34
+ name: {
35
+ ko: string;
36
+ en: string;
37
+ };
38
+ colors: ChartThemeColors;
39
+ }
40
+ /**
41
+ * Ready-made chart themes for the settings dialog. Applying one sets the five color settings;
42
+ * 'default' clears them so the chart follows the page theme again.
43
+ */
44
+ export declare const CHART_THEMES: readonly ChartThemePreset[];
45
+ /** The preset whose colors `settings` match, if any. */
46
+ export declare function matchChartTheme(settings: ChartSettings): ChartThemePreset | undefined;
26
47
  export declare const DEFAULT_CHART_SETTINGS: ChartSettings;
27
48
  /**
28
49
  * Everything needed to restore a chart layout: symbol, interval, chart type, settings,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@funnest/charts",
3
- "version": "0.6.2",
3
+ "version": "0.6.4",
4
4
  "description": "Canvas charting engine for financial charts",
5
5
  "keywords": [
6
6
  "chart",