npm package: @ksport-packages/ksport-components
Description: Shared React component library for the Dynamix platform by KSport
Latest version: 0.1.2

# @ksport-packages/ksport-components

Shared React component library for the Dynamix platform by KSport. Contains D3.js charts, data tables, MUI theme, PDF layout components, and data-fetching utilities — consumed by `ksport-dynamix` and `dynamic-pdf-service`.

## Installation

```bash
npm install @ksport-packages/ksport-components
```

### Peer dependencies

```bash
npm install react react-dom @mui/material @emotion/react @emotion/styled d3
```

---

## Charts

All chart components accept a `dimensions` prop and `isPdf?: boolean`. When `isPdf={true}`, all animations, transitions, hover effects, and D3 interactions are disabled — the SVG renders synchronously, which is required for Puppeteer PDF capture.

### HistogramChart

Vertical bar chart — one bar per player, coloured by role. Renders an average band and line.

```tsx
import { HistogramChart } from '@ksport-packages/ksport-components';
import type { HistogramBarItem, RoleConfig } from '@ksport-packages/ksport-components';

<HistogramChart
  data={data}                  // HistogramBarItem[]
  roleConfig={roleConfig}      // RoleConfig[]
  averageValue={42.5}
  metrics={{ name: 'Distance', unit: 'm' }}
  dimensions={{ width: 800, height: 300 }}
  isPdf={false}
/>
```

### HorizontalHistogramChart

Horizontal bar chart variant of the histogram.

```tsx
import { HorizontalHistogramChart } from '@ksport-packages/ksport-components';

<HorizontalHistogramChart
  data={data}             // HistogramBarItem[]
  roleConfig={roleConfig} // RoleConfig[]
  dimensions={{ width: 800, height: 400 }}
  isPdf={false}
/>
```

### RadarChart

Spider/radar chart — one axis per metric, one polygon per player.

```tsx
import { RadarChart } from '@ksport-packages/ksport-components';
import type { RadarDataPoint } from '@ksport-packages/ksport-components';

<RadarChart
  data={data}             // RadarDataPoint[]
  roleConfig={roleConfig} // RoleConfig[]
  dimensions={{ width: 500, height: 500 }}
  isPdf={false}
/>
```

### ScatterChart

Two-axis scatter plot — one dot per player with average crosshair lines.

```tsx
import { ScatterChart } from '@ksport-packages/ksport-components';
import type { ScatterItem } from '@ksport-packages/ksport-components';

<ScatterChart
  data={data}             // ScatterItem[]
  roleConfig={roleConfig} // RoleConfig[]
  dimensions={{ width: 600, height: 400 }}
  isPdf={false}
/>
```

### HistogramTrendChart

Bar chart over time — one bar per session/date.

```tsx
import { HistogramTrendChart } from '@ksport-packages/ksport-components';
import type { TrendBarItem } from '@ksport-packages/ksport-components';

<HistogramTrendChart
  data={data}   // TrendBarItem[]
  dimensions={{ width: 800, height: 300 }}
  isPdf={false}
/>
```

---

## Utilities

### mapPlayerRoles

Maps raw API role arrays into typed `RoleConfig[]` used by all chart components.

```ts
import { mapPlayerRoles } from '@ksport-packages/ksport-components';

const roleConfig = mapPlayerRoles(
  response.aggregates.roles, // raw roles from the API response
  allRoles                   // full roles list from /roles endpoint
);
```

---

## Data fetching

### createReportFetcher

Unified fetch abstraction for client (browser) and server (Node / PDF service) contexts.

```ts
import { createReportFetcher } from '@ksport-packages/ksport-components';

// Browser — token handled automatically via cookies/headers
const fetcher = createReportFetcher('client', { baseUrl: '/api' });

// Server — token forwarded from the incoming request
const fetcher = createReportFetcher('server', { baseUrl: process.env.API_URL }, token);

const data = await fetcher.post('/report/histogram', { idDashboardTeam: 1 });
```

Server fetches automatically set `cache: 'no-store'` so PDF generation always gets fresh data.

---

## Theme

The package exports the KSport MUI theme for use in `ThemeProvider`.

```tsx
import { createDynamixTheme, rawTheme } from '@ksport-packages/ksport-components/theme';
import { ThemeProvider } from '@mui/material';

// Next.js app — composed theme with settings support
const theme = createDynamixTheme(settings);
<ThemeProvider theme={theme}>...</ThemeProvider>

// PDF service — raw theme object to force light mode
import { createTheme } from '@mui/material';
const pdfTheme = createTheme({ ...rawTheme, palette: { ...rawTheme.palette, mode: 'light' } });
```

---

## PDF layouts

PDF layouts wrap chart components with A4 page constraints. Always pass `isPdf={true}` to every chart inside a layout.

```tsx
import { A4_CONTENT_WIDTH_PORTRAIT } from '@ksport-packages/ksport-components';

// Use A4 constants for fixed dimensions — never ResizeObserver in PDF context
<HistogramChart
  data={data}
  dimensions={{ width: A4_CONTENT_WIDTH_PORTRAIT, height: 300 }}
  isPdf={true}
/>
```

---

## TypeScript types

```ts
import type {
  // Chart data shapes
  HistogramBarItem,
  RadarDataPoint,
  ScatterItem,
  TrendBarItem,
  TrendDoubleBarItem,
  TrendPlayerBarItem,
  TrendLinePoint,

  // Chart config
  RoleConfig,
  MetricInfo,
  ChartDimensions,

  // Table data shapes
  TableColumn,
  TableRow,

  // Shared props
  PdfProps,
  StaticProps,

  // Report metadata
  ReportItem,
  DateRange,
} from '@ksport-packages/ksport-components';
```

---

## Rendering contexts

This package is designed for two rendering modes:

| Context | Mode | Notes |
|---|---|---|
| `ksport-dynamix` | CSR — browser fetches after mount | Use `ResizeObserver` in the container, pass `isPdf={false}` |
| `dynamic-pdf-service` | SSR — server fetches before Puppeteer | Use A4 constants for dimensions, pass `isPdf={true}` |

See [`docs/rendering-patterns.md`](./docs/rendering-patterns.md) for full code examples of both patterns.

---

## License

Private — KSport internal use only.