@overdoser/react-toolkit 0.0.6 → 0.0.8
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/AGENTS.md +15 -0
- package/components/Button/Button.d.ts +13 -0
- package/components/Chart/AreaChart.d.ts +85 -0
- package/components/Chart/Axis.d.ts +30 -0
- package/components/Chart/BarChart.d.ts +111 -0
- package/components/Chart/ChartContainer.d.ts +33 -0
- package/components/Chart/ChartLegend.d.ts +9 -0
- package/components/Chart/ChartTooltip.d.ts +32 -0
- package/components/Chart/LineChart.d.ts +112 -0
- package/components/Chart/PieChart.d.ts +100 -0
- package/components/Chart/RadarChart.d.ts +86 -0
- package/components/Chart/Sparkline.d.ts +31 -0
- package/components/Chart/TradingChart.d.ts +89 -0
- package/components/Chart/index.d.ts +18 -0
- package/components/Chart/scales.d.ts +21 -0
- package/components/Chart/trading/indicators.d.ts +28 -0
- package/components/Chart/trading/period.d.ts +19 -0
- package/components/Chart/trading/types.d.ts +122 -0
- package/components/Chart/types.d.ts +60 -0
- package/components/Chart/useChartDimensions.d.ts +12 -0
- package/components/Popover/Popover.d.ts +16 -1
- package/index.css +1 -1
- package/index.d.ts +2 -0
- package/index.js +3427 -1110
- package/llms.txt +373 -2
- package/manifest.json +307 -3
- package/package.json +1 -1
- package/recipes/dashboard-charts.tsx +123 -0
- package/recipes/interactive-area-chart.tsx +226 -0
- package/recipes/interactive-bar-chart.tsx +211 -0
- package/recipes/interactive-line-chart.tsx +221 -0
- package/recipes/interactive-pie-chart.tsx +191 -0
- package/recipes/trading-chart.tsx +188 -0
- package/components/Button/Button.stories.d.ts +0 -17
- package/components/Dropdown/Dropdown.stories.d.ts +0 -8
- package/components/Form/Form.stories.d.ts +0 -11
- package/components/Link/Link.stories.d.ts +0 -9
- package/components/List/List.stories.d.ts +0 -9
- package/components/Modal/Modal.stories.d.ts +0 -9
- package/components/Popover/Popover.stories.d.ts +0 -9
- package/components/Table/Table.stories.d.ts +0 -20
- package/components/Typography/Typography.stories.d.ts +0 -15
- package/components/inputs/Checkbox/Checkbox.stories.d.ts +0 -9
- package/components/inputs/Input/Input.stories.d.ts +0 -13
- package/components/inputs/Radio/Radio.stories.d.ts +0 -7
- package/components/inputs/Select/Select.stories.d.ts +0 -18
- package/components/inputs/Textarea/Textarea.stories.d.ts +0 -10
- package/test-setup.d.ts +0 -0
package/llms.txt
CHANGED
|
@@ -35,6 +35,7 @@ Props:
|
|
|
35
35
|
- `loading?: boolean` — default `false`. When `true`, button is disabled and `aria-busy`.
|
|
36
36
|
- `loadingStyle?: 'dots' | 'shimmer' | 'border'` — default `'dots'`. Only used when `loading` is true.
|
|
37
37
|
- `fullWidth?: boolean` — default `false`
|
|
38
|
+
- `iconOnly?: boolean` — default `false`. Squares the button and renders content larger and bolder, for single-glyph buttons (`‹`, `›`, `×`, `+`). Always pair with `aria-label`.
|
|
38
39
|
- `classes?: Partial<ButtonClasses>` where `ButtonClasses = { root, content, shimmer, dots, dot }`
|
|
39
40
|
|
|
40
41
|
Example:
|
|
@@ -221,7 +222,8 @@ Mode B example:
|
|
|
221
222
|
Import: `import { Popover } from '@overdoser/react-toolkit'`
|
|
222
223
|
|
|
223
224
|
Props:
|
|
224
|
-
- `trigger: ReactNode` — required.
|
|
225
|
+
- `trigger: ReactNode` — required. By default, wrapped in an internal `<button>` (so a plain `'Help'` string or an icon is fine).
|
|
226
|
+
- `asChild?: boolean` — default `false`. When `true` and `trigger` is a single React element, the trigger is rendered **as-is** with click/aria/ref merged into it via `cloneElement` (no wrapping `<button>`). Use this when you want to pass your own interactive element (e.g. a `<Button>`) without producing `<button>` nested inside `<button>` (a hydration error).
|
|
225
227
|
- `content: ReactNode` — required. Rendered inside an `[role="dialog"]` panel when open.
|
|
226
228
|
- `position?: 'top' | 'bottom' | 'left' | 'right'` — default `'bottom'`
|
|
227
229
|
- `open?: boolean` — controlled.
|
|
@@ -232,11 +234,20 @@ Closes on outside click and Escape. Auto-focuses the first focusable child of `c
|
|
|
232
234
|
|
|
233
235
|
`children` is intentionally typed as `never` — pass via `content`.
|
|
234
236
|
|
|
235
|
-
Example:
|
|
237
|
+
Example — string trigger (default wrapping):
|
|
236
238
|
```tsx
|
|
237
239
|
<Popover trigger="Help" content={<p>Some help text</p>} position="right" />
|
|
238
240
|
```
|
|
239
241
|
|
|
242
|
+
Example — passing a `<Button>` without nested-button warning:
|
|
243
|
+
```tsx
|
|
244
|
+
<Popover
|
|
245
|
+
asChild
|
|
246
|
+
trigger={<Button iconOnly aria-label="Settings"><GearIcon /></Button>}
|
|
247
|
+
content={<Settings />}
|
|
248
|
+
/>
|
|
249
|
+
```
|
|
250
|
+
|
|
240
251
|
### Modal
|
|
241
252
|
Import: `import { Modal } from '@overdoser/react-toolkit'`
|
|
242
253
|
|
|
@@ -434,6 +445,366 @@ Example:
|
|
|
434
445
|
<Textarea placeholder="Bio" rows={3} autoExpand />
|
|
435
446
|
```
|
|
436
447
|
|
|
448
|
+
### Charts: LineChart, AreaChart, BarChart, PieChart, RadarChart, TradingChart, Sparkline
|
|
449
|
+
Imports: `import { LineChart, AreaChart, BarChart, PieChart, RadarChart, TradingChart, Sparkline, type ChartConfig } from '@overdoser/react-toolkit'`
|
|
450
|
+
|
|
451
|
+
Responsive SVG charts, no external dependencies. Each chart fills its container width via `ResizeObserver`. Theme via five CSS variables: `--crk-chart-1` … `--crk-chart-5` (overridable on `:root`). Plus `--crk-chart-grid`, `--crk-chart-axis`, `--crk-chart-label-inside` (default `#ffffff` — used for labels positioned inside bar rectangles), `--crk-chart-tooltip-bg`, `--crk-chart-tooltip-text`.
|
|
452
|
+
|
|
453
|
+
`ChartConfig` shape:
|
|
454
|
+
```ts
|
|
455
|
+
type ChartConfig = Record<string, { label: string; color: string }>;
|
|
456
|
+
```
|
|
457
|
+
Keys must match data-row field names. The `color` is any CSS color; use the chart tokens for consistency.
|
|
458
|
+
|
|
459
|
+
Shared props (LineChart / AreaChart / BarChart):
|
|
460
|
+
- `data: T[]` — row data.
|
|
461
|
+
- `xKey: keyof T & string` — category field for the X axis.
|
|
462
|
+
- `config: ChartConfig` — series keyed by data-field name.
|
|
463
|
+
- `aspectRatio?: number` — default `16 / 9`.
|
|
464
|
+
- `height?: number` — fixed pixel height; overrides `aspectRatio`.
|
|
465
|
+
- `showGrid?: boolean` — default `true`.
|
|
466
|
+
- `showLegend?: boolean` — default `true`.
|
|
467
|
+
- `showTooltip?: boolean` — default `true`.
|
|
468
|
+
- `yTickCount?: number` — default `5`. Approximate.
|
|
469
|
+
- `yFormat?: (v: number) => string`
|
|
470
|
+
- `xFormat?: (v: string) => string`
|
|
471
|
+
- `valueFormat?: (v: number) => string` — used inside the default tooltip.
|
|
472
|
+
- `renderTooltip?: (row: T) => ReactNode` — replace the default tooltip body.
|
|
473
|
+
- `margin?: Partial<ChartMargin>` — `{ top, right, bottom, left }`. Defaults `{ 12, 16, 28, 48 }`.
|
|
474
|
+
- `emptyMessage?: ReactNode` — default `'No data'`.
|
|
475
|
+
- `classes?: Partial<ChartClasses>` where `ChartClasses = { root, svg, grid, axis, axisLabel, series, point, legend, legendItem, tooltip }`.
|
|
476
|
+
|
|
477
|
+
LineChart extras (covers every shadcn line-chart variant via composable props):
|
|
478
|
+
- `curve?: 'linear' | 'monotone' | 'step'` — default `'monotone'`. `'step'` is step-after (value holds until the next x).
|
|
479
|
+
- `showPoints?: boolean` — default `true`.
|
|
480
|
+
- `renderDot?: (args: { row, value, seriesKey, index, x, y, color, active }) => ReactNode` — replace the default circle with a custom SVG element per point.
|
|
481
|
+
- `dotColorKey?: keyof T & string` — when set, each dot's fill comes from `row[dotColorKey]` (the line itself keeps the series color).
|
|
482
|
+
- `showValues?: boolean` — default `false`. Renders a numeric label near each point.
|
|
483
|
+
- `valuePosition?: 'top' | 'bottom'` — default `'top'`.
|
|
484
|
+
- `renderLabel?: (args: { row, value, seriesKey, index }) => ReactNode` — custom label content. Overrides `valueFormat` for labels. Return `null` to skip.
|
|
485
|
+
- `activeIndex?: number` — highlight a specific point; other points fade.
|
|
486
|
+
- `onPointClick?: (args: { row, value, seriesKey, index }) => void` — fires when a dot (or the area around it) is clicked.
|
|
487
|
+
|
|
488
|
+
Quick mapping from shadcn variant names to LineChart props:
|
|
489
|
+
- **Default / Multiple** → no extras (multi-series via multiple keys in `config`).
|
|
490
|
+
- **Linear** → `curve="linear"`.
|
|
491
|
+
- **Step** → `curve="step"`.
|
|
492
|
+
- **Dots** → `showPoints` (on by default).
|
|
493
|
+
- **Dots Custom** → `renderDot`.
|
|
494
|
+
- **Dots Colors** → `dotColorKey` (each row has a field holding its dot color; e.g. `{ ..., fill: 'var(--crk-chart-3)' }` + `dotColorKey="fill"`).
|
|
495
|
+
- **Label / Label Custom** → `showValues` + `valuePosition`, or `renderLabel`.
|
|
496
|
+
- **Interactive** → multiple series in `data`, but `config` passed to the chart only includes the *active* series (`config={{ [active]: fullConfig[active] }}`). Consumer renders the selector UI — tiles, prev/next navigator, or `<Dropdown>` all work. See `recipes/interactive-line-chart.tsx` for all three. `activeIndex` + `onPointClick` are optional and pertain to highlighting a row WITHIN the active series, not selecting the series.
|
|
497
|
+
|
|
498
|
+
AreaChart extras (covers every shadcn area-chart variant via composable props):
|
|
499
|
+
- `curve?: 'linear' | 'monotone' | 'step'` — default `'monotone'`.
|
|
500
|
+
- `stacked?: boolean` — default `false`. Stacks series bottom-up in config-key order.
|
|
501
|
+
- `stackOffset?: 'none' | 'expand'` — default `'none'`. `'expand'` normalizes each row to sum to 1 (percentage stack). Requires `stacked`.
|
|
502
|
+
- `fillGradient?: boolean` — default `false`. Replaces flat fill with a per-series vertical linear gradient (opaque top → transparent bottom).
|
|
503
|
+
- `showXAxis?: boolean` / `showYAxis?: boolean` — default `true`. Pass `false` to hide either axis.
|
|
504
|
+
- `SeriesConfig.icon?: ReactNode` — if set on a series, the legend renders the icon (colored to match) in place of the swatch.
|
|
505
|
+
|
|
506
|
+
Quick mapping from shadcn variant names to AreaChart props:
|
|
507
|
+
- **Default / Linear / Step / Legend** → `curve` + `showLegend`.
|
|
508
|
+
- **Axes** → defaults (both axes shown). Pass `showYAxis={false}` to hide.
|
|
509
|
+
- **Stacked** → `stacked`.
|
|
510
|
+
- **Stacked Expand** → `stacked` + `stackOffset="expand"`.
|
|
511
|
+
- **Gradient** → `fillGradient`.
|
|
512
|
+
- **Icons** → put an `icon` field on each `config` entry.
|
|
513
|
+
- **Interactive** → for AreaChart this is a **data-range filter**, not a series toggle: all series stay visible (stacked, often `fillGradient`), and the selector swaps the slice of `data` shown (e.g. last 7d / 14d / 30d). Three selector UIs in `recipes/interactive-area-chart.tsx`: tiles, prev/next navigator, `<Dropdown>`.
|
|
514
|
+
|
|
515
|
+
Example — stacked + gradient:
|
|
516
|
+
```tsx
|
|
517
|
+
<AreaChart
|
|
518
|
+
data={data}
|
|
519
|
+
xKey="month"
|
|
520
|
+
config={config}
|
|
521
|
+
stacked
|
|
522
|
+
fillGradient
|
|
523
|
+
showYAxis={false}
|
|
524
|
+
/>
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
BarChart extras (covers every shadcn bar-chart variant via composable props):
|
|
528
|
+
- `orientation?: 'vertical' | 'horizontal'` — default `'vertical'`. `'horizontal'` swaps the axes so bars extend left→right.
|
|
529
|
+
- `stacked?: boolean` — default `false`. Series stack on top of each other (positive stacks up, negative stacks down). Ignored with a single series.
|
|
530
|
+
- `showValues?: boolean` — default `false`. Renders a numeric label on every bar.
|
|
531
|
+
- `valuePosition?: 'outside' | 'inside' | 'inside-start'` — default `'outside'`. Where the label sits relative to the bar: `'outside'` past the value end, `'inside'` inside near the value end, `'inside-start'` inside near the baseline. On vertical bars, `'inside-start'` rotates the label ±90° so it reads along the bar's length.
|
|
532
|
+
- `renderLabel?: (args: { row, value, seriesKey, index }) => ReactNode` — custom label content. Overrides `valueFormat` for labels. Return `null` to skip.
|
|
533
|
+
- `colorBy?: 'series' | 'index'` — default `'series'`. `'index'` picks color per row from `colors`; useful for "one color per category" charts.
|
|
534
|
+
- `colors?: string[]` — palette for `colorBy='index'`. Defaults to the five `--crk-chart-N` tokens.
|
|
535
|
+
- `negativeColor?: string` — override fill for bars whose value is negative.
|
|
536
|
+
- `activeIndex?: number` — highlight one category index; other groups fade.
|
|
537
|
+
- `onBarClick?: (args: { row, value, seriesKey, index }) => void` — fires when a bar is clicked.
|
|
538
|
+
- `groupPadding?: number` — default `0.2`. Inner padding between category groups.
|
|
539
|
+
- `barPadding?: number` — default `0.1`. Inner padding between grouped bars. Ignored when stacked.
|
|
540
|
+
- `barRadius?: number` — default `4`. Corner radius on the bar's value end.
|
|
541
|
+
|
|
542
|
+
Quick mapping from shadcn variant names to props:
|
|
543
|
+
- **Default / Multiple** → no extra props (single vs. multi-series via `config`).
|
|
544
|
+
- **Horizontal** → `orientation="horizontal"`.
|
|
545
|
+
- **Stacked** → `stacked`.
|
|
546
|
+
- **Label** → `showValues` (+ optional `valuePosition`).
|
|
547
|
+
- **Label Custom** → `renderLabel` + `valuePosition="inside-start"` (typically with `orientation="horizontal"`). `renderLabel` receives the row, so return e.g. `String(row[xKey])` to draw the category name inside the bar.
|
|
548
|
+
- **Mixed** → `colorBy="index"` (+ optional `colors`).
|
|
549
|
+
- **Negative** → numeric values that span zero; pair with `negativeColor` for distinct below-zero fill.
|
|
550
|
+
- **Active** → `activeIndex={n}`.
|
|
551
|
+
- **Interactive** → multiple series in `data`, but only the *active* series is passed to the chart's `config` (`config={{ [active]: fullConfig[active] }}`). Consumer renders the selector UI — tiles, prev/next navigator, or `<Dropdown>` all work. See `recipes/interactive-bar-chart.tsx` for all three. `activeIndex` + `onBarClick` are an *orthogonal* row-highlight feature, not the series-selection mechanism.
|
|
552
|
+
|
|
553
|
+
Example — LineChart:
|
|
554
|
+
```tsx
|
|
555
|
+
const config: ChartConfig = {
|
|
556
|
+
revenue: { label: 'Revenue', color: 'var(--crk-chart-1)' },
|
|
557
|
+
costs: { label: 'Costs', color: 'var(--crk-chart-2)' },
|
|
558
|
+
};
|
|
559
|
+
|
|
560
|
+
<LineChart
|
|
561
|
+
data={[{ month: 'Jan', revenue: 120, costs: 60 }, /* … */]}
|
|
562
|
+
xKey="month"
|
|
563
|
+
config={config}
|
|
564
|
+
yFormat={(v) => `$${v}k`}
|
|
565
|
+
/>
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
Example — BarChart variants:
|
|
569
|
+
```tsx
|
|
570
|
+
// Horizontal
|
|
571
|
+
<BarChart data={data} xKey="quarter" config={config} orientation="horizontal" />
|
|
572
|
+
|
|
573
|
+
// Stacked
|
|
574
|
+
<BarChart data={data} xKey="quarter" config={config} stacked />
|
|
575
|
+
|
|
576
|
+
// Mixed (one color per category)
|
|
577
|
+
<BarChart data={data} xKey="quarter" config={single} colorBy="index" />
|
|
578
|
+
|
|
579
|
+
// Negative values with a danger color below zero
|
|
580
|
+
<BarChart
|
|
581
|
+
data={deltas}
|
|
582
|
+
xKey="month"
|
|
583
|
+
config={{ delta: { label: 'Δ', color: 'var(--crk-chart-1)' } }}
|
|
584
|
+
negativeColor="var(--crk-chart-4)"
|
|
585
|
+
/>
|
|
586
|
+
|
|
587
|
+
// Active / interactive
|
|
588
|
+
<BarChart
|
|
589
|
+
data={data}
|
|
590
|
+
xKey="quarter"
|
|
591
|
+
config={single}
|
|
592
|
+
activeIndex={active}
|
|
593
|
+
onBarClick={({ index }) => setActive(index)}
|
|
594
|
+
/>
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
### PieChart
|
|
598
|
+
Import: `import { PieChart } from '@overdoser/react-toolkit'`
|
|
599
|
+
|
|
600
|
+
Single-ring pie / donut. One slice per row in `data`.
|
|
601
|
+
|
|
602
|
+
Props:
|
|
603
|
+
- `data: T[]` — one slice per row.
|
|
604
|
+
- `valueKey: keyof T & string` — numeric value field.
|
|
605
|
+
- `nameKey: keyof T & string` — slice label (legend, tooltip, label).
|
|
606
|
+
- `colorKey?: keyof T & string` — per-row fill field (falls back to `colors`).
|
|
607
|
+
- `colors?: string[]` — palette indexed by row order. Defaults to the five `--crk-chart-N` tokens.
|
|
608
|
+
- `innerRadius?: number | string` — pixels or `'NN%'`. `0` = pie, `>0` = donut. @default `0`
|
|
609
|
+
- `outerRadius?: number | string` — @default `'90%'`
|
|
610
|
+
- `strokeWidth?: number` — separator stroke between slices. `0` = "separator-none". @default `2`
|
|
611
|
+
- `strokeColor?: string` — @default `'var(--crk-color-bg)'`
|
|
612
|
+
- `padAngle?: number` — degrees of visual gap between slices. @default `0`
|
|
613
|
+
- `showLabels?: boolean` — render `${name} ${pct}` per slice. @default `false`
|
|
614
|
+
- `valuePosition?: 'outside' | 'inside'` — label position. @default `'outside'`
|
|
615
|
+
- `showLabelLines?: boolean` — draw a thin leader line from each slice edge to its outside label (slice-colored). No effect for inside labels. @default `true`
|
|
616
|
+
- `renderLabel?: (args: { row, value, fraction, index }) => ReactNode` — custom label content. Return `null` to skip.
|
|
617
|
+
- `centerLabel?: ReactNode` — content rendered at the centre (typical donut summary).
|
|
618
|
+
- `activeIndex?: number` — pull the slice outward; other slices fade.
|
|
619
|
+
- `onSliceClick?: (args: { row, value, index }) => void`
|
|
620
|
+
- `showLegend?: boolean` — @default `true`
|
|
621
|
+
- `showTooltip?: boolean` — @default `true`
|
|
622
|
+
- `valueFormat?: (v: number) => string`
|
|
623
|
+
- `renderTooltip?: (row: T) => ReactNode`
|
|
624
|
+
- `aspectRatio?: number` — @default `1` (square)
|
|
625
|
+
- `height?: number` — fixed pixel height.
|
|
626
|
+
- `emptyMessage?: ReactNode` — @default `'No data'`
|
|
627
|
+
- `className`, `style`, `classes?: Partial<ChartClasses>`
|
|
628
|
+
|
|
629
|
+
Quick mapping from shadcn variant names to PieChart props:
|
|
630
|
+
- **Simple / Donut** → `innerRadius` (0 → pie, > 0 → donut).
|
|
631
|
+
- **Legend** → `showLegend` (on by default).
|
|
632
|
+
- **Separator None** → `strokeWidth={0}`.
|
|
633
|
+
- **Label** → `showLabels` (default content: `${name} ${pct}`). Outside labels get a slice-colored leader line by default; disable with `showLabelLines={false}`.
|
|
634
|
+
- **Label Custom** → `renderLabel` (with the leader line still drawn).
|
|
635
|
+
- **Label List** → `valuePosition="inside"` + `renderLabel={({ row }) => String(row[nameKey])}`. Renders the slice name *on the colored surface* of each slice. Inside-position labels are styled with the `--crk-chart-label-inside` token (white by default) for contrast.
|
|
636
|
+
- **Donut Text** → `innerRadius` + `centerLabel`.
|
|
637
|
+
- **Donut Active** → `activeIndex={n}`.
|
|
638
|
+
- **Interactive** → metric/period filter — see `recipes/interactive-pie-chart.tsx`.
|
|
639
|
+
- **Stacked (nested rings)** → not currently supported.
|
|
640
|
+
|
|
641
|
+
Example — donut with centre summary:
|
|
642
|
+
```tsx
|
|
643
|
+
<PieChart
|
|
644
|
+
data={browsers}
|
|
645
|
+
nameKey="browser"
|
|
646
|
+
valueKey="visitors"
|
|
647
|
+
colorKey="fill"
|
|
648
|
+
innerRadius="62%"
|
|
649
|
+
centerLabel={<><strong>835</strong><div>Visitors</div></>}
|
|
650
|
+
/>
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
### RadarChart
|
|
654
|
+
Import: `import { RadarChart } from '@overdoser/react-toolkit'`
|
|
655
|
+
|
|
656
|
+
Multi-series spider / radar chart. One vertex per row in `data`, one polygon per key in `config`.
|
|
657
|
+
|
|
658
|
+
Props:
|
|
659
|
+
- `data: T[]` — one vertex per row.
|
|
660
|
+
- `axisKey: keyof T & string` — row field providing the axis label at that vertex.
|
|
661
|
+
- `config: ChartConfig` — series keyed by data-field name.
|
|
662
|
+
- `gridType?: 'polygon' | 'circle'` — concentric ring shape. @default `'polygon'`
|
|
663
|
+
- `showGrid?: boolean` — concentric grid rings. @default `true`
|
|
664
|
+
- `showRadialLines?: boolean` — spokes from center to each vertex. @default `true`
|
|
665
|
+
- `showAxisLabels?: boolean` — vertex labels around the outside. @default `true`
|
|
666
|
+
- `showRadiusAxis?: boolean` — radial tick labels along the top spoke. @default `false`
|
|
667
|
+
- `levels?: number` — approximate ring count. @default `5`
|
|
668
|
+
- `showPoints?: boolean` — dots at each series vertex. @default `true`
|
|
669
|
+
- `fillOpacity?: number` — series fill opacity. `0` = lines only. @default `0.4`
|
|
670
|
+
- `strokeWidth?: number` — series outline stroke width. @default `2`
|
|
671
|
+
- `renderAxisLabel?: (args: { row, index, angle, x, y, textAnchor }) => ReactNode` — custom axis-label rendering. Return `null` to skip.
|
|
672
|
+
- `axisFormat?: (label: string) => string` — format the default axis label.
|
|
673
|
+
- `valueFormat?: (v: number) => string` — used by the default tooltip and the radius axis labels.
|
|
674
|
+
- `renderTooltip?: (row: T) => ReactNode`
|
|
675
|
+
- `showLegend?: boolean` — @default `true`
|
|
676
|
+
- `showTooltip?: boolean` — @default `true`
|
|
677
|
+
- `aspectRatio?: number` — @default `1` (square)
|
|
678
|
+
- `height?: number`
|
|
679
|
+
- `emptyMessage?: ReactNode` — @default `'No data'`
|
|
680
|
+
- `className`, `style`, `classes?: Partial<ChartClasses>`
|
|
681
|
+
|
|
682
|
+
Quick mapping from shadcn variant names to RadarChart props:
|
|
683
|
+
- **Default / Multiple / Legend** → multi-series via multiple keys in `config`.
|
|
684
|
+
- **Dots** → `showPoints` (on by default).
|
|
685
|
+
- **Lines Only** → `fillOpacity={0}`.
|
|
686
|
+
- **Grid Circle / Grid Circle Fill** → `gridType="circle"` (+ `fillOpacity` for "fill").
|
|
687
|
+
- **Grid Circle No Lines** → `gridType="circle"` + `showRadialLines={false}`.
|
|
688
|
+
- **Grid Fill** → defaults (filled polygon grid).
|
|
689
|
+
- **Grid Custom** → override the grid via the `classes={{ grid: 'my-grid' }}` prop or theme tokens.
|
|
690
|
+
- **Grid None** → `showGrid={false}` (+ usually `showRadialLines={false}`).
|
|
691
|
+
- **Icons** → set `icon` on each `config` entry.
|
|
692
|
+
- **Label Custom** → `renderAxisLabel`.
|
|
693
|
+
- **Radius** → `showRadiusAxis`.
|
|
694
|
+
|
|
695
|
+
Example — dual-series radar with circular grid:
|
|
696
|
+
```tsx
|
|
697
|
+
<RadarChart
|
|
698
|
+
data={data}
|
|
699
|
+
axisKey="month"
|
|
700
|
+
config={config}
|
|
701
|
+
gridType="circle"
|
|
702
|
+
/>
|
|
703
|
+
```
|
|
704
|
+
|
|
705
|
+
### TradingChart
|
|
706
|
+
Import: `import { TradingChart, type Datafeed, type Bar, type Resolution, type IndicatorConfig } from '@overdoser/react-toolkit'`
|
|
707
|
+
|
|
708
|
+
Canvas-rendered, TradingView-style chart for OHLCV data. Different surface from the SVG charts: it owns its own data lifecycle via a `Datafeed` adapter and supports pan, zoom, crosshair, and a small built-in indicator library.
|
|
709
|
+
|
|
710
|
+
Props:
|
|
711
|
+
- `datafeed: Datafeed` — required. Plug-in adapter (see contract below).
|
|
712
|
+
- `symbol: string` — required.
|
|
713
|
+
- `resolution: Resolution` — bar size (the "tick interval"). TradingView-style: numeric strings are minutes (`'1'`, `'5'`, `'60'`); `'D'`, `'W'`, `'M'` for day/week/month; any other string passes through.
|
|
714
|
+
- `period?: Period` — visible time-range window (the "chart interval"): `'1D' | '5D' | '1M' | '3M' | '6M' | '1Y' | '5Y'` or any `<n><unit>` string (`'30d'`, `'48h'`, `'2y'`). When set, the chart fetches bars covering the period and the initial visible window spans all of them. Overrides `initialLookback`. Note: the chart does NOT auto-adjust `resolution` for you — pair with `suggestResolutionForPeriod()` / `suggestPeriodForResolution()` if you want them coupled.
|
|
715
|
+
- `seriesType?: 'candle' | 'bar' | 'line' | 'area'` — main pane style. @default `'candle'`. `'bar'` = OHLC bars (vertical high-low line, left tick at open, right tick at close).
|
|
716
|
+
- `timezone?: Timezone` / `defaultTimezone?: Timezone` / `onTimezoneChange?: (tz) => void` — controlled / uncontrolled / notification trio for the crosshair time label. `Timezone = 'local' | 'utc' | IANA-name`. Default `'local'`. Local mode renders `YYYY-MM-DD HH:MM:SS +HH:MM`, UTC renders `… UTC`, IANA strings render `… EST` (short timezone via `Intl.DateTimeFormat`).
|
|
717
|
+
- `showConfigPanel?: boolean` — show the gear button in the chart header + a Popover with a Timezone selector. @default `true`. Hide it if you want to manage timezone purely externally.
|
|
718
|
+
- `indicators?: IndicatorConfig[]` — see "Indicators" below.
|
|
719
|
+
- `precision?: number` — decimal places for price labels and tooltips. @default `2`
|
|
720
|
+
- `initialLookback?: number` — historical bars fetched on mount when `period` is not set. @default `500`
|
|
721
|
+
- `height?: number` — pixel height. @default `420`
|
|
722
|
+
- `upColor?: string` / `downColor?: string` — candle and volume colors.
|
|
723
|
+
- `lineColor?: string` — for `line` / `area` series.
|
|
724
|
+
- `onCrosshair?: (info: CrosshairInfo | null) => void`
|
|
725
|
+
- `onVisibleRangeChange?: (range, bars) => void`
|
|
726
|
+
- `className`, `style`
|
|
727
|
+
|
|
728
|
+
Datafeed contract:
|
|
729
|
+
```ts
|
|
730
|
+
interface Bar { time: number /* unix seconds */; open: number; high: number; low: number; close: number; volume?: number }
|
|
731
|
+
|
|
732
|
+
interface Datafeed {
|
|
733
|
+
getBars(args: { symbol; resolution; from; to; countBack? }): Promise<Bar[]>; // ascending by time
|
|
734
|
+
subscribeBars(args: { symbol; resolution; onTick(bar: Bar): void }): SubscriptionHandle;
|
|
735
|
+
unsubscribeBars(handle: SubscriptionHandle): void;
|
|
736
|
+
}
|
|
737
|
+
```
|
|
738
|
+
- `from`/`to` are unix seconds (TV convention).
|
|
739
|
+
- A tick whose `time` equals the previous bar's `time` updates the in-progress bar; otherwise the chart appends a new bar.
|
|
740
|
+
- Pan-left past the loaded window automatically fires another `getBars` for older history.
|
|
741
|
+
|
|
742
|
+
Indicators (`indicators?: IndicatorConfig[]`):
|
|
743
|
+
- `{ type: 'sma', period, color? }` — overlay on the main pane.
|
|
744
|
+
- `{ type: 'ema', period, color? }` — overlay on the main pane.
|
|
745
|
+
- `{ type: 'bollinger', period, stdDev?, color?, fillOpacity? }` — overlay, filled band between upper/lower.
|
|
746
|
+
- `{ type: 'rsi', period?, color?, overbought?, oversold? }` — its own sub-pane below the main pane.
|
|
747
|
+
- `{ type: 'volume', upColor?, downColor? }` — sub-pane histogram colored by candle direction.
|
|
748
|
+
|
|
749
|
+
Pure indicator functions are also exported (`sma`, `ema`, `bollinger`, `rsi`, `volumeSeries`) for custom rendering or analysis outside the chart.
|
|
750
|
+
|
|
751
|
+
Period / resolution coupling helpers (exported):
|
|
752
|
+
- `periodToSeconds(period: Period): number` — total seconds in a typed or `<n><unit>` period.
|
|
753
|
+
- `suggestResolutionForPeriod(period): Resolution` — opinionated mapping targeting ~200–500 visible bars.
|
|
754
|
+
- `suggestPeriodForResolution(resolution): Period` — inverse of the above.
|
|
755
|
+
|
|
756
|
+
Typical UI: two coupled dropdowns. Changing the period dropdown calls `suggestResolutionForPeriod()` on its new value to keep the bar count reasonable; changing the resolution dropdown calls `suggestPeriodForResolution()` on its new value.
|
|
757
|
+
|
|
758
|
+
Interactions:
|
|
759
|
+
- Drag = pan.
|
|
760
|
+
- Wheel = zoom (anchored on cursor).
|
|
761
|
+
- ←/→ keys = nudge pan.
|
|
762
|
+
- Hover = full crosshair (dashed horizontal + vertical lines) with a **price badge** on the right edge and a **time badge** under the X axis showing `YYYY-MM-DD HH:MM:SS <tz>` at the cursor's snapped bar (timezone is configurable via the gear panel or props). `onCrosshair` callback fires.
|
|
763
|
+
|
|
764
|
+
Out of scope (v1):
|
|
765
|
+
- Drawing tools (trend lines, fib, shapes).
|
|
766
|
+
- Custom indicator settings dialog.
|
|
767
|
+
- Touch gestures (pointer events work on touch but no pinch-zoom).
|
|
768
|
+
- Multi-symbol comparison overlays.
|
|
769
|
+
- Persistence / save-restore state.
|
|
770
|
+
|
|
771
|
+
Example — full indicator stack with a custom datafeed:
|
|
772
|
+
```tsx
|
|
773
|
+
<TradingChart
|
|
774
|
+
datafeed={myDatafeed}
|
|
775
|
+
symbol="AAPL"
|
|
776
|
+
resolution="60"
|
|
777
|
+
indicators={[
|
|
778
|
+
{ type: 'ema', period: 12, color: 'var(--crk-chart-2)' },
|
|
779
|
+
{ type: 'ema', period: 26, color: 'var(--crk-chart-3)' },
|
|
780
|
+
{ type: 'bollinger', period: 20, stdDev: 2 },
|
|
781
|
+
{ type: 'rsi', period: 14 },
|
|
782
|
+
{ type: 'volume' },
|
|
783
|
+
]}
|
|
784
|
+
height={560}
|
|
785
|
+
/>
|
|
786
|
+
```
|
|
787
|
+
|
|
788
|
+
### Sparkline
|
|
789
|
+
Tiny inline trend line — fixed pixel width/height, no axes/legend/tooltip.
|
|
790
|
+
|
|
791
|
+
Props:
|
|
792
|
+
- `data: number[]` — numeric series, left-to-right.
|
|
793
|
+
- `width?: number` — default `80`.
|
|
794
|
+
- `height?: number` — default `24`.
|
|
795
|
+
- `color?: string` — default `'var(--crk-chart-1)'`.
|
|
796
|
+
- `strokeWidth?: number` — default `1.5`.
|
|
797
|
+
- `curve?: 'linear' | 'monotone'` — default `'monotone'`.
|
|
798
|
+
- `fill?: boolean` — default `false`. Renders a low-opacity area under the line.
|
|
799
|
+
- `showLastPoint?: boolean` — default `false`. Draws a dot at the rightmost point.
|
|
800
|
+
- `aria-label?: string`
|
|
801
|
+
- Forwards ref to `SVGSVGElement`.
|
|
802
|
+
|
|
803
|
+
Example:
|
|
804
|
+
```tsx
|
|
805
|
+
<Sparkline data={[1, 3, 2, 4, 3, 5, 4]} fill showLastPoint />
|
|
806
|
+
```
|
|
807
|
+
|
|
437
808
|
## Hooks
|
|
438
809
|
|
|
439
810
|
### useClickOutside
|