react-klinecharts-ui 0.1.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/LICENSE +177 -0
- package/README.md +1132 -0
- package/dist/chunk-PUULIBFN.js +911 -0
- package/dist/chunk-PUULIBFN.js.map +1 -0
- package/dist/chunk-SLTXNLKN.cjs +932 -0
- package/dist/chunk-SLTXNLKN.cjs.map +1 -0
- package/dist/extensions.cjs +20 -0
- package/dist/extensions.cjs.map +1 -0
- package/dist/extensions.d.cts +69 -0
- package/dist/extensions.d.ts +69 -0
- package/dist/extensions.js +3 -0
- package/dist/extensions.js.map +1 -0
- package/dist/index.cjs +1497 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +426 -0
- package/dist/index.d.ts +426 -0
- package/dist/index.js +1390 -0
- package/dist/index.js.map +1 -0
- package/package.json +88 -0
package/README.md
ADDED
|
@@ -0,0 +1,1132 @@
|
|
|
1
|
+
# react-klinecharts-ui — Library Reference
|
|
2
|
+
|
|
3
|
+
**react-klinecharts-ui** is a headless React library for building financial trading terminals on top of [klinecharts](https://github.com/liihuu/KLineChart). It provides a state provider, a set of hooks, and overlay templates. No UI components are included — use any UI framework you prefer.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
1. [Installation](#installation)
|
|
10
|
+
2. [Concept](#concept)
|
|
11
|
+
3. [KlinechartsUIProvider](#klinechartsui-provider)
|
|
12
|
+
4. [Types](#types)
|
|
13
|
+
- [Datafeed](#datafeed)
|
|
14
|
+
- [PartialSymbolInfo](#partialsymbolinfo)
|
|
15
|
+
- [KlinechartsUIState](#klinechartsuistate)
|
|
16
|
+
- [KlinechartsUIAction](#klinechartsuiaction)
|
|
17
|
+
5. [Hooks](#hooks)
|
|
18
|
+
- [useKlinechartsUI](#useklinechartsui)
|
|
19
|
+
- [useKlinechartsUITheme](#useklinechartsui-theme)
|
|
20
|
+
- [useKlinechartsUILoading](#useklinechartsui-loading)
|
|
21
|
+
- [usePeriods](#useperiods)
|
|
22
|
+
- [useTimezone](#usetimezone)
|
|
23
|
+
- [useSymbolSearch](#usesymbolsearch)
|
|
24
|
+
- [useIndicators](#useindicators)
|
|
25
|
+
- [useDrawingTools](#usedrawingtools)
|
|
26
|
+
- [useKlinechartsUISettings](#useklinechartsuisettings)
|
|
27
|
+
- [useScreenshot](#usescreenshot)
|
|
28
|
+
- [useFullscreen](#usefullscreen)
|
|
29
|
+
- [useOrderLines](#useorderlines)
|
|
30
|
+
6. [Utilities](#utilities)
|
|
31
|
+
- [createDataLoader](#createdataloader)
|
|
32
|
+
7. [Data & Constants](#data--constants)
|
|
33
|
+
8. [Drawing Overlays](#drawing-overlays)
|
|
34
|
+
9. [Extensions](#extensions)
|
|
35
|
+
10. [State Callbacks](#state-callbacks)
|
|
36
|
+
11. [Full Export List](#full-export-list)
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
> **Note:** `react-klinecharts` is not yet published to the npm registry. Install it directly from GitHub:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm install react-klinecharts-ui github:NemeZZiZZ/react-klinecharts
|
|
46
|
+
# or with pnpm
|
|
47
|
+
pnpm add react-klinecharts-ui github:NemeZZiZZ/react-klinecharts
|
|
48
|
+
# or with yarn
|
|
49
|
+
yarn add react-klinecharts-ui github:NemeZZiZZ/react-klinecharts
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Concept
|
|
55
|
+
|
|
56
|
+
The library follows a **headless** pattern — all UI is written by the consumer. The library is responsible for:
|
|
57
|
+
|
|
58
|
+
- **State management** — current symbol, period, theme, indicators, timezone, screenshots
|
|
59
|
+
- **Datafeed integration** — abstract interface for loading historical data and subscribing to real-time updates
|
|
60
|
+
- **klinecharts overlay management** — indicators, drawing tools, order lines
|
|
61
|
+
- **Utilities** — `createDataLoader`, overlay templates
|
|
62
|
+
|
|
63
|
+
All hooks must be called inside `<KlinechartsUIProvider>`.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## KlinechartsUIProvider
|
|
68
|
+
|
|
69
|
+
The root provider. Wraps the application and supplies the context.
|
|
70
|
+
|
|
71
|
+
```tsx
|
|
72
|
+
import { KlinechartsUIProvider } from "react-klinecharts-ui";
|
|
73
|
+
|
|
74
|
+
<KlinechartsUIProvider
|
|
75
|
+
datafeed={myDatafeed}
|
|
76
|
+
defaultSymbol={{ ticker: "BTCUSDT", pricePrecision: 2 }}
|
|
77
|
+
defaultTheme="dark"
|
|
78
|
+
overlays={[orderLine]}
|
|
79
|
+
onSymbolChange={(symbol) => saveToStorage("symbol", symbol)}
|
|
80
|
+
>
|
|
81
|
+
<App />
|
|
82
|
+
</KlinechartsUIProvider>;
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Props
|
|
86
|
+
|
|
87
|
+
| Prop | Type | Default | Description |
|
|
88
|
+
| ------------------------ | ---------------------------------------------- | ------------------ | ---------------------------------------------------------------- |
|
|
89
|
+
| `datafeed` | `Datafeed` | — | **Required.** Datafeed interface implementation |
|
|
90
|
+
| `defaultSymbol` | `PartialSymbolInfo` | `null` | Initial trading instrument |
|
|
91
|
+
| `defaultPeriod` | `TerminalPeriod` | First in `periods` | Initial timeframe |
|
|
92
|
+
| `defaultTheme` | `string` | `"light"` | Initial theme (`"light"` or `"dark"`) |
|
|
93
|
+
| `defaultTimezone` | `string` | `"Asia/Shanghai"` | Initial timezone (IANA) |
|
|
94
|
+
| `defaultMainIndicators` | `string[]` | `["MA"]` | Indicators on the main chart at startup |
|
|
95
|
+
| `defaultSubIndicators` | `string[]` | `["VOL"]` | Indicators on sub-panels at startup |
|
|
96
|
+
| `defaultLocale` | `string` | `"en-US"` | Locale passed to klinecharts |
|
|
97
|
+
| `periods` | `TerminalPeriod[]` | `DEFAULT_PERIODS` | List of available timeframes |
|
|
98
|
+
| `styles` | `DeepPartial<Styles>` | — | Custom klinecharts styles (applied when the chart is ready) |
|
|
99
|
+
| `registerExtensions` | `boolean` | `true` | Whether to register built-in drawing overlays |
|
|
100
|
+
| `overlays` | `OverlayTemplate[]` | — | Additional overlay templates (e.g. `orderLine`, custom overlays) |
|
|
101
|
+
| `onStateChange` | `(action, nextState, prevState) => void` | — | Called synchronously on every dispatched action |
|
|
102
|
+
| `onSymbolChange` | `(symbol) => void` | — | Called when the symbol changes |
|
|
103
|
+
| `onPeriodChange` | `(period) => void` | — | Called when the period changes |
|
|
104
|
+
| `onThemeChange` | `(theme) => void` | — | Called when the theme changes |
|
|
105
|
+
| `onTimezoneChange` | `(timezone) => void` | — | Called when the timezone changes |
|
|
106
|
+
| `onMainIndicatorsChange` | `(indicators: string[]) => void` | — | Called when main indicators change |
|
|
107
|
+
| `onSubIndicatorsChange` | `(indicators: Record<string, string>) => void` | — | Called when sub-indicators change |
|
|
108
|
+
| `onSettingsChange` | `(settings: Record<string, unknown>) => void` | — | Called when settings change via `useKlinechartsUISettings` |
|
|
109
|
+
|
|
110
|
+
### Overlay registration
|
|
111
|
+
|
|
112
|
+
The provider registers overlays once on mount via `useRef` — passing an inline array is safe and does not cause re-registration:
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
// Safe — does not re-register on every render
|
|
116
|
+
<KlinechartsUIProvider overlays={[orderLine, myCustomOverlay]}>
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Types
|
|
122
|
+
|
|
123
|
+
### Datafeed
|
|
124
|
+
|
|
125
|
+
Data interface implemented by the consumer.
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
interface Datafeed {
|
|
129
|
+
/**
|
|
130
|
+
* Search symbols by a query string.
|
|
131
|
+
* signal — AbortSignal to cancel the request when a newer query is typed.
|
|
132
|
+
*/
|
|
133
|
+
searchSymbols(
|
|
134
|
+
search: string,
|
|
135
|
+
signal?: AbortSignal,
|
|
136
|
+
): Promise<PartialSymbolInfo[]>;
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Load historical bars.
|
|
140
|
+
* from/to — timestamps in milliseconds.
|
|
141
|
+
* When from=0, load the most recent available data.
|
|
142
|
+
*/
|
|
143
|
+
getHistoryKLineData(
|
|
144
|
+
symbol: SymbolInfo,
|
|
145
|
+
period: TerminalPeriod,
|
|
146
|
+
from: number,
|
|
147
|
+
to: number,
|
|
148
|
+
): Promise<KLineData[]>;
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Subscribe to real-time updates.
|
|
152
|
+
* callback is called for every new bar.
|
|
153
|
+
*/
|
|
154
|
+
subscribe(
|
|
155
|
+
symbol: SymbolInfo,
|
|
156
|
+
period: TerminalPeriod,
|
|
157
|
+
callback: (data: KLineData) => void,
|
|
158
|
+
): void;
|
|
159
|
+
|
|
160
|
+
/** Unsubscribe from real-time updates. */
|
|
161
|
+
unsubscribe(symbol: SymbolInfo, period: TerminalPeriod): void;
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### PartialSymbolInfo
|
|
166
|
+
|
|
167
|
+
Minimal description of a trading instrument.
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
interface PartialSymbolInfo {
|
|
171
|
+
ticker: string; // e.g. "BTCUSDT", "AAPL", "EUR/USD"
|
|
172
|
+
pricePrecision?: number; // Decimal places for price display
|
|
173
|
+
volumePrecision?: number; // Decimal places for volume display
|
|
174
|
+
[key: string]: unknown; // Any additional fields
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### KlinechartsUIState
|
|
179
|
+
|
|
180
|
+
Complete provider state. Accessible via `useKlinechartsUI().state`.
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
interface KlinechartsUIState {
|
|
184
|
+
chart: Chart | null; // klinecharts Chart instance (null before onReady)
|
|
185
|
+
datafeed: Datafeed; // The datafeed passed to the provider
|
|
186
|
+
symbol: PartialSymbolInfo | null; // Current symbol
|
|
187
|
+
period: TerminalPeriod; // Current timeframe
|
|
188
|
+
theme: string; // Current theme: "light" | "dark"
|
|
189
|
+
timezone: string; // Current timezone (IANA)
|
|
190
|
+
isLoading: boolean; // true while data is loading
|
|
191
|
+
locale: string; // klinecharts locale ("en-US")
|
|
192
|
+
periods: TerminalPeriod[]; // List of available timeframes
|
|
193
|
+
mainIndicators: string[]; // Active main chart indicators
|
|
194
|
+
subIndicators: Record<string, string>; // Active sub-indicators: { name → paneId }
|
|
195
|
+
styles: DeepPartial<Styles> | undefined; // Custom klinecharts styles
|
|
196
|
+
screenshotUrl: string | null; // URL of the last screenshot
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### KlinechartsUIAction
|
|
201
|
+
|
|
202
|
+
Union type of all possible actions for `dispatch`.
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
type KlinechartsUIAction =
|
|
206
|
+
| { type: "SET_CHART"; chart: Chart }
|
|
207
|
+
| { type: "SET_SYMBOL"; symbol: PartialSymbolInfo }
|
|
208
|
+
| { type: "SET_PERIOD"; period: TerminalPeriod }
|
|
209
|
+
| { type: "SET_THEME"; theme: string }
|
|
210
|
+
| { type: "SET_TIMEZONE"; timezone: string }
|
|
211
|
+
| { type: "SET_LOADING"; isLoading: boolean }
|
|
212
|
+
| { type: "SET_MAIN_INDICATORS"; indicators: string[] }
|
|
213
|
+
| { type: "SET_SUB_INDICATORS"; indicators: Record<string, string> }
|
|
214
|
+
| { type: "SET_STYLES"; styles: DeepPartial<Styles> | undefined }
|
|
215
|
+
| { type: "SET_LOCALE"; locale: string }
|
|
216
|
+
| { type: "SET_SCREENSHOT_URL"; url: string | null };
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## Hooks
|
|
222
|
+
|
|
223
|
+
### useKlinechartsUI
|
|
224
|
+
|
|
225
|
+
The primary hook — returns the full context: state, dispatch, datafeed, and fullscreen ref.
|
|
226
|
+
|
|
227
|
+
```typescript
|
|
228
|
+
const { state, dispatch, datafeed, onSettingsChange, fullscreenContainerRef } =
|
|
229
|
+
useKlinechartsUI();
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Return value:
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
interface KlinechartsUIContextValue {
|
|
236
|
+
state: KlinechartsUIState;
|
|
237
|
+
dispatch: Dispatch<KlinechartsUIAction>; // enhancedDispatch with synchronous callbacks
|
|
238
|
+
datafeed: Datafeed;
|
|
239
|
+
onSettingsChange?: (settings: Record<string, unknown>) => void;
|
|
240
|
+
fullscreenContainerRef: RefObject<HTMLElement | null>;
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
> **Note:** `dispatch` is `enhancedDispatch`. It synchronously computes the new state by calling the pure reducer directly and immediately invokes `onStateChange` / individual callbacks — without waiting for a React re-render.
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
### useKlinechartsUITheme
|
|
249
|
+
|
|
250
|
+
Manage the chart theme.
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
const { theme, setTheme, toggleTheme } = useKlinechartsUITheme();
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
| Field | Type | Description |
|
|
257
|
+
| ------------- | ------------------------- | ------------------------------------- |
|
|
258
|
+
| `theme` | `string` | Current theme: `"light"` or `"dark"` |
|
|
259
|
+
| `setTheme` | `(theme: string) => void` | Set a specific theme |
|
|
260
|
+
| `toggleTheme` | `() => void` | Toggle between `"light"` and `"dark"` |
|
|
261
|
+
|
|
262
|
+
```tsx
|
|
263
|
+
const { theme, toggleTheme } = useKlinechartsUITheme();
|
|
264
|
+
|
|
265
|
+
<button onClick={toggleTheme}>
|
|
266
|
+
{theme === "dark" ? <SunIcon /> : <MoonIcon />}
|
|
267
|
+
</button>;
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
### useKlinechartsUILoading
|
|
273
|
+
|
|
274
|
+
Loading state of chart data.
|
|
275
|
+
|
|
276
|
+
```typescript
|
|
277
|
+
const { isLoading } = useKlinechartsUILoading();
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
| Field | Type | Description |
|
|
281
|
+
| ----------- | --------- | ------------------------------------------------ |
|
|
282
|
+
| `isLoading` | `boolean` | `true` while `createDataLoader` is fetching bars |
|
|
283
|
+
|
|
284
|
+
```tsx
|
|
285
|
+
const { isLoading } = useKlinechartsUILoading();
|
|
286
|
+
|
|
287
|
+
{
|
|
288
|
+
isLoading && <div className="spinner" />;
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
### usePeriods
|
|
295
|
+
|
|
296
|
+
Manage timeframes.
|
|
297
|
+
|
|
298
|
+
```typescript
|
|
299
|
+
const { periods, activePeriod, setPeriod } = usePeriods();
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
| Field | Type | Description |
|
|
303
|
+
| -------------- | ---------------------------------- | --------------------------------- |
|
|
304
|
+
| `periods` | `TerminalPeriod[]` | Full list of available timeframes |
|
|
305
|
+
| `activePeriod` | `TerminalPeriod` | Currently selected timeframe |
|
|
306
|
+
| `setPeriod` | `(period: TerminalPeriod) => void` | Change the timeframe |
|
|
307
|
+
|
|
308
|
+
`TerminalPeriod` extends `KlinechartsPeriod` with a `label: string` field.
|
|
309
|
+
|
|
310
|
+
**Default timeframes:** 1m, 5m, 15m, 1H, 2H, 4H, D, W, M, Y
|
|
311
|
+
|
|
312
|
+
```tsx
|
|
313
|
+
const { periods, activePeriod, setPeriod } = usePeriods();
|
|
314
|
+
|
|
315
|
+
<div className="flex gap-1">
|
|
316
|
+
{periods.map((p) => (
|
|
317
|
+
<button
|
|
318
|
+
key={p.label}
|
|
319
|
+
onClick={() => setPeriod(p)}
|
|
320
|
+
className={activePeriod.label === p.label ? "active" : ""}
|
|
321
|
+
>
|
|
322
|
+
{p.label}
|
|
323
|
+
</button>
|
|
324
|
+
))}
|
|
325
|
+
</div>;
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
### useTimezone
|
|
331
|
+
|
|
332
|
+
Manage the chart timezone.
|
|
333
|
+
|
|
334
|
+
```typescript
|
|
335
|
+
const { timezones, activeTimezone, setTimezone } = useTimezone();
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
| Field | Type | Description |
|
|
339
|
+
| ---------------- | ---------------------------- | ------------------------- |
|
|
340
|
+
| `timezones` | `TimezoneItem[]` | Full list of timezones |
|
|
341
|
+
| `activeTimezone` | `string` | Current IANA timezone key |
|
|
342
|
+
| `setTimezone` | `(timezone: string) => void` | Change the timezone |
|
|
343
|
+
|
|
344
|
+
```typescript
|
|
345
|
+
interface TimezoneItem {
|
|
346
|
+
key: string; // IANA: "Europe/London", "America/New_York", "UTC"
|
|
347
|
+
localeKey: string; // Short name: "london", "new_york", "utc"
|
|
348
|
+
}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
**Available timezones:**
|
|
352
|
+
`UTC`, `Pacific/Honolulu`, `America/Juneau`, `America/Los_Angeles`, `America/Chicago`, `America/Toronto`, `America/Sao_Paulo`, `Europe/London`, `Europe/Berlin`, `Asia/Bahrain`, `Asia/Dubai`, `Asia/Ashkhabad`, `Asia/Almaty`, `Asia/Bangkok`, `Asia/Shanghai`, `Asia/Tokyo`, `Australia/Sydney`, `Pacific/Norfolk`
|
|
353
|
+
|
|
354
|
+
```tsx
|
|
355
|
+
const { timezones, activeTimezone, setTimezone } = useTimezone();
|
|
356
|
+
|
|
357
|
+
<select value={activeTimezone} onChange={(e) => setTimezone(e.target.value)}>
|
|
358
|
+
{timezones.map((tz) => (
|
|
359
|
+
<option key={tz.key} value={tz.key}>
|
|
360
|
+
{tz.key}
|
|
361
|
+
</option>
|
|
362
|
+
))}
|
|
363
|
+
</select>;
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
### useSymbolSearch
|
|
369
|
+
|
|
370
|
+
Search and select a trading instrument.
|
|
371
|
+
|
|
372
|
+
```typescript
|
|
373
|
+
const {
|
|
374
|
+
query,
|
|
375
|
+
results,
|
|
376
|
+
isSearching,
|
|
377
|
+
activeSymbol,
|
|
378
|
+
setQuery,
|
|
379
|
+
selectSymbol,
|
|
380
|
+
clearResults,
|
|
381
|
+
} = useSymbolSearch(debounceMs);
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
| Parameter | Type | Default | Description |
|
|
385
|
+
| ------------ | -------- | ------- | --------------------------------------------- |
|
|
386
|
+
| `debounceMs` | `number` | `300` | Delay before calling `datafeed.searchSymbols` |
|
|
387
|
+
|
|
388
|
+
| Field | Type | Description |
|
|
389
|
+
| -------------- | ------------------------------------- | --------------------------------------------- |
|
|
390
|
+
| `query` | `string` | Current search query |
|
|
391
|
+
| `results` | `PartialSymbolInfo[]` | Results from the last search |
|
|
392
|
+
| `isSearching` | `boolean` | `true` while the request is in flight |
|
|
393
|
+
| `activeSymbol` | `PartialSymbolInfo \| null` | Currently selected symbol from `state.symbol` |
|
|
394
|
+
| `setQuery` | `(q: string) => void` | Update the query (triggers debounced search) |
|
|
395
|
+
| `selectSymbol` | `(symbol: PartialSymbolInfo) => void` | Select a symbol — dispatches `SET_SYMBOL` |
|
|
396
|
+
| `clearResults` | `() => void` | Clear search results |
|
|
397
|
+
|
|
398
|
+
The hook automatically cancels in-flight requests via `AbortController` on every new keystroke and on unmount.
|
|
399
|
+
|
|
400
|
+
```tsx
|
|
401
|
+
const { query, results, isSearching, selectSymbol, setQuery } =
|
|
402
|
+
useSymbolSearch(300);
|
|
403
|
+
|
|
404
|
+
<input
|
|
405
|
+
value={query}
|
|
406
|
+
onChange={(e) => setQuery(e.target.value)}
|
|
407
|
+
placeholder="Search..."
|
|
408
|
+
/>;
|
|
409
|
+
{
|
|
410
|
+
isSearching && <Spinner />;
|
|
411
|
+
}
|
|
412
|
+
{
|
|
413
|
+
results.map((sym) => (
|
|
414
|
+
<button key={sym.ticker} onClick={() => selectSymbol(sym)}>
|
|
415
|
+
{sym.ticker}
|
|
416
|
+
</button>
|
|
417
|
+
));
|
|
418
|
+
}
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
---
|
|
422
|
+
|
|
423
|
+
### useIndicators
|
|
424
|
+
|
|
425
|
+
Full indicator management: add/remove, visibility, parameters, move between panes.
|
|
426
|
+
|
|
427
|
+
```typescript
|
|
428
|
+
const {
|
|
429
|
+
mainIndicators,
|
|
430
|
+
subIndicators,
|
|
431
|
+
activeMainIndicators,
|
|
432
|
+
activeSubIndicators,
|
|
433
|
+
availableMainIndicators,
|
|
434
|
+
availableSubIndicators,
|
|
435
|
+
addMainIndicator,
|
|
436
|
+
removeMainIndicator,
|
|
437
|
+
addSubIndicator,
|
|
438
|
+
removeSubIndicator,
|
|
439
|
+
toggleMainIndicator,
|
|
440
|
+
toggleSubIndicator,
|
|
441
|
+
moveToMain,
|
|
442
|
+
moveToSub,
|
|
443
|
+
setIndicatorVisible,
|
|
444
|
+
updateIndicatorParams,
|
|
445
|
+
getIndicatorParams,
|
|
446
|
+
isMainIndicatorActive,
|
|
447
|
+
isSubIndicatorActive,
|
|
448
|
+
} = useIndicators();
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
#### Fields
|
|
452
|
+
|
|
453
|
+
| Field | Type | Description |
|
|
454
|
+
| ------------------------- | ------------------------ | ------------------------------------------ |
|
|
455
|
+
| `mainIndicators` | `IndicatorInfo[]` | All main indicators with `isActive` flag |
|
|
456
|
+
| `subIndicators` | `IndicatorInfo[]` | All sub-indicators with `isActive` flag |
|
|
457
|
+
| `activeMainIndicators` | `string[]` | Active main indicator names only |
|
|
458
|
+
| `activeSubIndicators` | `Record<string, string>` | Active sub-indicators: `{ name → paneId }` |
|
|
459
|
+
| `availableMainIndicators` | `string[]` | Full list from `MAIN_INDICATORS` |
|
|
460
|
+
| `availableSubIndicators` | `string[]` | Full list from `SUB_INDICATORS` |
|
|
461
|
+
|
|
462
|
+
```typescript
|
|
463
|
+
interface IndicatorInfo {
|
|
464
|
+
name: string; // "MA", "MACD", "RSI", etc.
|
|
465
|
+
isActive: boolean; // Whether it is currently on the chart
|
|
466
|
+
}
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
#### Methods
|
|
470
|
+
|
|
471
|
+
| Method | Description |
|
|
472
|
+
| --------------------------------------------- | ------------------------------------------------------------- |
|
|
473
|
+
| `addMainIndicator(name)` | Creates the indicator on `candle_pane` with id `main_${name}` |
|
|
474
|
+
| `removeMainIndicator(name)` | Removes the indicator and updates state |
|
|
475
|
+
| `addSubIndicator(name)` | Creates the indicator on a new sub-pane with id `sub_${name}` |
|
|
476
|
+
| `removeSubIndicator(name)` | Removes the sub-indicator and its pane |
|
|
477
|
+
| `toggleMainIndicator(name)` | `add` if inactive, `remove` if active |
|
|
478
|
+
| `toggleSubIndicator(name)` | Same for sub-indicators |
|
|
479
|
+
| `moveToMain(name)` | Moves from sub-pane to `candle_pane` |
|
|
480
|
+
| `moveToSub(name)` | Moves from `candle_pane` to a new sub-pane |
|
|
481
|
+
| `setIndicatorVisible(name, isMain, visible)` | Show/hide indicator via `chart.overrideIndicator` |
|
|
482
|
+
| `updateIndicatorParams(name, paneId, params)` | Update `calcParams` via `chart.overrideIndicator` |
|
|
483
|
+
| `getIndicatorParams(name)` | Returns `[{ label, defaultValue }]` or `[]` if no parameters |
|
|
484
|
+
| `isMainIndicatorActive(name)` | Quick active check |
|
|
485
|
+
| `isSubIndicatorActive(name)` | Quick active check |
|
|
486
|
+
|
|
487
|
+
#### Available indicators
|
|
488
|
+
|
|
489
|
+
**Main chart (`MAIN_INDICATORS`):** MA, EMA, SMA, BOLL, SAR, BBI
|
|
490
|
+
|
|
491
|
+
**Sub-panes (`SUB_INDICATORS`):** MA, EMA, VOL, MACD, BOLL, KDJ, RSI, BIAS, BRAR, CCI, DMI, CR, PSY, DMA, TRIX, OBV, VR, WR, MTM, EMV, SAR, SMA, ROC, PVT, BBI, AO
|
|
492
|
+
|
|
493
|
+
**Indicators with configurable parameters:** SMA, BOLL, SAR, BBI, MACD, KDJ, BRAR, CCI, DMI, CR, PSY, DMA, TRIX, OBV, VR, MTM, EMV, ROC, AO and others.
|
|
494
|
+
|
|
495
|
+
---
|
|
496
|
+
|
|
497
|
+
### useDrawingTools
|
|
498
|
+
|
|
499
|
+
Manage drawing tools (chart overlays).
|
|
500
|
+
|
|
501
|
+
```typescript
|
|
502
|
+
const {
|
|
503
|
+
categories,
|
|
504
|
+
activeTool,
|
|
505
|
+
magnetMode,
|
|
506
|
+
isLocked,
|
|
507
|
+
isVisible,
|
|
508
|
+
selectTool,
|
|
509
|
+
clearActiveTool,
|
|
510
|
+
setMagnetMode,
|
|
511
|
+
toggleLock,
|
|
512
|
+
toggleVisibility,
|
|
513
|
+
removeAllDrawings,
|
|
514
|
+
} = useDrawingTools();
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
| Field/Method | Type | Description |
|
|
518
|
+
| --------------------- | -------------------------------- | ------------------------------------------------------- |
|
|
519
|
+
| `categories` | `DrawingCategoryItem[]` | Tool categories with nested tools |
|
|
520
|
+
| `activeTool` | `string \| null` | Name of the last selected tool |
|
|
521
|
+
| `magnetMode` | `"normal" \| "weak" \| "strong"` | Snap-to-OHLC mode |
|
|
522
|
+
| `isLocked` | `boolean` | Whether all drawings are locked |
|
|
523
|
+
| `isVisible` | `boolean` | Whether all drawings are visible |
|
|
524
|
+
| `selectTool(name)` | — | Start drawing via `chart.createOverlay` |
|
|
525
|
+
| `clearActiveTool()` | — | Deselect tool (local state only) |
|
|
526
|
+
| `setMagnetMode(mode)` | — | Change magnet mode for all existing and future drawings |
|
|
527
|
+
| `toggleLock()` | — | Toggle lock on all drawings |
|
|
528
|
+
| `toggleVisibility()` | — | Show/hide all drawings |
|
|
529
|
+
| `removeAllDrawings()` | — | Remove all drawings in the `drawing_tools` group |
|
|
530
|
+
|
|
531
|
+
```typescript
|
|
532
|
+
interface DrawingToolItem {
|
|
533
|
+
name: string; // klinecharts overlay name, e.g. "arrow", "fibonacciLine"
|
|
534
|
+
localeKey: string; // Localization key
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
interface DrawingCategoryItem {
|
|
538
|
+
key: string; // "singleLine" | "moreLine" | "polygon" | "fibonacci" | "wave"
|
|
539
|
+
tools: DrawingToolItem[];
|
|
540
|
+
}
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
**Categories and tools:**
|
|
544
|
+
|
|
545
|
+
| Category (`key`) | Tools |
|
|
546
|
+
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
547
|
+
| `singleLine` | horizontalStraightLine, horizontalRayLine, horizontalSegment, verticalStraightLine, verticalRayLine, verticalSegment, straightLine, rayLine, segment, arrow, priceLine |
|
|
548
|
+
| `moreLine` | priceChannelLine, parallelStraightLine |
|
|
549
|
+
| `polygon` | circle, rect, parallelogram, triangle |
|
|
550
|
+
| `fibonacci` | fibonacciLine, fibonacciSegment, fibonacciCircle, fibonacciSpiral, fibonacciSpeedResistanceFan, fibonacciExtension, gannBox |
|
|
551
|
+
| `wave` | xabcd, abcd, threeWaves, fiveWaves, eightWaves, anyWaves |
|
|
552
|
+
|
|
553
|
+
---
|
|
554
|
+
|
|
555
|
+
### useKlinechartsUISettings
|
|
556
|
+
|
|
557
|
+
Manage chart appearance: candle type, colors, price marks, axes, grid, crosshair, tooltips.
|
|
558
|
+
|
|
559
|
+
```typescript
|
|
560
|
+
const settings = useKlinechartsUISettings();
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
#### State
|
|
564
|
+
|
|
565
|
+
| Field | Type | Default | Description |
|
|
566
|
+
| ------------------------ | --------------- | ---------------- | ------------------------- |
|
|
567
|
+
| `candleType` | `string` | `"candle_solid"` | Candle display type |
|
|
568
|
+
| `candleUpColor` | `string` | `"#2DC08E"` | Bullish candle color |
|
|
569
|
+
| `candleDownColor` | `string` | `"#F92855"` | Bearish candle color |
|
|
570
|
+
| `showLastPrice` | `boolean` | `true` | Last price mark on Y-axis |
|
|
571
|
+
| `showHighPrice` | `boolean` | `true` | High price mark |
|
|
572
|
+
| `showLowPrice` | `boolean` | `true` | Low price mark |
|
|
573
|
+
| `showIndicatorLastValue` | `boolean` | `true` | Indicator last value mark |
|
|
574
|
+
| `priceAxisType` | `PriceAxisType` | `"normal"` | Y-axis scale type |
|
|
575
|
+
| `reverseCoordinate` | `boolean` | `false` | Invert Y-axis |
|
|
576
|
+
| `showTimeAxis` | `boolean` | `true` | Show X-axis |
|
|
577
|
+
| `showGrid` | `boolean` | `true` | Show grid |
|
|
578
|
+
| `showCrosshair` | `boolean` | `true` | Show crosshair |
|
|
579
|
+
| `showCandleTooltip` | `boolean` | `true` | OHLCV tooltip |
|
|
580
|
+
| `showIndicatorTooltip` | `boolean` | `true` | Indicator tooltip |
|
|
581
|
+
|
|
582
|
+
**Candle types:** `candle_solid`, `candle_stroke`, `candle_up_stroke`, `candle_down_stroke`, `ohlc`, `area`
|
|
583
|
+
|
|
584
|
+
**Price axis types:** `"normal"`, `"percentage"`, `"log"`
|
|
585
|
+
|
|
586
|
+
#### Extra fields
|
|
587
|
+
|
|
588
|
+
| Field | Type | Description |
|
|
589
|
+
| ---------------- | --------------------------------------------- | ----------------------------------------------------- |
|
|
590
|
+
| `candleTypes` | `CandleTypeItem[]` | List of `{ key, localeKey }` for rendering a selector |
|
|
591
|
+
| `priceAxisTypes` | `{ key: PriceAxisType; localeKey: string }[]` | List for rendering a selector |
|
|
592
|
+
|
|
593
|
+
#### Setters
|
|
594
|
+
|
|
595
|
+
Each field has a corresponding setter: `setCandleType`, `setCandleUpColor`, `setCandleDownColor`, `setShowLastPrice`, `setShowHighPrice`, `setShowLowPrice`, `setShowIndicatorLastValue`, `setPriceAxisType`, `setReverseCoordinate`, `setShowTimeAxis`, `setShowGrid`, `setShowCrosshair`, `setShowCandleTooltip`, `setShowIndicatorTooltip`.
|
|
596
|
+
|
|
597
|
+
All setters immediately apply changes via `chart.setStyles(...)`.
|
|
598
|
+
|
|
599
|
+
| Method | Description |
|
|
600
|
+
| ------------------- | ----------------------------------------------------------- |
|
|
601
|
+
| `resetToDefaults()` | Reset all settings to defaults via `chart.setStyles(theme)` |
|
|
602
|
+
|
|
603
|
+
> **Important:** Settings are stored in local `useState` inside the hook — they are not part of the provider's reducer state. The hook must be called unconditionally (not only when a dialog is open) to preserve settings across dialog open/close cycles. Changes trigger `onSettingsChange` from the provider.
|
|
604
|
+
|
|
605
|
+
---
|
|
606
|
+
|
|
607
|
+
### useScreenshot
|
|
608
|
+
|
|
609
|
+
Capture and download a chart screenshot.
|
|
610
|
+
|
|
611
|
+
```typescript
|
|
612
|
+
const { screenshotUrl, capture, download, clear } = useScreenshot();
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
| Field/Method | Type | Description |
|
|
616
|
+
| --------------------- | ----------------------------- | ------------------------------------------------------ |
|
|
617
|
+
| `screenshotUrl` | `string \| null` | JPEG data URL of the last screenshot |
|
|
618
|
+
| `capture()` | `() => void` | Capture the current chart state |
|
|
619
|
+
| `download(filename?)` | `(filename?: string) => void` | Download as a file (default: `"chart-screenshot.jpg"`) |
|
|
620
|
+
| `clear()` | `() => void` | Clear `screenshotUrl` from state |
|
|
621
|
+
|
|
622
|
+
Screenshot is created via `chart.getConvertPictureUrl(true, "jpeg", bgColor)`. Background depends on the current theme: `#151517` for dark, `#ffffff` for light.
|
|
623
|
+
|
|
624
|
+
```tsx
|
|
625
|
+
const { screenshotUrl, capture, download, clear } = useScreenshot();
|
|
626
|
+
|
|
627
|
+
<button onClick={capture}>Capture</button>;
|
|
628
|
+
{
|
|
629
|
+
screenshotUrl && (
|
|
630
|
+
<>
|
|
631
|
+
<img src={screenshotUrl} alt="chart" />
|
|
632
|
+
<button onClick={() => download()}>Download</button>
|
|
633
|
+
<button onClick={clear}>Close</button>
|
|
634
|
+
</>
|
|
635
|
+
);
|
|
636
|
+
}
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
---
|
|
640
|
+
|
|
641
|
+
### useFullscreen
|
|
642
|
+
|
|
643
|
+
Toggle fullscreen mode. Uses `fullscreenContainerRef` from the provider.
|
|
644
|
+
|
|
645
|
+
```typescript
|
|
646
|
+
const { isFullscreen, toggle, enter, exit, containerRef } = useFullscreen();
|
|
647
|
+
```
|
|
648
|
+
|
|
649
|
+
| Field/Method | Type | Description |
|
|
650
|
+
| -------------- | -------------------------------- | ------------------------------ |
|
|
651
|
+
| `isFullscreen` | `boolean` | Current fullscreen state |
|
|
652
|
+
| `toggle()` | `() => void` | Toggle |
|
|
653
|
+
| `enter()` | `() => void` | Enter fullscreen |
|
|
654
|
+
| `exit()` | `() => void` | Exit fullscreen |
|
|
655
|
+
| `containerRef` | `RefObject<HTMLElement \| null>` | The same ref from the provider |
|
|
656
|
+
|
|
657
|
+
Supports cross-browser vendor prefixes (`webkit`, `ms`).
|
|
658
|
+
|
|
659
|
+
**Important:** `containerRef` must be assigned to the container element that should occupy the full screen (typically the root layout element):
|
|
660
|
+
|
|
661
|
+
```tsx
|
|
662
|
+
const { containerRef, toggle, isFullscreen } = useFullscreen();
|
|
663
|
+
|
|
664
|
+
<div ref={containerRef as React.RefObject<HTMLDivElement>}>
|
|
665
|
+
<button onClick={toggle}>{isFullscreen ? "Exit" : "Fullscreen"}</button>
|
|
666
|
+
<ChartView />
|
|
667
|
+
</div>;
|
|
668
|
+
```
|
|
669
|
+
|
|
670
|
+
---
|
|
671
|
+
|
|
672
|
+
### useOrderLines
|
|
673
|
+
|
|
674
|
+
Create and manage horizontal price level lines (order lines).
|
|
675
|
+
|
|
676
|
+
> **Requirement:** The `orderLine` overlay must be registered via `overlays={[orderLine]}` on the provider.
|
|
677
|
+
|
|
678
|
+
```typescript
|
|
679
|
+
const {
|
|
680
|
+
createOrderLine,
|
|
681
|
+
updateOrderLine,
|
|
682
|
+
removeOrderLine,
|
|
683
|
+
removeAllOrderLines,
|
|
684
|
+
} = useOrderLines();
|
|
685
|
+
```
|
|
686
|
+
|
|
687
|
+
#### createOrderLine
|
|
688
|
+
|
|
689
|
+
```typescript
|
|
690
|
+
createOrderLine(options: OrderLineOptions): string | null
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
Returns the `id` of the created line, or `null` if the chart is not ready.
|
|
694
|
+
|
|
695
|
+
```typescript
|
|
696
|
+
interface OrderLineOptions extends OrderLineExtendData {
|
|
697
|
+
id?: string; // Auto-generated if omitted
|
|
698
|
+
price: number; // Price level
|
|
699
|
+
draggable?: boolean; // Allow drag to change price. Default: false
|
|
700
|
+
onPriceChange?: (price: number) => void; // Called when drag ends
|
|
701
|
+
}
|
|
702
|
+
```
|
|
703
|
+
|
|
704
|
+
All `OrderLineExtendData` fields (see [orderLine extension](#orderline)) are accepted directly — they flow through as overlay `extendData`.
|
|
705
|
+
|
|
706
|
+
#### updateOrderLine
|
|
707
|
+
|
|
708
|
+
```typescript
|
|
709
|
+
updateOrderLine(id: string, options: Partial<Omit<OrderLineOptions, "id">>): void
|
|
710
|
+
```
|
|
711
|
+
|
|
712
|
+
Updates an existing line. Only pass the fields you want to change.
|
|
713
|
+
|
|
714
|
+
#### removeOrderLine / removeAllOrderLines
|
|
715
|
+
|
|
716
|
+
```typescript
|
|
717
|
+
removeOrderLine(id: string): void
|
|
718
|
+
removeAllOrderLines(): void // Removes all overlays with name="orderLine"
|
|
719
|
+
```
|
|
720
|
+
|
|
721
|
+
```tsx
|
|
722
|
+
const { createOrderLine, updateOrderLine, removeOrderLine } = useOrderLines();
|
|
723
|
+
|
|
724
|
+
const id = createOrderLine({
|
|
725
|
+
price: 45000,
|
|
726
|
+
color: "#ff9900",
|
|
727
|
+
text: "Target",
|
|
728
|
+
line: { style: "dashed" },
|
|
729
|
+
mark: { bg: "#ff9900", color: "#fff" },
|
|
730
|
+
draggable: true,
|
|
731
|
+
onPriceChange: (newPrice) => console.log("Moved to:", newPrice),
|
|
732
|
+
});
|
|
733
|
+
|
|
734
|
+
updateOrderLine(id!, { color: "#00ff00" });
|
|
735
|
+
removeOrderLine(id!);
|
|
736
|
+
```
|
|
737
|
+
|
|
738
|
+
---
|
|
739
|
+
|
|
740
|
+
## Utilities
|
|
741
|
+
|
|
742
|
+
### createDataLoader
|
|
743
|
+
|
|
744
|
+
Creates a klinecharts `DataLoader` from a `Datafeed` instance.
|
|
745
|
+
|
|
746
|
+
```typescript
|
|
747
|
+
function createDataLoader(
|
|
748
|
+
datafeed: Datafeed,
|
|
749
|
+
dispatch: Dispatch<KlinechartsUIAction>,
|
|
750
|
+
): DataLoader;
|
|
751
|
+
```
|
|
752
|
+
|
|
753
|
+
This bridges the `Datafeed` interface to the klinecharts native `DataLoader` format.
|
|
754
|
+
|
|
755
|
+
**Behavior:**
|
|
756
|
+
|
|
757
|
+
| klinecharts request type | Action |
|
|
758
|
+
| ------------------------ | ------------------------------------------------------------------------------------------------------- |
|
|
759
|
+
| `"init"` | Loads the latest ~1000 bars (`to=Date.now(), from=0`), saves `oldestTimestamp`, increments `currentGen` |
|
|
760
|
+
| `"forward"` | Loads bars older than `oldestTimestamp - 1` for left-scroll pagination |
|
|
761
|
+
| `"backward"` | Ignored (real-time handled via `subscribeBar`) |
|
|
762
|
+
|
|
763
|
+
**Race condition protection:** each `"init"` increments `currentGen`. If a `"forward"` request completes after a new `"init"` has started, the result is discarded.
|
|
764
|
+
|
|
765
|
+
```tsx
|
|
766
|
+
function ChartView() {
|
|
767
|
+
const { state, dispatch, datafeed } = useKlinechartsUI();
|
|
768
|
+
|
|
769
|
+
const dataLoader = useMemo(
|
|
770
|
+
() => createDataLoader(datafeed, dispatch),
|
|
771
|
+
[datafeed, dispatch],
|
|
772
|
+
);
|
|
773
|
+
|
|
774
|
+
return (
|
|
775
|
+
<KLineChart
|
|
776
|
+
dataLoader={dataLoader}
|
|
777
|
+
symbol={state.symbol ?? undefined}
|
|
778
|
+
period={state.period}
|
|
779
|
+
locale={state.locale}
|
|
780
|
+
timezone={state.timezone}
|
|
781
|
+
styles={state.theme}
|
|
782
|
+
onReady={(chart) => dispatch({ type: "SET_CHART", chart })}
|
|
783
|
+
/>
|
|
784
|
+
);
|
|
785
|
+
}
|
|
786
|
+
```
|
|
787
|
+
|
|
788
|
+
---
|
|
789
|
+
|
|
790
|
+
## Data & Constants
|
|
791
|
+
|
|
792
|
+
All constants are exported from the root `index.ts`:
|
|
793
|
+
|
|
794
|
+
### DEFAULT_PERIODS
|
|
795
|
+
|
|
796
|
+
```typescript
|
|
797
|
+
const DEFAULT_PERIODS: TerminalPeriod[] = [
|
|
798
|
+
{ span: 1, type: "minute", label: "1m" },
|
|
799
|
+
{ span: 5, type: "minute", label: "5m" },
|
|
800
|
+
{ span: 15, type: "minute", label: "15m" },
|
|
801
|
+
{ span: 1, type: "hour", label: "1H" },
|
|
802
|
+
{ span: 2, type: "hour", label: "2H" },
|
|
803
|
+
{ span: 4, type: "hour", label: "4H" },
|
|
804
|
+
{ span: 1, type: "day", label: "D" },
|
|
805
|
+
{ span: 1, type: "week", label: "W" },
|
|
806
|
+
{ span: 1, type: "month", label: "M" },
|
|
807
|
+
{ span: 1, type: "year", label: "Y" },
|
|
808
|
+
];
|
|
809
|
+
```
|
|
810
|
+
|
|
811
|
+
### TIMEZONES
|
|
812
|
+
|
|
813
|
+
Array of `TimezoneOption[]` — 18 timezones. Fields: `key` (IANA) and `localeKey` (short name).
|
|
814
|
+
|
|
815
|
+
### MAIN_INDICATORS / SUB_INDICATORS
|
|
816
|
+
|
|
817
|
+
String arrays of indicator names used as the available-for-selection list.
|
|
818
|
+
|
|
819
|
+
### INDICATOR_PARAMS
|
|
820
|
+
|
|
821
|
+
```typescript
|
|
822
|
+
const INDICATOR_PARAMS: Record<string, IndicatorDefinition>;
|
|
823
|
+
|
|
824
|
+
interface IndicatorDefinition {
|
|
825
|
+
name: string;
|
|
826
|
+
localeKey: string;
|
|
827
|
+
params: { label: string; defaultValue: number }[];
|
|
828
|
+
}
|
|
829
|
+
```
|
|
830
|
+
|
|
831
|
+
Used internally by `getIndicatorParams` inside `useIndicators`.
|
|
832
|
+
|
|
833
|
+
### DRAWING_CATEGORIES
|
|
834
|
+
|
|
835
|
+
Array of drawing tool categories. Used by `useDrawingTools`.
|
|
836
|
+
|
|
837
|
+
### CANDLE_TYPES
|
|
838
|
+
|
|
839
|
+
```typescript
|
|
840
|
+
const CANDLE_TYPES: CandleTypeOption[] = [
|
|
841
|
+
{ key: "candle_solid", localeKey: "candle_solid" },
|
|
842
|
+
{ key: "candle_stroke", localeKey: "candle_stroke" },
|
|
843
|
+
{ key: "candle_up_stroke", localeKey: "candle_up_stroke" },
|
|
844
|
+
{ key: "candle_down_stroke", localeKey: "candle_down_stroke" },
|
|
845
|
+
{ key: "ohlc", localeKey: "ohlc" },
|
|
846
|
+
{ key: "area", localeKey: "area" },
|
|
847
|
+
];
|
|
848
|
+
```
|
|
849
|
+
|
|
850
|
+
### PRICE_AXIS_TYPES
|
|
851
|
+
|
|
852
|
+
```typescript
|
|
853
|
+
const PRICE_AXIS_TYPES = ["normal", "percentage", "log"] as const;
|
|
854
|
+
type PriceAxisType = "normal" | "percentage" | "log";
|
|
855
|
+
```
|
|
856
|
+
|
|
857
|
+
---
|
|
858
|
+
|
|
859
|
+
## Drawing Overlays
|
|
860
|
+
|
|
861
|
+
`OverlayTemplate` instances for drawing tools. Automatically registered when `registerExtensions: true` (default).
|
|
862
|
+
|
|
863
|
+
**Named exports:**
|
|
864
|
+
|
|
865
|
+
| Export | Overlay name | Description |
|
|
866
|
+
| ----------------------------- | ------------------------------- | ------------------- |
|
|
867
|
+
| `arrow` | `"arrow"` | Arrow |
|
|
868
|
+
| `circle` | `"circle"` | Circle |
|
|
869
|
+
| `rect` | `"rect"` | Rectangle |
|
|
870
|
+
| `triangle` | `"triangle"` | Triangle |
|
|
871
|
+
| `parallelogram` | `"parallelogram"` | Parallelogram |
|
|
872
|
+
| `fibonacciCircle` | `"fibonacciCircle"` | Fibonacci circle |
|
|
873
|
+
| `fibonacciSegment` | `"fibonacciSegment"` | Fibonacci segment |
|
|
874
|
+
| `fibonacciSpiral` | `"fibonacciSpiral"` | Fibonacci spiral |
|
|
875
|
+
| `fibonacciSpeedResistanceFan` | `"fibonacciSpeedResistanceFan"` | Fibonacci fan |
|
|
876
|
+
| `fibonacciExtension` | `"fibonacciExtension"` | Fibonacci extension |
|
|
877
|
+
| `gannBox` | `"gannBox"` | Gann box |
|
|
878
|
+
| `threeWaves` | `"threeWaves"` | 3-wave pattern |
|
|
879
|
+
| `fiveWaves` | `"fiveWaves"` | 5-wave pattern |
|
|
880
|
+
| `eightWaves` | `"eightWaves"` | 8-wave pattern |
|
|
881
|
+
| `anyWaves` | `"anyWaves"` | Custom wave pattern |
|
|
882
|
+
| `abcd` | `"abcd"` | ABCD pattern |
|
|
883
|
+
| `xabcd` | `"xabcd"` | XABCD pattern |
|
|
884
|
+
|
|
885
|
+
---
|
|
886
|
+
|
|
887
|
+
## Extensions
|
|
888
|
+
|
|
889
|
+
### registerExtensions
|
|
890
|
+
|
|
891
|
+
Registers all built-in drawing overlays via `registerOverlay`. Called automatically by the provider when `registerExtensions: true`.
|
|
892
|
+
|
|
893
|
+
```typescript
|
|
894
|
+
import { registerExtensions } from "react-klinecharts-ui";
|
|
895
|
+
registerExtensions(); // Idempotent — repeated calls are ignored
|
|
896
|
+
```
|
|
897
|
+
|
|
898
|
+
### orderLine
|
|
899
|
+
|
|
900
|
+
Overlay template for horizontal price level lines. **Not registered automatically** — must be passed explicitly to the provider.
|
|
901
|
+
|
|
902
|
+
```typescript
|
|
903
|
+
import { orderLine, KlinechartsUIProvider } from "react-klinecharts-ui";
|
|
904
|
+
|
|
905
|
+
<KlinechartsUIProvider overlays={[orderLine]}>...</KlinechartsUIProvider>;
|
|
906
|
+
```
|
|
907
|
+
|
|
908
|
+
**Implementation details:**
|
|
909
|
+
|
|
910
|
+
- `needDefaultYAxisFigure: false` — custom rendering of the Y-axis mark
|
|
911
|
+
- `createYAxisFigures` — draws a colored price mark on the right axis
|
|
912
|
+
- `createPointFigures` — draws a horizontal line with an optional text label
|
|
913
|
+
- `performEventPressedMove` — updates `points[0].value` during drag
|
|
914
|
+
- Uses `chart.getSymbol()?.pricePrecision ?? 2` for price formatting
|
|
915
|
+
|
|
916
|
+
#### OrderLineExtendData
|
|
917
|
+
|
|
918
|
+
All fields are optional. Defaults produce an orange dashed line with a white-on-orange price mark.
|
|
919
|
+
|
|
920
|
+
```typescript
|
|
921
|
+
interface OrderLineExtendData {
|
|
922
|
+
/** Primary color for line, mark bg, and label fallback. Default: "rgba(255, 165, 0, 0.85)" */
|
|
923
|
+
color?: string;
|
|
924
|
+
/** Optional text label displayed above the line. */
|
|
925
|
+
text?: string;
|
|
926
|
+
/** Line style overrides. */
|
|
927
|
+
line?: OrderLineLineStyle;
|
|
928
|
+
/** Y-axis price mark style overrides. */
|
|
929
|
+
mark?: OrderLineMarkStyle;
|
|
930
|
+
/** Text label style overrides. */
|
|
931
|
+
label?: OrderLineLabelStyle;
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
interface OrderLineLineStyle {
|
|
935
|
+
style?: "solid" | "dashed" | "dotted"; // Default: "dashed"
|
|
936
|
+
width?: number; // Default: 1
|
|
937
|
+
dashedValue?: [number, number]; // Default: [4, 2]
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
interface OrderLineMarkStyle {
|
|
941
|
+
color?: string; // Text color. Default: "#ffffff"
|
|
942
|
+
bg?: string; // Background (falls back to top-level color)
|
|
943
|
+
borderRadius?: number; // Default: 2
|
|
944
|
+
font?: OrderLineFontStyle;
|
|
945
|
+
padding?: OrderLinePadding;
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
interface OrderLineLabelStyle {
|
|
949
|
+
color?: string; // Text color (falls back to top-level color)
|
|
950
|
+
bg?: string; // Background. Default: "transparent"
|
|
951
|
+
borderRadius?: number; // Default: 0
|
|
952
|
+
font?: OrderLineFontStyle;
|
|
953
|
+
padding?: OrderLinePadding;
|
|
954
|
+
offset?: OrderLinePadding; // Position offset. Defaults: x=8, y=3
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
interface OrderLineFontStyle {
|
|
958
|
+
size?: number; // Default: 11
|
|
959
|
+
family?: string; // Default: "Helvetica Neue, Arial, sans-serif"
|
|
960
|
+
weight?: string; // Default: "bold" (mark) / "normal" (label)
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
interface OrderLinePadding {
|
|
964
|
+
x?: number;
|
|
965
|
+
y?: number;
|
|
966
|
+
}
|
|
967
|
+
```
|
|
968
|
+
|
|
969
|
+
All sub-interfaces (`OrderLineLineStyle`, `OrderLineMarkStyle`, `OrderLineLabelStyle`, `OrderLineFontStyle`, `OrderLinePadding`) are exported as named types from both the main and `extensions` entry points.
|
|
970
|
+
|
|
971
|
+
### overlays (array)
|
|
972
|
+
|
|
973
|
+
Array of all built-in drawing overlays — for direct access to the list:
|
|
974
|
+
|
|
975
|
+
```typescript
|
|
976
|
+
import { overlays } from "react-klinecharts-ui";
|
|
977
|
+
// overlays === [arrow, circle, rect, triangle, ...] (17 items)
|
|
978
|
+
```
|
|
979
|
+
|
|
980
|
+
---
|
|
981
|
+
|
|
982
|
+
## State Callbacks
|
|
983
|
+
|
|
984
|
+
Callbacks are invoked **synchronously** inside `enhancedDispatch`, before the React re-render — enabling immediate state persistence.
|
|
985
|
+
|
|
986
|
+
```tsx
|
|
987
|
+
<KlinechartsUIProvider
|
|
988
|
+
datafeed={datafeed}
|
|
989
|
+
onStateChange={(action, nextState, prevState) => {
|
|
990
|
+
// Called for every dispatched action
|
|
991
|
+
console.log(action.type, nextState);
|
|
992
|
+
}}
|
|
993
|
+
onSymbolChange={(symbol) => {
|
|
994
|
+
localStorage.setItem('symbol', JSON.stringify(symbol));
|
|
995
|
+
}}
|
|
996
|
+
onPeriodChange={(period) => {
|
|
997
|
+
localStorage.setItem('period', JSON.stringify(period));
|
|
998
|
+
}}
|
|
999
|
+
onThemeChange={(theme) => {
|
|
1000
|
+
localStorage.setItem('theme', theme);
|
|
1001
|
+
}}
|
|
1002
|
+
onTimezoneChange={(timezone) => {
|
|
1003
|
+
localStorage.setItem('timezone', timezone);
|
|
1004
|
+
}}
|
|
1005
|
+
onMainIndicatorsChange={(indicators) => {
|
|
1006
|
+
localStorage.setItem('mainIndicators', JSON.stringify(indicators));
|
|
1007
|
+
}}
|
|
1008
|
+
onSubIndicatorsChange={(indicators) => {
|
|
1009
|
+
localStorage.setItem('subIndicators', JSON.stringify(indicators));
|
|
1010
|
+
}}
|
|
1011
|
+
onSettingsChange={(settings) => {
|
|
1012
|
+
// Called from useKlinechartsUISettings on every change
|
|
1013
|
+
localStorage.setItem('settings', JSON.stringify(settings));
|
|
1014
|
+
}}
|
|
1015
|
+
>
|
|
1016
|
+
```
|
|
1017
|
+
|
|
1018
|
+
**Restoring persisted state:**
|
|
1019
|
+
|
|
1020
|
+
```tsx
|
|
1021
|
+
const savedSymbol = JSON.parse(localStorage.getItem('symbol') ?? 'null');
|
|
1022
|
+
const savedTheme = localStorage.getItem('theme') ?? 'dark';
|
|
1023
|
+
|
|
1024
|
+
<KlinechartsUIProvider
|
|
1025
|
+
defaultSymbol={savedSymbol ?? { ticker: 'BTCUSDT' }}
|
|
1026
|
+
defaultTheme={savedTheme}
|
|
1027
|
+
>
|
|
1028
|
+
```
|
|
1029
|
+
|
|
1030
|
+
---
|
|
1031
|
+
|
|
1032
|
+
## Full Export List
|
|
1033
|
+
|
|
1034
|
+
```typescript
|
|
1035
|
+
// Provider & context
|
|
1036
|
+
export { KlinechartsUIProvider };
|
|
1037
|
+
export {
|
|
1038
|
+
useKlinechartsUI,
|
|
1039
|
+
KlinechartsUIStateContext,
|
|
1040
|
+
KlinechartsUIDispatchContext,
|
|
1041
|
+
};
|
|
1042
|
+
export type {
|
|
1043
|
+
KlinechartsUIOptions,
|
|
1044
|
+
KlinechartsUIState,
|
|
1045
|
+
KlinechartsUIAction,
|
|
1046
|
+
KlinechartsUIContextValue,
|
|
1047
|
+
KlinechartsUIDispatchValue,
|
|
1048
|
+
Datafeed,
|
|
1049
|
+
PartialSymbolInfo,
|
|
1050
|
+
};
|
|
1051
|
+
|
|
1052
|
+
// Hooks
|
|
1053
|
+
export { useKlinechartsUITheme, type UseKlinechartsUIThemeReturn };
|
|
1054
|
+
export { useKlinechartsUILoading, type UseKlinechartsUILoadingReturn };
|
|
1055
|
+
export { usePeriods, type UsePeriodsReturn };
|
|
1056
|
+
export { useTimezone, type UseTimezoneReturn, type TimezoneItem };
|
|
1057
|
+
export { useSymbolSearch, type UseSymbolSearchReturn };
|
|
1058
|
+
export { useIndicators, type UseIndicatorsReturn, type IndicatorInfo };
|
|
1059
|
+
export {
|
|
1060
|
+
useDrawingTools,
|
|
1061
|
+
type UseDrawingToolsReturn,
|
|
1062
|
+
type DrawingToolItem,
|
|
1063
|
+
type DrawingCategoryItem,
|
|
1064
|
+
};
|
|
1065
|
+
export {
|
|
1066
|
+
useKlinechartsUISettings,
|
|
1067
|
+
type UseKlinechartsUISettingsReturn,
|
|
1068
|
+
type KlinechartsUISettingsState,
|
|
1069
|
+
type CandleTypeItem,
|
|
1070
|
+
};
|
|
1071
|
+
export { useScreenshot, type UseScreenshotReturn };
|
|
1072
|
+
export { useFullscreen, type UseFullscreenReturn };
|
|
1073
|
+
export { useOrderLines, type UseOrderLinesReturn, type OrderLineOptions };
|
|
1074
|
+
|
|
1075
|
+
// Data
|
|
1076
|
+
export { DEFAULT_PERIODS, type TerminalPeriod };
|
|
1077
|
+
export { TIMEZONES, type TimezoneOption };
|
|
1078
|
+
export {
|
|
1079
|
+
MAIN_INDICATORS,
|
|
1080
|
+
SUB_INDICATORS,
|
|
1081
|
+
INDICATOR_PARAMS,
|
|
1082
|
+
type IndicatorParamConfig,
|
|
1083
|
+
type IndicatorDefinition,
|
|
1084
|
+
};
|
|
1085
|
+
export {
|
|
1086
|
+
DRAWING_CATEGORIES,
|
|
1087
|
+
type DrawingTool,
|
|
1088
|
+
type DrawingToolCategory,
|
|
1089
|
+
type MagnetMode,
|
|
1090
|
+
};
|
|
1091
|
+
export {
|
|
1092
|
+
CANDLE_TYPES,
|
|
1093
|
+
PRICE_AXIS_TYPES,
|
|
1094
|
+
type CandleTypeOption,
|
|
1095
|
+
type PriceAxisType,
|
|
1096
|
+
};
|
|
1097
|
+
|
|
1098
|
+
// Utilities
|
|
1099
|
+
export { createDataLoader };
|
|
1100
|
+
|
|
1101
|
+
// Drawing overlays (all 17)
|
|
1102
|
+
export {
|
|
1103
|
+
arrow,
|
|
1104
|
+
circle,
|
|
1105
|
+
rect,
|
|
1106
|
+
triangle,
|
|
1107
|
+
parallelogram,
|
|
1108
|
+
fibonacciCircle,
|
|
1109
|
+
fibonacciSegment,
|
|
1110
|
+
fibonacciSpiral,
|
|
1111
|
+
fibonacciSpeedResistanceFan,
|
|
1112
|
+
fibonacciExtension,
|
|
1113
|
+
gannBox,
|
|
1114
|
+
threeWaves,
|
|
1115
|
+
fiveWaves,
|
|
1116
|
+
eightWaves,
|
|
1117
|
+
anyWaves,
|
|
1118
|
+
abcd,
|
|
1119
|
+
xabcd,
|
|
1120
|
+
};
|
|
1121
|
+
|
|
1122
|
+
// Extensions
|
|
1123
|
+
export { registerExtensions, overlays, orderLine };
|
|
1124
|
+
export type {
|
|
1125
|
+
OrderLineExtendData,
|
|
1126
|
+
OrderLineLineStyle,
|
|
1127
|
+
OrderLineMarkStyle,
|
|
1128
|
+
OrderLineLabelStyle,
|
|
1129
|
+
OrderLineFontStyle,
|
|
1130
|
+
OrderLinePadding,
|
|
1131
|
+
};
|
|
1132
|
+
```
|