
Security News
/Research
Wallet-Draining npm Package Impersonates Nodemailer to Hijack Crypto Transactions
Malicious npm package impersonates Nodemailer and drains wallets by hijacking crypto transactions across multiple blockchains.
@dschz/solid-lightweight-charts
Advanced tools
TradingView Lightweight Charts™ as SolidJS components
A fully typed SolidJS wrapper around TradingView's Lightweight Charts, providing declarative, reactive charting with support for time series, price, and yield curve data.
TimeChart
for time-based financial dataPriceChart
for numeric-based price dataYieldCurveChart
for rate curves and duration-based data<TimeChart.Series />
, <PriceChart.Series />
)lightweight-charts
APIs when neededInstall via your favorite package manager:
npm install solid-js lightweight-charts @dschz/solid-lightweight-charts
pnpm install solid-js lightweight-charts @dschz/solid-lightweight-charts
yarn install solid-js lightweight-charts @dschz/solid-lightweight-charts
bun install solid-js lightweight-charts @dschz/solid-lightweight-charts
These are peer dependencies, so they must be installed manually:
solid-js
lightweight-charts
import { TimeChart } from "@dschz/solid-lightweight-charts";
<TimeChart>
<TimeChart.Series
type="Line"
data={[
{ time: "2023-01-01", value: 100 },
{ time: "2023-01-02", value: 105 },
]}
lineWidth={2}
color="#2962FF"
/>
</TimeChart>;
import { PriceChart } from "@dschz/solid-lightweight-charts";
<PriceChart>
<PriceChart.Series
type="Line"
data={[
{ time: 0, value: 100 },
{ time: 1, value: 105 },
]}
lineWidth={2}
color="#2962FF"
/>
</PriceChart>;
import { YieldCurveChart } from "@dschz/solid-lightweight-charts";
<YieldCurveChart>
<YieldCurveChart.Series
type="Line"
data={[
{ time: 0, value: 3.5 }, // 0M
{ time: 12, value: 3.8 }, // 12M
{ time: 60, value: 4.2 }, // 5Y
]}
lineWidth={2}
color="#2962FF"
/>
</YieldCurveChart>;
Chart components (TimeChart
, PriceChart
, YieldCurveChart
) do not apply any default sizing styles. You have complete control over how your charts are sized.
It's important to understand that chart components have two levels of configuration:
<TimeChart
class="h-[400px] w-full" // Applied to container div
style={{ border: "1px solid red" }} // Applied to container div
autoSize={true} // Passed to Lightweight Charts
width={800} // Passed to Lightweight Charts (ignored if autoSize=true)
height={400} // Passed to Lightweight Charts (ignored if autoSize=true)
>
<TimeChart.Series type="Line" data={data} />
</TimeChart>
Container Level (class
, style
, id
):
Chart Level (autoSize
, width
, height
, chart options):
Option 1: CSS Classes (Recommended)
<TimeChart class="h-[400px] w-full">
<TimeChart.Series type="Line" data={data} />
</TimeChart>
Option 2: Inline Styles
<TimeChart style={{ height: "400px", width: "100%" }}>
<TimeChart.Series type="Line" data={data} />
</TimeChart>
Option 3: Fixed Dimensions (autoSize=false)
<TimeChart autoSize={false} width={800} height={400}>
<TimeChart.Series type="Line" data={data} />
</TimeChart>
autoSize: true
(default): Chart fills its container div. The width
and height
props are ignored.autoSize: false
: Chart uses explicit width
and height
props for fixed dimensions.Key Point: When autoSize={true}
, the chart will automatically resize to match whatever size you've given the container div via class
or style
.
All chart containers include the solid-lwc-container
class for easy global styling:
.solid-lwc-container {
height: 400px;
width: 100%;
}
Responsive with Tailwind:
<TimeChart class="h-[400px] w-full md:h-[500px]">
<TimeChart.Series type="Line" data={data} />
</TimeChart>
Fixed size for specific use cases:
<TimeChart autoSize={false} width={600} height={300}>
<TimeChart.Series type="Line" data={data} />
</TimeChart>
Parent container sizing:
<div class="h-[400px] w-full">
<TimeChart style={{ height: "100%", width: "100%" }}>
<TimeChart.Series type="Line" data={data} />
</TimeChart>
</div>
Container styling + chart options:
<TimeChart
class="h-[500px] w-full border rounded-lg shadow"
rightPriceScale={{ visible: true }}
timeScale={{ timeVisible: true }}
>
<TimeChart.Series type="Line" data={data} />
</TimeChart>
Important: Charts need explicit dimensions to render. If you see a blank chart, make sure you've provided sizing through CSS classes, inline styles, or fixed dimensions.
import { TimeChart } from "@dschz/solid-lightweight-charts";
<TimeChart>
{/* Main pane with price data and declarative markers */}
<TimeChart.Series
type="Candlestick"
data={candleData}
markers={(data) => [
{
time: data[10].time,
position: "aboveBar",
color: "#f68410",
shape: "circle",
text: "Buy",
},
{
time: data[20].time,
position: "belowBar",
color: "#e91e63",
shape: "arrowDown",
text: "Sell",
},
]}
onSetMarkers={(markers) => console.log("Markers updated:", markers)}
/>
{/* Secondary pane with volume */}
<TimeChart.Pane>
<TimeChart.Series
type="Histogram"
data={volumeData}
priceScaleId="volume"
color="rgba(76, 175, 80, 0.8)"
/>
</TimeChart.Pane>
</TimeChart>;
import { TimeChart } from "@dschz/solid-lightweight-charts";
// Define your custom pane view
const customPaneView = {
updateAllViews() {
/* implementation */
},
paneViews() {
/* implementation */
},
priceValueBuilder(plotRow) {
/* implementation */
},
isWhitespace(data) {
/* implementation */
},
defaultOptions() {
/* implementation */
},
};
<TimeChart>
<TimeChart.CustomSeries
paneView={customPaneView}
data={customData}
onCreateSeries={(series) => console.log("Custom series created:", series)}
/>
</TimeChart>;
import { TimeChart, type SeriesPrimitive } from "@dschz/solid-lightweight-charts";
import type {
ISeriesPrimitiveAxisView,
IPrimitivePaneView,
IPrimitivePaneRenderer,
Time,
SeriesAttachedParameter,
} from "lightweight-charts";
// Trend line primitive with proper TypeScript implementation
class TrendLinePrimitive implements SeriesPrimitive<"Line", Time> {
private _paneViews: TrendLinePaneView[];
private _point1: { time: Time; value: number };
private _point2: { time: Time; value: number };
constructor(point1: { time: Time; value: number }, point2: { time: Time; value: number }) {
this._point1 = point1;
this._point2 = point2;
this._paneViews = [new TrendLinePaneView(this)];
}
updateAllViews() {
this._paneViews.forEach((pv) => pv.update());
}
paneViews() {
return this._paneViews;
}
attached(param: SeriesAttachedParameter<Time, "Line">) {
// Implementation for when primitive is attached
}
detached() {
// Cleanup when primitive is detached
}
getPoint1() {
return this._point1;
}
getPoint2() {
return this._point2;
}
}
class TrendLinePaneView implements IPrimitivePaneView {
private _source: TrendLinePrimitive;
private _renderer: TrendLinePaneRenderer;
constructor(source: TrendLinePrimitive) {
this._source = source;
this._renderer = new TrendLinePaneRenderer();
}
update() {
this._renderer.setData({
point1: this._source.getPoint1(),
point2: this._source.getPoint2(),
});
}
renderer() {
return this._renderer;
}
zOrder() {
return "normal" as const;
}
}
class TrendLinePaneRenderer implements IPrimitivePaneRenderer {
private _data: { point1: any; point2: any } | null = null;
setData(data: { point1: any; point2: any } | null) {
this._data = data;
}
draw(target: any) {
if (!this._data) return;
// Canvas 2D rendering implementation
target.useBitmapCoordinateSpace((scope: any) => {
const ctx = scope.context;
// Draw trend line using this._data.point1 and this._data.point2
// ... drawing logic
});
}
}
const trendLine = new TrendLinePrimitive(
{ time: "2023-01-01" as Time, value: 100 },
{ time: "2023-01-10" as Time, value: 120 },
);
<TimeChart>
<TimeChart.Series
type="Line"
data={priceData}
primitives={[trendLine]}
onAttachPrimitives={(primitives) => console.log("Primitives attached:", primitives)}
/>
</TimeChart>;
import { TimeChart, type PanePrimitive } from "@dschz/solid-lightweight-charts";
import type {
IPanePrimitivePaneView,
IPrimitivePaneRenderer,
PaneAttachedParameter,
Time,
} from "lightweight-charts";
// Watermark primitive with proper TypeScript implementation
class WatermarkPrimitive implements PanePrimitive<Time> {
private _paneViews: WatermarkPaneView[];
private _text: string;
private _color: string;
private _fontSize: number;
constructor(text: string, color = "rgba(128, 128, 128, 0.3)", fontSize = 48) {
this._text = text;
this._color = color;
this._fontSize = fontSize;
this._paneViews = [new WatermarkPaneView(this)];
}
updateAllViews() {
this._paneViews.forEach((pv) => pv.update());
}
paneViews() {
return this._paneViews;
}
attached(param: PaneAttachedParameter<Time>) {
// Pane primitives can use this for initialization
}
detached() {
// Cleanup if needed
}
getText() {
return this._text;
}
getColor() {
return this._color;
}
getFontSize() {
return this._fontSize;
}
}
class WatermarkPaneView implements IPanePrimitivePaneView {
private _source: WatermarkPrimitive;
private _renderer: WatermarkPaneRenderer;
constructor(source: WatermarkPrimitive) {
this._source = source;
this._renderer = new WatermarkPaneRenderer();
}
update() {
this._renderer.setData({
text: this._source.getText(),
color: this._source.getColor(),
fontSize: this._source.getFontSize(),
});
}
renderer() {
return this._renderer;
}
zOrder() {
return "bottom" as const;
}
}
class WatermarkPaneRenderer implements IPrimitivePaneRenderer {
private _data: { text: string; color: string; fontSize: number } | null = null;
setData(data: { text: string; color: string; fontSize: number } | null) {
this._data = data;
}
draw(target: any) {
if (!this._data) return;
target.useBitmapCoordinateSpace((scope: any) => {
const ctx = scope.context;
const { width, height } = scope.bitmapSize;
ctx.save();
ctx.font = `${this._data!.fontSize}px Arial`;
ctx.fillStyle = this._data!.color;
ctx.textAlign = "center";
ctx.textBaseline = "middle";
// Draw watermark in center of pane
ctx.fillText(this._data!.text, width / 2, height / 2);
ctx.restore();
});
}
}
const watermark = new WatermarkPrimitive("DEMO CHART");
<TimeChart>
<TimeChart.Series type="Line" data={priceData} />
<TimeChart.Pane
primitives={[watermark]}
onAttachPrimitives={(primitives) => console.log("Pane primitives attached")}
>
<TimeChart.Series type="Histogram" data={volumeData} />
</TimeChart.Pane>
</TimeChart>;
💡 Complete Examples: For fully working primitive implementations with comprehensive TypeScript types, see the interactive examples in our playground:
SeriesPrimitivesExample.tsx
- Trend lines, support/resistance, price alerts, annotationsPanePrimitivesExample.tsx
- Watermarks, grid overlays, corner badges
See playground/App.tsx
for a complete working showcase with live interactive examples:
Core Chart Types:
Advanced Features (New in v0.2.0):
Run the playground locally:
git clone https://github.com/dsnchz/solid-lightweight-charts
cd solid-lightweight-charts
bun install
bun start
Full documentation and advanced guides coming soon.
MIT © Daniel Sanchez
0.3.3
FAQs
TradingView Lightweight Charts™ as SolidJS components
We found that @dschz/solid-lightweight-charts demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
/Research
Malicious npm package impersonates Nodemailer and drains wallets by hijacking crypto transactions across multiple blockchains.
Security News
This episode explores the hard problem of reachability analysis, from static analysis limits to handling dynamic languages and massive dependency trees.
Security News
/Research
Malicious Nx npm versions stole secrets and wallet info using AI CLI tools; Socket’s AI scanner detected the supply chain attack and flagged the malware.