@funnest/charts 0.6.22 → 0.6.24
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 +12 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +178 -5
- package/dist/render/screenshot-legend.d.ts +73 -0
- package/dist/resolution.d.ts +6 -0
- package/package.json +1 -1
package/dist/chart.d.ts
CHANGED
|
@@ -145,6 +145,15 @@ export interface LegendItem extends LegendItemOptions {
|
|
|
145
145
|
id: string;
|
|
146
146
|
visible: boolean;
|
|
147
147
|
}
|
|
148
|
+
export interface ScreenshotOptions {
|
|
149
|
+
/**
|
|
150
|
+
* Paints the legend into the image, where @funnest/charts-ui shows it: symbol · interval ·
|
|
151
|
+
* exchange and the capture time, the last bar's OHLC and change, compares, and the values of
|
|
152
|
+
* visible indicators (overlays at the top, pane indicators and volume on their panes).
|
|
153
|
+
* Default false: a bare chart has no legend on screen either.
|
|
154
|
+
*/
|
|
155
|
+
legend?: boolean;
|
|
156
|
+
}
|
|
148
157
|
export interface IndicatorLegendItem {
|
|
149
158
|
id: string;
|
|
150
159
|
type: IndicatorType;
|
|
@@ -321,7 +330,9 @@ export declare class Chart {
|
|
|
321
330
|
/** Inverse of indexToTime(). */
|
|
322
331
|
private timeToIndex;
|
|
323
332
|
/** Snapshot of the chart (without the crosshair) at device resolution. */
|
|
324
|
-
takeScreenshot(): HTMLCanvasElement;
|
|
333
|
+
takeScreenshot(options?: ScreenshotOptions): HTMLCanvasElement;
|
|
334
|
+
/** The legend rows, painted where the DOM legend sits (see ScreenshotOptions.legend). */
|
|
335
|
+
private paintScreenshotLegend;
|
|
325
336
|
/**
|
|
326
337
|
* Re-fetches the latest window and merges it in, keeping the view. Datafeeds trigger this
|
|
327
338
|
* via the `onResetCache` callback of subscribeBars after a WebSocket reconnect, so bars
|
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, LegendItem, LegendItemOptions, ReplayStatus } from './chart';
|
|
4
|
+
export type { ChartContextMenu, ChartEvents, ChartLayout, ChartOptions, ChartPaneLayout, CompareInfo, IndicatorLegendItem, LegendItem, LegendItemOptions, ReplayStatus, ScreenshotOptions } 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';
|
|
@@ -12,7 +12,7 @@ export type { DirectionPreset, ThemeTokens } from './theme';
|
|
|
12
12
|
export { createTheme, darkTheme, directionColors, lightTheme } from './theme';
|
|
13
13
|
export type { FormatPriceOptions } from './price';
|
|
14
14
|
export { decimalsOf, formatCompact, formatPrice, krxTickSize, resolveTickSize, roundToTick } from './price';
|
|
15
|
-
export { isIntradayResolution, resolutionToMs } from './resolution';
|
|
15
|
+
export { isIntradayResolution, resolutionLabel, resolutionToMs } from './resolution';
|
|
16
16
|
export type { ChartType } from './render/renderer';
|
|
17
17
|
export type { BuiltinDrawingType, Drawing, DrawingDefinition, DrawingGeometry, DrawingPoint, DrawingRenderContext, DrawingStyle, DrawingColorSlot, DrawingType, } from './objects/drawings';
|
|
18
18
|
export { BUILTIN_DRAWINGS, distToSegment, FIB_LEVELS } from './objects/drawings';
|
package/dist/index.js
CHANGED
|
@@ -2587,6 +2587,85 @@ function drawCrosshairValue(p, m, ch) {
|
|
|
2587
2587
|
p.text(valueLabel, f.plotWidth + 8, by, pal.background);
|
|
2588
2588
|
}
|
|
2589
2589
|
|
|
2590
|
+
// src/render/screenshot-legend.ts
|
|
2591
|
+
var ROW_GAP = 2;
|
|
2592
|
+
var DOT2 = 8;
|
|
2593
|
+
var DOT_GAP = 6;
|
|
2594
|
+
var LEGEND_LEFT = 12;
|
|
2595
|
+
var LEGEND_TOP = 8;
|
|
2596
|
+
var LEGEND_RIGHT_CLEARANCE = 80;
|
|
2597
|
+
function layoutLegend(rows, left, top, maxWidth, measure) {
|
|
2598
|
+
const runs = [];
|
|
2599
|
+
let y = top;
|
|
2600
|
+
let right = left;
|
|
2601
|
+
rows.forEach((row, i) => {
|
|
2602
|
+
if (i > 0) y += ROW_GAP;
|
|
2603
|
+
let x = left;
|
|
2604
|
+
let lineStart = true;
|
|
2605
|
+
const widths = row.groups.map((g) => g.reduce((w, r) => w + runWidth(r, row.size, measure), 0));
|
|
2606
|
+
row.groups.forEach((group, gi) => {
|
|
2607
|
+
const w = widths[gi];
|
|
2608
|
+
if (!lineStart && x + row.gap + w > left + maxWidth) {
|
|
2609
|
+
y += row.lineHeight;
|
|
2610
|
+
x = left;
|
|
2611
|
+
lineStart = true;
|
|
2612
|
+
}
|
|
2613
|
+
if (!lineStart) x += row.gap;
|
|
2614
|
+
for (const run of group) {
|
|
2615
|
+
runs.push({ run, x, y: y + row.lineHeight / 2, size: row.size });
|
|
2616
|
+
x += runWidth(run, row.size, measure);
|
|
2617
|
+
}
|
|
2618
|
+
right = Math.max(right, x);
|
|
2619
|
+
lineStart = false;
|
|
2620
|
+
});
|
|
2621
|
+
y += row.lineHeight;
|
|
2622
|
+
});
|
|
2623
|
+
return { runs, bottom: y, right };
|
|
2624
|
+
}
|
|
2625
|
+
function runWidth(run, size, measure) {
|
|
2626
|
+
return (run.dot ? DOT2 + DOT_GAP : 0) + (run.text ? measure(run.text, size, run.weight ?? 400) : 0);
|
|
2627
|
+
}
|
|
2628
|
+
var font = (size, weight, family) => `${weight} ${size}px ${family}`;
|
|
2629
|
+
function canvasMeasure(ctx, family) {
|
|
2630
|
+
return (text, size, weight) => {
|
|
2631
|
+
ctx.font = font(size, weight, family);
|
|
2632
|
+
return ctx.measureText(text).width;
|
|
2633
|
+
};
|
|
2634
|
+
}
|
|
2635
|
+
function paintLegend(ctx, layout, family, backdrop) {
|
|
2636
|
+
ctx.save();
|
|
2637
|
+
if (backdrop && layout.runs.length) {
|
|
2638
|
+
const pad = 4;
|
|
2639
|
+
ctx.globalAlpha = 0.85;
|
|
2640
|
+
ctx.fillStyle = backdrop.color;
|
|
2641
|
+
ctx.beginPath();
|
|
2642
|
+
ctx.roundRect(backdrop.left - pad, backdrop.top - pad, layout.right - backdrop.left + pad * 2, layout.bottom - backdrop.top + pad * 2, 6);
|
|
2643
|
+
ctx.fill();
|
|
2644
|
+
ctx.globalAlpha = 1;
|
|
2645
|
+
}
|
|
2646
|
+
ctx.textBaseline = "middle";
|
|
2647
|
+
ctx.textAlign = "left";
|
|
2648
|
+
for (const { run, x, y, size } of layout.runs) {
|
|
2649
|
+
let tx = x;
|
|
2650
|
+
if (run.dot) {
|
|
2651
|
+
ctx.fillStyle = run.color;
|
|
2652
|
+
ctx.beginPath();
|
|
2653
|
+
ctx.arc(x + DOT2 / 2, y, DOT2 / 2, 0, Math.PI * 2);
|
|
2654
|
+
ctx.fill();
|
|
2655
|
+
tx += DOT2 + DOT_GAP;
|
|
2656
|
+
if (!run.text) continue;
|
|
2657
|
+
}
|
|
2658
|
+
ctx.font = font(size, run.weight ?? 400, family);
|
|
2659
|
+
ctx.fillStyle = run.color;
|
|
2660
|
+
ctx.fillText(run.text, tx, y);
|
|
2661
|
+
}
|
|
2662
|
+
ctx.restore();
|
|
2663
|
+
}
|
|
2664
|
+
var LEGEND_STRINGS = {
|
|
2665
|
+
ko: { open: "\uC2DC", high: "\uACE0", low: "\uC800", close: "\uC885", volume: "\uAC70\uB798\uB7C9", volumePane: "\uAC70\uB798\uB7C9" },
|
|
2666
|
+
en: { open: "O", high: "H", low: "L", close: "C", volume: "Vol", volumePane: "Volume" }
|
|
2667
|
+
};
|
|
2668
|
+
|
|
2590
2669
|
// src/resolution.ts
|
|
2591
2670
|
var MINUTE = 6e4;
|
|
2592
2671
|
var DAY_MS = 864e5;
|
|
@@ -2610,6 +2689,28 @@ function resolutionToMs(resolution) {
|
|
|
2610
2689
|
function isIntradayResolution(resolution) {
|
|
2611
2690
|
return resolutionToMs(resolution) < DAY_MS;
|
|
2612
2691
|
}
|
|
2692
|
+
function resolutionLabel(resolution, locale, form = "short") {
|
|
2693
|
+
const match = /^(\d*)([SDWM]?)$/i.exec(resolution.trim());
|
|
2694
|
+
if (!match) return resolution;
|
|
2695
|
+
const n = match[1] ? Number(match[1]) : 1;
|
|
2696
|
+
const unit = (match[2] ?? "").toUpperCase();
|
|
2697
|
+
const ko = locale === "ko";
|
|
2698
|
+
const long = form === "long";
|
|
2699
|
+
switch (unit) {
|
|
2700
|
+
case "S":
|
|
2701
|
+
return ko ? `${n}\uCD08` : `${n}s`;
|
|
2702
|
+
case "D":
|
|
2703
|
+
return ko ? n === 1 && !long ? "\uC77C" : `${n}\uC77C` : `${n}D`;
|
|
2704
|
+
case "W":
|
|
2705
|
+
return ko ? n === 1 && !long ? "\uC8FC" : `${n}\uC8FC` : `${n}W`;
|
|
2706
|
+
case "M":
|
|
2707
|
+
if (n % 12 === 0) return ko ? `${n / 12}\uB144` : `${n / 12}Y`;
|
|
2708
|
+
return ko ? n === 1 && !long ? "\uC6D4" : `${n}\uAC1C\uC6D4` : `${n}M`;
|
|
2709
|
+
default:
|
|
2710
|
+
if (n >= 60 && n % 60 === 0) return ko ? `${n / 60}\uC2DC\uAC04` : `${n / 60}h`;
|
|
2711
|
+
return ko ? `${n}\uBD84` : `${n}m`;
|
|
2712
|
+
}
|
|
2713
|
+
}
|
|
2613
2714
|
|
|
2614
2715
|
// src/realtime.ts
|
|
2615
2716
|
var offsetFormatters = /* @__PURE__ */ new Map();
|
|
@@ -3178,15 +3279,86 @@ var Chart = class {
|
|
|
3178
3279
|
return i + (b > a ? (time - a) / (b - a) : 0);
|
|
3179
3280
|
}
|
|
3180
3281
|
/** Snapshot of the chart (without the crosshair) at device resolution. */
|
|
3181
|
-
takeScreenshot() {
|
|
3282
|
+
takeScreenshot(options = {}) {
|
|
3182
3283
|
if (this.rafId || this.mainDirty) this.render();
|
|
3183
3284
|
const src2 = this.mainLayer.canvas;
|
|
3184
3285
|
const out = document.createElement("canvas");
|
|
3185
3286
|
out.width = src2.width;
|
|
3186
3287
|
out.height = src2.height;
|
|
3187
|
-
out.getContext("2d")
|
|
3288
|
+
const ctx = out.getContext("2d");
|
|
3289
|
+
if (ctx) {
|
|
3290
|
+
ctx.drawImage(src2, 0, 0);
|
|
3291
|
+
if (options.legend) this.paintScreenshotLegend(ctx);
|
|
3292
|
+
}
|
|
3188
3293
|
return out;
|
|
3189
3294
|
}
|
|
3295
|
+
/** The legend rows, painted where the DOM legend sits (see ScreenshotOptions.legend). */
|
|
3296
|
+
paintScreenshotLegend(ctx) {
|
|
3297
|
+
const symbol = this.symbol;
|
|
3298
|
+
const frame = this.frame;
|
|
3299
|
+
if (!symbol || !frame) return;
|
|
3300
|
+
const pal = this.resolvePalette();
|
|
3301
|
+
const family = this.colors.fontFamily(this.theme.fontFamily);
|
|
3302
|
+
const measure = canvasMeasure(ctx, family);
|
|
3303
|
+
const words = LEGEND_STRINGS[this.locale];
|
|
3304
|
+
const bars = this.store.bars;
|
|
3305
|
+
const last = bars.length - 1;
|
|
3306
|
+
const bar = bars[last];
|
|
3307
|
+
const prev = bars[last - 1];
|
|
3308
|
+
const fmt = (p) => formatPrice(p, this.pricePrecision);
|
|
3309
|
+
const dir = (v) => v > 0 ? pal.up : v < 0 ? pal.down : pal.text;
|
|
3310
|
+
const label = (text) => ({ text, color: pal.textSecondary });
|
|
3311
|
+
const value = (text, color) => ({ text, color, weight: 600 });
|
|
3312
|
+
const dot = { text: "\xB7", color: pal.textSecondary };
|
|
3313
|
+
const title = [[{ text: symbol.name, color: pal.text, weight: 700 }], [dot]];
|
|
3314
|
+
if (this.resolution) title.push([label(resolutionLabel(this.resolution, this.locale))], [dot]);
|
|
3315
|
+
title.push([label(symbol.exchange)], [label(this.formatter.crosshairLabel(Date.now(), true))]);
|
|
3316
|
+
const rows = [{ groups: title, gap: 6, size: 13, lineHeight: 20 }];
|
|
3317
|
+
if (bar) {
|
|
3318
|
+
const c = dir(bar.close - bar.open);
|
|
3319
|
+
const change = prev ? bar.close - prev.close : 0;
|
|
3320
|
+
const pct = prev && prev.close ? change / prev.close * 100 : 0;
|
|
3321
|
+
const sign = change > 0 ? "+" : "";
|
|
3322
|
+
const groups = [
|
|
3323
|
+
[label(`${words.open} `), value(fmt(bar.open), c)],
|
|
3324
|
+
[label(`${words.high} `), value(fmt(bar.high), c)],
|
|
3325
|
+
[label(`${words.low} `), value(fmt(bar.low), c)],
|
|
3326
|
+
[label(`${words.close} `), value(fmt(bar.close), c)],
|
|
3327
|
+
[value(`${sign}${fmt(change)} (${sign}${pct.toFixed(2)}%)`, dir(change))]
|
|
3328
|
+
];
|
|
3329
|
+
if (bar.volume !== void 0) groups.push([label(`${words.volume} `), value(formatCompact(bar.volume, this.locale), pal.text)]);
|
|
3330
|
+
rows.push({ groups, gap: 10, size: 12, lineHeight: 18 });
|
|
3331
|
+
}
|
|
3332
|
+
for (const cmp of this.compareLegend()) {
|
|
3333
|
+
rows.push({ groups: [[{ text: "", color: cmp.color, dot: true }, { text: cmp.name, color: pal.text }], [value(cmp.value, pal.text)]], gap: 6, size: 12, lineHeight: 22 });
|
|
3334
|
+
}
|
|
3335
|
+
const indicators = this.indicatorLegend().filter((item) => item.visible);
|
|
3336
|
+
const indicatorRow = (item) => ({
|
|
3337
|
+
groups: [[label(item.title)], ...item.values.map((v) => [value(v.value, v.color)])],
|
|
3338
|
+
gap: 8,
|
|
3339
|
+
size: 12,
|
|
3340
|
+
lineHeight: 20
|
|
3341
|
+
});
|
|
3342
|
+
for (const item of indicators) if (item.overlay) rows.push(indicatorRow(item));
|
|
3343
|
+
for (const item of this.legendExtras) if (item.visible) rows.push({ groups: [[label(item.name)]], gap: 8, size: 12, lineHeight: 20 });
|
|
3344
|
+
const dpr = this.mainLayer.dpr;
|
|
3345
|
+
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
3346
|
+
const maxWidth = Math.max(80, this.size.width - LEGEND_LEFT - LEGEND_RIGHT_CLEARANCE);
|
|
3347
|
+
const main = layoutLegend(rows, LEGEND_LEFT, LEGEND_TOP, maxWidth, measure);
|
|
3348
|
+
const covers = main.bottom + 4 > this.mainScale.insetTop;
|
|
3349
|
+
paintLegend(ctx, main, family, covers ? { color: pal.background, top: LEGEND_TOP, left: LEGEND_LEFT } : null);
|
|
3350
|
+
for (const pane of frame.panes) {
|
|
3351
|
+
let row = null;
|
|
3352
|
+
if (pane.kind === "volume") {
|
|
3353
|
+
const v = bar?.volume;
|
|
3354
|
+
row = { groups: [[label(words.volumePane)], ...v !== void 0 ? [[value(formatCompact(v, this.locale), pal.text)]] : []], gap: 8, size: 12, lineHeight: 20 };
|
|
3355
|
+
} else if (pane.kind === "indicator") {
|
|
3356
|
+
const item = indicators.find((i) => i.id === pane.id);
|
|
3357
|
+
if (item) row = indicatorRow(item);
|
|
3358
|
+
}
|
|
3359
|
+
if (row) paintLegend(ctx, layoutLegend([row], LEGEND_LEFT, pane.top + 4, maxWidth, measure), family, null);
|
|
3360
|
+
}
|
|
3361
|
+
}
|
|
3190
3362
|
/**
|
|
3191
3363
|
* Re-fetches the latest window and merges it in, keeping the view. Datafeeds trigger this
|
|
3192
3364
|
* via the `onResetCache` callback of subscribeBars after a WebSocket reconnect, so bars
|
|
@@ -4042,9 +4214,9 @@ var Chart = class {
|
|
|
4042
4214
|
return (v) => formatPrice(v, decimals);
|
|
4043
4215
|
};
|
|
4044
4216
|
const fontFamily = this.colors.fontFamily(this.theme.fontFamily);
|
|
4045
|
-
const
|
|
4217
|
+
const font2 = `${this.theme.fontSize}px ${fontFamily}`;
|
|
4046
4218
|
const ctx = this.mainLayer.ctx;
|
|
4047
|
-
ctx.font =
|
|
4219
|
+
ctx.font = font2;
|
|
4048
4220
|
let range = { from: 0, to: -1 };
|
|
4049
4221
|
let highLow = null;
|
|
4050
4222
|
let priceTicks = [];
|
|
@@ -4128,7 +4300,7 @@ var Chart = class {
|
|
|
4128
4300
|
settings: this.settingsValue,
|
|
4129
4301
|
overlays: [...overlays.map((o) => o.output), ...compareOverlays],
|
|
4130
4302
|
palette: this.resolvePalette(),
|
|
4131
|
-
font,
|
|
4303
|
+
font: font2,
|
|
4132
4304
|
radius: this.theme.radius,
|
|
4133
4305
|
countdown: this.countdownLabel
|
|
4134
4306
|
};
|
|
@@ -4807,6 +4979,7 @@ export {
|
|
|
4807
4979
|
monitorLatency,
|
|
4808
4980
|
parseChartState,
|
|
4809
4981
|
priceSource,
|
|
4982
|
+
resolutionLabel,
|
|
4810
4983
|
resolutionToMs,
|
|
4811
4984
|
resolveTickSize,
|
|
4812
4985
|
roundToTick,
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The legend painted into screenshots: the same rows @funnest/charts-ui shows over the chart
|
|
3
|
+
* (symbol · interval · exchange, OHLC and change, compares, indicator values), as text on the
|
|
4
|
+
* canvas, so a saved or shared image says what it is. Layout mirrors the DOM legend's CSS
|
|
5
|
+
* (12px from the left, 8px from the top, 80px clear of the price axis, wrapping items).
|
|
6
|
+
*/
|
|
7
|
+
/** A piece of text (or a color dot) drawn as-is. */
|
|
8
|
+
export interface LegendRun {
|
|
9
|
+
text: string;
|
|
10
|
+
color: string;
|
|
11
|
+
/** Default 400. */
|
|
12
|
+
weight?: number;
|
|
13
|
+
/** A filled circle of this color before the text (compare rows). */
|
|
14
|
+
dot?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/** Runs that stay together on one line; groups wrap between them. */
|
|
17
|
+
export type LegendGroup = LegendRun[];
|
|
18
|
+
export interface LegendRow {
|
|
19
|
+
groups: LegendGroup[];
|
|
20
|
+
/** Space between groups. */
|
|
21
|
+
gap: number;
|
|
22
|
+
size: number;
|
|
23
|
+
lineHeight: number;
|
|
24
|
+
}
|
|
25
|
+
export interface PlacedRun {
|
|
26
|
+
run: LegendRun;
|
|
27
|
+
x: number;
|
|
28
|
+
/** Middle of the line. */
|
|
29
|
+
y: number;
|
|
30
|
+
size: number;
|
|
31
|
+
}
|
|
32
|
+
export interface LegendLayout {
|
|
33
|
+
runs: PlacedRun[];
|
|
34
|
+
/** Bottom of the last line. */
|
|
35
|
+
bottom: number;
|
|
36
|
+
/** Right edge of the widest line. */
|
|
37
|
+
right: number;
|
|
38
|
+
}
|
|
39
|
+
export type MeasureText = (text: string, size: number, weight: number) => number;
|
|
40
|
+
export declare const LEGEND_LEFT = 12;
|
|
41
|
+
export declare const LEGEND_TOP = 8;
|
|
42
|
+
export declare const LEGEND_RIGHT_CLEARANCE = 80;
|
|
43
|
+
/** Places rows top-down from (left, top), wrapping groups that don't fit within maxWidth. */
|
|
44
|
+
export declare function layoutLegend(rows: readonly LegendRow[], left: number, top: number, maxWidth: number, measure: MeasureText): LegendLayout;
|
|
45
|
+
export declare function canvasMeasure(ctx: CanvasRenderingContext2D, family: string): MeasureText;
|
|
46
|
+
/**
|
|
47
|
+
* Paints a layout. With `backdrop`, a translucent panel goes behind it first — for legends taller
|
|
48
|
+
* than the space the chart keeps clear above the candles.
|
|
49
|
+
*/
|
|
50
|
+
export declare function paintLegend(ctx: CanvasRenderingContext2D, layout: LegendLayout, family: string, backdrop: {
|
|
51
|
+
color: string;
|
|
52
|
+
top: number;
|
|
53
|
+
left: number;
|
|
54
|
+
} | null): void;
|
|
55
|
+
/** Words the screenshot legend uses (the widget's own strings live in @funnest/charts-ui). */
|
|
56
|
+
export declare const LEGEND_STRINGS: {
|
|
57
|
+
readonly ko: {
|
|
58
|
+
readonly open: '시';
|
|
59
|
+
readonly high: '고';
|
|
60
|
+
readonly low: '저';
|
|
61
|
+
readonly close: '종';
|
|
62
|
+
readonly volume: '거래량';
|
|
63
|
+
readonly volumePane: '거래량';
|
|
64
|
+
};
|
|
65
|
+
readonly en: {
|
|
66
|
+
readonly open: 'O';
|
|
67
|
+
readonly high: 'H';
|
|
68
|
+
readonly low: 'L';
|
|
69
|
+
readonly close: 'C';
|
|
70
|
+
readonly volume: 'Vol';
|
|
71
|
+
readonly volumePane: 'Volume';
|
|
72
|
+
};
|
|
73
|
+
};
|
package/dist/resolution.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Locale } from './model/time-format';
|
|
1
2
|
import type { Resolution } from './types';
|
|
2
3
|
export declare const DAY_MS = 86400000;
|
|
3
4
|
/**
|
|
@@ -6,3 +7,8 @@ export declare const DAY_MS = 86400000;
|
|
|
6
7
|
*/
|
|
7
8
|
export declare function resolutionToMs(resolution: Resolution): number;
|
|
8
9
|
export declare function isIntradayResolution(resolution: Resolution): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* '1' → 1분, '60' → 1시간, '1D' → 일 (short) / 1일 (long), '12M' → 1년.
|
|
12
|
+
* Short labels are for the toolbar chips, long ones for the interval menu.
|
|
13
|
+
*/
|
|
14
|
+
export declare function resolutionLabel(resolution: Resolution, locale: Locale, form?: 'short' | 'long'): string;
|