@funnest/charts-ui 0.6.0 → 0.6.1
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/components/context-menu.d.ts +8 -0
- package/dist/context.d.ts +13 -1
- package/dist/i18n.d.ts +6 -0
- package/dist/icons.d.ts +0 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +105 -17
- package/dist/pane.d.ts +2 -1
- package/dist/trading-chart.d.ts +6 -1
- package/package.json +2 -2
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { WidgetContext } from '../context';
|
|
2
|
+
/**
|
|
3
|
+
* Right-click menu on the chart (mouse only): undo/redo, the host's own items
|
|
4
|
+
* (`contextMenuItems`), a horizontal line at the clicked price, reset and settings.
|
|
5
|
+
*/
|
|
6
|
+
export declare function ContextMenu({ ctx }: {
|
|
7
|
+
ctx: WidgetContext;
|
|
8
|
+
}): import("preact").JSX.Element | null;
|
package/dist/context.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Chart, ChartLayout, ChartType, CompareInfo, Datafeed, Drawing, DrawingType, IndicatorConfig, Locale, ReplayStatus, Resolution, SymbolInfo } from '@funnest/charts';
|
|
1
|
+
import type { Chart, ChartContextMenu, ChartLayout, ChartType, CompareInfo, Datafeed, Drawing, DrawingType, IndicatorConfig, Locale, ReplayStatus, Resolution, SymbolInfo } from '@funnest/charts';
|
|
2
2
|
import type { LayoutId } from './layouts';
|
|
3
3
|
import type { WidgetStorage } from './storage';
|
|
4
4
|
import type { Store } from './store';
|
|
@@ -39,6 +39,17 @@ export interface UiState {
|
|
|
39
39
|
compares: CompareInfo[];
|
|
40
40
|
replay: ReplayStatus;
|
|
41
41
|
}
|
|
42
|
+
/** A row in the chart's right-click menu, or a divider. */
|
|
43
|
+
export type ContextMenuItem = {
|
|
44
|
+
label: string;
|
|
45
|
+
shortcut?: string;
|
|
46
|
+
disabled?: boolean;
|
|
47
|
+
onSelect(): void;
|
|
48
|
+
} | 'separator';
|
|
49
|
+
/** Extra right-click items for a click on `chart` (e.g. "create an alert at this price"). */
|
|
50
|
+
export type ContextMenuItems = (target: ChartContextMenu & {
|
|
51
|
+
chart: Chart;
|
|
52
|
+
}) => ContextMenuItem[];
|
|
42
53
|
export interface IntervalGroup {
|
|
43
54
|
id: 'minutes' | 'hours' | 'days';
|
|
44
55
|
intervals: Resolution[];
|
|
@@ -65,6 +76,7 @@ export interface WidgetContext {
|
|
|
65
76
|
drawingToolbar: boolean;
|
|
66
77
|
/** Show the Funnest logo badge on the chart. */
|
|
67
78
|
attribution: boolean;
|
|
79
|
+
contextMenuItems: ContextMenuItems | undefined;
|
|
68
80
|
slots: {
|
|
69
81
|
toolbar: HTMLElement;
|
|
70
82
|
toolbarEnd: HTMLElement;
|
package/dist/i18n.d.ts
CHANGED
|
@@ -47,6 +47,9 @@ export declare const STRINGS: {
|
|
|
47
47
|
scaleLog: string;
|
|
48
48
|
scalePercent: string;
|
|
49
49
|
undo: string;
|
|
50
|
+
horizontalAt: string;
|
|
51
|
+
resetChart: string;
|
|
52
|
+
chartSettingsMore: string;
|
|
50
53
|
redo: string;
|
|
51
54
|
compare: string;
|
|
52
55
|
compareSymbol: string;
|
|
@@ -173,6 +176,9 @@ export declare const STRINGS: {
|
|
|
173
176
|
scaleLog: string;
|
|
174
177
|
scalePercent: string;
|
|
175
178
|
undo: string;
|
|
179
|
+
horizontalAt: string;
|
|
180
|
+
resetChart: string;
|
|
181
|
+
chartSettingsMore: string;
|
|
176
182
|
redo: string;
|
|
177
183
|
compare: string;
|
|
178
184
|
compareSymbol: string;
|
package/dist/icons.d.ts
CHANGED
|
@@ -40,8 +40,6 @@ export declare const FunnestMark: () => import("preact").JSX.Element;
|
|
|
40
40
|
export declare const LinkIcon: () => import("preact").JSX.Element;
|
|
41
41
|
export declare const MaximizeIcon: () => import("preact").JSX.Element;
|
|
42
42
|
export declare const RestoreIcon: () => import("preact").JSX.Element;
|
|
43
|
-
export declare const UndoIcon: () => import("preact").JSX.Element;
|
|
44
|
-
export declare const RedoIcon: () => import("preact").JSX.Element;
|
|
45
43
|
/** Two price lines diverging (compare symbols). */
|
|
46
44
|
export declare const CompareIcon: () => import("preact").JSX.Element;
|
|
47
45
|
export declare const ReplayIcon: () => import("preact").JSX.Element;
|
package/dist/index.d.ts
CHANGED
|
@@ -8,6 +8,6 @@ export { createMultiChart } from './multi-chart';
|
|
|
8
8
|
export type { MultiChart, MultiChartEvents, MultiChartOptions, MultiChartState, PaneSpec } from './multi-chart';
|
|
9
9
|
export { LAYOUT_GROUPS, LAYOUTS, MAX_PANES, paneCount } from './layouts';
|
|
10
10
|
export type { LayoutId, SplitNode, SplitSizes } from './layouts';
|
|
11
|
-
export type { IntervalGroup, LayoutSync, SearchCategory } from './context';
|
|
11
|
+
export type { ContextMenuItem, ContextMenuItems, IntervalGroup, LayoutSync, SearchCategory } from './context';
|
|
12
12
|
export type { ColorScheme, TradingChart, TradingChartOptions, TradingChartSlots } from './trading-chart';
|
|
13
13
|
export { resolutionLabel } from './i18n';
|
package/dist/index.js
CHANGED
|
@@ -470,6 +470,9 @@ var STRINGS = {
|
|
|
470
470
|
scaleLog: "\uB85C\uADF8",
|
|
471
471
|
scalePercent: "%",
|
|
472
472
|
undo: "\uB418\uB3CC\uB9AC\uAE30",
|
|
473
|
+
horizontalAt: "{price}\uC5D0 \uC218\uD3C9\uC120 \uAE0B\uAE30",
|
|
474
|
+
resetChart: "\uCC28\uD2B8 \uCD08\uAE30\uD654",
|
|
475
|
+
chartSettingsMore: "\uCC28\uD2B8 \uC124\uC815\u2026",
|
|
473
476
|
redo: "\uB2E4\uC2DC \uC2E4\uD589",
|
|
474
477
|
compare: "\uBE44\uAD50",
|
|
475
478
|
compareSymbol: "\uBE44\uAD50\uD560 \uC885\uBAA9 \uCD94\uAC00",
|
|
@@ -598,6 +601,9 @@ var STRINGS = {
|
|
|
598
601
|
scaleLog: "Log",
|
|
599
602
|
scalePercent: "%",
|
|
600
603
|
undo: "Undo",
|
|
604
|
+
horizontalAt: "Horizontal line at {price}",
|
|
605
|
+
resetChart: "Reset chart",
|
|
606
|
+
chartSettingsMore: "Chart settings\u2026",
|
|
601
607
|
redo: "Redo",
|
|
602
608
|
compare: "Compare",
|
|
603
609
|
compareSymbol: "Add symbol to compare",
|
|
@@ -815,14 +821,6 @@ var LinkIcon = () => /* @__PURE__ */ a3(Icon, { children: [
|
|
|
815
821
|
] });
|
|
816
822
|
var MaximizeIcon = () => /* @__PURE__ */ a3(Icon, { size: 16, children: /* @__PURE__ */ a3("path", { d: "M11 4h5v5M9 16H4v-5M16 4l-5 5M4 16l5-5" }) });
|
|
817
823
|
var RestoreIcon = () => /* @__PURE__ */ a3(Icon, { size: 16, children: /* @__PURE__ */ a3("path", { d: "M15 9h-4V5M5 11h4v4M11 9l5-5M9 11l-5 5" }) });
|
|
818
|
-
var UndoIcon = () => /* @__PURE__ */ a3(Icon, { size: 18, children: [
|
|
819
|
-
/* @__PURE__ */ a3("path", { d: "M7 5L3.5 8.5 7 12" }),
|
|
820
|
-
/* @__PURE__ */ a3("path", { d: "M3.5 8.5h8.5a4.5 4.5 0 0 1 0 9H9" })
|
|
821
|
-
] });
|
|
822
|
-
var RedoIcon = () => /* @__PURE__ */ a3(Icon, { size: 18, children: [
|
|
823
|
-
/* @__PURE__ */ a3("path", { d: "M13 5l3.5 3.5L13 12" }),
|
|
824
|
-
/* @__PURE__ */ a3("path", { d: "M16.5 8.5H8a4.5 4.5 0 0 0 0 9h3" })
|
|
825
|
-
] });
|
|
826
824
|
var CompareIcon = () => /* @__PURE__ */ a3(Icon, { children: [
|
|
827
825
|
/* @__PURE__ */ a3("path", { d: "M3 14l4-4 3 2 7-7" }),
|
|
828
826
|
/* @__PURE__ */ a3("path", { d: "M3 9l4 2 3-3 7 5", opacity: "0.55" })
|
|
@@ -2043,7 +2041,6 @@ function Toolbar({ ctx }) {
|
|
|
2043
2041
|
const s3 = useStore(ctx.store);
|
|
2044
2042
|
const t3 = STRINGS[s3.locale];
|
|
2045
2043
|
const canSearch = typeof ctx.datafeed.searchSymbols === "function";
|
|
2046
|
-
const mod = /Mac|iPhone|iPad/.test(navigator.platform) ? "\u2318" : "Ctrl";
|
|
2047
2044
|
return /* @__PURE__ */ a3("div", { class: "fnc-toolbar", role: "toolbar", children: [
|
|
2048
2045
|
/* @__PURE__ */ a3(
|
|
2049
2046
|
"button",
|
|
@@ -2117,8 +2114,6 @@ function Toolbar({ ctx }) {
|
|
|
2117
2114
|
children: /* @__PURE__ */ a3(PencilIcon, {})
|
|
2118
2115
|
}
|
|
2119
2116
|
),
|
|
2120
|
-
/* @__PURE__ */ a3("button", { class: "fnc-btn fnc-btn-undo", "data-tip": `${t3.undo} (${mod}+Z)`, "aria-label": t3.undo, disabled: !s3.canUndo, onClick: () => ctx.chart.undo(), children: /* @__PURE__ */ a3(UndoIcon, {}) }),
|
|
2121
|
-
/* @__PURE__ */ a3("button", { class: "fnc-btn fnc-btn-undo", "data-tip": `${t3.redo} (${mod}+Shift+Z)`, "aria-label": t3.redo, disabled: !s3.canRedo, onClick: () => ctx.chart.redo(), children: /* @__PURE__ */ a3(RedoIcon, {}) }),
|
|
2122
2117
|
/* @__PURE__ */ a3(Slot, { el: ctx.slots.toolbarEnd, fixed: true }),
|
|
2123
2118
|
/* @__PURE__ */ a3(
|
|
2124
2119
|
"button",
|
|
@@ -2151,7 +2146,88 @@ function Toolbar({ ctx }) {
|
|
|
2151
2146
|
import { createChart } from "@funnest/charts";
|
|
2152
2147
|
|
|
2153
2148
|
// src/components/overlay.tsx
|
|
2154
|
-
import { formatCompact, formatPrice as
|
|
2149
|
+
import { formatCompact, formatPrice as formatPrice3 } from "@funnest/charts";
|
|
2150
|
+
|
|
2151
|
+
// src/components/context-menu.tsx
|
|
2152
|
+
import { formatPrice as formatPrice2 } from "@funnest/charts";
|
|
2153
|
+
var MARGIN2 = 8;
|
|
2154
|
+
function ContextMenu({ ctx }) {
|
|
2155
|
+
const s3 = useStore(ctx.store);
|
|
2156
|
+
const t3 = STRINGS[s3.locale];
|
|
2157
|
+
const [target, setTarget] = d2(null);
|
|
2158
|
+
const ref = T2(null);
|
|
2159
|
+
A2(() => ctx.chart.on("contextMenu", setTarget), [ctx.chart]);
|
|
2160
|
+
A2(() => {
|
|
2161
|
+
if (!target) return;
|
|
2162
|
+
const close = () => setTarget(null);
|
|
2163
|
+
const onDown = (e3) => !ref.current?.contains(e3.target) && close();
|
|
2164
|
+
const onKey = (e3) => e3.key === "Escape" && close();
|
|
2165
|
+
document.addEventListener("pointerdown", onDown, true);
|
|
2166
|
+
document.addEventListener("keydown", onKey);
|
|
2167
|
+
window.addEventListener("wheel", close, { passive: true });
|
|
2168
|
+
window.addEventListener("resize", close);
|
|
2169
|
+
return () => {
|
|
2170
|
+
document.removeEventListener("pointerdown", onDown, true);
|
|
2171
|
+
document.removeEventListener("keydown", onKey);
|
|
2172
|
+
window.removeEventListener("wheel", close);
|
|
2173
|
+
window.removeEventListener("resize", close);
|
|
2174
|
+
};
|
|
2175
|
+
}, [target]);
|
|
2176
|
+
F2(() => {
|
|
2177
|
+
const el = ref.current;
|
|
2178
|
+
const stage = el?.closest(".fnc-stage");
|
|
2179
|
+
if (!el || !target || !stage) return;
|
|
2180
|
+
const w3 = el.offsetWidth;
|
|
2181
|
+
const h3 = el.offsetHeight;
|
|
2182
|
+
const { width, height } = stage.getBoundingClientRect();
|
|
2183
|
+
const x2 = target.x + w3 + MARGIN2 > width ? Math.max(MARGIN2, target.x - w3) : target.x;
|
|
2184
|
+
const y3 = target.y + h3 + MARGIN2 > height ? Math.max(MARGIN2, target.y - h3) : target.y;
|
|
2185
|
+
el.style.transform = `translate(${Math.round(x2)}px, ${Math.round(y3)}px)`;
|
|
2186
|
+
}, [target]);
|
|
2187
|
+
if (!target) return null;
|
|
2188
|
+
const mac = /Mac|iPhone|iPad/.test(navigator.platform);
|
|
2189
|
+
const mod = mac ? "\u2318" : "Ctrl+";
|
|
2190
|
+
const price = target.price;
|
|
2191
|
+
const precision = s3.symbol?.pricePrecision ?? 2;
|
|
2192
|
+
const extra = ctx.contextMenuItems?.({ ...target, chart: ctx.chart }) ?? [];
|
|
2193
|
+
const items = [
|
|
2194
|
+
{ label: t3.undo, shortcut: `${mod}Z`, disabled: !s3.canUndo, onSelect: () => ctx.chart.undo() },
|
|
2195
|
+
{ label: t3.redo, shortcut: `${mod}${mac ? "\u21E7" : "Shift+"}Z`, disabled: !s3.canRedo, onSelect: () => ctx.chart.redo() },
|
|
2196
|
+
"separator",
|
|
2197
|
+
...extra.length ? [...extra, "separator"] : []
|
|
2198
|
+
];
|
|
2199
|
+
if (price !== null) {
|
|
2200
|
+
const time = target.time ?? ctx.chart.bars[ctx.chart.bars.length - 1]?.time ?? Date.now();
|
|
2201
|
+
items.push({
|
|
2202
|
+
label: t3.horizontalAt.replace("{price}", formatPrice2(price, precision)),
|
|
2203
|
+
onSelect: () => ctx.chart.addDrawing({ type: "horizontal", points: [{ time, price }] })
|
|
2204
|
+
});
|
|
2205
|
+
}
|
|
2206
|
+
items.push(
|
|
2207
|
+
{ label: t3.resetChart, onSelect: () => ctx.chart.resetView() },
|
|
2208
|
+
{ label: t3.chartSettingsMore, onSelect: () => ctx.store.set({ dialog: { kind: "chartSettings" } }) }
|
|
2209
|
+
);
|
|
2210
|
+
return /* @__PURE__ */ a3("div", { class: "fnc-menu fnc-ctx-menu", role: "menu", ref, onContextMenu: (e3) => e3.preventDefault(), children: items.map(
|
|
2211
|
+
(item) => item === "separator" ? /* @__PURE__ */ a3("div", { class: "fnc-ctx-sep", role: "separator" }) : /* @__PURE__ */ a3(
|
|
2212
|
+
"button",
|
|
2213
|
+
{
|
|
2214
|
+
class: "fnc-menu-item",
|
|
2215
|
+
role: "menuitem",
|
|
2216
|
+
disabled: item.disabled,
|
|
2217
|
+
onClick: () => {
|
|
2218
|
+
setTarget(null);
|
|
2219
|
+
item.onSelect();
|
|
2220
|
+
},
|
|
2221
|
+
children: [
|
|
2222
|
+
/* @__PURE__ */ a3("span", { children: item.label }),
|
|
2223
|
+
item.shortcut && /* @__PURE__ */ a3("kbd", { children: item.shortcut })
|
|
2224
|
+
]
|
|
2225
|
+
}
|
|
2226
|
+
)
|
|
2227
|
+
) });
|
|
2228
|
+
}
|
|
2229
|
+
|
|
2230
|
+
// src/components/overlay.tsx
|
|
2155
2231
|
var ZOOM_STEP = 1.25;
|
|
2156
2232
|
var CONTROL_OFFSET = 52;
|
|
2157
2233
|
var dirClass = (v3) => v3 > 0 ? "fnc-up" : v3 < 0 ? "fnc-down" : "fnc-flat";
|
|
@@ -2243,7 +2319,7 @@ function Legend({ ctx }) {
|
|
|
2243
2319
|
const bars = ctx.chart.bars;
|
|
2244
2320
|
const bar = hover?.bar ?? bars[bars.length - 1];
|
|
2245
2321
|
const prev = hover ? hover.prev : bars[bars.length - 2];
|
|
2246
|
-
const fmt = (p3) =>
|
|
2322
|
+
const fmt = (p3) => formatPrice3(p3, s3.symbol.pricePrecision);
|
|
2247
2323
|
let values = null;
|
|
2248
2324
|
if (bar) {
|
|
2249
2325
|
const cls = dirClass(bar.close - bar.open);
|
|
@@ -2452,7 +2528,8 @@ function Overlay({ ctx }) {
|
|
|
2452
2528
|
/* @__PURE__ */ a3(NavControls, { ctx }),
|
|
2453
2529
|
/* @__PURE__ */ a3(ReplayBar, { ctx }),
|
|
2454
2530
|
/* @__PURE__ */ a3(SelectionBar, { ctx }),
|
|
2455
|
-
/* @__PURE__ */ a3(PaneTools, { ctx })
|
|
2531
|
+
/* @__PURE__ */ a3(PaneTools, { ctx }),
|
|
2532
|
+
/* @__PURE__ */ a3(ContextMenu, { ctx })
|
|
2456
2533
|
] });
|
|
2457
2534
|
}
|
|
2458
2535
|
|
|
@@ -3255,7 +3332,6 @@ var CSS = (
|
|
|
3255
3332
|
every toolbar button stays reachable. Ctrl/\u2318+Z still undoes when the buttons are hidden. \u2500\u2500 */
|
|
3256
3333
|
.fnc-root { container: fnc / inline-size; }
|
|
3257
3334
|
@container fnc (max-width: 1100px) {
|
|
3258
|
-
.fnc-btn-undo { display: none; }
|
|
3259
3335
|
.fnc-btn-label span { display: none; }
|
|
3260
3336
|
.fnc-toolbar .fnc-btn-label { padding: 0 6px; }
|
|
3261
3337
|
}
|
|
@@ -3369,6 +3445,13 @@ var CSS = (
|
|
|
3369
3445
|
.fnc-switch[data-on='true'] { background: var(--fnc-text-2); }
|
|
3370
3446
|
.fnc-switch[data-on='true']::after { transform: translateX(16px); }
|
|
3371
3447
|
|
|
3448
|
+
/* \u2500\u2500 Right-click menu \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
3449
|
+
.fnc-ctx-menu { top: 0; left: 0; z-index: 40; min-width: 220px; pointer-events: auto; }
|
|
3450
|
+
.fnc-ctx-menu .fnc-menu-item { justify-content: space-between; gap: 24px; color: var(--fnc-text); }
|
|
3451
|
+
.fnc-ctx-menu .fnc-menu-item:disabled { color: var(--fnc-text-2); }
|
|
3452
|
+
.fnc-ctx-menu kbd { font: inherit; font-size: 12px; color: var(--fnc-text-2); }
|
|
3453
|
+
.fnc-ctx-sep { height: 1px; margin: 4px 6px; background: var(--fnc-border); }
|
|
3454
|
+
|
|
3372
3455
|
/* \u2500\u2500 Drawing tool groups \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
3373
3456
|
.fnc-tool-group { position: relative; display: flex; }
|
|
3374
3457
|
.fnc-tool-group[data-open='true'] { z-index: 30; }
|
|
@@ -3441,7 +3524,7 @@ var CSS = (
|
|
|
3441
3524
|
|
|
3442
3525
|
/* \u2500\u2500 Mobile \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
3443
3526
|
@media (max-width: 640px) {
|
|
3444
|
-
.fnc-btn-compare, .fnc-btn-replay
|
|
3527
|
+
.fnc-btn-compare, .fnc-btn-replay { display: none; }
|
|
3445
3528
|
.fnc-toolbar { padding: 0 4px; gap: 2px; }
|
|
3446
3529
|
.fnc-toolbar .fnc-btn { width: 32px; height: 32px; }
|
|
3447
3530
|
.fnc-toolbar .fnc-btn-wide, .fnc-toolbar .fnc-btn-label { width: auto; padding: 0 6px; }
|
|
@@ -3809,6 +3892,7 @@ function createPane(shell, config) {
|
|
|
3809
3892
|
showLogo: config.symbolLogo,
|
|
3810
3893
|
drawingToolbar: config.drawingToolbar,
|
|
3811
3894
|
attribution: config.attribution,
|
|
3895
|
+
contextMenuItems: config.contextMenuItems,
|
|
3812
3896
|
slots: shell.slots,
|
|
3813
3897
|
multi: config.multi,
|
|
3814
3898
|
setDrawbarCollapsed: shell.setDrawbarCollapsed,
|
|
@@ -3883,6 +3967,7 @@ function createTradingChart(container, options) {
|
|
|
3883
3967
|
chartType = "candles",
|
|
3884
3968
|
attribution = true,
|
|
3885
3969
|
colorScheme = "system",
|
|
3970
|
+
contextMenuItems,
|
|
3886
3971
|
theme,
|
|
3887
3972
|
...chartOptions
|
|
3888
3973
|
} = options;
|
|
@@ -3905,7 +3990,8 @@ function createTradingChart(container, options) {
|
|
|
3905
3990
|
searchCategories,
|
|
3906
3991
|
symbolLogo,
|
|
3907
3992
|
drawingToolbar,
|
|
3908
|
-
attribution
|
|
3993
|
+
attribution,
|
|
3994
|
+
contextMenuItems
|
|
3909
3995
|
});
|
|
3910
3996
|
shell.main.insertBefore(pane.stage, shell.slots.bottom);
|
|
3911
3997
|
shell.setPanes(() => [pane]);
|
|
@@ -3976,6 +4062,7 @@ function createMultiChart(container, options) {
|
|
|
3976
4062
|
chartType = "candles",
|
|
3977
4063
|
attribution = true,
|
|
3978
4064
|
colorScheme = "system",
|
|
4065
|
+
contextMenuItems,
|
|
3979
4066
|
theme,
|
|
3980
4067
|
...chartOptions
|
|
3981
4068
|
} = options;
|
|
@@ -4041,6 +4128,7 @@ function createMultiChart(container, options) {
|
|
|
4041
4128
|
drawingToolbar,
|
|
4042
4129
|
// One badge for the whole widget, not one per pane.
|
|
4043
4130
|
attribution: attribution && index === 0,
|
|
4131
|
+
contextMenuItems,
|
|
4044
4132
|
multi: controls
|
|
4045
4133
|
});
|
|
4046
4134
|
const cell = div("fnc-pane");
|
package/dist/pane.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** @jsxImportSource preact */
|
|
2
2
|
import { type Chart, type ChartOptions, type ChartType, type Datafeed, type Resolution } from '@funnest/charts';
|
|
3
|
-
import type { IntervalGroup, MultiControls, SearchCategory, UiState, WidgetContext } from './context';
|
|
3
|
+
import type { ContextMenuItems, IntervalGroup, MultiControls, SearchCategory, UiState, WidgetContext } from './context';
|
|
4
4
|
import { type Shell } from './shell';
|
|
5
5
|
import { Store } from './store';
|
|
6
6
|
export interface PaneConfig {
|
|
@@ -14,6 +14,7 @@ export interface PaneConfig {
|
|
|
14
14
|
symbolLogo: boolean;
|
|
15
15
|
drawingToolbar: boolean;
|
|
16
16
|
attribution: boolean;
|
|
17
|
+
contextMenuItems?: ContextMenuItems | undefined;
|
|
17
18
|
multi?: MultiControls | undefined;
|
|
18
19
|
}
|
|
19
20
|
/**
|
package/dist/trading-chart.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** @jsxImportSource preact */
|
|
2
2
|
import { type Chart, type ChartOptions, type ChartType, type Datafeed, type Locale, type ChartState, type Resolution, type ThemeTokens } from '@funnest/charts';
|
|
3
|
-
import type { IntervalGroup, SearchCategory } from './context';
|
|
3
|
+
import type { ContextMenuItems, IntervalGroup, SearchCategory } from './context';
|
|
4
4
|
import { type ColorScheme, type TradingChartSlots } from './shell';
|
|
5
5
|
export type { ColorScheme, TradingChartSlots } from './shell';
|
|
6
6
|
/** Interval menu: 분 | 시간 | 일. '12M' is shown as 1년. */
|
|
@@ -45,6 +45,11 @@ export interface TradingChartOptions extends Omit<ChartOptions, 'datafeed'> {
|
|
|
45
45
|
* `theme` overrides are applied on top of whichever base is active.
|
|
46
46
|
*/
|
|
47
47
|
colorScheme?: ColorScheme;
|
|
48
|
+
/**
|
|
49
|
+
* Extra rows for the chart's right-click menu (between undo/redo and the built-in actions),
|
|
50
|
+
* e.g. "이 가격에 알림 만들기". Called on every right-click with the price and time under the pointer.
|
|
51
|
+
*/
|
|
52
|
+
contextMenuItems?: ContextMenuItems;
|
|
48
53
|
}
|
|
49
54
|
export interface TradingChart {
|
|
50
55
|
/** The underlying engine, for anything the widget doesn't wrap. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@funnest/charts-ui",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Pro trading UI (toolbar, drawing tools, sheets) for Funnest Charts. Framework-agnostic.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"chart",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"NOTICE"
|
|
43
43
|
],
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@funnest/charts": "0.6.
|
|
45
|
+
"@funnest/charts": "0.6.1"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"preact": "^11.2.0"
|