@iccandle/news
v0.0.12
Published
React component that wraps an existing [TradingView Charting Library](https://www.tradingview.com/charting-library-docs/) widget and adds ICCandle's **economic calendar analysis UI**: an interactive panel that displays news events as timescale marks on th
Readme
@iccandle/news
React component that wraps an existing TradingView Charting Library widget and adds ICCandle's economic calendar analysis UI: an interactive panel that displays news events as timescale marks on the chart, draws pip-range visualizations (high/low rectangles, trend lines, pip annotations) around selected events, and lets users compare historical price reactions across similar news releases.
Published as ESM and CommonJS; component styles are bundled and injected at runtime (no separate CSS import).
Install
npm install @iccandle/newsPrerequisites
- React 18+ —
reactandreact-domare peer dependencies (install them in your app). - 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. - ICCandle API key — issued by ICCandle for theme, chart data, news events, and scanner validation.
Quick start
import { useState } from "react";
import type { IChartingLibraryWidget } from "charting_library/charting_library";
import { NewsWidget } from "@iccandle/news-widget";
function App() {
const [chartWidget, setChartWidget] = useState<IChartingLibraryWidget | null>(
null,
);
const widgetKey = "your-iccandle-api-key";
return (
<NewsWidget
chartWidget={chartWidget}
widgetKey={widgetKey}
defaultSymbol="XAU_USD"
chartInterval="15"
theme="dark"
>
{/* Your chart container + TradingView bootstrap; call setChartWidget when ready */}
<div id="tv_chart_container" style={{ height: "100%" }} />
</NewsWidget>
);
}Replace the chart placeholder with your TradingView initialization and pass the IChartingLibraryWidget instance when onChartReady (or equivalent) fires.
Usage guide
Step 1 — Install the package
npm install @iccandle/newsEnsure react and react-dom are installed and meet the peer version range.
Step 2 — Host the Charting Library
- 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). - 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/news-widget; it loads at runtime vialibrary_path(or equivalent) on the widget options.
Step 3 — Bootstrap TradingView and capture the widget instance
Create a ref for the chart DOM node, instantiate the widget in useEffect, store the instance in React state, and remove it on cleanup:
import { useEffect, useRef, useState } from "react";
import type {
ChartingLibraryWidgetOptions,
IChartingLibraryWidget,
ResolutionString,
} from "charting_library/charting_library";
import { widget } from "charting_library/charting_library";
const LIBRARY_PATH = "/charting_library/"; // must match your hosted assets
// Inside your component:
const containerRef = useRef<HTMLDivElement>(null);
const [chartWidget, setChartWidget] = useState<IChartingLibraryWidget | null>(
null,
);
useEffect(
() => {
const el = containerRef.current;
if (!el) return;
const options: ChartingLibraryWidgetOptions = {
container: el,
library_path: LIBRARY_PATH,
symbol: "XAU_USD",
interval: "15" as ResolutionString,
datafeed: yourDatafeed,
locale: "en",
autosize: true,
};
const tv = new widget(options);
setChartWidget(tv);
return () => {
try {
tv.remove();
} catch {
/* no-op */
}
setChartWidget(null);
};
},
[
/* library_path, datafeed identity, or other inputs that should recreate the chart */
],
);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(...).
Step 4 — Wrap the chart with NewsWidget
NewsWidget must wrap the same subtree that contains the chart container so the event panel and chart visualizations position correctly. Pass the live widget instance (or null while mounting):
import { NewsWidget } from "@iccandle/news-widget";
const widgetKey = "your-iccandle-api-key";
<NewsWidget
chartWidget={chartWidget}
widgetKey={widgetKey}
defaultSymbol="XAU_USD"
chartInterval="15"
theme="dark"
>
<div ref={containerRef} style={{ height: "100%", minHeight: 400 }} />
</NewsWidget>;When a news event is selected, the widget switches to a 50/50 split layout: the event detail card and TradingView chart (with pip-range overlays) on the left, and the ICCandle iframe on the right. On mobile (<1024px) the panels stack vertically.
Step 5 — Interact with news events
Once the widget is mounted:
- Economic calendar events appear as timescale marks on the chart's time axis.
- Clicking an event opens the detail panel showing event metadata (actual, forecast, previous values), impact status, and a list of similar historical events.
- Pip-range visualization draws automatically on the chart: green rectangles for upside range, red rectangles for downside range, dotted trend lines at highs/lows, and pip annotations at extremes.
- Candle window is configurable (10–50 candles) to control how far after the event the range analysis extends.
TypeScript: import NewsWidgetProps if you wrap NewsWidget 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.
Theme and remote branding
theme="light"/"dark"/"system"— forces that palette for the widget chrome and chart overlays."system"resolves automatically based on the user's OSprefers-color-schemesetting.- On mount, the widget fetches your org's tokens from ICCandle (see Widget key and remote theming) and sets CSS custom properties on the widget root, e.g.
--iccandle-primary,--iccandle-border, so the event panel and chart overlays match your configured light/dark branding.
Full working example
Minimal end-to-end pattern: chart container ref, widget lifecycle, NewsWidget with event analysis. Replace yourDatafeed and widget options with your real datafeed and TradingView settings.
import { useEffect, useRef, useState } from "react";
import type {
ChartingLibraryWidgetOptions,
IChartingLibraryWidget,
ResolutionString,
} from "charting_library/charting_library";
import { widget } from "charting_library/charting_library";
import { NewsWidget } from "@iccandle/news-widget";
const LIBRARY_PATH = "/charting_library/";
const WIDGET_KEY = "your-iccandle-api-key";
export function ChartWithNewsWidget() {
const containerRef = useRef<HTMLDivElement>(null);
const [chartWidget, setChartWidget] = useState<IChartingLibraryWidget | null>(
null,
);
useEffect(() => {
const el = containerRef.current;
if (!el) return;
const options: ChartingLibraryWidgetOptions = {
container: el,
library_path: LIBRARY_PATH,
symbol: "XAU_USD",
interval: "15" as ResolutionString,
datafeed: yourDatafeed,
locale: "en",
autosize: true,
fullscreen: false,
};
const tv = new widget(options);
setChartWidget(tv);
return () => {
try {
tv.remove();
} catch {
/* no-op */
}
setChartWidget(null);
};
}, []);
return (
<div style={{ height: 600, width: "100%" }}>
<NewsWidget
chartWidget={chartWidget}
widgetKey={WIDGET_KEY}
defaultSymbol="XAU_USD"
chartInterval="15"
theme="dark"
>
<div ref={containerRef} style={{ height: "100%", width: "100%" }} />
</NewsWidget>
</div>
);
}For a concrete in-repo reference (custom datafeed, timezone, visibility handling), see src/tradingview/TradingviewChart.tsx in this repository's dev app.
Common patterns
| Pattern | Approach |
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Full-page chart | Set the parent container to height: 100vh and let NewsWidget fill the space with autosize: true. |
| Dashboard embed | Give the parent a fixed height (e.g. 600px) and NewsWidget handles the split layout internally. |
| News / events on the time axis | If your datafeed implements getTimescaleMarks, you can sync marks with localStorage — see Optional: timescale marks (news/events). | |
Troubleshooting
| Issue | What to check |
| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Chart area stays blank | library_path must point to the folder URL where TradingView static files are served; container ref must be mounted before new widget(...). |
| chartWidget is always null | Ensure you call setChartWidget after the widget is created (or inside onChartReady if your integration requires it). |
| Event panel or theme looks wrong | Confirm widgetKey is valid; theme fetch uses api-key: <widgetKey>. Network or auth failures may leave defaults. |
| CORS / network errors on APIs | In local dev, browser calls to ICCandle APIs may be blocked by CORS unless you proxy; the widget should still function with fallback styling—verify in production or behind your proxy. |
| No events showing on chart | The widget falls back to the defaultSymbol if selected symbol is unrecognized, but ensure chartInterval is one of the accepted values ("1", "5", "15", "30", "60"). |
API
Exports
| Name | Kind | Description |
| ----------------- | --------- | ------------------------------------------------- |
| NewsWidget | Component | Economic calendar analysis overlay for your chart |
| NewsWidgetProps | Type | Props for NewsWidget |
| SymbolMapper | Type | Mapping from ICCandle tickers to your broker's symbol names |
| ICCANDLE_TICKERS | Type | Union of all ICCandle ticker strings (keys of SymbolMapper) |
NewsWidget props
| Prop | Type | Required | Description |
| --------------- | ------------------------------------ | -------- | --------------------------------------------------------------------------------------------------------------------------- |
| chartWidget | IChartingLibraryWidget \| null | Yes | Live TradingView widget instance (null until ready). |
| children | ReactNode | Yes | Your chart UI (e.g. container + library bootstrap). |
| widgetKey | string | Yes | ICCandle API key. Used for theme fetch, chart data, news events, and scanner validation. |
| defaultSymbol | string | Yes | Default trading symbol used to initialize the chart (e.g. "XAU_USD", "EURUSD", "BTCUSDT"). Also used as the fallback when a symbol is unrecognized, unmapped, or unavailable. |
| symbolMapper | SymbolMapper | No | Maps ICCandle ticker names to your TradingView symbol names (e.g. { XAUUSD: "GOLD", USDCAD: "USD_CAD" }). When omitted or when a ticker has no entry, the widget falls back to defaultSymbol. See Symbol name mapping. |
| chartInterval | "1" \| "5" \| "15" \| "30" \| "60" | Yes | Initial chart candle interval in minutes used when showing the chart. Defaults to "15". |
| theme | "light" \| "dark" \| "system" | No | Affects resolved theme tokens and chart overlays. "system" resolves to light or dark based on prefers-color-scheme. |
Widget key and remote theming
On mount, the component loads branding colors from ICCandle:
- URL:
https://api.iccandle.ai/corporate-client/v1/widgetStyle/search/user/?service_type=search - Header:
api-key: <widgetKey>
CSS custom properties (--iccandle-primary, --iccandle-border, --iccandle-background, --iccandle-text, etc.) are applied on the widget root so the event panel and chart overlays match your configured light/dark tokens.
Theme prop vs. API tokens: The theme prop ("light" | "dark" | "system") chooses which variant of those tokens to apply.
Behavior summary
- Subscribes to chart readiness, resolution, symbol changes, and drawing events.
- Displays economic calendar events as interactive timescale marks on the chart.
- On event selection, switches to a split layout with an event detail panel and pip-range chart visualization.
- Draws pip-range rectangles (green for upside, red for downside), dotted trend lines, and pip annotations on the chart.
- Fetches similar historical events for comparison and shows event metadata (actual, forecast, previous values).
- Supports configurable candle windows (10–50 candles) for range analysis.
- Stores selected events in
localStorage(keyiccandle:current-news-event) for timescale mark sync. - Listens for
windowmessageevents for chart/news integration.
Chart switching between TradingView and ICCandle
The widget dynamically switches between the third-party TradingView chart and ICCandle's own history chart depending on how much price data is available after the event:
- ICCandle history chart (elapsed events): When a user clicks an older event where the selected timeframe has fully elapsed (roughly 50+ candles after the event time), the widget replaces the TradingView chart with ICCandle's history chart rendered via iframe. This chart provides ICCandle's curated pip-range analysis.
- TradingView chart (recent/upcoming events): When the event's timeframe has not yet fully elapsed, the widget keeps the TradingView chart visible in a split layout — event detail card and TradingView chart on the left, ICCandle iframe on the right — and draws pip-range overlays directly on the TradingView chart.
Symbol handling and limitations
ICCandle's history chart supports a fixed set of symbols. When a currency event occurs (e.g. a USD news release), only symbols related to that currency are available in the ICCandle chart, so the impact visualization is scoped to relevant pairs.
In the TradingView chart, however, symbol filtering cannot be controlled by the widget — the impact is drawn on whatever symbol is currently active, which may not be directly related to the event's currency. Keep this in mind when interpreting pip-range overlays on unrelated symbols in the TradingView chart.
Symbol name mapping (symbolMapper)
ICCandle and your broker/TradingView setup often use different naming conventions for the same instrument — for example, ICCandle uses XAUUSD while your chart may use GOLD, or ICCandle uses USDCAD while your chart may use USD_CAD. The optional symbolMapper prop lets you define a mapping from ICCandle's ticker names to your chart's symbol names:
<NewsWidget
chartWidget={chartWidget}
widgetKey="your-api-key"
defaultSymbol="XAUUSD"
chartInterval="15"
theme="dark"
symbolMapper={{
XAUUSD: "GOLD",
USDCAD: "USD_CAD",
EURUSD: "EURUSD",
// ... map ICCandle tickers to your broker's symbol names
}}
>
{children}
</NewsWidget>When a symbol change event is received from the ICCandle iframe, the widget looks up the symbol in symbolMapper. If no mapping is found (or symbolMapper is not provided), the widget falls back to defaultSymbol. This ensures the TradingView chart always navigates to a valid symbol.
Optional: timescale marks (news/events)
If your data feed implements getTimescaleMarks, you can surface stored events (e.g. from localStorage under iccandle:current-news-event) as marks on the time axis. Example shape:
getTimescaleMarks: async (
symbolInfo: LibrarySymbolInfo,
from: number,
to: number,
onResult: GetMarksCallback<TimescaleMark>,
) => {
const marks: TimescaleMark[] = [];
//...your code here
try {
const currentNewsEvent = JSON.parse(
localStorage.getItem("iccandle:current-news-event") || "{}",
) as NewsEventType;
const { id, timestamp, event_name, currency, forecast, previous, actual } =
currentNewsEvent;
if (!id || !Number.isFinite(timestamp) || timestamp <= 0) return;
const hasAlready = marks.some((m) => String(m.id) === String(id));
if (hasAlready) return;
marks.push({
id: id,
time: timestamp / 1000,
color: "green",
label: event_name.slice(0, 1),
tooltip: [
event_name,
`Current Forecast: ${forecast || "-"}`,
`Previous Forecast: ${previous || "-"}`,
`Previous Actual: ${actual || "-"}`,
],
...(currency ? { imageUrl: `/images/symbols/${currency}.svg` } : {}),
});
} catch {
// no-op
}
onResult(marks);
};Adjust paths and types to match your app and TradingView typings.
License
MIT. TradingView Charting Library is subject to its own license from TradingView.
