@forgecharts/sdk 1.1.28 → 1.1.30
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/index.js +8100 -48
- package/dist/index.js.map +1 -1
- package/dist/internal.js +8851 -31
- package/dist/internal.js.map +1 -1
- package/dist/react/index.js +11558 -27
- package/dist/react/index.js.map +1 -1
- package/dist/react/internal.js +12147 -43
- package/dist/react/internal.js.map +1 -1
- package/package.json +1 -1
- package/dist/__tests__/backwardCompatibility.test.js +0 -159
- package/dist/__tests__/backwardCompatibility.test.js.map +0 -1
- package/dist/__tests__/candleInvariant.test.js +0 -415
- package/dist/__tests__/candleInvariant.test.js.map +0 -1
- package/dist/__tests__/public-api-surface.js +0 -38
- package/dist/__tests__/public-api-surface.js.map +0 -1
- package/dist/__tests__/timeframeBoundary.test.js +0 -452
- package/dist/__tests__/timeframeBoundary.test.js.map +0 -1
- package/dist/api/DrawingManager.js +0 -190
- package/dist/api/DrawingManager.js.map +0 -1
- package/dist/api/EventBus.js +0 -44
- package/dist/api/EventBus.js.map +0 -1
- package/dist/api/IndicatorDAG.js +0 -316
- package/dist/api/IndicatorDAG.js.map +0 -1
- package/dist/api/IndicatorRegistry.js +0 -39
- package/dist/api/IndicatorRegistry.js.map +0 -1
- package/dist/api/LayoutManager.js +0 -51
- package/dist/api/LayoutManager.js.map +0 -1
- package/dist/api/PaneManager.js +0 -119
- package/dist/api/PaneManager.js.map +0 -1
- package/dist/api/ReferenceAPI.js +0 -153
- package/dist/api/ReferenceAPI.js.map +0 -1
- package/dist/api/TChart.js +0 -765
- package/dist/api/TChart.js.map +0 -1
- package/dist/api/createChart.js +0 -42
- package/dist/api/createChart.js.map +0 -1
- package/dist/api/drawing tools/fib gann menu/fibRetracement.js +0 -22
- package/dist/api/drawing tools/fib gann menu/fibRetracement.js.map +0 -1
- package/dist/api/drawing tools/lines menu/crossLine.js +0 -16
- package/dist/api/drawing tools/lines menu/crossLine.js.map +0 -1
- package/dist/api/drawing tools/lines menu/disjointChannel.js +0 -59
- package/dist/api/drawing tools/lines menu/disjointChannel.js.map +0 -1
- package/dist/api/drawing tools/lines menu/extendedLine.js +0 -17
- package/dist/api/drawing tools/lines menu/extendedLine.js.map +0 -1
- package/dist/api/drawing tools/lines menu/flatTopBottom.js +0 -41
- package/dist/api/drawing tools/lines menu/flatTopBottom.js.map +0 -1
- package/dist/api/drawing tools/lines menu/horizontal.js +0 -19
- package/dist/api/drawing tools/lines menu/horizontal.js.map +0 -1
- package/dist/api/drawing tools/lines menu/horizontalRay.js +0 -20
- package/dist/api/drawing tools/lines menu/horizontalRay.js.map +0 -1
- package/dist/api/drawing tools/lines menu/infoLine.js +0 -107
- package/dist/api/drawing tools/lines menu/infoLine.js.map +0 -1
- package/dist/api/drawing tools/lines menu/insidePitchfork.js +0 -31
- package/dist/api/drawing tools/lines menu/insidePitchfork.js.map +0 -1
- package/dist/api/drawing tools/lines menu/modifiedSchiffPitchfork.js +0 -15
- package/dist/api/drawing tools/lines menu/modifiedSchiffPitchfork.js.map +0 -1
- package/dist/api/drawing tools/lines menu/parallelChannel.js +0 -43
- package/dist/api/drawing tools/lines menu/parallelChannel.js.map +0 -1
- package/dist/api/drawing tools/lines menu/pitchfork.js +0 -12
- package/dist/api/drawing tools/lines menu/pitchfork.js.map +0 -1
- package/dist/api/drawing tools/lines menu/ray.js +0 -23
- package/dist/api/drawing tools/lines menu/ray.js.map +0 -1
- package/dist/api/drawing tools/lines menu/regressionTrend.js +0 -127
- package/dist/api/drawing tools/lines menu/regressionTrend.js.map +0 -1
- package/dist/api/drawing tools/lines menu/schiffPitchfork.js +0 -15
- package/dist/api/drawing tools/lines menu/schiffPitchfork.js.map +0 -1
- package/dist/api/drawing tools/lines menu/trendAngle.js +0 -51
- package/dist/api/drawing tools/lines menu/trendAngle.js.map +0 -1
- package/dist/api/drawing tools/lines menu/trendline.js +0 -11
- package/dist/api/drawing tools/lines menu/trendline.js.map +0 -1
- package/dist/api/drawing tools/lines menu/vertical.js +0 -11
- package/dist/api/drawing tools/lines menu/vertical.js.map +0 -1
- package/dist/api/drawing tools/pointers menu/crosshair.js +0 -16
- package/dist/api/drawing tools/pointers menu/crosshair.js.map +0 -1
- package/dist/api/drawing tools/pointers menu/cursor.js +0 -15
- package/dist/api/drawing tools/pointers menu/cursor.js.map +0 -1
- package/dist/api/drawing tools/pointers menu/demonstration.js +0 -30
- package/dist/api/drawing tools/pointers menu/demonstration.js.map +0 -1
- package/dist/api/drawing tools/pointers menu/dot.js +0 -23
- package/dist/api/drawing tools/pointers menu/dot.js.map +0 -1
- package/dist/api/drawing tools/shapes menu/rectangle.js +0 -19
- package/dist/api/drawing tools/shapes menu/rectangle.js.map +0 -1
- package/dist/api/drawing tools/shapes menu/text.js +0 -25
- package/dist/api/drawing tools/shapes menu/text.js.map +0 -1
- package/dist/api/drawingUtils.js +0 -83
- package/dist/api/drawingUtils.js.map +0 -1
- package/dist/core/CanvasLayer.js +0 -56
- package/dist/core/CanvasLayer.js.map +0 -1
- package/dist/core/Chart.js +0 -839
- package/dist/core/Chart.js.map +0 -1
- package/dist/core/CoordTransform.js +0 -224
- package/dist/core/CoordTransform.js.map +0 -1
- package/dist/core/Crosshair.js +0 -186
- package/dist/core/Crosshair.js.map +0 -1
- package/dist/core/IndicatorEngine.js +0 -181
- package/dist/core/IndicatorEngine.js.map +0 -1
- package/dist/core/InteractionManager.js +0 -698
- package/dist/core/InteractionManager.js.map +0 -1
- package/dist/core/PriceScale.js +0 -113
- package/dist/core/PriceScale.js.map +0 -1
- package/dist/core/Series.js +0 -114
- package/dist/core/Series.js.map +0 -1
- package/dist/core/TimeScale.js +0 -150
- package/dist/core/TimeScale.js.map +0 -1
- package/dist/datafeed/DatafeedConnector.js +0 -268
- package/dist/datafeed/DatafeedConnector.js.map +0 -1
- package/dist/engine/CandleEngine.js +0 -318
- package/dist/engine/CandleEngine.js.map +0 -1
- package/dist/engine/__tests__/CandleEngine.test.js +0 -300
- package/dist/engine/__tests__/CandleEngine.test.js.map +0 -1
- package/dist/engine/candleInvariants.js +0 -134
- package/dist/engine/candleInvariants.js.map +0 -1
- package/dist/engine/mergeUtils.js +0 -64
- package/dist/engine/mergeUtils.js.map +0 -1
- package/dist/engine/timeframeUtils.js +0 -100
- package/dist/engine/timeframeUtils.js.map +0 -1
- package/dist/licensing/ChartRuntimeResolver.js +0 -310
- package/dist/licensing/ChartRuntimeResolver.js.map +0 -1
- package/dist/licensing/LicenseManager.js +0 -114
- package/dist/licensing/LicenseManager.js.map +0 -1
- package/dist/licensing/__tests__/ChartRuntimeResolver.test.js +0 -177
- package/dist/licensing/__tests__/ChartRuntimeResolver.test.js.map +0 -1
- package/dist/licensing/__tests__/LicenseManager.test.js +0 -153
- package/dist/licensing/__tests__/LicenseManager.test.js.map +0 -1
- package/dist/licensing/licenseTypes.js +0 -2
- package/dist/licensing/licenseTypes.js.map +0 -1
- package/dist/pine/PineCompiler.js +0 -44
- package/dist/pine/PineCompiler.js.map +0 -1
- package/dist/pine/diagnostics.js +0 -11
- package/dist/pine/diagnostics.js.map +0 -1
- package/dist/pine/index.js +0 -5
- package/dist/pine/index.js.map +0 -1
- package/dist/pine/pine-ast.js +0 -19
- package/dist/pine/pine-ast.js.map +0 -1
- package/dist/pine/pine-lexer.js +0 -249
- package/dist/pine/pine-lexer.js.map +0 -1
- package/dist/pine/pine-parser.js +0 -416
- package/dist/pine/pine-parser.js.map +0 -1
- package/dist/pine/pine-transpiler.js +0 -260
- package/dist/pine/pine-transpiler.js.map +0 -1
- package/dist/pixi/LayerName.js +0 -35
- package/dist/pixi/LayerName.js.map +0 -1
- package/dist/pixi/PixiCandlestickRenderer.js +0 -107
- package/dist/pixi/PixiCandlestickRenderer.js.map +0 -1
- package/dist/pixi/PixiChart.js +0 -367
- package/dist/pixi/PixiChart.js.map +0 -1
- package/dist/pixi/PixiCrosshairRenderer.js +0 -110
- package/dist/pixi/PixiCrosshairRenderer.js.map +0 -1
- package/dist/pixi/PixiDrawingRenderer.js +0 -111
- package/dist/pixi/PixiDrawingRenderer.js.map +0 -1
- package/dist/pixi/PixiGridRenderer.js +0 -114
- package/dist/pixi/PixiGridRenderer.js.map +0 -1
- package/dist/pixi/PixiLayerManager.js +0 -92
- package/dist/pixi/PixiLayerManager.js.map +0 -1
- package/dist/react/canvas/ChartCanvas.js +0 -604
- package/dist/react/canvas/ChartCanvas.js.map +0 -1
- package/dist/react/canvas/ChartContextMenu.js +0 -5
- package/dist/react/canvas/ChartContextMenu.js.map +0 -1
- package/dist/react/canvas/ChartSettingsDialog.js +0 -28
- package/dist/react/canvas/ChartSettingsDialog.js.map +0 -1
- package/dist/react/canvas/IndicatorLabel.js +0 -196
- package/dist/react/canvas/IndicatorLabel.js.map +0 -1
- package/dist/react/canvas/IndicatorPane.js +0 -395
- package/dist/react/canvas/IndicatorPane.js.map +0 -1
- package/dist/react/canvas/PointerOverlay.js +0 -61
- package/dist/react/canvas/PointerOverlay.js.map +0 -1
- package/dist/react/canvas/toolbars/LeftToolbar.js +0 -407
- package/dist/react/canvas/toolbars/LeftToolbar.js.map +0 -1
- package/dist/react/hooks/useChartCapabilities.js +0 -66
- package/dist/react/hooks/useChartCapabilities.js.map +0 -1
- package/dist/react/shell/ManagedAppShell.js +0 -440
- package/dist/react/shell/ManagedAppShell.js.map +0 -1
- package/dist/react/trading/TradingBridge.js +0 -73
- package/dist/react/trading/TradingBridge.js.map +0 -1
- package/dist/react/workspace/ChartWorkspace.js +0 -42
- package/dist/react/workspace/ChartWorkspace.js.map +0 -1
- package/dist/react/workspace/FloatingPanel.js +0 -82
- package/dist/react/workspace/FloatingPanel.js.map +0 -1
- package/dist/react/workspace/IndicatorsDialog.js +0 -121
- package/dist/react/workspace/IndicatorsDialog.js.map +0 -1
- package/dist/react/workspace/LayoutMenu.js +0 -113
- package/dist/react/workspace/LayoutMenu.js.map +0 -1
- package/dist/react/workspace/SymbolSearchDialog.js +0 -245
- package/dist/react/workspace/SymbolSearchDialog.js.map +0 -1
- package/dist/react/workspace/TabBar.js +0 -29
- package/dist/react/workspace/TabBar.js.map +0 -1
- package/dist/react/workspace/toolbars/BottomToolbar.js +0 -236
- package/dist/react/workspace/toolbars/BottomToolbar.js.map +0 -1
- package/dist/react/workspace/toolbars/RightToolbar.js +0 -18
- package/dist/react/workspace/toolbars/RightToolbar.js.map +0 -1
- package/dist/react/workspace/toolbars/TopToolbar.js +0 -82
- package/dist/react/workspace/toolbars/TopToolbar.js.map +0 -1
- package/dist/renderers/CandlestickRenderer.js +0 -98
- package/dist/renderers/CandlestickRenderer.js.map +0 -1
- package/dist/renderers/HistogramRenderer.js +0 -50
- package/dist/renderers/HistogramRenderer.js.map +0 -1
- package/dist/renderers/LineRenderer.js +0 -64
- package/dist/renderers/LineRenderer.js.map +0 -1
- package/dist/theme/colors.js +0 -19
- package/dist/theme/colors.js.map +0 -1
- package/dist/tools/barDivergenceCheck.js +0 -200
- package/dist/tools/barDivergenceCheck.js.map +0 -1
- package/dist/trading/TradingOverlayStore.js +0 -139
- package/dist/trading/TradingOverlayStore.js.map +0 -1
- package/dist/trading/UnmanagedIngestion.js +0 -114
- package/dist/trading/UnmanagedIngestion.js.map +0 -1
- package/dist/trading/__tests__/ManagedTradingController.test.js +0 -271
- package/dist/trading/__tests__/ManagedTradingController.test.js.map +0 -1
- package/dist/trading/__tests__/TradingOverlayStore.test.js +0 -267
- package/dist/trading/__tests__/TradingOverlayStore.test.js.map +0 -1
- package/dist/trading/__tests__/UnmanagedIngestion.test.js +0 -170
- package/dist/trading/__tests__/UnmanagedIngestion.test.js.map +0 -1
- package/dist/trading/managed/ManagedTradingController.js +0 -247
- package/dist/trading/managed/ManagedTradingController.js.map +0 -1
- package/dist/trading/managed/managedCapabilities.js +0 -79
- package/dist/trading/managed/managedCapabilities.js.map +0 -1
- package/dist/trading/managed/managedTypes.js +0 -13
- package/dist/trading/managed/managedTypes.js.map +0 -1
- package/dist/trading/tradingTypes.js +0 -8
- package/dist/trading/tradingTypes.js.map +0 -1
- package/dist/tscript/TScriptIndicator.js +0 -47
- package/dist/tscript/TScriptIndicator.js.map +0 -1
- package/dist/tscript/ast.js +0 -22
- package/dist/tscript/ast.js.map +0 -1
- package/dist/tscript/lexer.js +0 -187
- package/dist/tscript/lexer.js.map +0 -1
- package/dist/tscript/parser.js +0 -318
- package/dist/tscript/parser.js.map +0 -1
- package/dist/tscript/runtime.js +0 -475
- package/dist/tscript/runtime.js.map +0 -1
- package/dist/tscript/series.js +0 -79
- package/dist/tscript/series.js.map +0 -1
- package/dist/types/IChart.js +0 -2
- package/dist/types/IChart.js.map +0 -1
- package/dist/types/IRenderer.js +0 -2
- package/dist/types/IRenderer.js.map +0 -1
- package/dist/types/ISeries.js +0 -2
- package/dist/types/ISeries.js.map +0 -1
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
/**
|
|
3
|
-
* FloatingPanel — a draggable, resizable floating panel shell.
|
|
4
|
-
*
|
|
5
|
-
* Renders `position: fixed` with a title bar (drag to move) and 8 resize
|
|
6
|
-
* handles (edges + corners). Pass panel content as `children`.
|
|
7
|
-
*/
|
|
8
|
-
import { useRef, useState } from 'react';
|
|
9
|
-
export function FloatingPanel({ title, onClose, defaultWidth = 380, defaultHeight = 520, minWidth = 200, minHeight = 120, children, }) {
|
|
10
|
-
const [pos, setPos] = useState(() => ({
|
|
11
|
-
x: Math.max(0, window.innerWidth - defaultWidth - 24),
|
|
12
|
-
y: 72,
|
|
13
|
-
}));
|
|
14
|
-
const [size, setSize] = useState({ w: defaultWidth, h: defaultHeight });
|
|
15
|
-
// Refs capture drag-start values to avoid stale-closure accumulation
|
|
16
|
-
const moveRef = useRef(null);
|
|
17
|
-
const resizeRef = useRef(null);
|
|
18
|
-
// ── Drag to move ──────────────────────────────────────────────────────────
|
|
19
|
-
const startMove = (e) => {
|
|
20
|
-
if (e.target.closest('.fp-close'))
|
|
21
|
-
return;
|
|
22
|
-
e.preventDefault();
|
|
23
|
-
moveRef.current = { ox: e.clientX, oy: e.clientY, px: pos.x, py: pos.y };
|
|
24
|
-
const onMove = (ev) => {
|
|
25
|
-
if (!moveRef.current)
|
|
26
|
-
return;
|
|
27
|
-
setPos({
|
|
28
|
-
x: moveRef.current.px + ev.clientX - moveRef.current.ox,
|
|
29
|
-
y: moveRef.current.py + ev.clientY - moveRef.current.oy,
|
|
30
|
-
});
|
|
31
|
-
};
|
|
32
|
-
const onUp = () => {
|
|
33
|
-
moveRef.current = null;
|
|
34
|
-
window.removeEventListener('mousemove', onMove);
|
|
35
|
-
window.removeEventListener('mouseup', onUp);
|
|
36
|
-
};
|
|
37
|
-
window.addEventListener('mousemove', onMove);
|
|
38
|
-
window.addEventListener('mouseup', onUp);
|
|
39
|
-
};
|
|
40
|
-
// ── Resize from any edge/corner ───────────────────────────────────────────
|
|
41
|
-
const startResize = (e, edges) => {
|
|
42
|
-
e.preventDefault();
|
|
43
|
-
e.stopPropagation();
|
|
44
|
-
resizeRef.current = {
|
|
45
|
-
edges,
|
|
46
|
-
ox: e.clientX, oy: e.clientY,
|
|
47
|
-
pw: size.w, ph: size.h,
|
|
48
|
-
px: pos.x, py: pos.y,
|
|
49
|
-
};
|
|
50
|
-
const onMove = (ev) => {
|
|
51
|
-
if (!resizeRef.current)
|
|
52
|
-
return;
|
|
53
|
-
const { edges: ed, ox, oy, pw, ph, px, py } = resizeRef.current;
|
|
54
|
-
const dx = ev.clientX - ox;
|
|
55
|
-
const dy = ev.clientY - oy;
|
|
56
|
-
let nx = px, ny = py, nw = pw, nh = ph;
|
|
57
|
-
if (ed.includes('e'))
|
|
58
|
-
nw = Math.max(minWidth, pw + dx);
|
|
59
|
-
if (ed.includes('s'))
|
|
60
|
-
nh = Math.max(minHeight, ph + dy);
|
|
61
|
-
if (ed.includes('w')) {
|
|
62
|
-
nw = Math.max(minWidth, pw - dx);
|
|
63
|
-
nx = px + pw - nw;
|
|
64
|
-
}
|
|
65
|
-
if (ed.includes('n')) {
|
|
66
|
-
nh = Math.max(minHeight, ph - dy);
|
|
67
|
-
ny = py + ph - nh;
|
|
68
|
-
}
|
|
69
|
-
setSize({ w: nw, h: nh });
|
|
70
|
-
setPos({ x: nx, y: ny });
|
|
71
|
-
};
|
|
72
|
-
const onUp = () => {
|
|
73
|
-
resizeRef.current = null;
|
|
74
|
-
window.removeEventListener('mousemove', onMove);
|
|
75
|
-
window.removeEventListener('mouseup', onUp);
|
|
76
|
-
};
|
|
77
|
-
window.addEventListener('mousemove', onMove);
|
|
78
|
-
window.addEventListener('mouseup', onUp);
|
|
79
|
-
};
|
|
80
|
-
return (_jsxs("div", { className: "fp-shell", style: { left: pos.x, top: pos.y, width: size.w, height: size.h }, children: [_jsxs("div", { className: "fp-titlebar", onMouseDown: startMove, children: [_jsx("span", { className: "fp-title", children: title }), _jsx("button", { className: "fp-close", onClick: onClose, title: "Close", children: _jsxs("svg", { viewBox: "0 0 14 14", width: "12", height: "12", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", children: [_jsx("line", { x1: "2", y1: "2", x2: "12", y2: "12" }), _jsx("line", { x1: "12", y1: "2", x2: "2", y2: "12" })] }) })] }), _jsx("div", { className: "fp-content", children: children }), _jsx("div", { className: "fp-resize fp-resize-n", onMouseDown: (e) => startResize(e, 'n') }), _jsx("div", { className: "fp-resize fp-resize-s", onMouseDown: (e) => startResize(e, 's') }), _jsx("div", { className: "fp-resize fp-resize-e", onMouseDown: (e) => startResize(e, 'e') }), _jsx("div", { className: "fp-resize fp-resize-w", onMouseDown: (e) => startResize(e, 'w') }), _jsx("div", { className: "fp-resize fp-resize-nw", onMouseDown: (e) => startResize(e, 'nw') }), _jsx("div", { className: "fp-resize fp-resize-ne", onMouseDown: (e) => startResize(e, 'ne') }), _jsx("div", { className: "fp-resize fp-resize-sw", onMouseDown: (e) => startResize(e, 'sw') }), _jsx("div", { className: "fp-resize fp-resize-se", onMouseDown: (e) => startResize(e, 'se') })] }));
|
|
81
|
-
}
|
|
82
|
-
//# sourceMappingURL=FloatingPanel.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"FloatingPanel.js","sourceRoot":"","sources":["../../../src/react/workspace/FloatingPanel.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { useState, useEffect, useRef } from 'react';
|
|
3
|
-
const CATEGORIES = ['All', 'Trend', 'Momentum', 'Volume', 'Volatility'];
|
|
4
|
-
// Sorted alphabetically by label
|
|
5
|
-
const CATALOGUE = [
|
|
6
|
-
{
|
|
7
|
-
type: 'atr',
|
|
8
|
-
label: 'ATR',
|
|
9
|
-
description: 'Average True Range — measures market volatility as the average of true ranges.',
|
|
10
|
-
author: 'ForgeCharts',
|
|
11
|
-
category: 'Volatility',
|
|
12
|
-
defaultConfig: { type: 'atr', params: { period: 14 }, overlay: false },
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
type: 'bbands',
|
|
16
|
-
label: 'Bollinger Bands',
|
|
17
|
-
description: 'Volatility bands placed above and below an SMA at ±N standard deviations.',
|
|
18
|
-
author: 'ForgeCharts',
|
|
19
|
-
category: 'Trend',
|
|
20
|
-
defaultConfig: { type: 'bbands', params: { period: 20, multiplier: 2 }, overlay: true },
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
type: 'ema',
|
|
24
|
-
label: 'EMA',
|
|
25
|
-
description: 'Exponential Moving Average — weights recent bars more heavily.',
|
|
26
|
-
author: 'ForgeCharts',
|
|
27
|
-
category: 'Trend',
|
|
28
|
-
defaultConfig: { type: 'ema', params: { period: 20 }, overlay: true },
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
type: 'macd',
|
|
32
|
-
label: 'MACD',
|
|
33
|
-
description: 'Moving Average Convergence/Divergence — trend-following momentum oscillator.',
|
|
34
|
-
author: 'ForgeCharts',
|
|
35
|
-
category: 'Momentum',
|
|
36
|
-
defaultConfig: { type: 'macd', params: { fast: 12, slow: 26, signal: 9 }, overlay: false },
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
type: 'obv',
|
|
40
|
-
label: 'OBV',
|
|
41
|
-
description: 'On-Balance Volume — running tally that adds/subtracts volume based on direction.',
|
|
42
|
-
author: 'ForgeCharts',
|
|
43
|
-
category: 'Volume',
|
|
44
|
-
defaultConfig: { type: 'obv', overlay: false },
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
type: 'rsi',
|
|
48
|
-
label: 'RSI',
|
|
49
|
-
description: 'Relative Strength Index — measures speed and magnitude of price changes (0–100).',
|
|
50
|
-
author: 'ForgeCharts',
|
|
51
|
-
category: 'Momentum',
|
|
52
|
-
defaultConfig: { type: 'rsi', params: { period: 14 }, overlay: false },
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
type: 'sma',
|
|
56
|
-
label: 'SMA',
|
|
57
|
-
description: 'Simple Moving Average — average closing price over N bars.',
|
|
58
|
-
author: 'ForgeCharts',
|
|
59
|
-
category: 'Trend',
|
|
60
|
-
defaultConfig: { type: 'sma', params: { period: 20 }, overlay: true },
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
type: 'stochastic',
|
|
64
|
-
label: 'Stochastic',
|
|
65
|
-
description: 'Stochastic Oscillator — compares closing price to high-low range over N bars.',
|
|
66
|
-
author: 'ForgeCharts',
|
|
67
|
-
category: 'Momentum',
|
|
68
|
-
defaultConfig: { type: 'stochastic', params: { k: 14, d: 3 }, overlay: false },
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
type: 'volume',
|
|
72
|
-
label: 'Volume',
|
|
73
|
-
description: 'Bar volume rendered as a histogram in a separate sub-pane.',
|
|
74
|
-
author: 'ForgeCharts',
|
|
75
|
-
category: 'Volume',
|
|
76
|
-
defaultConfig: { type: 'volume', overlay: false },
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
type: 'wma',
|
|
80
|
-
label: 'WMA',
|
|
81
|
-
description: 'Weighted Moving Average — linearly weighted toward recent bars.',
|
|
82
|
-
author: 'ForgeCharts',
|
|
83
|
-
category: 'Trend',
|
|
84
|
-
defaultConfig: { type: 'wma', params: { period: 20 }, overlay: true },
|
|
85
|
-
},
|
|
86
|
-
];
|
|
87
|
-
// ── Component ─────────────────────────────────────────────────────────────────
|
|
88
|
-
export function IndicatorsDialog({ onAdd, onClose }) {
|
|
89
|
-
const [category, setCategory] = useState('All');
|
|
90
|
-
const [query, setQuery] = useState('');
|
|
91
|
-
const [added, setAdded] = useState(null);
|
|
92
|
-
const dialogRef = useRef(null);
|
|
93
|
-
const inputRef = useRef(null);
|
|
94
|
-
useEffect(() => { inputRef.current?.focus(); }, []);
|
|
95
|
-
useEffect(() => {
|
|
96
|
-
const handler = (e) => { if (e.key === 'Escape')
|
|
97
|
-
onClose(); };
|
|
98
|
-
window.addEventListener('keydown', handler);
|
|
99
|
-
return () => window.removeEventListener('keydown', handler);
|
|
100
|
-
}, [onClose]);
|
|
101
|
-
const handleBackdrop = (e) => {
|
|
102
|
-
if (dialogRef.current && !dialogRef.current.contains(e.target))
|
|
103
|
-
onClose();
|
|
104
|
-
};
|
|
105
|
-
const q = query.trim().toLowerCase();
|
|
106
|
-
const visible = CATALOGUE.filter((entry) => {
|
|
107
|
-
const matchesCat = category === 'All' || entry.category === category;
|
|
108
|
-
const matchesQ = !q || entry.label.toLowerCase().includes(q) || entry.description.toLowerCase().includes(q);
|
|
109
|
-
return matchesCat && matchesQ;
|
|
110
|
-
});
|
|
111
|
-
const handleAdd = (entry) => {
|
|
112
|
-
onAdd(entry.defaultConfig);
|
|
113
|
-
setAdded(entry.type);
|
|
114
|
-
setTimeout(() => setAdded(null), 1400);
|
|
115
|
-
};
|
|
116
|
-
return (_jsx("div", { className: "ind-backdrop", onMouseDown: handleBackdrop, children: _jsxs("div", { className: "ind-dialog", ref: dialogRef, role: "dialog", "aria-modal": "true", "aria-label": "Indicators", children: [_jsxs("div", { className: "ind-header", children: [_jsx("span", { className: "ind-title", children: "Indicators" }), _jsx("button", { className: "ind-close", onClick: onClose, "aria-label": "Close", children: _jsxs("svg", { viewBox: "0 0 14 14", width: "12", height: "12", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", fill: "none", children: [_jsx("line", { x1: "2", y1: "2", x2: "12", y2: "12" }), _jsx("line", { x1: "12", y1: "2", x2: "2", y2: "12" })] }) })] }), _jsxs("div", { className: "ind-search-row", children: [_jsxs("svg", { viewBox: "0 0 16 16", width: "13", height: "13", stroke: "currentColor", fill: "none", strokeWidth: "1.8", strokeLinecap: "round", style: { opacity: 0.5, flexShrink: 0 }, children: [_jsx("circle", { cx: "6.5", cy: "6.5", r: "4.5" }), _jsx("line", { x1: "10.5", y1: "10.5", x2: "14", y2: "14" })] }), _jsx("input", { ref: inputRef, className: "ind-search-input", type: "text", value: query, onChange: (e) => setQuery(e.target.value), placeholder: "Search indicators\u2026", autoComplete: "off", spellCheck: false }), query && (_jsx("button", { className: "ind-search-clear", onClick: () => setQuery(''), "aria-label": "Clear", children: _jsxs("svg", { viewBox: "0 0 12 12", width: "10", height: "10", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", fill: "none", children: [_jsx("line", { x1: "2", y1: "2", x2: "10", y2: "10" }), _jsx("line", { x1: "10", y1: "2", x2: "2", y2: "10" })] }) }))] }), _jsx("div", { className: "ind-tabs", children: CATEGORIES.map((cat) => (_jsx("button", { className: `ind-tab${cat === category ? ' active' : ''}`, onClick: () => setCategory(cat), children: cat }, cat))) }), _jsx("div", { className: "ind-list-wrap", children: visible.length === 0 ? (_jsxs("div", { className: "ind-empty", children: ["No indicators match \"", query, "\""] })) : (_jsxs(_Fragment, { children: [_jsxs("div", { className: "ind-section-hdr", children: [_jsx("span", { children: "Built-in" }), _jsx("span", { className: "ind-section-count", children: visible.length })] }), visible.map((entry) => {
|
|
117
|
-
const isAdded = added === entry.type;
|
|
118
|
-
return (_jsxs("button", { className: `ind-list-row${isAdded ? ' added' : ''}`, onClick: () => handleAdd(entry), children: [_jsxs("div", { className: "ind-list-info", children: [_jsx("span", { className: "ind-list-name", children: entry.label }), _jsxs("span", { className: "ind-list-meta", children: [entry.author, " \u00B7 ", entry.category] })] }), _jsx("span", { className: `ind-list-badge${entry.defaultConfig.overlay ? ' overlay' : ' pane'}`, children: entry.defaultConfig.overlay ? 'Overlay' : 'Pane' }), _jsx("span", { className: "ind-list-add", children: isAdded ? (_jsxs(_Fragment, { children: [_jsx("svg", { viewBox: "0 0 12 10", width: "11", height: "10", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", fill: "none", children: _jsx("polyline", { points: "1,5 4,8 11,1" }) }), "Added"] })) : (_jsxs(_Fragment, { children: [_jsxs("svg", { viewBox: "0 0 12 12", width: "11", height: "11", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", fill: "none", children: [_jsx("line", { x1: "6", y1: "1", x2: "6", y2: "11" }), _jsx("line", { x1: "1", y1: "6", x2: "11", y2: "6" })] }), "Add to Chart"] })) })] }, entry.type));
|
|
119
|
-
})] })) })] }) }));
|
|
120
|
-
}
|
|
121
|
-
//# sourceMappingURL=IndicatorsDialog.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"IndicatorsDialog.js","sourceRoot":"","sources":["../../../src/react/workspace/IndicatorsDialog.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useRef, useState } from 'react';
|
|
3
|
-
export function LayoutMenu({ currentName, currentLayoutId, autoSave, onFetchLayouts, onSave, onLoad, onRename, onCopy, onToggleAutoSave, onDelete, onOpenInNewTab, }) {
|
|
4
|
-
const [open, setOpen] = useState(false);
|
|
5
|
-
const [view, setView] = useState('menu');
|
|
6
|
-
const [inputVal, setInputVal] = useState('');
|
|
7
|
-
const [busy, setBusy] = useState(false);
|
|
8
|
-
const [error, setError] = useState(null);
|
|
9
|
-
const [layouts, setLayouts] = useState([]);
|
|
10
|
-
const [loadError, setLoadError] = useState(null);
|
|
11
|
-
const [fetching, setFetching] = useState(false);
|
|
12
|
-
const [confirmDelete, setConfirmDelete] = useState(null);
|
|
13
|
-
const menuRef = useRef(null);
|
|
14
|
-
// Close on outside click
|
|
15
|
-
useEffect(() => {
|
|
16
|
-
if (!open)
|
|
17
|
-
return;
|
|
18
|
-
const handler = (e) => {
|
|
19
|
-
if (menuRef.current && !menuRef.current.contains(e.target)) {
|
|
20
|
-
setOpen(false);
|
|
21
|
-
setView('menu');
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
document.addEventListener('mousedown', handler);
|
|
25
|
-
return () => document.removeEventListener('mousedown', handler);
|
|
26
|
-
}, [open]);
|
|
27
|
-
// Fetch saved layouts when menu opens
|
|
28
|
-
useEffect(() => {
|
|
29
|
-
if (!open)
|
|
30
|
-
return;
|
|
31
|
-
setLoadError(null);
|
|
32
|
-
setFetching(true);
|
|
33
|
-
onFetchLayouts()
|
|
34
|
-
.then(setLayouts)
|
|
35
|
-
.catch((err) => setLoadError(err.message))
|
|
36
|
-
.finally(() => setFetching(false));
|
|
37
|
-
}, [open]);
|
|
38
|
-
const isSaved = !!currentLayoutId;
|
|
39
|
-
function openMenu() {
|
|
40
|
-
setError(null);
|
|
41
|
-
setView('menu');
|
|
42
|
-
setOpen((o) => !o);
|
|
43
|
-
}
|
|
44
|
-
function startView(v, prefill) {
|
|
45
|
-
setInputVal(prefill);
|
|
46
|
-
setError(null);
|
|
47
|
-
setView(v);
|
|
48
|
-
}
|
|
49
|
-
async function handleSubmit(action) {
|
|
50
|
-
const name = inputVal.trim();
|
|
51
|
-
if (!name)
|
|
52
|
-
return;
|
|
53
|
-
setBusy(true);
|
|
54
|
-
setError(null);
|
|
55
|
-
try {
|
|
56
|
-
await action(name);
|
|
57
|
-
setOpen(false);
|
|
58
|
-
setView('menu');
|
|
59
|
-
}
|
|
60
|
-
catch (err) {
|
|
61
|
-
setError(err instanceof Error ? err.message : 'Action failed');
|
|
62
|
-
}
|
|
63
|
-
finally {
|
|
64
|
-
setBusy(false);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
async function handleLoad(id) {
|
|
68
|
-
setOpen(false);
|
|
69
|
-
try {
|
|
70
|
-
await onLoad(id);
|
|
71
|
-
}
|
|
72
|
-
catch (err) {
|
|
73
|
-
// Silently ignore — App.tsx surfaces errors via tab state
|
|
74
|
-
console.error('Load layout error:', err);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
async function handleOpenInNewTabLocal(id) {
|
|
78
|
-
setOpen(false);
|
|
79
|
-
try {
|
|
80
|
-
await onOpenInNewTab(id);
|
|
81
|
-
}
|
|
82
|
-
catch (err) {
|
|
83
|
-
console.error('Open layout in new tab error:', err);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
async function handleConfirmDelete() {
|
|
87
|
-
if (!confirmDelete)
|
|
88
|
-
return;
|
|
89
|
-
try {
|
|
90
|
-
await onDelete(confirmDelete.id);
|
|
91
|
-
setLayouts((prev) => prev.filter((l) => l.id !== confirmDelete.id));
|
|
92
|
-
setConfirmDelete(null);
|
|
93
|
-
}
|
|
94
|
-
catch {
|
|
95
|
-
setConfirmDelete(null);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
function fmtError(msg) {
|
|
99
|
-
return msg.includes('401') || msg.includes('Missing authorization')
|
|
100
|
-
? 'Sign in to use layouts'
|
|
101
|
-
: msg;
|
|
102
|
-
}
|
|
103
|
-
function renderForm(label, placeholder, action, note) {
|
|
104
|
-
return (_jsxs("div", { className: "layout-save-form", children: [_jsx("div", { className: "layout-save-label", children: label }), note && _jsx("div", { className: "layout-dropdown-empty", style: { padding: '0 0 4px' }, children: note }), _jsx("input", { className: "layout-save-input", value: inputVal, onChange: (e) => setInputVal(e.target.value), onKeyDown: (e) => {
|
|
105
|
-
if (e.key === 'Enter')
|
|
106
|
-
handleSubmit(action);
|
|
107
|
-
if (e.key === 'Escape')
|
|
108
|
-
setView('menu');
|
|
109
|
-
}, placeholder: placeholder, autoFocus: true }), error && (_jsx("div", { className: "layout-dropdown-error", style: { padding: 0, fontSize: 11 }, children: fmtError(error) })), _jsxs("div", { className: "layout-save-actions", children: [_jsx("button", { onClick: () => setView('menu'), children: "Cancel" }), _jsx("button", { className: inputVal.trim() && !busy ? 'active' : undefined, onClick: () => handleSubmit(action), disabled: busy || !inputVal.trim(), children: busy ? 'Saving…' : 'Save' })] })] }));
|
|
110
|
-
}
|
|
111
|
-
return (_jsxs("div", { className: "layout-menu-root", ref: menuRef, children: [_jsxs("button", { className: open ? 'active' : undefined, onClick: openMenu, title: "Manage chart layouts", style: { display: 'flex', alignItems: 'center', gap: 4 }, children: [_jsxs("svg", { viewBox: "0 0 14 14", width: "12", height: "12", fill: "currentColor", children: [_jsx("rect", { x: "1", y: "1", width: "5", height: "5", rx: "1" }), _jsx("rect", { x: "8", y: "1", width: "5", height: "5", rx: "1" }), _jsx("rect", { x: "1", y: "8", width: "5", height: "5", rx: "1" }), _jsx("rect", { x: "8", y: "8", width: "5", height: "5", rx: "1" })] }), currentName ?? 'Layout', " \u25BE", autoSave && isSaved && (_jsx("span", { className: "layout-autosave-dot", title: "Auto-save enabled" }))] }), open && (_jsxs("div", { className: "layout-dropdown", children: [view === 'menu' && (_jsxs(_Fragment, { children: [_jsxs("label", { className: "layout-dropdown-item layout-autosave-row", children: [_jsxs("svg", { className: "layout-menu-icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("polyline", { points: "23 4 23 10 17 10" }), _jsx("path", { d: "M20.49 15a9 9 0 1 1-2.12-9.36L23 10" })] }), "Auto-save", _jsxs("span", { className: "layout-autosave-status", children: [autoSave && isSaved && _jsx("span", { style: { color: 'var(--up)' }, children: "ON" }), autoSave && !isSaved && _jsx("span", { style: { color: 'var(--text-muted)' }, children: "save first" })] }), _jsx("span", { className: `layout-toggle-switch${autoSave ? ' on' : ''}`, onClick: (e) => { e.preventDefault(); onToggleAutoSave(!autoSave); }, role: "switch", "aria-checked": autoSave, children: _jsx("span", { className: "layout-toggle-thumb" }) })] }), _jsx("div", { className: "layout-dropdown-divider" }), _jsxs("button", { className: "layout-dropdown-item", onClick: () => startView('save', currentName ?? ''), children: [_jsxs("svg", { className: "layout-menu-icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("path", { d: "M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z" }), _jsx("polyline", { points: "17 21 17 13 7 13 7 21" }), _jsx("polyline", { points: "7 3 7 8 15 8" })] }), "Save layout\u2026"] }), isSaved && (_jsxs("button", { className: "layout-dropdown-item", onClick: () => startView('rename', currentName ?? ''), children: [_jsxs("svg", { className: "layout-menu-icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("path", { d: "M12 20h9" }), _jsx("path", { d: "M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4 12.5-12.5z" })] }), "Rename\u2026"] })), _jsxs("button", { className: "layout-dropdown-item", onClick: () => startView('copy', `${currentName ?? 'Layout'} copy`), children: [_jsxs("svg", { className: "layout-menu-icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", ry: "2" }), _jsx("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })] }), "Copy layout\u2026"] }), _jsx("div", { className: "layout-dropdown-divider" }), fetching && _jsx("div", { className: "layout-dropdown-empty", children: "Loading\u2026" }), !fetching && loadError && (_jsx("div", { className: "layout-dropdown-error", children: fmtError(loadError) })), !fetching && !loadError && layouts.length === 0 && (_jsx("div", { className: "layout-dropdown-empty", children: "No saved layouts yet" })), !fetching && !loadError && layouts.length > 0 && (_jsxs(_Fragment, { children: [_jsx("div", { className: "layout-dropdown-section", children: "Saved layouts" }), layouts.map((l) => (_jsxs("div", { style: { display: 'flex', alignItems: 'center' }, children: [_jsxs("button", { className: `layout-dropdown-item${l.id === currentLayoutId ? ' layout-dropdown-item--current' : ''}`, onClick: () => l.id === currentLayoutId ? handleLoad(l.id) : handleOpenInNewTabLocal(l.id), title: `${l.symbol} · ${l.timeframe} · ${new Date(l.updated_at).toLocaleDateString()}`, style: { flex: 1, textAlign: 'left' }, children: [l.id === currentLayoutId ? (_jsx("svg", { className: "layout-menu-icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: _jsx("polyline", { points: "20 6 9 17 4 12" }) })) : (_jsx("svg", { className: "layout-menu-icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: _jsx("path", { d: "M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z" }) })), _jsx("span", { style: { overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', minWidth: 0 }, children: l.name })] }), _jsx("button", { onClick: (e) => { e.stopPropagation(); setConfirmDelete({ id: l.id, name: l.name }); }, title: "Delete layout", style: { padding: '4px 8px', opacity: 0.45, flexShrink: 0, lineHeight: 1, width: 'auto' }, className: "layout-dropdown-item", children: "\u2715" })] }, l.id)))] })), confirmDelete && (_jsxs("div", { style: { padding: '8px 12px', borderTop: '1px solid var(--border)' }, children: [_jsxs("div", { style: { fontSize: 12, marginBottom: 8 }, children: ["Delete ", _jsx("strong", { children: confirmDelete.name }), "? This cannot be undone."] }), _jsxs("div", { style: { display: 'flex', gap: 6, justifyContent: 'flex-end' }, children: [_jsx("button", { onClick: () => setConfirmDelete(null), children: "Cancel" }), _jsx("button", { onClick: handleConfirmDelete, style: { color: 'var(--down, #ef5350)' }, children: "Delete" })] })] }))] })), view === 'save' && renderForm('Layout name', 'My layout', onSave), view === 'rename' && renderForm('Rename layout', currentName ?? 'Layout', onRename), view === 'copy' && renderForm('Copy to new layout', `${currentName ?? 'Layout'} copy`, onCopy, 'Creates a copy of the current layout in a new tab.')] }))] }));
|
|
112
|
-
}
|
|
113
|
-
//# sourceMappingURL=LayoutMenu.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"LayoutMenu.js","sourceRoot":"","sources":["../../../src/react/workspace/LayoutMenu.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,245 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useState, useEffect, useRef, useCallback } from 'react';
|
|
3
|
-
const PAGE_SIZE = 100;
|
|
4
|
-
const TABS = [
|
|
5
|
-
{ label: 'All', market: '' },
|
|
6
|
-
{ label: 'Stocks', market: 'stocks' },
|
|
7
|
-
{ label: 'Funds', market: 'etfs' },
|
|
8
|
-
{ label: 'Futures', market: 'futures' },
|
|
9
|
-
{ label: 'Forex', market: 'forex' },
|
|
10
|
-
{ label: 'Crypto', market: 'crypto' },
|
|
11
|
-
{ label: 'Indices', market: 'indices' },
|
|
12
|
-
{ label: 'Bonds', market: 'bonds' },
|
|
13
|
-
{ label: 'Economy', market: 'economy' },
|
|
14
|
-
{ label: 'Options', market: 'options' },
|
|
15
|
-
];
|
|
16
|
-
function refSymbolsToEntries(symbols) {
|
|
17
|
-
return symbols.map(s => ({
|
|
18
|
-
symbol: s.symbol,
|
|
19
|
-
name: s.displayName,
|
|
20
|
-
symbolKey: s.symbolKey,
|
|
21
|
-
exchange: s.exchange,
|
|
22
|
-
assetType: s.assetType,
|
|
23
|
-
market: s.market,
|
|
24
|
-
...(s.logoUrl ? { logoUrl: s.logoUrl } : {}),
|
|
25
|
-
}));
|
|
26
|
-
}
|
|
27
|
-
function stringColor(str) {
|
|
28
|
-
const palette = [
|
|
29
|
-
'#f7931a', '#627eea', '#2775ca', '#26a17b', '#e84142',
|
|
30
|
-
'#00adef', '#e91e63', '#9945ff', '#00d4aa', '#ff6b35',
|
|
31
|
-
];
|
|
32
|
-
let h = 0;
|
|
33
|
-
for (let i = 0; i < str.length; i++)
|
|
34
|
-
h = (Math.imul(31, h) + str.charCodeAt(i)) | 0;
|
|
35
|
-
return palette[Math.abs(h) % palette.length] ?? '#888888';
|
|
36
|
-
}
|
|
37
|
-
function badgeLabel(assetType, market) {
|
|
38
|
-
const a = assetType?.toLowerCase() ?? '';
|
|
39
|
-
const m = market?.toLowerCase() ?? '';
|
|
40
|
-
if (a && m && a !== m)
|
|
41
|
-
return `${a} ${m}`;
|
|
42
|
-
return a || m || '';
|
|
43
|
-
}
|
|
44
|
-
function SymbolIcon({ logoUrl, letter, color }) {
|
|
45
|
-
const [failed, setFailed] = useState(false);
|
|
46
|
-
return (_jsx("span", { className: "sym-row-icon", style: { background: (logoUrl && !failed) ? 'transparent' : color }, children: logoUrl && !failed
|
|
47
|
-
? _jsx("img", { src: logoUrl, alt: "", className: "sym-logo-img", onError: () => setFailed(true) })
|
|
48
|
-
: letter }));
|
|
49
|
-
}
|
|
50
|
-
export function SymbolSearchDialog({ current, onSelect, onClose, symbolResolver }) {
|
|
51
|
-
const [query, setQuery] = useState('');
|
|
52
|
-
const [activeTab, setActiveTab] = useState(0);
|
|
53
|
-
const [tabSymbols, setTabSymbols] = useState([]);
|
|
54
|
-
const [tabLoading, setTabLoading] = useState(false);
|
|
55
|
-
const [tabLoadingMore, setTabLoadingMore] = useState(false);
|
|
56
|
-
const [tabOffset, setTabOffset] = useState(0);
|
|
57
|
-
const [tabHasMore, setTabHasMore] = useState(false);
|
|
58
|
-
const [searchResults, setSearchResults] = useState(null);
|
|
59
|
-
const [isSearching, setIsSearching] = useState(false);
|
|
60
|
-
const [searchingMore, setSearchingMore] = useState(false);
|
|
61
|
-
const [searchOffset, setSearchOffset] = useState(0);
|
|
62
|
-
const [searchHasMore, setSearchHasMore] = useState(false);
|
|
63
|
-
const inputRef = useRef(null);
|
|
64
|
-
const dialogRef = useRef(null);
|
|
65
|
-
const sentinelRef = useRef(null);
|
|
66
|
-
const searchTimer = useRef(null);
|
|
67
|
-
const queryRef = useRef(query);
|
|
68
|
-
const activeTabRef = useRef(activeTab);
|
|
69
|
-
queryRef.current = query;
|
|
70
|
-
activeTabRef.current = activeTab;
|
|
71
|
-
useEffect(() => { inputRef.current?.focus(); }, []);
|
|
72
|
-
useEffect(() => {
|
|
73
|
-
const h = (e) => { if (e.key === 'Escape')
|
|
74
|
-
onClose(); };
|
|
75
|
-
window.addEventListener('keydown', h);
|
|
76
|
-
return () => window.removeEventListener('keydown', h);
|
|
77
|
-
}, [onClose]);
|
|
78
|
-
// Tab browse: use getSymbols() for all tabs — supports offset pagination.
|
|
79
|
-
useEffect(() => {
|
|
80
|
-
const market = TABS[activeTab]?.market ?? '';
|
|
81
|
-
let cancelled = false;
|
|
82
|
-
setTabLoading(true);
|
|
83
|
-
setTabSymbols([]);
|
|
84
|
-
setTabOffset(0);
|
|
85
|
-
setTabHasMore(false);
|
|
86
|
-
symbolResolver.getSymbols({ ...(market ? { market } : {}), limit: PAGE_SIZE, offset: 0 })
|
|
87
|
-
.then((r) => {
|
|
88
|
-
if (!cancelled) {
|
|
89
|
-
setTabSymbols(refSymbolsToEntries(r.symbols));
|
|
90
|
-
setTabHasMore(r.symbols.length === PAGE_SIZE);
|
|
91
|
-
setTabOffset(PAGE_SIZE);
|
|
92
|
-
}
|
|
93
|
-
})
|
|
94
|
-
.catch(() => { })
|
|
95
|
-
.finally(() => { if (!cancelled)
|
|
96
|
-
setTabLoading(false); });
|
|
97
|
-
return () => { cancelled = true; };
|
|
98
|
-
}, [activeTab]);
|
|
99
|
-
const loadMoreTab = useCallback(async () => {
|
|
100
|
-
if (tabLoadingMore || !tabHasMore)
|
|
101
|
-
return;
|
|
102
|
-
const market = TABS[activeTabRef.current]?.market ?? '';
|
|
103
|
-
setTabLoadingMore(true);
|
|
104
|
-
try {
|
|
105
|
-
const r = await symbolResolver.getSymbols({ ...(market ? { market } : {}), limit: PAGE_SIZE, offset: tabOffset });
|
|
106
|
-
setTabSymbols(prev => [...prev, ...refSymbolsToEntries(r.symbols)]);
|
|
107
|
-
setTabHasMore(r.symbols.length === PAGE_SIZE);
|
|
108
|
-
setTabOffset(prev => prev + PAGE_SIZE);
|
|
109
|
-
}
|
|
110
|
-
catch { /* ignore */ }
|
|
111
|
-
finally {
|
|
112
|
-
setTabLoadingMore(false);
|
|
113
|
-
}
|
|
114
|
-
}, [tabLoadingMore, tabHasMore, tabOffset]);
|
|
115
|
-
const loadMoreSearch = useCallback(async () => {
|
|
116
|
-
if (searchingMore || !searchHasMore)
|
|
117
|
-
return;
|
|
118
|
-
const q = queryRef.current.trim();
|
|
119
|
-
if (!q)
|
|
120
|
-
return;
|
|
121
|
-
const market = TABS[activeTabRef.current]?.market;
|
|
122
|
-
setSearchingMore(true);
|
|
123
|
-
try {
|
|
124
|
-
const res = await symbolResolver.searchSymbols(q, {
|
|
125
|
-
limit: PAGE_SIZE, offset: searchOffset,
|
|
126
|
-
...(market ? { market } : {}),
|
|
127
|
-
});
|
|
128
|
-
setSearchResults(prev => prev ? [...prev, ...refSymbolsToEntries(res.symbols)] : refSymbolsToEntries(res.symbols));
|
|
129
|
-
setSearchHasMore(res.symbols.length === PAGE_SIZE);
|
|
130
|
-
setSearchOffset(prev => prev + PAGE_SIZE);
|
|
131
|
-
}
|
|
132
|
-
catch { /* ignore */ }
|
|
133
|
-
finally {
|
|
134
|
-
setSearchingMore(false);
|
|
135
|
-
}
|
|
136
|
-
}, [searchingMore, searchHasMore, searchOffset]);
|
|
137
|
-
// Stable refs so the IntersectionObserver callback always calls the latest version
|
|
138
|
-
const loadMoreTabRef = useRef(loadMoreTab);
|
|
139
|
-
const loadMoreSearchRef = useRef(loadMoreSearch);
|
|
140
|
-
loadMoreTabRef.current = loadMoreTab;
|
|
141
|
-
loadMoreSearchRef.current = loadMoreSearch;
|
|
142
|
-
// Sentinel IntersectionObserver — fires loadMore when the bottom of the list enters view
|
|
143
|
-
useEffect(() => {
|
|
144
|
-
const sentinel = sentinelRef.current;
|
|
145
|
-
if (!sentinel)
|
|
146
|
-
return;
|
|
147
|
-
const observer = new IntersectionObserver(entries => {
|
|
148
|
-
if (entries[0]?.isIntersecting) {
|
|
149
|
-
if (queryRef.current.trim()) {
|
|
150
|
-
void loadMoreSearchRef.current();
|
|
151
|
-
}
|
|
152
|
-
else {
|
|
153
|
-
void loadMoreTabRef.current();
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}, { threshold: 0.1 });
|
|
157
|
-
observer.observe(sentinel);
|
|
158
|
-
return () => observer.disconnect();
|
|
159
|
-
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
|
160
|
-
const doSearch = useCallback((q, tab) => {
|
|
161
|
-
if (searchTimer.current)
|
|
162
|
-
clearTimeout(searchTimer.current);
|
|
163
|
-
if (!q.trim()) {
|
|
164
|
-
setSearchResults(null);
|
|
165
|
-
setSearchOffset(0);
|
|
166
|
-
setSearchHasMore(false);
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
setIsSearching(true);
|
|
170
|
-
searchTimer.current = setTimeout(async () => {
|
|
171
|
-
try {
|
|
172
|
-
const market = TABS[tab]?.market;
|
|
173
|
-
const res = await symbolResolver.searchSymbols(q.trim(), {
|
|
174
|
-
limit: PAGE_SIZE, offset: 0,
|
|
175
|
-
...(market ? { market } : {}),
|
|
176
|
-
});
|
|
177
|
-
setSearchResults(refSymbolsToEntries(res.symbols));
|
|
178
|
-
setSearchHasMore(res.symbols.length === PAGE_SIZE);
|
|
179
|
-
setSearchOffset(PAGE_SIZE);
|
|
180
|
-
}
|
|
181
|
-
catch {
|
|
182
|
-
setSearchResults([]);
|
|
183
|
-
setSearchHasMore(false);
|
|
184
|
-
}
|
|
185
|
-
finally {
|
|
186
|
-
setIsSearching(false);
|
|
187
|
-
}
|
|
188
|
-
}, 180);
|
|
189
|
-
}, []);
|
|
190
|
-
const handleQueryChange = (value) => {
|
|
191
|
-
setQuery(value);
|
|
192
|
-
doSearch(value, activeTab);
|
|
193
|
-
};
|
|
194
|
-
const handleTabChange = (i) => {
|
|
195
|
-
setActiveTab(i);
|
|
196
|
-
if (queryRef.current.trim())
|
|
197
|
-
doSearch(queryRef.current, i);
|
|
198
|
-
};
|
|
199
|
-
const handleBackdrop = (e) => {
|
|
200
|
-
if (dialogRef.current && !dialogRef.current.contains(e.target))
|
|
201
|
-
onClose();
|
|
202
|
-
};
|
|
203
|
-
const isSearch = query.trim().length > 0;
|
|
204
|
-
const displayList = isSearch ? (searchResults ?? []) : tabSymbols;
|
|
205
|
-
// Use exchange:symbol format (strip market prefix from symbolKey) so the
|
|
206
|
-
// datafeed can pass it directly to the TV API, e.g. "BINANCE:BTCUSDT"
|
|
207
|
-
const toFeedSymbol = (entry) => {
|
|
208
|
-
if (!entry.symbolKey)
|
|
209
|
-
return entry.symbol;
|
|
210
|
-
const parts = entry.symbolKey.split(':');
|
|
211
|
-
// symbolKey is MARKET:EXCHANGE:SYMBOL → we want EXCHANGE:SYMBOL
|
|
212
|
-
return parts.length >= 3 ? parts.slice(1).join(':') : entry.symbolKey;
|
|
213
|
-
};
|
|
214
|
-
const pick = (entry) => { onSelect(toFeedSymbol(entry)); onClose(); };
|
|
215
|
-
const renderRow = (entry) => {
|
|
216
|
-
const iconColor = stringColor(entry.symbol);
|
|
217
|
-
const exchColor = stringColor(entry.exchange);
|
|
218
|
-
const letter = entry.symbol.charAt(0).toUpperCase();
|
|
219
|
-
const exchAbbr = entry.exchange.slice(0, 2).toUpperCase();
|
|
220
|
-
const badge = badgeLabel(entry.assetType, entry.market);
|
|
221
|
-
return (_jsxs("button", { className: `sym-row${entry.symbol === current ? ' active' : ''}`, onClick: () => pick(entry), children: [_jsx(SymbolIcon, { letter: letter, color: iconColor, ...(entry.logoUrl ? { logoUrl: entry.logoUrl } : {}) }), _jsxs("span", { className: "sym-row-info", children: [_jsx("span", { className: "sym-row-ticker", children: entry.symbol }), _jsx("span", { className: "sym-row-name", children: entry.name })] }), badge && _jsx("span", { className: "sym-row-badge", children: badge }), _jsx("span", { className: "sym-row-exchange", children: entry.exchange }), _jsx("span", { className: "sym-row-exch-icon", style: { background: exchColor }, children: exchAbbr })] }, entry.symbolKey ?? `${entry.exchange}:${entry.symbol}`));
|
|
222
|
-
};
|
|
223
|
-
const renderDirectRow = () => {
|
|
224
|
-
const q = query.trim();
|
|
225
|
-
if (!q)
|
|
226
|
-
return null;
|
|
227
|
-
return (_jsxs("button", { className: "sym-row", onClick: () => { onSelect(q.toUpperCase()); onClose(); }, style: { borderTop: '1px solid var(--sym-border, rgba(255,255,255,.08))', marginTop: 4 }, children: [_jsx("span", { className: "sym-row-icon", style: { background: '#444', fontSize: 11, fontWeight: 700 }, children: "\u2192" }), _jsxs("span", { className: "sym-row-info", children: [_jsx("span", { className: "sym-row-ticker", children: q.toUpperCase() }), _jsx("span", { className: "sym-row-name", children: "Use this symbol directly" })] })] }));
|
|
228
|
-
};
|
|
229
|
-
const renderBody = () => {
|
|
230
|
-
if (isSearch && isSearching)
|
|
231
|
-
return _jsx("div", { className: "sym-list", children: renderDirectRow() });
|
|
232
|
-
if (isSearch && searchResults !== null && searchResults.length === 0)
|
|
233
|
-
return _jsx("div", { className: "sym-list", children: renderDirectRow() });
|
|
234
|
-
if (!isSearch && tabLoading)
|
|
235
|
-
return _jsx("div", { className: "sym-empty", children: "Loading..." });
|
|
236
|
-
if (displayList.length === 0 && !isSearch && !tabLoading)
|
|
237
|
-
return _jsx("div", { className: "sym-empty", children: "No data \u2014 run a Symbol Sync from the Studio" });
|
|
238
|
-
const loadingMore = isSearch ? searchingMore : tabLoadingMore;
|
|
239
|
-
if (isSearch)
|
|
240
|
-
return (_jsxs("div", { className: "sym-list", children: [displayList.map(renderRow), renderDirectRow(), _jsx("div", { ref: sentinelRef, className: "sym-sentinel" }), loadingMore && _jsx("div", { className: "sym-loading-more", children: "Loading more\u2026" })] }));
|
|
241
|
-
return (_jsxs("div", { className: "sym-list", children: [displayList.map(renderRow), _jsx("div", { ref: sentinelRef, className: "sym-sentinel" }), loadingMore && _jsx("div", { className: "sym-loading-more", children: "Loading more\u2026" })] }));
|
|
242
|
-
};
|
|
243
|
-
return (_jsx("div", { className: "sym-backdrop", onMouseDown: handleBackdrop, children: _jsxs("div", { className: "sym-dialog", ref: dialogRef, role: "dialog", "aria-modal": "true", "aria-label": "Symbol Search", children: [_jsxs("div", { className: "sym-header", children: [_jsx("span", { className: "sym-header-title", children: "Symbol Search" }), _jsx("button", { className: "sym-header-close", onClick: onClose, "aria-label": "Close", children: _jsxs("svg", { viewBox: "0 0 14 14", width: "13", height: "13", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", fill: "none", children: [_jsx("line", { x1: "2", y1: "2", x2: "12", y2: "12" }), _jsx("line", { x1: "12", y1: "2", x2: "2", y2: "12" })] }) })] }), _jsxs("div", { className: "sym-search-row", children: [_jsxs("svg", { className: "sym-search-icon", viewBox: "0 0 16 16", width: "15", height: "15", stroke: "currentColor", fill: "none", strokeWidth: "1.8", strokeLinecap: "round", children: [_jsx("circle", { cx: "6.5", cy: "6.5", r: "4.5" }), _jsx("line", { x1: "10.5", y1: "10.5", x2: "14", y2: "14" })] }), _jsx("input", { ref: inputRef, className: "sym-search-input", type: "text", value: query, onChange: (e) => handleQueryChange(e.target.value), placeholder: "Search symbols or names...", autoComplete: "off", spellCheck: false }), query && (_jsx("button", { className: "sym-search-clear", onClick: () => { setQuery(''); setSearchResults(null); }, "aria-label": "Clear", children: _jsxs("svg", { viewBox: "0 0 12 12", width: "11", height: "11", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", fill: "none", children: [_jsx("line", { x1: "2", y1: "2", x2: "10", y2: "10" }), _jsx("line", { x1: "10", y1: "2", x2: "2", y2: "10" })] }) }))] }), _jsx("div", { className: "sym-tabs", children: TABS.map((tab, i) => (_jsx("button", { className: `sym-tab${i === activeTab ? ' active' : ''}`, onClick: () => handleTabChange(i), children: tab.label }, tab.label))) }), _jsx("div", { className: "sym-list-wrap", children: renderBody() }), _jsx("div", { className: "sym-footer", children: "Search using ISIN and CUSIP codes" })] }) }));
|
|
244
|
-
}
|
|
245
|
-
//# sourceMappingURL=SymbolSearchDialog.js.map
|