@iccandle/news
v0.0.2
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 analysis panel on the left and the chart (with pip-range overlays) 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"— forces that palette for the widget chrome and chart overlays.- 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 |
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 selected symbol is unrecognized or unavailable. |
| chartInterval | "1" \| "5" \| "15" \| "30" \| "60" | Yes | Initial chart candle interval in minutes used when showing the chart. Defaults to "15". |
| theme | "light" \| "dark" \| | Yes | Affects resolved theme tokens and chart overlays. |
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") 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.
Optional: timescale marks (news/events)
If your data feed implements getTimescaleMarks, you can surface stored events (e.g. from localStorage under tv: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.
