@dwlf/charting 1.0.0 → 1.1.1
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 +225 -19
- package/dist/charting/__tests__/chartSpec.test.d.ts +1 -0
- package/dist/charting/scales.d.ts +14 -0
- package/dist/charting/types.d.ts +454 -0
- package/dist/charting.css +1 -1
- package/dist/components/DWLFChart.d.ts +119 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/components/overlays/AlertLineAnnotationView.d.ts +14 -0
- package/dist/components/overlays/AnnotationLayer.d.ts +55 -0
- package/dist/components/overlays/ArrowAnnotationView.d.ts +24 -0
- package/dist/components/overlays/BosLineAnnotationView.d.ts +22 -0
- package/dist/components/overlays/BrushAnnotationView.d.ts +20 -0
- package/dist/components/overlays/ChannelAnnotationView.d.ts +23 -0
- package/dist/components/overlays/CrossLineAnnotationView.d.ts +29 -0
- package/dist/components/overlays/DiagonalLineOverlay.d.ts +31 -0
- package/dist/components/overlays/EmojiAnnotationView.d.ts +22 -0
- package/dist/components/overlays/FairValueGapAnnotationView.d.ts +23 -0
- package/dist/components/overlays/FibExtensionAnnotationView.d.ts +19 -0
- package/dist/components/overlays/FibRetracementAnnotationView.d.ts +19 -0
- package/dist/components/overlays/HLineAnnotationView.d.ts +15 -0
- package/dist/components/overlays/HorizontalLineOverlay.d.ts +23 -0
- package/dist/components/overlays/MarkerOverlay.d.ts +66 -0
- package/dist/components/overlays/MeasureAnnotationView.d.ts +25 -0
- package/dist/components/overlays/MessageBubbleOverlay.d.ts +55 -0
- package/dist/components/overlays/OrderBlockAnnotationView.d.ts +23 -0
- package/dist/components/overlays/PitchforkAnnotationView.d.ts +19 -0
- package/dist/components/overlays/PositionOverlay.d.ts +52 -0
- package/dist/components/overlays/RayAnnotationView.d.ts +30 -0
- package/dist/components/overlays/RectangleAnnotationView.d.ts +23 -0
- package/dist/components/overlays/SMAOverlay.d.ts +20 -0
- package/dist/components/overlays/TextAnnotationView.d.ts +24 -0
- package/dist/components/overlays/TimeRangeAnnotationView.d.ts +22 -0
- package/dist/components/overlays/TrendLineAnnotationView.d.ts +23 -0
- package/dist/components/overlays/VLineAnnotationView.d.ts +26 -0
- package/dist/components/overlays/annotationConstants.d.ts +21 -0
- package/dist/components/overlays/annotationUtils.d.ts +13 -0
- package/dist/components/overlays/useAnnotationDrag.d.ts +18 -0
- package/dist/components/overlays/usePointAnnotationDrag.d.ts +23 -0
- package/dist/hooks/useCandlestickChart.d.ts +18 -0
- package/dist/hooks/useChartAnimations.d.ts +49 -0
- package/dist/hooks/useChartLayout.d.ts +12 -0
- package/dist/hooks/useChartPanZoom.d.ts +7 -0
- package/dist/hooks/useChartPanZoomVirtual.d.ts +24 -0
- package/dist/hooks/useContainerSize.d.ts +4 -0
- package/dist/hooks/useOverlayToggles.d.ts +19 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +56 -0
- package/dist/index.js +13 -13
- package/dist/utils/indicators.d.ts +40 -0
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -22,17 +22,14 @@ import type { ChartSpec } from '@dwlf/charting';
|
|
|
22
22
|
const spec: ChartSpec = {
|
|
23
23
|
panes: [
|
|
24
24
|
{
|
|
25
|
-
|
|
25
|
+
id: 'price',
|
|
26
|
+
heightRatio: 3,
|
|
27
|
+
yScale: { mode: 'auto' },
|
|
26
28
|
series: [
|
|
27
29
|
{
|
|
30
|
+
key: 'candles',
|
|
28
31
|
type: 'ohlc',
|
|
29
|
-
data: candles
|
|
30
|
-
x: new Date(c.t * 1000).toISOString(),
|
|
31
|
-
open: c.o,
|
|
32
|
-
high: c.h,
|
|
33
|
-
low: c.l,
|
|
34
|
-
close: c.c,
|
|
35
|
-
})),
|
|
32
|
+
data: candles, // array of { t, o, h, l, c }
|
|
36
33
|
},
|
|
37
34
|
],
|
|
38
35
|
},
|
|
@@ -40,22 +37,201 @@ const spec: ChartSpec = {
|
|
|
40
37
|
};
|
|
41
38
|
|
|
42
39
|
function MyChart() {
|
|
43
|
-
return <DWLFChart spec={spec} />;
|
|
40
|
+
return <DWLFChart spec={spec} darkMode={true} enablePanZoom={true} />;
|
|
44
41
|
}
|
|
45
42
|
```
|
|
46
43
|
|
|
44
|
+
## Dark Mode
|
|
45
|
+
|
|
46
|
+
Dark mode is supported via the `darkMode` prop (defaults to `true`):
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
<DWLFChart spec={spec} darkMode={true} />
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
This controls the background, text, grid, crosshair, tooltip, and candle colors automatically.
|
|
53
|
+
|
|
54
|
+
For further customisation, use `axisColors`:
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
<DWLFChart
|
|
58
|
+
spec={spec}
|
|
59
|
+
darkMode={true}
|
|
60
|
+
axisColors={{ dark: '#8b949e', light: '#57606a' }}
|
|
61
|
+
/>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Timestamps
|
|
65
|
+
|
|
66
|
+
**Important:** The charting library expects timestamps in **milliseconds** (Unix epoch in ms). If your data uses seconds (common in crypto APIs), multiply by 1000:
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
const chartData = candles.map(c => ({
|
|
70
|
+
t: c.t * 1000, // seconds → milliseconds
|
|
71
|
+
o: c.o,
|
|
72
|
+
h: c.h,
|
|
73
|
+
l: c.l,
|
|
74
|
+
c: c.c,
|
|
75
|
+
}));
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
When pairing with `@dwlf/indicators`, note that indicator output uses the same timestamp format as input. If your source data uses seconds, the indicator output will too — convert when passing to the chart.
|
|
79
|
+
|
|
80
|
+
## Series Configuration
|
|
81
|
+
|
|
82
|
+
Each pane contains an array of series. Every series needs a `key` (unique identifier), `type`, and `data`.
|
|
83
|
+
|
|
84
|
+
### Series Types
|
|
85
|
+
|
|
86
|
+
| Type | Description | Data format |
|
|
87
|
+
|------|-------------|-------------|
|
|
88
|
+
| `ohlc` | Candlestick chart | `{ t, o, h, l, c }[]` |
|
|
89
|
+
| `line` | Line chart | `{ t, v }[]` |
|
|
90
|
+
| `hist` | Histogram bars | `{ t, v }[]` |
|
|
91
|
+
| `area` | Filled area | `{ t, v }[]` |
|
|
92
|
+
| `marker` | Point markers | `{ t, price, text?, tooltip?, shape? }[]` |
|
|
93
|
+
| `position` | Trade positions | `{ t, price, type, stopLoss?, takeProfit? }[]` |
|
|
94
|
+
|
|
95
|
+
### Series Colors
|
|
96
|
+
|
|
97
|
+
Set colors with the `color` shorthand or `style.color` (both work):
|
|
98
|
+
|
|
99
|
+
```tsx
|
|
100
|
+
// Shorthand
|
|
101
|
+
{ key: 'ema8', type: 'line', data: ema8, color: '#58a6ff' }
|
|
102
|
+
|
|
103
|
+
// Full style object (takes precedence)
|
|
104
|
+
{ key: 'ema8', type: 'line', data: ema8, style: { color: '#58a6ff', lineWidth: 2, dashed: true } }
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Style Options
|
|
108
|
+
|
|
109
|
+
```tsx
|
|
110
|
+
interface SeriesStyle {
|
|
111
|
+
color?: string; // Series color
|
|
112
|
+
lineWidth?: number; // Line thickness (default: 1.5)
|
|
113
|
+
dashed?: boolean; // Dashed line
|
|
114
|
+
opacity?: number; // Opacity (0-1)
|
|
115
|
+
markerShape?: 'arrow-up' | 'arrow-down' | 'circle';
|
|
116
|
+
markerSize?: number;
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Multi-Pane Layout
|
|
121
|
+
|
|
122
|
+
Use `heightRatio` to control pane proportions:
|
|
123
|
+
|
|
124
|
+
```tsx
|
|
125
|
+
const spec: ChartSpec = {
|
|
126
|
+
panes: [
|
|
127
|
+
{
|
|
128
|
+
id: 'price',
|
|
129
|
+
heightRatio: 3, // 75% of height
|
|
130
|
+
yScale: { mode: 'auto' },
|
|
131
|
+
series: [{ key: 'candles', type: 'ohlc', data: candles }],
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
id: 'dss',
|
|
135
|
+
heightRatio: 1, // 25% of height
|
|
136
|
+
yScale: { mode: 'fixed', min: 0, max: 100 },
|
|
137
|
+
series: [
|
|
138
|
+
{ key: 'dss', type: 'line', data: dssData, color: '#22c55e' },
|
|
139
|
+
{ key: 'signal', type: 'line', data: signalData, color: '#ef4444' },
|
|
140
|
+
],
|
|
141
|
+
guides: [
|
|
142
|
+
{ y: 80, dashed: true, label: 'OB', color: '#ef4444' },
|
|
143
|
+
{ y: 20, dashed: true, label: 'OS', color: '#22c55e' },
|
|
144
|
+
],
|
|
145
|
+
},
|
|
146
|
+
],
|
|
147
|
+
};
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## DWLFChart Props
|
|
151
|
+
|
|
152
|
+
| Prop | Type | Default | Description |
|
|
153
|
+
|------|------|---------|-------------|
|
|
154
|
+
| `spec` | `ChartSpec` | — | Chart specification (panes, series, guides) |
|
|
155
|
+
| `darkMode` | `boolean` | `true` | Dark/light theme |
|
|
156
|
+
| `enablePanZoom` | `boolean` | `false` | Enable scroll-to-zoom and drag-to-pan |
|
|
157
|
+
| `timeframe` | `string` | `'daily'` | Affects X-axis date formatting (`'daily'`, `'weekly'`, `'4h'`, `'1h'`) |
|
|
158
|
+
| `initialVisibleCount` | `number` | — | Number of candles visible initially (controls default zoom) |
|
|
159
|
+
| `extraRightSlots` | `number` | — | Extra padding on the right edge |
|
|
160
|
+
| `compressGaps` | `boolean` | `false` | Remove weekend/holiday gaps |
|
|
161
|
+
| `crosshairSnapMode` | `'series' \| 'pointer'` | `'series'` | `'pointer'` follows mouse freely, `'series'` snaps to nearest candle |
|
|
162
|
+
| `showCrosshairPriceLabel` | `boolean` | — | Show price label on crosshair |
|
|
163
|
+
| `axisColors` | `{ light?: string; dark?: string }` | — | Custom axis/crosshair colors |
|
|
164
|
+
| `annotations` | `Annotation[]` | — | Chart annotations (lines, text, fib, etc.) |
|
|
165
|
+
| `className` | `string` | — | CSS class on container |
|
|
166
|
+
| `style` | `CSSProperties` | — | Inline styles on container |
|
|
167
|
+
| `animationState` | `ChartAnimationState` | — | Control entry animations |
|
|
168
|
+
|
|
169
|
+
## Crosshair Modes
|
|
170
|
+
|
|
171
|
+
By default the crosshair snaps to the nearest candle (`'series'` mode). Most traders prefer the crosshair to follow the mouse freely — use `'pointer'` mode:
|
|
172
|
+
|
|
173
|
+
```tsx
|
|
174
|
+
<DWLFChart spec={spec} crosshairSnapMode="pointer" />
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
| Mode | Behaviour |
|
|
178
|
+
|------|-----------|
|
|
179
|
+
| `'series'` (default) | Snaps to nearest candle — good for precise OHLC readouts |
|
|
180
|
+
| `'pointer'` | Follows mouse position freely — feels more natural for interactive use |
|
|
181
|
+
|
|
182
|
+
## Pan & Zoom
|
|
183
|
+
|
|
184
|
+
Set `enablePanZoom={true}` to enable scroll-to-zoom and drag-to-pan. **This is off by default**, so the chart won't capture mouse scroll events unless you opt in.
|
|
185
|
+
|
|
186
|
+
```tsx
|
|
187
|
+
<DWLFChart spec={spec} enablePanZoom={true} />
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
If the chart is embedded in a scrollable page, be aware that `enablePanZoom` will capture scroll events over the chart area for zooming. You may want to place the chart in a fixed-height container so page scrolling still works outside the chart.
|
|
191
|
+
|
|
192
|
+
Use `initialVisibleCount` to control how many candles are visible on first render (the default shows all data):
|
|
193
|
+
|
|
194
|
+
```tsx
|
|
195
|
+
<DWLFChart spec={spec} enablePanZoom={true} initialVisibleCount={100} />
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Right-Side Buffer
|
|
199
|
+
|
|
200
|
+
By default the chart fits data edge-to-edge. To add empty space on the right (useful for seeing the latest candle clearly or leaving room for annotations), use `extraRightSlots`:
|
|
201
|
+
|
|
202
|
+
```tsx
|
|
203
|
+
<DWLFChart spec={spec} extraRightSlots={5} />
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
This adds 5 candle-widths of empty space to the right of the last data point.
|
|
207
|
+
|
|
208
|
+
Alternatively, you can append placeholder candles to your data with the same timestamp spacing but no visible data — the chart will render the empty space naturally.
|
|
209
|
+
|
|
47
210
|
## Annotations
|
|
48
211
|
|
|
49
|
-
20+ built-in annotation types with
|
|
212
|
+
20+ built-in annotation types with creation helpers:
|
|
50
213
|
|
|
51
214
|
```tsx
|
|
52
|
-
import {
|
|
215
|
+
import {
|
|
216
|
+
DWLFChart,
|
|
217
|
+
AnnotationLayer,
|
|
218
|
+
createHLineAnnotation,
|
|
219
|
+
createTrendLineAnnotation,
|
|
220
|
+
createFibRetracementAnnotation,
|
|
221
|
+
} from '@dwlf/charting';
|
|
53
222
|
|
|
54
223
|
const annotations = [
|
|
55
|
-
createHLineAnnotation({ price:
|
|
56
|
-
createTrendLineAnnotation({ time1, price1, time2, price2 }),
|
|
224
|
+
createHLineAnnotation({ price: 42000, label: 'Support', color: '#22c55e' }),
|
|
225
|
+
createTrendLineAnnotation({ time1, price1, time2, price2, color: '#3b82f6' }),
|
|
57
226
|
createFibRetracementAnnotation({ time1, price1, time2, price2 }),
|
|
58
227
|
];
|
|
228
|
+
|
|
229
|
+
<DWLFChart
|
|
230
|
+
spec={spec}
|
|
231
|
+
annotations={annotations}
|
|
232
|
+
onAnnotationSelect={(id) => console.log('selected', id)}
|
|
233
|
+
onAnnotationMove={(id, update) => console.log('moved', id, update)}
|
|
234
|
+
/>
|
|
59
235
|
```
|
|
60
236
|
|
|
61
237
|
**Available annotations:** Horizontal Line, Vertical Line, Text, Trend Line, Ray, Cross Line, Rectangle, Channel, Fibonacci Retracement, Fibonacci Extension, Measure, Pitchfork, Arrow, Time Range, Alert Line, Brush, Emoji, Order Block, Fair Value Gap, BOS Line.
|
|
@@ -64,17 +240,47 @@ const annotations = [
|
|
|
64
240
|
|
|
65
241
|
```tsx
|
|
66
242
|
import {
|
|
67
|
-
useCandlestickChart,
|
|
68
|
-
useChartPanZoom,
|
|
69
|
-
useChartLayout,
|
|
70
|
-
useContainerSize,
|
|
71
|
-
useChartAnimations,
|
|
243
|
+
useCandlestickChart, // D3 scales and layout for candlestick data
|
|
244
|
+
useChartPanZoom, // Pan and zoom state management
|
|
245
|
+
useChartLayout, // Chart dimension calculations
|
|
246
|
+
useContainerSize, // Responsive container sizing
|
|
247
|
+
useChartAnimations, // Entry animation orchestration
|
|
248
|
+
useOverlayToggles, // Overlay visibility management
|
|
72
249
|
} from '@dwlf/charting';
|
|
73
250
|
```
|
|
74
251
|
|
|
252
|
+
## Using with @dwlf/indicators
|
|
253
|
+
|
|
254
|
+
Fetch candles from your data source, compute indicators, render:
|
|
255
|
+
|
|
256
|
+
```tsx
|
|
257
|
+
import { EMA, Bollinger, DSS } from '@dwlf/indicators';
|
|
258
|
+
import { DWLFChart } from '@dwlf/charting';
|
|
259
|
+
import '@dwlf/charting/styles';
|
|
260
|
+
|
|
261
|
+
// Compute indicators (timestamps must match your candle timestamps)
|
|
262
|
+
const ema8 = EMA.computeEMA(candles, 8);
|
|
263
|
+
const bb = Bollinger.computeBollingerBands(candles, { length: 20 });
|
|
264
|
+
|
|
265
|
+
// Build chart spec — remember to convert timestamps to milliseconds
|
|
266
|
+
const spec = {
|
|
267
|
+
panes: [{
|
|
268
|
+
id: 'price',
|
|
269
|
+
heightRatio: 1,
|
|
270
|
+
yScale: { mode: 'auto' },
|
|
271
|
+
series: [
|
|
272
|
+
{ key: 'candles', type: 'ohlc', data: candles.map(c => ({ ...c, t: c.t * 1000 })) },
|
|
273
|
+
{ key: 'ema8', type: 'line', data: ema8.ema.map(p => ({ t: p.t * 1000, v: p.v })), color: '#58a6ff' },
|
|
274
|
+
{ key: 'bb-upper', type: 'line', data: bb.upper.map(p => ({ t: p.t * 1000, v: p.v })), color: '#8b949e', style: { dashed: true } },
|
|
275
|
+
{ key: 'bb-lower', type: 'line', data: bb.lower.map(p => ({ t: p.t * 1000, v: p.v })), color: '#8b949e', style: { dashed: true } },
|
|
276
|
+
],
|
|
277
|
+
}],
|
|
278
|
+
};
|
|
279
|
+
```
|
|
280
|
+
|
|
75
281
|
## Used By
|
|
76
282
|
|
|
77
|
-
This is the same charting engine that powers [DWLF](https://dwlf.co.uk) — a market intelligence platform for
|
|
283
|
+
This is the same charting engine that powers [DWLF](https://dwlf.co.uk) — a market intelligence platform for AI agents and traders.
|
|
78
284
|
|
|
79
285
|
## License
|
|
80
286
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ChartSpec, LinePoint, OhlcPoint, PaneComputedScale, PaneSpec, SeriesSpec } from './types';
|
|
2
|
+
export type ResolvePaneDomainOptions = {
|
|
3
|
+
includeOverlaysInAutoScale?: boolean;
|
|
4
|
+
};
|
|
5
|
+
export declare const resolvePaneDomain: (pane: PaneSpec, options?: ResolvePaneDomainOptions) => [number, number];
|
|
6
|
+
export declare const createPaneScale: (domain: [number, number], height: number) => PaneComputedScale;
|
|
7
|
+
export type BuildPaneScalesOptions = {
|
|
8
|
+
includeOverlaysInAutoScale?: boolean;
|
|
9
|
+
};
|
|
10
|
+
export declare const buildPaneScales: (spec: ChartSpec, paneHeights: Record<string, number>, options?: BuildPaneScalesOptions) => Record<string, PaneComputedScale>;
|
|
11
|
+
export declare const collectPaneTimes: (pane: PaneSpec) => number[];
|
|
12
|
+
export declare const collectSpecTimes: (spec: ChartSpec) => number[];
|
|
13
|
+
export declare const findClosestTime: (times: number[], value: number) => number;
|
|
14
|
+
export type { LinePoint, OhlcPoint, PaneSpec, SeriesSpec };
|