react-klinecharts-ui 1.0.0 → 1.2.0
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/README.md +233 -15
- package/dist/chart.cjs +70 -0
- package/dist/chart.cjs.map +1 -0
- package/dist/chart.d.cts +45 -0
- package/dist/chart.d.ts +45 -0
- package/dist/chart.js +68 -0
- package/dist/chart.js.map +1 -0
- package/dist/chunk-F24D6PWY.cjs +98 -0
- package/dist/chunk-F24D6PWY.cjs.map +1 -0
- package/dist/chunk-O7E57I66.js +92 -0
- package/dist/chunk-O7E57I66.js.map +1 -0
- package/dist/chunk-PZ5AY32C.js +9 -0
- package/dist/chunk-PZ5AY32C.js.map +1 -0
- package/dist/chunk-Q7SFCCGT.cjs +11 -0
- package/dist/chunk-Q7SFCCGT.cjs.map +1 -0
- package/dist/{chunk-JD4NBJ5F.js → chunk-RIT2LJQT.js} +4 -9
- package/dist/chunk-RIT2LJQT.js.map +1 -0
- package/dist/{chunk-LGYYJ2GP.cjs → chunk-SZDU2D3D.cjs} +5 -10
- package/dist/chunk-SZDU2D3D.cjs.map +1 -0
- package/dist/extensions.cjs +10 -9
- package/dist/extensions.js +2 -1
- package/dist/index.cjs +550 -224
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +268 -7
- package/dist/index.d.ts +268 -7
- package/dist/index.js +451 -145
- package/dist/index.js.map +1 -1
- package/package.json +19 -2
- package/dist/chunk-JD4NBJ5F.js.map +0 -1
- package/dist/chunk-LGYYJ2GP.cjs.map +0 -1
package/README.md
CHANGED
|
@@ -69,6 +69,17 @@ pnpm add react-klinecharts-ui klinecharts
|
|
|
69
69
|
yarn add react-klinecharts-ui klinecharts
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
+
> **Rendering a chart?** `react-klinecharts-ui` is headless — it does not render
|
|
73
|
+
> the canvas itself. The fastest path is the optional `ChartCanvas` wrapper,
|
|
74
|
+
> which needs `react-klinecharts`:
|
|
75
|
+
>
|
|
76
|
+
> ```bash
|
|
77
|
+
> npm install react-klinecharts-ui klinecharts react-klinecharts
|
|
78
|
+
> ```
|
|
79
|
+
>
|
|
80
|
+
> You can also initialise the chart yourself with `klinecharts.init()` and skip
|
|
81
|
+
> `react-klinecharts` entirely — see [Renderer-agnostic](#renderer-agnostic).
|
|
82
|
+
|
|
72
83
|
---
|
|
73
84
|
|
|
74
85
|
## Concept
|
|
@@ -82,6 +93,170 @@ The library follows a **headless** pattern — all UI is written by the consumer
|
|
|
82
93
|
|
|
83
94
|
All hooks must be called inside `<KlinechartsUIProvider>`.
|
|
84
95
|
|
|
96
|
+
### Renderer-agnostic
|
|
97
|
+
|
|
98
|
+
`react-klinecharts-ui` is **headless** — it owns state (symbol, period, indicators, alerts, replay, …) and drives a klinecharts `Chart` instance, but it does **not** render the canvas. The only bridge between a renderer and the provider is a single dispatch:
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
dispatch({ type: "SET_CHART", chart });
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Once the chart instance is registered, every hook (`useIndicators`, `useAlerts`, `useReplay`, …) reads and mutates it via `state.chart.*`. You can initialise that instance **three ways**:
|
|
105
|
+
|
|
106
|
+
**1. `ChartCanvas` (fastest, optional peer `react-klinecharts`)** — the thin wrapper shipped at `react-klinecharts-ui/chart` wires the `<KLineChart>` renderer, builds the data loader, forwards symbol/period/theme from provider state, and dispatches `SET_CHART` for you:
|
|
107
|
+
|
|
108
|
+
```tsx
|
|
109
|
+
import { KlinechartsUIProvider } from "react-klinecharts-ui";
|
|
110
|
+
import { ChartCanvas } from "react-klinecharts-ui/chart";
|
|
111
|
+
|
|
112
|
+
<KlinechartsUIProvider datafeed={datafeed} defaultSymbol={symbol} defaultTheme="dark">
|
|
113
|
+
<ChartCanvas className="h-[500px]" />
|
|
114
|
+
</KlinechartsUIProvider>;
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**2. `<KLineChart>` from `react-klinecharts` directly** — full control over props, at the cost of writing the `onReady` bridge yourself:
|
|
118
|
+
|
|
119
|
+
```tsx
|
|
120
|
+
import { useMemo } from "react";
|
|
121
|
+
import { KLineChart } from "react-klinecharts";
|
|
122
|
+
import { useKlinechartsUI, createDataLoader } from "react-klinecharts-ui";
|
|
123
|
+
|
|
124
|
+
function ChartView() {
|
|
125
|
+
const { state, dispatch, datafeed } = useKlinechartsUI();
|
|
126
|
+
const dataLoader = useMemo(() => createDataLoader(datafeed, dispatch), [datafeed, dispatch]);
|
|
127
|
+
return (
|
|
128
|
+
<KLineChart
|
|
129
|
+
dataLoader={dataLoader}
|
|
130
|
+
symbol={state.symbol ?? undefined}
|
|
131
|
+
period={state.period}
|
|
132
|
+
styles={state.theme}
|
|
133
|
+
onReady={(chart) => dispatch({ type: "SET_CHART", chart })}
|
|
134
|
+
/>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**3. Direct `klinecharts.init()` (no `react-klinecharts` at all)** — for custom lifecycles, SSR/Next.js, or when you want zero extra dependencies:
|
|
140
|
+
|
|
141
|
+
```tsx
|
|
142
|
+
import { useEffect, useRef } from "react";
|
|
143
|
+
import { init, dispose } from "klinecharts";
|
|
144
|
+
import { useKlinechartsUI } from "react-klinecharts-ui";
|
|
145
|
+
|
|
146
|
+
function ChartView() {
|
|
147
|
+
const { dispatch, datafeed } = useKlinechartsUI();
|
|
148
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
149
|
+
useEffect(() => {
|
|
150
|
+
const chart = init(ref.current!);
|
|
151
|
+
dispatch({ type: "SET_CHART", chart }); // the bridge
|
|
152
|
+
chart!.applyNewData(/* load bars yourself */);
|
|
153
|
+
return () => dispose(ref.current!);
|
|
154
|
+
}, []);
|
|
155
|
+
return <div ref={ref} style={{ height: 500 }} />;
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Whatever route you pick, the hooks work the same — they only care about the `Chart` instance in the store.
|
|
160
|
+
|
|
161
|
+
### Persistence
|
|
162
|
+
|
|
163
|
+
By default, user-facing state (alerts, chart settings, the active indicator
|
|
164
|
+
set) lives only in memory and is **lost on page reload**. Pass a `storage`
|
|
165
|
+
option to the provider to hydrate it on mount and write it back on every
|
|
166
|
+
change. The adapter mirrors the Web Storage API, so `localStorage` works out
|
|
167
|
+
of the box:
|
|
168
|
+
|
|
169
|
+
```tsx
|
|
170
|
+
<KlinechartsUIProvider datafeed={datafeed} storage={{}}>
|
|
171
|
+
{/* alerts / settings / indicators now survive refresh */}
|
|
172
|
+
</KlinechartsUIProvider>
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
`storage={{}}` uses the defaults: `localStorage` adapter, the `alerts` /
|
|
176
|
+
`settings` / `indicators` namespaces, and a `"rkui:"` key prefix. You can
|
|
177
|
+
override any of them — e.g. plug in a remote or IndexedDB-backed adapter:
|
|
178
|
+
|
|
179
|
+
```tsx
|
|
180
|
+
import type { StorageAdapter } from "react-klinecharts-ui";
|
|
181
|
+
|
|
182
|
+
const remoteAdapter: StorageAdapter = {
|
|
183
|
+
getItem: (key) => mySyncCache.get(key) ?? null,
|
|
184
|
+
setItem: (key, value) => {
|
|
185
|
+
mySyncCache.set(key, value);
|
|
186
|
+
flushToServer(key, value); // async, fire-and-forget
|
|
187
|
+
},
|
|
188
|
+
removeItem: (key) => { mySyncCache.delete(key); deleteFromServer(key); },
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
<KlinechartsUIProvider datafeed={datafeed} storage={{ adapter: remoteAdapter }}>
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**Scope.** The adapter covers the reducer store today: `alerts`, `settings`
|
|
195
|
+
(`useKlinechartsUISettings`), and `indicators` (the active lists, pane ids,
|
|
196
|
+
axis bindings, and visibility). Per-hook `useState` values — script code
|
|
197
|
+
(`useScriptEditor`), compared symbols (`useCompare`), watchlist, annotations —
|
|
198
|
+
are not yet covered by the adapter and remain in memory. `useLayoutManager`
|
|
199
|
+
(named snapshot presets) is orthogonal: it serializes the whole chart
|
|
200
|
+
(indicators + drawings + meta) on demand to its own keys, independent of the
|
|
201
|
+
live `storage` adapter.
|
|
202
|
+
|
|
203
|
+
The adapter contract is **synchronous** (matching the Web Storage API). For
|
|
204
|
+
async backends, keep a synchronous in-memory cache and flush in the
|
|
205
|
+
background — the provider reads/writes through `getItem`/`setItem` only.
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
### Workspace & multi-chart
|
|
210
|
+
|
|
211
|
+
`KlinechartsUIProvider` owns exactly one chart. To render a **grid** of charts
|
|
212
|
+
that share crosshair / scroll / zoom / symbol / period, wrap several providers
|
|
213
|
+
in a `WorkspaceProvider` and drop a `useChartSync` bridge inside each:
|
|
214
|
+
|
|
215
|
+
```tsx
|
|
216
|
+
import {
|
|
217
|
+
KlinechartsUIProvider,
|
|
218
|
+
WorkspaceProvider,
|
|
219
|
+
useChartSync,
|
|
220
|
+
useWorkspace,
|
|
221
|
+
} from "react-klinecharts-ui";
|
|
222
|
+
|
|
223
|
+
const cells = [
|
|
224
|
+
{ id: "a", symbol: { ticker: "BTCUSDT" }, period: { span: 1, type: "minute", label: "1m" } },
|
|
225
|
+
{ id: "b", symbol: { ticker: "ETHUSDT" }, period: { span: 1, type: "minute", label: "1m" } },
|
|
226
|
+
];
|
|
227
|
+
|
|
228
|
+
// Rendered inside each KlinechartsUIProvider — registers its chart with the
|
|
229
|
+
// workspace and mirrors viewport events to siblings.
|
|
230
|
+
function ChartSyncBridge({ cellId }: { cellId: string }) {
|
|
231
|
+
useChartSync({ cellId });
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
<WorkspaceProvider defaultCells={cells}>
|
|
236
|
+
<div style={{ display: "grid", gridTemplateColumns: "1fr 1fr" }}>
|
|
237
|
+
{cells.map((c) => (
|
|
238
|
+
<KlinechartsUIProvider key={c.id} datafeed={datafeed} defaultSymbol={c.symbol} defaultPeriod={c.period}>
|
|
239
|
+
<ChartSyncBridge cellId={c.id} />
|
|
240
|
+
<ChartCanvas />
|
|
241
|
+
</KlinechartsUIProvider>
|
|
242
|
+
))}
|
|
243
|
+
</div>
|
|
244
|
+
</WorkspaceProvider>
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
`useChartSync` mirrors crosshair / scroll / zoom between the registered charts
|
|
248
|
+
using only the **public** klinecharts API (`executeAction`, `scrollToTimestamp`,
|
|
249
|
+
`setBarSpace`) — no internal `_chartStore`. A re-entrancy guard prevents
|
|
250
|
+
feedback loops. Per-channel sync can be disabled via the `sync` prop
|
|
251
|
+
(`{ scroll: false }`).
|
|
252
|
+
|
|
253
|
+
> **Scope of this foundation.** Each cell keeps its own alerts, replay, and
|
|
254
|
+
> drawings (per-provider). Hoisting shared alerts/replay/drawings to the
|
|
255
|
+
> workspace level, plus tabbed layouts and server-persisted workspaces, is
|
|
256
|
+
> planned. Read the
|
|
257
|
+
> [multi-chart example](https://nemezzizz.github.io/react-klinecharts-ui/examples/multi-chart/)
|
|
258
|
+
> for a runnable 2×2 grid.
|
|
259
|
+
|
|
85
260
|
---
|
|
86
261
|
|
|
87
262
|
## KlinechartsUIProvider
|
|
@@ -575,6 +750,7 @@ const {
|
|
|
575
750
|
isLocked,
|
|
576
751
|
isVisible,
|
|
577
752
|
autoRetrigger,
|
|
753
|
+
overlays,
|
|
578
754
|
selectTool,
|
|
579
755
|
clearActiveTool,
|
|
580
756
|
setMagnetMode,
|
|
@@ -582,24 +758,31 @@ const {
|
|
|
582
758
|
toggleVisibility,
|
|
583
759
|
removeAllDrawings,
|
|
584
760
|
setAutoRetrigger,
|
|
761
|
+
removeDrawing,
|
|
762
|
+
setDrawingVisible,
|
|
763
|
+
setDrawingLocked,
|
|
585
764
|
} = useDrawingTools();
|
|
586
765
|
```
|
|
587
766
|
|
|
588
|
-
| Field/Method
|
|
589
|
-
|
|
|
590
|
-
| `categories`
|
|
591
|
-
| `activeTool`
|
|
592
|
-
| `magnetMode`
|
|
593
|
-
| `isLocked`
|
|
594
|
-
| `isVisible`
|
|
595
|
-
| `autoRetrigger`
|
|
596
|
-
| `
|
|
597
|
-
| `
|
|
598
|
-
| `
|
|
599
|
-
| `
|
|
600
|
-
| `
|
|
601
|
-
| `
|
|
602
|
-
| `
|
|
767
|
+
| Field/Method | Type | Description |
|
|
768
|
+
| ------------------------ | -------------------------------- | ------------------------------------------------------- |
|
|
769
|
+
| `categories` | `DrawingCategoryItem[]` | Tool categories with nested tools |
|
|
770
|
+
| `activeTool` | `string \| null` | Name of the last selected tool |
|
|
771
|
+
| `magnetMode` | `"normal" \| "weak" \| "strong"` | Snap-to-OHLC mode |
|
|
772
|
+
| `isLocked` | `boolean` | Whether all drawings are locked |
|
|
773
|
+
| `isVisible` | `boolean` | Whether all drawings are visible |
|
|
774
|
+
| `autoRetrigger` | `boolean` | Re-arm the tool after finishing a shape (default `true`) |
|
|
775
|
+
| `overlays` | `DrawingOverlayInfo[]` | Reactive list of drawings in the `drawing_tools` group |
|
|
776
|
+
| `selectTool(name)` | — | Start drawing via `chart.createOverlay` |
|
|
777
|
+
| `clearActiveTool()` | — | Deselect tool (local state only) |
|
|
778
|
+
| `setMagnetMode(mode)` | — | Change magnet mode for all existing and future drawings |
|
|
779
|
+
| `toggleLock()` | — | Toggle lock on all drawings |
|
|
780
|
+
| `toggleVisibility()` | — | Show/hide all drawings |
|
|
781
|
+
| `removeAllDrawings()` | — | Remove all drawings in the `drawing_tools` group |
|
|
782
|
+
| `setAutoRetrigger(enabled)` | — | Enable/disable auto re-arming |
|
|
783
|
+
| `removeDrawing(id)` | — | Remove a single drawing by id |
|
|
784
|
+
| `setDrawingVisible(id, visible)` | — | Show/hide a single drawing |
|
|
785
|
+
| `setDrawingLocked(id, locked)` | — | Lock/unlock a single drawing |
|
|
603
786
|
|
|
604
787
|
```typescript
|
|
605
788
|
interface DrawingToolItem {
|
|
@@ -611,8 +794,39 @@ interface DrawingCategoryItem {
|
|
|
611
794
|
key: string; // "singleLine" | "moreLine" | "polygon" | "fibonacci" | "wave"
|
|
612
795
|
tools: DrawingToolItem[];
|
|
613
796
|
}
|
|
797
|
+
|
|
798
|
+
interface DrawingOverlayInfo {
|
|
799
|
+
id: string; // Stable id from klinecharts (chart.getOverlays()[].id)
|
|
800
|
+
name: string; // Overlay name, e.g. "segment", "fibonacciLine", "arrow"
|
|
801
|
+
paneId: string; // Pane id where the drawing lives
|
|
802
|
+
locked: boolean; // Current lock state
|
|
803
|
+
visible: boolean; // Current visibility
|
|
804
|
+
}
|
|
614
805
|
```
|
|
615
806
|
|
|
807
|
+
#### Per-drawing management
|
|
808
|
+
|
|
809
|
+
`overlays` is a **reactive** snapshot of the drawings in the `drawing_tools` group. It updates when a drawing is created (via `selectTool` + finishing a shape on the canvas), removed, or has its `locked`/`visible` properties changed — both through the per-drawing operations above and through the batch operations (`toggleLock`, `toggleVisibility`, `removeAllDrawings`).
|
|
810
|
+
|
|
811
|
+
Because klinecharts v10 has no overlay change events, the hook also runs a 1s polling fallback so changes made **outside** the hook (e.g. the user pressing <kbd>Delete</kbd> via klinecharts, or undo/redo) are still reflected.
|
|
812
|
+
|
|
813
|
+
```typescript
|
|
814
|
+
// Build an Object Tree panel from `overlays`
|
|
815
|
+
const { overlays, removeDrawing, setDrawingVisible, setDrawingLocked } = useDrawingTools();
|
|
816
|
+
// overlays.map((o) => (
|
|
817
|
+
// <Row
|
|
818
|
+
// key={o.id}
|
|
819
|
+
// label={drawingLabel(o.name)} // "segment" -> "segment" locale key
|
|
820
|
+
// visible={o.visible}
|
|
821
|
+
// locked={o.locked}
|
|
822
|
+
// onToggleVis={() => setDrawingVisible(o.id, !o.visible)}
|
|
823
|
+
// onDel={() => removeDrawing(o.id)}
|
|
824
|
+
// />
|
|
825
|
+
// ));
|
|
826
|
+
```
|
|
827
|
+
|
|
828
|
+
`drawingLabel(name)` is an exported helper that maps a klinecharts overlay name to its `localeKey` using `DRAWING_CATEGORIES` (falls back to the name itself when the tool is unknown), so consumers don't have to duplicate the category table.
|
|
829
|
+
|
|
616
830
|
**Categories and tools:**
|
|
617
831
|
|
|
618
832
|
| Category (`key`) | Tools |
|
|
@@ -2084,4 +2298,8 @@ export type {
|
|
|
2084
2298
|
DepthOverlayExtendData,
|
|
2085
2299
|
DepthOverlayRow,
|
|
2086
2300
|
};
|
|
2301
|
+
|
|
2302
|
+
// Chart entry (optional — peer-depends on react-klinecharts).
|
|
2303
|
+
// import from "react-klinecharts-ui/chart"
|
|
2304
|
+
export { ChartCanvas, type ChartCanvasProps };
|
|
2087
2305
|
```
|
package/dist/chart.cjs
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkF24D6PWY_cjs = require('./chunk-F24D6PWY.cjs');
|
|
4
|
+
require('./chunk-Q7SFCCGT.cjs');
|
|
5
|
+
var react = require('react');
|
|
6
|
+
var reactKlinecharts = require('react-klinecharts');
|
|
7
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
8
|
+
|
|
9
|
+
function ChartCanvas({
|
|
10
|
+
className,
|
|
11
|
+
children,
|
|
12
|
+
options,
|
|
13
|
+
styles
|
|
14
|
+
}) {
|
|
15
|
+
const { state, dispatch, datafeed } = chunkF24D6PWY_cjs.useKlinechartsUI();
|
|
16
|
+
const dataLoader = react.useMemo(
|
|
17
|
+
() => chunkF24D6PWY_cjs.createDataLoader(datafeed, dispatch),
|
|
18
|
+
[datafeed, dispatch]
|
|
19
|
+
);
|
|
20
|
+
const mainIndicatorsRef = react.useRef(state.mainIndicators);
|
|
21
|
+
const subIndicatorsRef = react.useRef(state.subIndicators);
|
|
22
|
+
react.useEffect(() => {
|
|
23
|
+
mainIndicatorsRef.current = state.mainIndicators;
|
|
24
|
+
subIndicatorsRef.current = state.subIndicators;
|
|
25
|
+
}, [state.mainIndicators, state.subIndicators]);
|
|
26
|
+
const handleReady = react.useCallback(
|
|
27
|
+
(chart) => {
|
|
28
|
+
dispatch({ type: "SET_CHART", chart });
|
|
29
|
+
mainIndicatorsRef.current.forEach((name) => {
|
|
30
|
+
chart.createIndicator(
|
|
31
|
+
{ name, id: `main_${name}` },
|
|
32
|
+
{ isStack: true, pane: { id: "candle_pane" } }
|
|
33
|
+
);
|
|
34
|
+
});
|
|
35
|
+
const subUpdates = {};
|
|
36
|
+
Object.keys(subIndicatorsRef.current).forEach((name) => {
|
|
37
|
+
const id = `sub_${name}`;
|
|
38
|
+
chart.createIndicator({ name, id });
|
|
39
|
+
const ind = chart.getIndicators({ id })[0];
|
|
40
|
+
if (ind?.paneId) subUpdates[name] = ind.paneId;
|
|
41
|
+
});
|
|
42
|
+
if (Object.keys(subUpdates).length > 0) {
|
|
43
|
+
dispatch({
|
|
44
|
+
type: "SET_SUB_INDICATORS",
|
|
45
|
+
indicators: { ...subIndicatorsRef.current, ...subUpdates }
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
[dispatch]
|
|
50
|
+
);
|
|
51
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
52
|
+
reactKlinecharts.KLineChart,
|
|
53
|
+
{
|
|
54
|
+
className,
|
|
55
|
+
options,
|
|
56
|
+
styles: styles ?? state.theme,
|
|
57
|
+
dataLoader,
|
|
58
|
+
symbol: state.symbol ?? void 0,
|
|
59
|
+
period: state.period,
|
|
60
|
+
locale: state.locale,
|
|
61
|
+
timezone: state.timezone,
|
|
62
|
+
onReady: handleReady,
|
|
63
|
+
children
|
|
64
|
+
}
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
exports.ChartCanvas = ChartCanvas;
|
|
69
|
+
//# sourceMappingURL=chart.cjs.map
|
|
70
|
+
//# sourceMappingURL=chart.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/chart/ChartCanvas.tsx"],"names":["useKlinechartsUI","useMemo","createDataLoader","useRef","useEffect","useCallback","jsx","KLineChart"],"mappings":";;;;;;;;AAsDO,SAAS,WAAA,CAAY;AAAA,EAC1B,SAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAA,EAAgC;AAC9B,EAAA,MAAM,EAAE,KAAA,EAAO,QAAA,EAAU,QAAA,KAAaA,kCAAA,EAAiB;AAEvD,EAAA,MAAM,UAAA,GAAaC,aAAA;AAAA,IACjB,MAAMC,kCAAA,CAAiB,QAAA,EAAU,QAAQ,CAAA;AAAA,IACzC,CAAC,UAAU,QAAQ;AAAA,GACrB;AAKA,EAAA,MAAM,iBAAA,GAAoBC,YAAA,CAAO,KAAA,CAAM,cAAc,CAAA;AACrD,EAAA,MAAM,gBAAA,GAAmBA,YAAA,CAAO,KAAA,CAAM,aAAa,CAAA;AACnD,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,iBAAA,CAAkB,UAAU,KAAA,CAAM,cAAA;AAClC,IAAA,gBAAA,CAAiB,UAAU,KAAA,CAAM,aAAA;AAAA,EACnC,GAAG,CAAC,KAAA,CAAM,cAAA,EAAgB,KAAA,CAAM,aAAa,CAAC,CAAA;AAE9C,EAAA,MAAM,WAAA,GAAcC,iBAAA;AAAA,IAClB,CAAC,KAAA,KAAiB;AAEhB,MAAA,QAAA,CAAS,EAAE,IAAA,EAAM,WAAA,EAAa,KAAA,EAAO,CAAA;AAIrC,MAAA,iBAAA,CAAkB,OAAA,CAAQ,OAAA,CAAQ,CAAC,IAAA,KAAS;AAC1C,QAAA,KAAA,CAAM,eAAA;AAAA,UACJ,EAAE,IAAA,EAAM,EAAA,EAAI,CAAA,KAAA,EAAQ,IAAI,CAAA,CAAA,EAAG;AAAA,UAC3B,EAAE,OAAA,EAAS,IAAA,EAAM,MAAM,EAAE,EAAA,EAAI,eAAc;AAAE,SAC/C;AAAA,MACF,CAAC,CAAA;AAED,MAAA,MAAM,aAAqC,EAAC;AAC5C,MAAA,MAAA,CAAO,KAAK,gBAAA,CAAiB,OAAO,CAAA,CAAE,OAAA,CAAQ,CAAC,IAAA,KAAS;AACtD,QAAA,MAAM,EAAA,GAAK,OAAO,IAAI,CAAA,CAAA;AACtB,QAAA,KAAA,CAAM,eAAA,CAAgB,EAAE,IAAA,EAAM,EAAA,EAAI,CAAA;AAClC,QAAA,MAAM,MAAM,KAAA,CAAM,aAAA,CAAc,EAAE,EAAA,EAAI,EAAE,CAAC,CAAA;AACzC,QAAA,IAAI,GAAA,EAAK,MAAA,EAAQ,UAAA,CAAW,IAAI,IAAI,GAAA,CAAI,MAAA;AAAA,MAC1C,CAAC,CAAA;AACD,MAAA,IAAI,MAAA,CAAO,IAAA,CAAK,UAAU,CAAA,CAAE,SAAS,CAAA,EAAG;AACtC,QAAA,QAAA,CAAS;AAAA,UACP,IAAA,EAAM,oBAAA;AAAA,UACN,YAAY,EAAE,GAAG,gBAAA,CAAiB,OAAA,EAAS,GAAG,UAAA;AAAW,SAC1D,CAAA;AAAA,MACH;AAAA,IACF,CAAA;AAAA,IACA,CAAC,QAAQ;AAAA,GACX;AAEA,EAAA,uBACEC,cAAA;AAAA,IAACC,2BAAA;AAAA,IAAA;AAAA,MACC,SAAA;AAAA,MACA,OAAA;AAAA,MACA,MAAA,EAAQ,UAAU,KAAA,CAAM,KAAA;AAAA,MACxB,UAAA;AAAA,MACA,MAAA,EAAQ,MAAM,MAAA,IAAU,MAAA;AAAA,MACxB,QAAQ,KAAA,CAAM,MAAA;AAAA,MACd,QAAQ,KAAA,CAAM,MAAA;AAAA,MACd,UAAU,KAAA,CAAM,QAAA;AAAA,MAChB,OAAA,EAAS,WAAA;AAAA,MAER;AAAA;AAAA,GACH;AAEJ","file":"chart.cjs","sourcesContent":["import {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n type ReactNode,\n} from \"react\";\nimport { KLineChart } from \"react-klinecharts\";\nimport type { Chart, Options, DeepPartial, Styles } from \"klinecharts\";\nimport {\n useKlinechartsUI,\n} from \"../provider/ChartTerminalContext\";\nimport { createDataLoader } from \"../utils/createDataLoader\";\n\nexport interface ChartCanvasProps {\n /** className applied to the chart container div. */\n className?: string;\n /**\n * Optional children rendered inside `<KLineChart>` (use the `<Widget>`\n * component from `react-klinecharts` to portal React into chart DOM layers).\n */\n children?: ReactNode;\n /**\n * Chart initialization options, applied once on mount. Forwarded to\n * `<KLineChart>` as the `options` prop.\n */\n options?: Options;\n /**\n * Styles override applied on mount and whenever it changes. Forwarded to\n * `<KLineChart>` as the `styles` prop.\n */\n styles?: string | DeepPartial<Styles>;\n}\n\n/**\n * Thin renderer wrapper for `react-klinecharts-ui`.\n *\n * `react-klinecharts-ui` is **headless / renderer-agnostic**: it only needs a\n * klinecharts `Chart` instance to be registered via\n * `dispatch({ type: \"SET_CHART\", chart })`. This component wires the\n * `<KLineChart>` renderer from `react-klinecharts` to that bridge for you —\n * building the data loader, forwarding symbol/period/theme/locale/timezone\n * from provider state, bootstrapping the default indicators, and dispatching\n * `SET_CHART` on ready.\n *\n * It is the fastest path to a working chart. For full control (custom\n * lifecycle, a different renderer, or direct `klinecharts.init()`), render the\n * chart yourself and dispatch `SET_CHART` — see the README \"Renderer-agnostic\"\n * section.\n *\n * This entry point requires `react-klinecharts` as an optional peer\n * dependency. Install it explicitly when you import from\n * `react-klinecharts-ui/chart`.\n */\nexport function ChartCanvas({\n className,\n children,\n options,\n styles,\n}: ChartCanvasProps): ReactNode {\n const { state, dispatch, datafeed } = useKlinechartsUI();\n\n const dataLoader = useMemo(\n () => createDataLoader(datafeed, dispatch),\n [datafeed, dispatch],\n );\n\n // Keep the latest default indicator lists in refs so `handleReady` stays\n // stable (only depends on `dispatch`) yet reads current values when the\n // chart finishes initializing.\n const mainIndicatorsRef = useRef(state.mainIndicators);\n const subIndicatorsRef = useRef(state.subIndicators);\n useEffect(() => {\n mainIndicatorsRef.current = state.mainIndicators;\n subIndicatorsRef.current = state.subIndicators;\n }, [state.mainIndicators, state.subIndicators]);\n\n const handleReady = useCallback(\n (chart: Chart) => {\n // The bridge: register the chart instance so every hook can drive it.\n dispatch({ type: \"SET_CHART\", chart });\n\n // Bootstrap the provider's default indicators onto the fresh chart,\n // mirroring the canonical pattern in examples/ChartView.tsx.\n mainIndicatorsRef.current.forEach((name) => {\n chart.createIndicator(\n { name, id: `main_${name}` },\n { isStack: true, pane: { id: \"candle_pane\" } },\n );\n });\n\n const subUpdates: Record<string, string> = {};\n Object.keys(subIndicatorsRef.current).forEach((name) => {\n const id = `sub_${name}`;\n chart.createIndicator({ name, id });\n const ind = chart.getIndicators({ id })[0];\n if (ind?.paneId) subUpdates[name] = ind.paneId;\n });\n if (Object.keys(subUpdates).length > 0) {\n dispatch({\n type: \"SET_SUB_INDICATORS\",\n indicators: { ...subIndicatorsRef.current, ...subUpdates },\n });\n }\n },\n [dispatch],\n );\n\n return (\n <KLineChart\n className={className}\n options={options}\n styles={styles ?? state.theme}\n dataLoader={dataLoader}\n symbol={state.symbol ?? undefined}\n period={state.period}\n locale={state.locale}\n timezone={state.timezone}\n onReady={handleReady}\n >\n {children}\n </KLineChart>\n );\n}\n"]}
|
package/dist/chart.d.cts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { Options, DeepPartial, Styles } from 'klinecharts';
|
|
3
|
+
|
|
4
|
+
interface ChartCanvasProps {
|
|
5
|
+
/** className applied to the chart container div. */
|
|
6
|
+
className?: string;
|
|
7
|
+
/**
|
|
8
|
+
* Optional children rendered inside `<KLineChart>` (use the `<Widget>`
|
|
9
|
+
* component from `react-klinecharts` to portal React into chart DOM layers).
|
|
10
|
+
*/
|
|
11
|
+
children?: ReactNode;
|
|
12
|
+
/**
|
|
13
|
+
* Chart initialization options, applied once on mount. Forwarded to
|
|
14
|
+
* `<KLineChart>` as the `options` prop.
|
|
15
|
+
*/
|
|
16
|
+
options?: Options;
|
|
17
|
+
/**
|
|
18
|
+
* Styles override applied on mount and whenever it changes. Forwarded to
|
|
19
|
+
* `<KLineChart>` as the `styles` prop.
|
|
20
|
+
*/
|
|
21
|
+
styles?: string | DeepPartial<Styles>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Thin renderer wrapper for `react-klinecharts-ui`.
|
|
25
|
+
*
|
|
26
|
+
* `react-klinecharts-ui` is **headless / renderer-agnostic**: it only needs a
|
|
27
|
+
* klinecharts `Chart` instance to be registered via
|
|
28
|
+
* `dispatch({ type: "SET_CHART", chart })`. This component wires the
|
|
29
|
+
* `<KLineChart>` renderer from `react-klinecharts` to that bridge for you —
|
|
30
|
+
* building the data loader, forwarding symbol/period/theme/locale/timezone
|
|
31
|
+
* from provider state, bootstrapping the default indicators, and dispatching
|
|
32
|
+
* `SET_CHART` on ready.
|
|
33
|
+
*
|
|
34
|
+
* It is the fastest path to a working chart. For full control (custom
|
|
35
|
+
* lifecycle, a different renderer, or direct `klinecharts.init()`), render the
|
|
36
|
+
* chart yourself and dispatch `SET_CHART` — see the README "Renderer-agnostic"
|
|
37
|
+
* section.
|
|
38
|
+
*
|
|
39
|
+
* This entry point requires `react-klinecharts` as an optional peer
|
|
40
|
+
* dependency. Install it explicitly when you import from
|
|
41
|
+
* `react-klinecharts-ui/chart`.
|
|
42
|
+
*/
|
|
43
|
+
declare function ChartCanvas({ className, children, options, styles, }: ChartCanvasProps): ReactNode;
|
|
44
|
+
|
|
45
|
+
export { ChartCanvas, type ChartCanvasProps };
|
package/dist/chart.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { Options, DeepPartial, Styles } from 'klinecharts';
|
|
3
|
+
|
|
4
|
+
interface ChartCanvasProps {
|
|
5
|
+
/** className applied to the chart container div. */
|
|
6
|
+
className?: string;
|
|
7
|
+
/**
|
|
8
|
+
* Optional children rendered inside `<KLineChart>` (use the `<Widget>`
|
|
9
|
+
* component from `react-klinecharts` to portal React into chart DOM layers).
|
|
10
|
+
*/
|
|
11
|
+
children?: ReactNode;
|
|
12
|
+
/**
|
|
13
|
+
* Chart initialization options, applied once on mount. Forwarded to
|
|
14
|
+
* `<KLineChart>` as the `options` prop.
|
|
15
|
+
*/
|
|
16
|
+
options?: Options;
|
|
17
|
+
/**
|
|
18
|
+
* Styles override applied on mount and whenever it changes. Forwarded to
|
|
19
|
+
* `<KLineChart>` as the `styles` prop.
|
|
20
|
+
*/
|
|
21
|
+
styles?: string | DeepPartial<Styles>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Thin renderer wrapper for `react-klinecharts-ui`.
|
|
25
|
+
*
|
|
26
|
+
* `react-klinecharts-ui` is **headless / renderer-agnostic**: it only needs a
|
|
27
|
+
* klinecharts `Chart` instance to be registered via
|
|
28
|
+
* `dispatch({ type: "SET_CHART", chart })`. This component wires the
|
|
29
|
+
* `<KLineChart>` renderer from `react-klinecharts` to that bridge for you —
|
|
30
|
+
* building the data loader, forwarding symbol/period/theme/locale/timezone
|
|
31
|
+
* from provider state, bootstrapping the default indicators, and dispatching
|
|
32
|
+
* `SET_CHART` on ready.
|
|
33
|
+
*
|
|
34
|
+
* It is the fastest path to a working chart. For full control (custom
|
|
35
|
+
* lifecycle, a different renderer, or direct `klinecharts.init()`), render the
|
|
36
|
+
* chart yourself and dispatch `SET_CHART` — see the README "Renderer-agnostic"
|
|
37
|
+
* section.
|
|
38
|
+
*
|
|
39
|
+
* This entry point requires `react-klinecharts` as an optional peer
|
|
40
|
+
* dependency. Install it explicitly when you import from
|
|
41
|
+
* `react-klinecharts-ui/chart`.
|
|
42
|
+
*/
|
|
43
|
+
declare function ChartCanvas({ className, children, options, styles, }: ChartCanvasProps): ReactNode;
|
|
44
|
+
|
|
45
|
+
export { ChartCanvas, type ChartCanvasProps };
|
package/dist/chart.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { useKlinechartsUI, createDataLoader } from './chunk-O7E57I66.js';
|
|
2
|
+
import './chunk-PZ5AY32C.js';
|
|
3
|
+
import { useMemo, useRef, useEffect, useCallback } from 'react';
|
|
4
|
+
import { KLineChart } from 'react-klinecharts';
|
|
5
|
+
import { jsx } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
function ChartCanvas({
|
|
8
|
+
className,
|
|
9
|
+
children,
|
|
10
|
+
options,
|
|
11
|
+
styles
|
|
12
|
+
}) {
|
|
13
|
+
const { state, dispatch, datafeed } = useKlinechartsUI();
|
|
14
|
+
const dataLoader = useMemo(
|
|
15
|
+
() => createDataLoader(datafeed, dispatch),
|
|
16
|
+
[datafeed, dispatch]
|
|
17
|
+
);
|
|
18
|
+
const mainIndicatorsRef = useRef(state.mainIndicators);
|
|
19
|
+
const subIndicatorsRef = useRef(state.subIndicators);
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
mainIndicatorsRef.current = state.mainIndicators;
|
|
22
|
+
subIndicatorsRef.current = state.subIndicators;
|
|
23
|
+
}, [state.mainIndicators, state.subIndicators]);
|
|
24
|
+
const handleReady = useCallback(
|
|
25
|
+
(chart) => {
|
|
26
|
+
dispatch({ type: "SET_CHART", chart });
|
|
27
|
+
mainIndicatorsRef.current.forEach((name) => {
|
|
28
|
+
chart.createIndicator(
|
|
29
|
+
{ name, id: `main_${name}` },
|
|
30
|
+
{ isStack: true, pane: { id: "candle_pane" } }
|
|
31
|
+
);
|
|
32
|
+
});
|
|
33
|
+
const subUpdates = {};
|
|
34
|
+
Object.keys(subIndicatorsRef.current).forEach((name) => {
|
|
35
|
+
const id = `sub_${name}`;
|
|
36
|
+
chart.createIndicator({ name, id });
|
|
37
|
+
const ind = chart.getIndicators({ id })[0];
|
|
38
|
+
if (ind?.paneId) subUpdates[name] = ind.paneId;
|
|
39
|
+
});
|
|
40
|
+
if (Object.keys(subUpdates).length > 0) {
|
|
41
|
+
dispatch({
|
|
42
|
+
type: "SET_SUB_INDICATORS",
|
|
43
|
+
indicators: { ...subIndicatorsRef.current, ...subUpdates }
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
[dispatch]
|
|
48
|
+
);
|
|
49
|
+
return /* @__PURE__ */ jsx(
|
|
50
|
+
KLineChart,
|
|
51
|
+
{
|
|
52
|
+
className,
|
|
53
|
+
options,
|
|
54
|
+
styles: styles ?? state.theme,
|
|
55
|
+
dataLoader,
|
|
56
|
+
symbol: state.symbol ?? void 0,
|
|
57
|
+
period: state.period,
|
|
58
|
+
locale: state.locale,
|
|
59
|
+
timezone: state.timezone,
|
|
60
|
+
onReady: handleReady,
|
|
61
|
+
children
|
|
62
|
+
}
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export { ChartCanvas };
|
|
67
|
+
//# sourceMappingURL=chart.js.map
|
|
68
|
+
//# sourceMappingURL=chart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/chart/ChartCanvas.tsx"],"names":[],"mappings":";;;;;;AAsDO,SAAS,WAAA,CAAY;AAAA,EAC1B,SAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAA,EAAgC;AAC9B,EAAA,MAAM,EAAE,KAAA,EAAO,QAAA,EAAU,QAAA,KAAa,gBAAA,EAAiB;AAEvD,EAAA,MAAM,UAAA,GAAa,OAAA;AAAA,IACjB,MAAM,gBAAA,CAAiB,QAAA,EAAU,QAAQ,CAAA;AAAA,IACzC,CAAC,UAAU,QAAQ;AAAA,GACrB;AAKA,EAAA,MAAM,iBAAA,GAAoB,MAAA,CAAO,KAAA,CAAM,cAAc,CAAA;AACrD,EAAA,MAAM,gBAAA,GAAmB,MAAA,CAAO,KAAA,CAAM,aAAa,CAAA;AACnD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,iBAAA,CAAkB,UAAU,KAAA,CAAM,cAAA;AAClC,IAAA,gBAAA,CAAiB,UAAU,KAAA,CAAM,aAAA;AAAA,EACnC,GAAG,CAAC,KAAA,CAAM,cAAA,EAAgB,KAAA,CAAM,aAAa,CAAC,CAAA;AAE9C,EAAA,MAAM,WAAA,GAAc,WAAA;AAAA,IAClB,CAAC,KAAA,KAAiB;AAEhB,MAAA,QAAA,CAAS,EAAE,IAAA,EAAM,WAAA,EAAa,KAAA,EAAO,CAAA;AAIrC,MAAA,iBAAA,CAAkB,OAAA,CAAQ,OAAA,CAAQ,CAAC,IAAA,KAAS;AAC1C,QAAA,KAAA,CAAM,eAAA;AAAA,UACJ,EAAE,IAAA,EAAM,EAAA,EAAI,CAAA,KAAA,EAAQ,IAAI,CAAA,CAAA,EAAG;AAAA,UAC3B,EAAE,OAAA,EAAS,IAAA,EAAM,MAAM,EAAE,EAAA,EAAI,eAAc;AAAE,SAC/C;AAAA,MACF,CAAC,CAAA;AAED,MAAA,MAAM,aAAqC,EAAC;AAC5C,MAAA,MAAA,CAAO,KAAK,gBAAA,CAAiB,OAAO,CAAA,CAAE,OAAA,CAAQ,CAAC,IAAA,KAAS;AACtD,QAAA,MAAM,EAAA,GAAK,OAAO,IAAI,CAAA,CAAA;AACtB,QAAA,KAAA,CAAM,eAAA,CAAgB,EAAE,IAAA,EAAM,EAAA,EAAI,CAAA;AAClC,QAAA,MAAM,MAAM,KAAA,CAAM,aAAA,CAAc,EAAE,EAAA,EAAI,EAAE,CAAC,CAAA;AACzC,QAAA,IAAI,GAAA,EAAK,MAAA,EAAQ,UAAA,CAAW,IAAI,IAAI,GAAA,CAAI,MAAA;AAAA,MAC1C,CAAC,CAAA;AACD,MAAA,IAAI,MAAA,CAAO,IAAA,CAAK,UAAU,CAAA,CAAE,SAAS,CAAA,EAAG;AACtC,QAAA,QAAA,CAAS;AAAA,UACP,IAAA,EAAM,oBAAA;AAAA,UACN,YAAY,EAAE,GAAG,gBAAA,CAAiB,OAAA,EAAS,GAAG,UAAA;AAAW,SAC1D,CAAA;AAAA,MACH;AAAA,IACF,CAAA;AAAA,IACA,CAAC,QAAQ;AAAA,GACX;AAEA,EAAA,uBACE,GAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,SAAA;AAAA,MACA,OAAA;AAAA,MACA,MAAA,EAAQ,UAAU,KAAA,CAAM,KAAA;AAAA,MACxB,UAAA;AAAA,MACA,MAAA,EAAQ,MAAM,MAAA,IAAU,MAAA;AAAA,MACxB,QAAQ,KAAA,CAAM,MAAA;AAAA,MACd,QAAQ,KAAA,CAAM,MAAA;AAAA,MACd,UAAU,KAAA,CAAM,QAAA;AAAA,MAChB,OAAA,EAAS,WAAA;AAAA,MAER;AAAA;AAAA,GACH;AAEJ","file":"chart.js","sourcesContent":["import {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n type ReactNode,\n} from \"react\";\nimport { KLineChart } from \"react-klinecharts\";\nimport type { Chart, Options, DeepPartial, Styles } from \"klinecharts\";\nimport {\n useKlinechartsUI,\n} from \"../provider/ChartTerminalContext\";\nimport { createDataLoader } from \"../utils/createDataLoader\";\n\nexport interface ChartCanvasProps {\n /** className applied to the chart container div. */\n className?: string;\n /**\n * Optional children rendered inside `<KLineChart>` (use the `<Widget>`\n * component from `react-klinecharts` to portal React into chart DOM layers).\n */\n children?: ReactNode;\n /**\n * Chart initialization options, applied once on mount. Forwarded to\n * `<KLineChart>` as the `options` prop.\n */\n options?: Options;\n /**\n * Styles override applied on mount and whenever it changes. Forwarded to\n * `<KLineChart>` as the `styles` prop.\n */\n styles?: string | DeepPartial<Styles>;\n}\n\n/**\n * Thin renderer wrapper for `react-klinecharts-ui`.\n *\n * `react-klinecharts-ui` is **headless / renderer-agnostic**: it only needs a\n * klinecharts `Chart` instance to be registered via\n * `dispatch({ type: \"SET_CHART\", chart })`. This component wires the\n * `<KLineChart>` renderer from `react-klinecharts` to that bridge for you —\n * building the data loader, forwarding symbol/period/theme/locale/timezone\n * from provider state, bootstrapping the default indicators, and dispatching\n * `SET_CHART` on ready.\n *\n * It is the fastest path to a working chart. For full control (custom\n * lifecycle, a different renderer, or direct `klinecharts.init()`), render the\n * chart yourself and dispatch `SET_CHART` — see the README \"Renderer-agnostic\"\n * section.\n *\n * This entry point requires `react-klinecharts` as an optional peer\n * dependency. Install it explicitly when you import from\n * `react-klinecharts-ui/chart`.\n */\nexport function ChartCanvas({\n className,\n children,\n options,\n styles,\n}: ChartCanvasProps): ReactNode {\n const { state, dispatch, datafeed } = useKlinechartsUI();\n\n const dataLoader = useMemo(\n () => createDataLoader(datafeed, dispatch),\n [datafeed, dispatch],\n );\n\n // Keep the latest default indicator lists in refs so `handleReady` stays\n // stable (only depends on `dispatch`) yet reads current values when the\n // chart finishes initializing.\n const mainIndicatorsRef = useRef(state.mainIndicators);\n const subIndicatorsRef = useRef(state.subIndicators);\n useEffect(() => {\n mainIndicatorsRef.current = state.mainIndicators;\n subIndicatorsRef.current = state.subIndicators;\n }, [state.mainIndicators, state.subIndicators]);\n\n const handleReady = useCallback(\n (chart: Chart) => {\n // The bridge: register the chart instance so every hook can drive it.\n dispatch({ type: \"SET_CHART\", chart });\n\n // Bootstrap the provider's default indicators onto the fresh chart,\n // mirroring the canonical pattern in examples/ChartView.tsx.\n mainIndicatorsRef.current.forEach((name) => {\n chart.createIndicator(\n { name, id: `main_${name}` },\n { isStack: true, pane: { id: \"candle_pane\" } },\n );\n });\n\n const subUpdates: Record<string, string> = {};\n Object.keys(subIndicatorsRef.current).forEach((name) => {\n const id = `sub_${name}`;\n chart.createIndicator({ name, id });\n const ind = chart.getIndicators({ id })[0];\n if (ind?.paneId) subUpdates[name] = ind.paneId;\n });\n if (Object.keys(subUpdates).length > 0) {\n dispatch({\n type: \"SET_SUB_INDICATORS\",\n indicators: { ...subIndicatorsRef.current, ...subUpdates },\n });\n }\n },\n [dispatch],\n );\n\n return (\n <KLineChart\n className={className}\n options={options}\n styles={styles ?? state.theme}\n dataLoader={dataLoader}\n symbol={state.symbol ?? undefined}\n period={state.period}\n locale={state.locale}\n timezone={state.timezone}\n onReady={handleReady}\n >\n {children}\n </KLineChart>\n );\n}\n"]}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var react = require('react');
|
|
4
|
+
|
|
5
|
+
// src/provider/ChartTerminalContext.ts
|
|
6
|
+
var KlinechartsUIStateContext = react.createContext(null);
|
|
7
|
+
var KlinechartsUIDispatchContext = react.createContext(null);
|
|
8
|
+
function useKlinechartsUIDispatch() {
|
|
9
|
+
const ctx = react.useContext(KlinechartsUIDispatchContext);
|
|
10
|
+
if (!ctx) {
|
|
11
|
+
throw new Error(
|
|
12
|
+
"useKlinechartsUI must be used within a <KlinechartsUIProvider>"
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
return ctx;
|
|
16
|
+
}
|
|
17
|
+
function useKlinechartsUI() {
|
|
18
|
+
const state = react.useContext(KlinechartsUIStateContext);
|
|
19
|
+
const dispatch = react.useContext(KlinechartsUIDispatchContext);
|
|
20
|
+
if (!state || !dispatch) {
|
|
21
|
+
throw new Error(
|
|
22
|
+
"useKlinechartsUI must be used within a <KlinechartsUIProvider>"
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
return { state, ...dispatch };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// src/utils/createDataLoader.ts
|
|
29
|
+
function createDataLoader(datafeed, dispatch) {
|
|
30
|
+
let oldestTimestamp = null;
|
|
31
|
+
let currentGen = 0;
|
|
32
|
+
return {
|
|
33
|
+
getBars: async (params) => {
|
|
34
|
+
try {
|
|
35
|
+
dispatch({ type: "SET_LOADING", isLoading: true });
|
|
36
|
+
if (params.type === "init") {
|
|
37
|
+
oldestTimestamp = null;
|
|
38
|
+
const gen = ++currentGen;
|
|
39
|
+
const data = await datafeed.getHistoryKLineData(
|
|
40
|
+
params.symbol,
|
|
41
|
+
{ ...params.period, label: "" },
|
|
42
|
+
0,
|
|
43
|
+
Date.now()
|
|
44
|
+
);
|
|
45
|
+
if (gen !== currentGen) return;
|
|
46
|
+
if (data.length > 0) {
|
|
47
|
+
oldestTimestamp = data[0].timestamp;
|
|
48
|
+
}
|
|
49
|
+
params.callback(data, {
|
|
50
|
+
forward: data.length > 0,
|
|
51
|
+
backward: false
|
|
52
|
+
});
|
|
53
|
+
} else if (params.type === "forward" && oldestTimestamp !== null) {
|
|
54
|
+
const gen = currentGen;
|
|
55
|
+
const data = await datafeed.getHistoryKLineData(
|
|
56
|
+
params.symbol,
|
|
57
|
+
{ ...params.period, label: "" },
|
|
58
|
+
0,
|
|
59
|
+
oldestTimestamp - 1
|
|
60
|
+
);
|
|
61
|
+
if (gen !== currentGen) return;
|
|
62
|
+
if (data.length > 0) {
|
|
63
|
+
oldestTimestamp = data[0].timestamp;
|
|
64
|
+
}
|
|
65
|
+
params.callback(data, {
|
|
66
|
+
forward: data.length > 0,
|
|
67
|
+
backward: false
|
|
68
|
+
});
|
|
69
|
+
} else if (params.type === "backward") {
|
|
70
|
+
params.callback([], { forward: false, backward: false });
|
|
71
|
+
}
|
|
72
|
+
} catch (error) {
|
|
73
|
+
console.error("Failed to load chart data:", error);
|
|
74
|
+
params.callback([], { forward: false, backward: false });
|
|
75
|
+
} finally {
|
|
76
|
+
dispatch({ type: "SET_LOADING", isLoading: false });
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
subscribeBar: (params) => {
|
|
80
|
+
datafeed.subscribe(
|
|
81
|
+
params.symbol,
|
|
82
|
+
{ ...params.period, label: "" },
|
|
83
|
+
(klineData) => params.callback(klineData)
|
|
84
|
+
);
|
|
85
|
+
},
|
|
86
|
+
unsubscribeBar: (params) => {
|
|
87
|
+
datafeed.unsubscribe(params.symbol, { ...params.period, label: "" });
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
exports.KlinechartsUIDispatchContext = KlinechartsUIDispatchContext;
|
|
93
|
+
exports.KlinechartsUIStateContext = KlinechartsUIStateContext;
|
|
94
|
+
exports.createDataLoader = createDataLoader;
|
|
95
|
+
exports.useKlinechartsUI = useKlinechartsUI;
|
|
96
|
+
exports.useKlinechartsUIDispatch = useKlinechartsUIDispatch;
|
|
97
|
+
//# sourceMappingURL=chunk-F24D6PWY.cjs.map
|
|
98
|
+
//# sourceMappingURL=chunk-F24D6PWY.cjs.map
|