@iccandle/reactjs-widget 0.1.3 → 0.1.6
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 +186 -244
- package/dist/widget-iccandle.cjs +17 -17
- package/dist/widget-iccandle.js +1859 -1896
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,181 +1,40 @@
|
|
|
1
1
|
# @iccandle/reactjs-widget
|
|
2
2
|
|
|
3
|
-
React
|
|
3
|
+
React overlay for the [TradingView Charting Library](https://www.tradingview.com/charting-library-docs/) that adds ICCandle’s **pattern scanner**, **results iframe**, **pattern tracker**, and **news/event** integration.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
The package ships ESM + CommonJS. Component styles are injected at runtime (no separate CSS import).
|
|
6
6
|
|
|
7
|
-
##
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
npm install @iccandle/reactjs-widget
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
### How to get an API key
|
|
14
|
-
|
|
15
|
-
1. Register or sign in at the [ICCandle corporate portal](https://corporate-iccandle.vercel.app/).
|
|
16
|
-
2. Use **Create API key** in the dashboard.
|
|
17
|
-
3. When selecting a service, choose **search** so the key is valid for this widget (remote theming, candle cache, and scanner validation).
|
|
18
|
-
|
|
19
|
-
Issued keys use the format `icc_search_` followed by 48 hexadecimal characters.
|
|
20
|
-
|
|
21
|
-
### Prerequisites
|
|
22
|
-
|
|
23
|
-
- **React 18+** — `react` and `react-dom` are **peer dependencies** (install them in your app).
|
|
24
|
-
- **TradingView Charting Library** — obtain it under your own license from TradingView, host the static assets (e.g. under `/charting_library/` in your public folder), and load the library at runtime. **This package does not ship the charting library.**
|
|
25
|
-
- **ICCandle API key** — required for theme, candle cache, and scanner validation; format `icc_search_` plus 48 hex characters. See [How to get an API key](#how-to-get-an-api-key) above.
|
|
26
|
-
|
|
27
|
-
## Quick start
|
|
28
|
-
|
|
29
|
-
```tsx
|
|
30
|
-
import { useState } from "react";
|
|
31
|
-
import type { IChartingLibraryWidget } from "charting_library/charting_library";
|
|
32
|
-
import { WidgetIccandle } from "@iccandle/reactjs-widget";
|
|
7
|
+
## What it does
|
|
33
8
|
|
|
34
|
-
|
|
35
|
-
const [chartWidget, setChartWidget] = useState<IChartingLibraryWidget | null>(
|
|
36
|
-
null,
|
|
37
|
-
);
|
|
38
|
-
const widgetKey = "icc_search_..."; // ICCandle-issued key (48 hex chars after prefix)
|
|
9
|
+
`WidgetIccandle` wraps your chart and renders:
|
|
39
10
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
submitCallback={(iframeSrc) => {
|
|
46
|
-
// Full URL for the ICCandle plugin iframe (open in modal, new window, etc.)
|
|
47
|
-
console.log(iframeSrc);
|
|
48
|
-
}}
|
|
49
|
-
>
|
|
50
|
-
{/* Your chart container + TradingView bootstrap; call setChartWidget when ready */}
|
|
51
|
-
<div id="tv_chart_container" style={{ height: "100%" }} />
|
|
52
|
-
</WidgetIccandle>
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
```
|
|
11
|
+
| Surface | Role |
|
|
12
|
+
| -------- | ---- |
|
|
13
|
+
| **Scanner popup** | Draggable overlay over the chart. Select a bar window with TradingView’s Date Range tool, then run a scan or subscribe to pattern alerts. |
|
|
14
|
+
| **Results iframe** | Side-by-side panel hosting the ICCandle embed app (`embed-iccandle-app.iccandle.ai`) — search results, similar events, auth, billing. |
|
|
15
|
+
| **Chart sync** | Bidirectional `postMessage` bridge: pattern selection, chart replay, news marks, sign-in tokens, loading state. |
|
|
56
16
|
|
|
57
|
-
|
|
17
|
+
Typical flow:
|
|
58
18
|
|
|
59
|
-
|
|
19
|
+
1. User draws a **Date Range** on the chart (or activates the scanner).
|
|
20
|
+
2. Scanner caches the selected candles and opens the results iframe with search parameters.
|
|
21
|
+
3. The embed app returns matches; selecting a pattern redraws the range on the chart. Replay / news flows inject predicted candles via custom indicators.
|
|
60
22
|
|
|
61
|
-
|
|
23
|
+
## Install
|
|
62
24
|
|
|
63
25
|
```bash
|
|
64
26
|
npm install @iccandle/reactjs-widget
|
|
27
|
+
# or
|
|
28
|
+
pnpm add @iccandle/reactjs-widget
|
|
65
29
|
```
|
|
66
30
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
### Step 2 — Host the Charting Library
|
|
70
|
-
|
|
71
|
-
1. Copy the TradingView Charting Library build into a path your app can serve as static files (e.g. `public/charting_library/` in Vite or Create React App).
|
|
72
|
-
2. Import the library constructor from that path in your bundler setup (see TradingView’s integration docs for your framework). The library is **not** bundled inside `@iccandle/reactjs-widget`; it loads at runtime via `library_path` (or equivalent) on the widget options.
|
|
73
|
-
|
|
74
|
-
### Step 3 — Bootstrap TradingView and capture the widget instance
|
|
75
|
-
|
|
76
|
-
Create a ref for the chart DOM node, instantiate the widget in `useEffect`, store the instance in React state, and remove it on cleanup:
|
|
77
|
-
|
|
78
|
-
```tsx
|
|
79
|
-
import { useEffect, useRef, useState } from "react";
|
|
80
|
-
import type {
|
|
81
|
-
ChartingLibraryWidgetOptions,
|
|
82
|
-
IChartingLibraryWidget,
|
|
83
|
-
ResolutionString,
|
|
84
|
-
} from "charting_library/charting_library";
|
|
85
|
-
import { widget } from "charting_library/charting_library";
|
|
86
|
-
|
|
87
|
-
const LIBRARY_PATH = "/charting_library/"; // must match your hosted assets
|
|
88
|
-
|
|
89
|
-
// Inside your component:
|
|
90
|
-
const containerRef = useRef<HTMLDivElement>(null);
|
|
91
|
-
const [chartWidget, setChartWidget] = useState<IChartingLibraryWidget | null>(
|
|
92
|
-
null,
|
|
93
|
-
);
|
|
94
|
-
|
|
95
|
-
useEffect(() => {
|
|
96
|
-
const el = containerRef.current;
|
|
97
|
-
if (!el) return;
|
|
98
|
-
|
|
99
|
-
const options: ChartingLibraryWidgetOptions = {
|
|
100
|
-
container: el,
|
|
101
|
-
library_path: LIBRARY_PATH,
|
|
102
|
-
symbol: "EURUSD",
|
|
103
|
-
interval: "60" as ResolutionString,
|
|
104
|
-
datafeed: yourDatafeed,
|
|
105
|
-
locale: "en",
|
|
106
|
-
autosize: true,
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
const tv = new widget(options);
|
|
110
|
-
setChartWidget(tv);
|
|
111
|
-
|
|
112
|
-
return () => {
|
|
113
|
-
try {
|
|
114
|
-
tv.remove();
|
|
115
|
-
} catch {
|
|
116
|
-
/* no-op */
|
|
117
|
-
}
|
|
118
|
-
setChartWidget(null);
|
|
119
|
-
};
|
|
120
|
-
}, [/* library_path, datafeed identity, or other inputs that should recreate the chart */]);
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
You must supply a valid `datafeed`, `symbol`, `interval`, `locale`, and any other options required by your TradingView license and app. Import paths for `widget` and types differ by setup (`charting_library/charting_library`, `./public/charting_library`, etc.—follow TradingView’s docs for your bundler). If your integration only exposes the instance after `onChartReady`, call `setChartWidget` inside that callback instead of immediately after `new widget(...)`.
|
|
124
|
-
|
|
125
|
-
### Step 4 — Wrap the chart with `WidgetIccandle`
|
|
126
|
-
|
|
127
|
-
`WidgetIccandle` must wrap the same subtree that contains the chart container so the scanner overlay positions correctly. Pass the live widget instance (or `null` while mounting):
|
|
128
|
-
|
|
129
|
-
```tsx
|
|
130
|
-
import { WidgetIccandle } from "@iccandle/reactjs-widget";
|
|
131
|
-
|
|
132
|
-
const widgetKey = "icc_search_..."; // your ICCandle key
|
|
133
|
-
|
|
134
|
-
<WidgetIccandle
|
|
135
|
-
chartWidget={chartWidget}
|
|
136
|
-
widgetKey={widgetKey}
|
|
137
|
-
theme="system"
|
|
138
|
-
submitCallback={(iframeSrc) => {
|
|
139
|
-
/* see Step 5 */
|
|
140
|
-
}}
|
|
141
|
-
>
|
|
142
|
-
<div ref={containerRef} style={{ height: "100%", minHeight: 400 }} />
|
|
143
|
-
</WidgetIccandle>
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
### Step 5 — Handle the plugin iframe URL
|
|
147
|
-
|
|
148
|
-
After a successful scan setup, `submitCallback` receives a **full HTTPS URL** for the ICCandle plugin iframe. The query string typically includes the bar window (timestamps / size), symbol, `candle_id`, `apiKey` (your widget key), resolved theme, and any active filters—use it as-is in an iframe `src` or deep link.
|
|
149
|
-
|
|
150
|
-
**Open in a new tab**
|
|
151
|
-
|
|
152
|
-
```ts
|
|
153
|
-
submitCallback={(iframeSrc) => {
|
|
154
|
-
window.open(iframeSrc, "_blank", "noopener,noreferrer");
|
|
155
|
-
}}
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
**Show in a modal or side panel**
|
|
159
|
-
|
|
160
|
-
Store the URL in state and render:
|
|
161
|
-
|
|
162
|
-
```tsx
|
|
163
|
-
{iframeSrc ? (
|
|
164
|
-
<iframe title="ICCandle pattern search" src={iframeSrc} className="..." />
|
|
165
|
-
) : null}
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
**TypeScript:** import `WidgetIccandleProps` if you wrap `WidgetIccandle` in your own component and want explicit prop typing. Import `IChartingLibraryWidget` from **your** Charting Library typings path (`charting_library/charting_library` or the path your project uses)—this package does not re-export TradingView types.
|
|
169
|
-
|
|
170
|
-
### Theme and remote branding
|
|
171
|
-
|
|
172
|
-
- **`theme="light"` / `"dark"`** — forces that palette for the scanner chrome and for values forwarded into the plugin URL.
|
|
173
|
-
- **`theme="system"`** (recommended when you don’t control parent theme) — follows `prefers-color-scheme` for light/dark resolution.
|
|
174
|
-
- On mount, the widget fetches your org’s tokens from ICCandle (see [Widget key and remote theming](#widget-key-and-remote-theming)) and sets CSS custom properties on the widget root, e.g. `--iccandle-primary`, `--iccandle-border`, so the in-chart scanner matches your configured light/dark branding. The same resolved theme is reflected in the iframe URL so the plugin UI stays consistent.
|
|
31
|
+
### Prerequisites
|
|
175
32
|
|
|
176
|
-
|
|
33
|
+
- **React 18+** — `react` and `react-dom` are peer dependencies.
|
|
34
|
+
- **TradingView Charting Library** — obtain under your own license, host the static assets (e.g. `/charting_library/`), and bootstrap the widget yourself. **This package does not ship the charting library.**
|
|
35
|
+
- **Auth token** — API calls (candle cache, pattern tracker) use `Bearer` auth from `localStorage` key `iccandle_token`. The embedded results app sets this via a `sign-in-success` `postMessage` after login.
|
|
177
36
|
|
|
178
|
-
|
|
37
|
+
## Quick start
|
|
179
38
|
|
|
180
39
|
```tsx
|
|
181
40
|
import { useEffect, useRef, useState } from "react";
|
|
@@ -185,18 +44,44 @@ import type {
|
|
|
185
44
|
ResolutionString,
|
|
186
45
|
} from "charting_library/charting_library";
|
|
187
46
|
import { widget } from "charting_library/charting_library";
|
|
188
|
-
import {
|
|
47
|
+
import {
|
|
48
|
+
WidgetIccandle,
|
|
49
|
+
withPlayChart,
|
|
50
|
+
getCustomIndicators,
|
|
51
|
+
} from "@iccandle/reactjs-widget";
|
|
189
52
|
|
|
190
53
|
const LIBRARY_PATH = "/charting_library/";
|
|
191
|
-
const WIDGET_KEY = "icc_search_your48hexcharactershere............";
|
|
192
54
|
|
|
193
|
-
|
|
55
|
+
function App() {
|
|
194
56
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
195
57
|
const [chartWidget, setChartWidget] = useState<IChartingLibraryWidget | null>(
|
|
196
58
|
null,
|
|
197
59
|
);
|
|
198
|
-
const [pluginSrc, setPluginSrc] = useState("");
|
|
199
60
|
|
|
61
|
+
return (
|
|
62
|
+
<div style={{ height: "100vh", width: "100%" }}>
|
|
63
|
+
<WidgetIccandle chartWidget={chartWidget} theme="light" language="en">
|
|
64
|
+
{(chartRefs) => (
|
|
65
|
+
<ChartHost
|
|
66
|
+
containerRef={containerRef}
|
|
67
|
+
chartRefs={chartRefs}
|
|
68
|
+
onReady={setChartWidget}
|
|
69
|
+
/>
|
|
70
|
+
)}
|
|
71
|
+
</WidgetIccandle>
|
|
72
|
+
</div>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function ChartHost({
|
|
77
|
+
containerRef,
|
|
78
|
+
chartRefs,
|
|
79
|
+
onReady,
|
|
80
|
+
}: {
|
|
81
|
+
containerRef: React.RefObject<HTMLDivElement | null>;
|
|
82
|
+
chartRefs: import("@iccandle/reactjs-widget").WidgetIccandleChartRefs;
|
|
83
|
+
onReady: (w: IChartingLibraryWidget | null) => void;
|
|
84
|
+
}) {
|
|
200
85
|
useEffect(() => {
|
|
201
86
|
const el = containerRef.current;
|
|
202
87
|
if (!el) return;
|
|
@@ -206,18 +91,18 @@ export function ChartWithIccandleScanner() {
|
|
|
206
91
|
library_path: LIBRARY_PATH,
|
|
207
92
|
symbol: "EURUSD",
|
|
208
93
|
interval: "60" as ResolutionString,
|
|
209
|
-
datafeed: yourDatafeed,
|
|
94
|
+
datafeed: withPlayChart(yourDatafeed), // enables chart replay injection
|
|
210
95
|
locale: "en",
|
|
211
96
|
autosize: true,
|
|
212
|
-
fullscreen: false,
|
|
213
97
|
drawings_access: {
|
|
214
98
|
type: "black",
|
|
215
99
|
tools: [{ name: "Date Range" }],
|
|
216
100
|
},
|
|
101
|
+
custom_indicators_getter: () => getCustomIndicators("light"),
|
|
217
102
|
};
|
|
218
103
|
|
|
219
104
|
const tv = new widget(options);
|
|
220
|
-
|
|
105
|
+
onReady(tv);
|
|
221
106
|
|
|
222
107
|
return () => {
|
|
223
108
|
try {
|
|
@@ -225,108 +110,139 @@ export function ChartWithIccandleScanner() {
|
|
|
225
110
|
} catch {
|
|
226
111
|
/* no-op */
|
|
227
112
|
}
|
|
228
|
-
|
|
113
|
+
onReady(null);
|
|
229
114
|
};
|
|
230
|
-
}, []);
|
|
115
|
+
}, [containerRef, chartRefs, onReady]);
|
|
231
116
|
|
|
232
|
-
return
|
|
233
|
-
<div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
|
|
234
|
-
<div style={{ height: 500, width: "100%" }}>
|
|
235
|
-
<WidgetIccandle
|
|
236
|
-
chartWidget={chartWidget}
|
|
237
|
-
widgetKey={WIDGET_KEY}
|
|
238
|
-
theme="system"
|
|
239
|
-
submitCallback={(iframeSrc) => setPluginSrc(iframeSrc)}
|
|
240
|
-
>
|
|
241
|
-
<div ref={containerRef} style={{ height: "100%", width: "100%" }} />
|
|
242
|
-
</WidgetIccandle>
|
|
243
|
-
</div>
|
|
244
|
-
{pluginSrc ? (
|
|
245
|
-
<iframe
|
|
246
|
-
title="ICCandle search"
|
|
247
|
-
src={pluginSrc}
|
|
248
|
-
style={{ width: "100%", height: 600, border: "1px solid #ccc" }}
|
|
249
|
-
/>
|
|
250
|
-
) : null}
|
|
251
|
-
</div>
|
|
252
|
-
);
|
|
117
|
+
return <div ref={containerRef} style={{ height: "100%", width: "100%" }} />;
|
|
253
118
|
}
|
|
254
119
|
```
|
|
255
120
|
|
|
256
|
-
|
|
121
|
+
Use a **render-prop `children`** when you need `chartRefs` for generated-candle studies (replay / predict). A plain React node also works if you do not need those refs.
|
|
257
122
|
|
|
258
|
-
|
|
123
|
+
For a full in-repo reference, see [`src/tradingview/TradingviewChart.tsx`](src/tradingview/TradingviewChart.tsx).
|
|
259
124
|
|
|
260
|
-
|
|
261
|
-
| -------- | -------- |
|
|
262
|
-
| **Modal iframe** | On `submitCallback`, set state and render `<iframe src={url} />` inside a `<dialog>`, Radix Dialog, MUI Modal, etc. |
|
|
263
|
-
| **New tab** | `window.open(iframeSrc, "_blank", "noopener,noreferrer")`. |
|
|
264
|
-
| **Split layout** | Keep the chart in one column and mount the iframe in another when `pluginSrc` is set (as in the example above). |
|
|
265
|
-
| **News / events on the time axis** | If your datafeed implements `getTimescaleMarks`, you can sync marks with `localStorage` — see [Optional: timescale marks (news/events)](#optional-timescale-marks-newsevents). |
|
|
125
|
+
## Features
|
|
266
126
|
|
|
267
|
-
###
|
|
127
|
+
### Pattern scanner
|
|
268
128
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
129
|
+
- Subscribes to chart readiness, symbol, resolution, and drawing events.
|
|
130
|
+
- Manages a `date_range` multipoint drawing so the user can adjust the bar window (default window size: **25** bars).
|
|
131
|
+
- On scan: posts candles to `https://scan-service.iccandle.ai/cacheCandle`, then navigates the results iframe with query params (`ws`, `tk`, `et`, `symbol`, `tf`, `cid`, filters, theme).
|
|
132
|
+
- Optional **advanced filters** (symbols, top-k, lookback period, probability window) stored in `localStorage` under `search-filter`.
|
|
133
|
+
|
|
134
|
+
### Results iframe
|
|
135
|
+
|
|
136
|
+
- Loads `https://embed-iccandle-app.iccandle.ai/{language}?theme=...` by default.
|
|
137
|
+
- After scan / news navigation, the `src` updates with search or similar-events paths.
|
|
138
|
+
- On iframe load, the parent posts `{ type: "parent-origin", origin }` so Stripe checkout can return to the host domain. If the host URL has `?payment=success`, it also posts `{ type: "payment-success" }` so the embed can refresh subscription state.
|
|
139
|
+
|
|
140
|
+
### Pattern tracker
|
|
141
|
+
|
|
142
|
+
From the scanner popup, users can open a subscription modal to track a custom pattern (name + timeframes + symbols). Requires a valid `iccandle_token`.
|
|
143
|
+
|
|
144
|
+
### News / economic events
|
|
145
|
+
|
|
146
|
+
- Clicking a timescale mark can open an **event info** modal (currency calendar events; skips holidays / early / sentiment-only marks).
|
|
147
|
+
- “Go to detail” loads similar events in the iframe and draws a vertical line on the chart.
|
|
148
|
+
- Marks can be driven from `localStorage` keys `tv:selected-news-events` and `tv:clicked-news-event` if your datafeed implements `getTimescaleMarks` (see below).
|
|
149
|
+
|
|
150
|
+
### Chart replay (play candles)
|
|
151
|
+
|
|
152
|
+
Wrap your datafeed with `withPlayChart` and register custom indicators via `getCustomIndicators` so the embed can inject predicted / replay bars without live ticks fighting the playback.
|
|
276
153
|
|
|
277
154
|
## API
|
|
278
155
|
|
|
279
156
|
### Exports
|
|
280
157
|
|
|
281
|
-
| Name
|
|
282
|
-
|
|
|
283
|
-
| `WidgetIccandle`
|
|
284
|
-
| `WidgetIccandleProps
|
|
158
|
+
| Name | Kind | Description |
|
|
159
|
+
| ---- | ---- | ----------- |
|
|
160
|
+
| `WidgetIccandle` | Component | Chart overlay + results iframe |
|
|
161
|
+
| `WidgetIccandleProps` | Type | Props for `WidgetIccandle` |
|
|
162
|
+
| `WidgetIccandleChartRefs` | Type | Refs for highlight bars / generated-candle studies |
|
|
163
|
+
| `WidgetLanguage` | Type | Supported locale codes |
|
|
164
|
+
| `withPlayChart` | Function | Wraps a TradingView datafeed for replay bar injection |
|
|
165
|
+
| `getCustomIndicators` | Function | Returns ICCandle custom indicators (generated candles) |
|
|
166
|
+
| `getGeneratedCandlesMaskColor` | Function | Theme-aware mask color for generated candles |
|
|
285
167
|
|
|
286
168
|
### `WidgetIccandle` props
|
|
287
169
|
|
|
288
|
-
| Prop
|
|
289
|
-
|
|
|
290
|
-
| `chartWidget`
|
|
291
|
-
| `children`
|
|
292
|
-
| `
|
|
293
|
-
| `
|
|
294
|
-
| `
|
|
170
|
+
| Prop | Type | Required | Description |
|
|
171
|
+
| ---- | ---- | -------- | ----------- |
|
|
172
|
+
| `chartWidget` | `IChartingLibraryWidget \| null` | Yes | Live TradingView widget (`null` until ready). |
|
|
173
|
+
| `children` | `ReactNode \| ((chartRefs) => ReactNode)` | Yes | Chart UI, or render prop receiving `WidgetIccandleChartRefs`. |
|
|
174
|
+
| `theme` | `"light" \| "dark" \| "system"` | No | Scanner chrome + iframe theme. `"system"` follows `prefers-color-scheme`. |
|
|
175
|
+
| `language` | `WidgetLanguage` | No | UI + iframe locale. One of: `en`, `zh`, `vi`, `th`, `ko`, `ja`, `mn`, `ru`. Defaults to `en`. |
|
|
176
|
+
| `onCloseResult` | `() => void` | No | Called when the embed posts `close-result`. |
|
|
177
|
+
| `iframeLoaded` | `boolean` | No | When `false`, disables scan / track actions until the results iframe is ready. Defaults to enabled behavior in the scanner. |
|
|
295
178
|
|
|
296
|
-
|
|
179
|
+
`IChartingLibraryWidget` must be imported from **your** Charting Library typings — this package does not re-export TradingView types.
|
|
297
180
|
|
|
298
|
-
|
|
181
|
+
### `withPlayChart(datafeed)`
|
|
299
182
|
|
|
300
|
-
|
|
301
|
-
- **Header:** `api-key: <widgetKey>`
|
|
183
|
+
Wraps `subscribeBars` so ICCandle can push replay bars and optionally block live ticks during playback.
|
|
302
184
|
|
|
303
|
-
|
|
185
|
+
```ts
|
|
186
|
+
import { withPlayChart } from "@iccandle/reactjs-widget";
|
|
304
187
|
|
|
305
|
-
|
|
188
|
+
datafeed: withPlayChart(myDatafeed),
|
|
189
|
+
// or factory + args:
|
|
190
|
+
datafeed: withPlayChart(createDatafeed, arg1, arg2),
|
|
191
|
+
```
|
|
306
192
|
|
|
307
|
-
###
|
|
193
|
+
### `getCustomIndicators(theme?)`
|
|
308
194
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
195
|
+
Returns a Promise of TradingView `CustomIndicator[]` used for generated / predicted candle overlays. Pass `"light"` or `"dark"` to match chart theme. Wire it into widget options:
|
|
196
|
+
|
|
197
|
+
```ts
|
|
198
|
+
custom_indicators_getter: () => getCustomIndicators("light"),
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Auth and storage
|
|
202
|
+
|
|
203
|
+
| Key | Purpose |
|
|
204
|
+
| --- | ------- |
|
|
205
|
+
| `iccandle_token` | Bearer token for scan cache, pattern tracker, and related APIs. Set by the embed via `sign-in-success`. |
|
|
206
|
+
| `search-filter` | Scanner advanced options (symbols, top_k, period, probability). |
|
|
207
|
+
| `tv:selected-news-events` | JSON array of news events used as timescale marks. |
|
|
208
|
+
| `tv:clicked-news-event` | Last clicked calendar event for mark highlighting. |
|
|
209
|
+
| `tv:latest-symbol` | Last chart symbol (used by the demo app / fallbacks). |
|
|
210
|
+
|
|
211
|
+
## postMessage bridge
|
|
212
|
+
|
|
213
|
+
Messages are accepted only from the results origin (`https://embed-iccandle-app.iccandle.ai`).
|
|
214
|
+
|
|
215
|
+
| Direction | Type / action | Effect |
|
|
216
|
+
| --------- | ------------- | ------ |
|
|
217
|
+
| Embed → parent | `play-chart` | Inject / clear replay candles on the chart |
|
|
218
|
+
| Embed → parent | `loading` | Toggle scanner loading UI |
|
|
219
|
+
| Embed → parent | `sign-in-success` | Persist `iccandle_token` from `payload.id_token` |
|
|
220
|
+
| Embed → parent | `close-result` | Clears play state; calls `onCloseResult` |
|
|
221
|
+
| Embed → parent | `pattern_selected` / `custom_pattern_selected` | Draw date range for the compared pattern |
|
|
222
|
+
| Embed → parent | `clear_pattern_selected` / `clear_custom_pattern_selected` | Remove pattern date range |
|
|
223
|
+
| Embed → parent | `eventClicked` | Center chart, draw event line, show mark |
|
|
224
|
+
| Embed → parent | `replay` | Start / stop event replay candles |
|
|
225
|
+
| Embed → parent | `back` / `back-to-similar-events` | Clear event line / replay |
|
|
226
|
+
| Embed → parent | `nav-click` | Hide scanner on `/news`; restore otherwise |
|
|
227
|
+
| Parent → embed | `parent-origin` | Host origin for Stripe return |
|
|
228
|
+
| Parent → embed | `payment-success` | Refresh subscription after checkout |
|
|
313
229
|
|
|
314
230
|
## Optional: timescale marks (news/events)
|
|
315
231
|
|
|
316
|
-
If your
|
|
232
|
+
If your datafeed implements `getTimescaleMarks`, surface stored events as marks:
|
|
317
233
|
|
|
318
234
|
```ts
|
|
319
235
|
getTimescaleMarks: async (
|
|
320
|
-
symbolInfo
|
|
321
|
-
from
|
|
322
|
-
to
|
|
323
|
-
onResult
|
|
236
|
+
symbolInfo,
|
|
237
|
+
from,
|
|
238
|
+
to,
|
|
239
|
+
onResult,
|
|
324
240
|
) => {
|
|
325
|
-
const marks
|
|
241
|
+
const marks = [];
|
|
326
242
|
try {
|
|
327
243
|
const allNewsEvents = JSON.parse(
|
|
328
244
|
localStorage.getItem("tv:selected-news-events") || "[]",
|
|
329
|
-
)
|
|
245
|
+
);
|
|
330
246
|
|
|
331
247
|
allNewsEvents?.forEach(({ id, timestamp, event_name, currency }) => {
|
|
332
248
|
if (!id || !Number.isFinite(timestamp) || timestamp <= 0) return;
|
|
@@ -349,17 +265,43 @@ getTimescaleMarks: async (
|
|
|
349
265
|
};
|
|
350
266
|
```
|
|
351
267
|
|
|
352
|
-
|
|
268
|
+
## Theming
|
|
269
|
+
|
|
270
|
+
Scanner UI uses CSS variables on `.iccandle-selector-widget`:
|
|
271
|
+
|
|
272
|
+
- `--iccandle-primary`
|
|
273
|
+
- `--iccandle-primary-gradient-end`
|
|
274
|
+
- `--iccandle-background`
|
|
275
|
+
- `--iccandle-border`
|
|
276
|
+
- `--iccandle-text`
|
|
277
|
+
- `--iccandle-secondary`
|
|
278
|
+
- `--iccandle-font`
|
|
279
|
+
|
|
280
|
+
Light and dark defaults live in the bundled stylesheet. The `theme` prop toggles the `.iccandle-dark` class and is forwarded to the iframe.
|
|
353
281
|
|
|
354
282
|
## Development (this repo)
|
|
355
283
|
|
|
356
|
-
| Script
|
|
357
|
-
|
|
|
358
|
-
| Dev demo
|
|
359
|
-
| Library build | `
|
|
360
|
-
|
|
|
284
|
+
| Script | Command | Purpose |
|
|
285
|
+
| ------ | ------- | ------- |
|
|
286
|
+
| Dev demo | `pnpm run dev` | Vite app with local charting library |
|
|
287
|
+
| Library build | `pnpm run build` | Emits `dist/` (ESM, CJS, injected CSS, `.d.ts`) |
|
|
288
|
+
| Web build | `pnpm run build:web` | SPA build to `dist-web/` |
|
|
289
|
+
| Deploy web | `pnpm run deploy:web` | Build + Vercel production deploy |
|
|
290
|
+
| Lint | `pnpm run lint` | ESLint |
|
|
291
|
+
| Preview web | `pnpm run preview` | Preview the web build |
|
|
292
|
+
|
|
293
|
+
`prepublishOnly` runs `build` before npm publish.
|
|
294
|
+
|
|
295
|
+
## Troubleshooting
|
|
361
296
|
|
|
362
|
-
|
|
297
|
+
| Issue | What to check |
|
|
298
|
+
| ----- | --------------- |
|
|
299
|
+
| Chart stays blank | `library_path` must serve TradingView static files; container must be mounted before `new widget(...)`. |
|
|
300
|
+
| `chartWidget` is always `null` | Call `setChartWidget` after create (or inside `onChartReady` if required). |
|
|
301
|
+
| Scan fails / 401 | Ensure the user signed in via the results iframe so `iccandle_token` is set. |
|
|
302
|
+
| Date Range tool missing | Enable it in `drawings_access` (see Quick start). |
|
|
303
|
+
| Replay bars do not appear | Wrap the datafeed with `withPlayChart` and register `getCustomIndicators`. |
|
|
304
|
+
| Scanner actions disabled | Pass `iframeLoaded={true}` once the results iframe has loaded, or omit the prop if you do not gate on load. |
|
|
363
305
|
|
|
364
306
|
## License
|
|
365
307
|
|