@silverpoint/react 0.1.0 → 0.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.
Files changed (2) hide show
  1. package/README.md +228 -0
  2. package/package.json +3 -3
package/README.md ADDED
@@ -0,0 +1,228 @@
1
+ # @silverpoint/react
2
+
3
+ React components for **silverpoint**: charts drawn in the manner of a Renaissance silverpoint
4
+ drawing, with a fine silver line on a prepared ground, tone built from hatching, and white
5
+ heightening on the live value. The hand-drawn irregularity is only in the ornament. The data
6
+ geometry is exact, and every chart has a `precision` mode that turns the inking off.
7
+
8
+ - 33 charts, each importable on its own subpath so you only ship the charts you use.
9
+ - React 18.2+ and 19. Client components (`"use client"`) and server entry points for React
10
+ Server Components.
11
+ - Accessible: an accessible name, a hidden data table, keyboard navigation, and a
12
+ `prefers-contrast` / `forced-colors` fallback to `precision`.
13
+
14
+ ## Installation
15
+
16
+ ```sh
17
+ npm install @silverpoint/react @silverpoint/grounds @silverpoint/fonts
18
+ ```
19
+
20
+ | Package | Why |
21
+ |---|---|
22
+ | `@silverpoint/react` | The components. Brings `@silverpoint/core` with it. |
23
+ | `@silverpoint/grounds` | The stylesheet (`styles.css`) that colours the strokes. Required. |
24
+ | `@silverpoint/fonts` | Optional. Self-hosted EB Garamond, the typeface the charts are designed for. |
25
+
26
+ Peer dependencies: `react` and `react-dom` `^18.2.0 || ^19.0.0`. You need a bundler (Vite,
27
+ Next.js, or anything else that resolves `exports` and CSS imports). No `optimizeDeps` entry and
28
+ no extra configuration are needed.
29
+
30
+ Import the two stylesheets **once**, at the root of the app.
31
+
32
+ ## Quickstart (Vite)
33
+
34
+ ```sh
35
+ npm create vite@latest my-charts -- --template react-ts
36
+ cd my-charts
37
+ npm install @silverpoint/react @silverpoint/grounds @silverpoint/fonts
38
+ ```
39
+
40
+ Replace `src/App.tsx` with:
41
+
42
+ ```tsx
43
+ import '@silverpoint/fonts/fonts.css';
44
+ import '@silverpoint/grounds/styles.css';
45
+ import { LineChart } from '@silverpoint/react/line-chart';
46
+
47
+ const data = [
48
+ { hour: '00', hits: 18 },
49
+ { hour: '04', hits: 11 },
50
+ { hour: '08', hits: 42 },
51
+ { hour: '12', hits: 64 },
52
+ { hour: '16', hits: 57 },
53
+ { hour: '20', hits: 30 },
54
+ ];
55
+
56
+ export default function App() {
57
+ return (
58
+ <div style={{ width: 480 }}>
59
+ <LineChart data={data} xKey="hour" valueKey="hits" title="Hits per hour" />
60
+ </div>
61
+ );
62
+ }
63
+ ```
64
+
65
+ Then run `npm run dev`. The chart takes the width of its container. `height` is the height of
66
+ the drawing area and defaults to 160 px.
67
+
68
+ ## Examples
69
+
70
+ ### One ground for the whole app
71
+
72
+ `SilverpointProvider` sets the ground, the substrate, the mode and the locale for every chart
73
+ below it. A prop on a chart overrides the provider.
74
+
75
+ ```tsx
76
+ import '@silverpoint/fonts/fonts.css';
77
+ import '@silverpoint/grounds/styles.css';
78
+ import { SilverpointProvider } from '@silverpoint/react';
79
+ import { BarChart } from '@silverpoint/react/bar-chart';
80
+ import { DonutChart } from '@silverpoint/react/donut-chart';
81
+
82
+ const sales = [
83
+ { month: 'Jan', units: 120 },
84
+ { month: 'Feb', units: 98 },
85
+ { month: 'Mar', units: 143 },
86
+ ];
87
+
88
+ const channels = [
89
+ { channel: 'Web', share: 54 },
90
+ { channel: 'Stores', share: 31 },
91
+ { channel: 'Partners', share: 15 },
92
+ ];
93
+
94
+ export function Dashboard() {
95
+ return (
96
+ <SilverpointProvider ground="silverpoint" substrate="green" locale="en-GB">
97
+ <BarChart data={sales} xKey="month" valueKey="units" title="Units sold" unit="units" />
98
+ <DonutChart data={channels} nameKey="channel" valueKey="share" title="Sales by channel" centerLabel="%" />
99
+ </SilverpointProvider>
100
+ );
101
+ }
102
+ ```
103
+
104
+ Substrates: `cream` (the default), `green`, `blue`, `ochre`.
105
+
106
+ ### Precision mode
107
+
108
+ `mode="precision"` switches the inking off entirely and draws exact, even strokes. It suits
109
+ print, dense dashboards, and readers who prefer it. The chart switches to it by itself when the
110
+ system asks for more contrast (`prefers-contrast: more` or `forced-colors: active`). No prop can
111
+ override that.
112
+
113
+ ```tsx
114
+ <LineChart data={data} xKey="hour" valueKey="hits" title="Hits per hour" mode="precision" />
115
+ ```
116
+
117
+ ### Interaction and a custom readout
118
+
119
+ ```tsx
120
+ import { useState } from 'react';
121
+ import { LineChart } from '@silverpoint/react/line-chart';
122
+
123
+ export function Explorer({ data }: { data: { hour: string; hits: number }[] }) {
124
+ const [active, setActive] = useState<string>('—');
125
+ return (
126
+ <>
127
+ <LineChart
128
+ data={data}
129
+ xKey="hour"
130
+ valueKey="hits"
131
+ title="Hits per hour"
132
+ onActiveChange={(item) => setActive(item ? `${item.datum.hour}: ${item.value}` : '—')}
133
+ onSelect={(item) => console.log('selected', item.datum)}
134
+ tooltip={(item) => <strong>{item.value} hits</strong>}
135
+ />
136
+ <p>Under the pointer: {active}</p>
137
+ </>
138
+ );
139
+ }
140
+ ```
141
+
142
+ `onActiveChange` receives the item under the pointer or keyboard focus, and `null` when it
143
+ leaves. `onSelect` fires on click, `Enter` or `Space`.
144
+
145
+ ### Imperative handle
146
+
147
+ ```tsx
148
+ import { useRef } from 'react';
149
+ import { LineChart, type ChartHandle } from '@silverpoint/react/line-chart';
150
+
151
+ export function Exportable({ data }: { data: { hour: string; hits: number }[] }) {
152
+ const chart = useRef<ChartHandle>(null);
153
+ const download = () => {
154
+ const svg = chart.current?.toSVGString() ?? '';
155
+ const url = URL.createObjectURL(new Blob([svg], { type: 'image/svg+xml' }));
156
+ window.open(url);
157
+ };
158
+ return (
159
+ <>
160
+ <LineChart ref={chart} data={data} xKey="hour" valueKey="hits" title="Hits per hour" />
161
+ <button onClick={download}>Export SVG</button>
162
+ </>
163
+ );
164
+ }
165
+ ```
166
+
167
+ ### Next.js and React Server Components
168
+
169
+ The default subpaths are client components (`"use client"`). They work in the App Router and
170
+ hydrate without a mismatch. For pure SVG with no client JavaScript, use the server entry point.
171
+ It has no interaction, and `id`, `width` and `height` are required:
172
+
173
+ ```tsx
174
+ // app/page.tsx — a Server Component
175
+ import '@silverpoint/fonts/fonts.css';
176
+ import '@silverpoint/grounds/styles.css';
177
+ import { LineChart } from '@silverpoint/react/server/line-chart';
178
+
179
+ const data = [
180
+ { hour: '00', hits: 18 },
181
+ { hour: '12', hits: 64 },
182
+ { hour: '20', hits: 30 },
183
+ ];
184
+
185
+ export default function Page() {
186
+ return <LineChart id="hits" width={480} height={160} data={data} xKey="hour" valueKey="hits" title="Hits per hour" />;
187
+ }
188
+ ```
189
+
190
+ ## Props every chart shares
191
+
192
+ | Prop | Default | |
193
+ |---|---|---|
194
+ | `data` | demo dataset | The rows to draw. |
195
+ | `ground` / `substrate` / `mode` | `'silverpoint'` / `'cream'` / `'ink'` | Style; `mode: 'precision'` turns off inking. |
196
+ | `seed`, `id` | derived, stable | The hand drawing is deterministic: same props, same strokes. |
197
+ | `height`, `width` | `160`, container width | Size of the drawing area in px. |
198
+ | `chrome` | `'card'` | `'bare'` draws only the plot. |
199
+ | `title`, `badge`, `value`, `unit`, `footerLeft`, `footerRight` | — | The card's text. |
200
+ | `label`, `description`, `dataTable` | from `title`, —, `'hidden'` | Accessibility. |
201
+ | `locale`, `numberFormat` | environment | Number formatting. |
202
+ | `hatchFill` | `'tile'` | `'per-shape'` gives richer hatching at a much greater weight. |
203
+
204
+ ## The 33 charts
205
+
206
+ Every chart is available as `@silverpoint/react/<kebab-case-name>` (and from the barrel
207
+ `@silverpoint/react`):
208
+
209
+ `LineChart`, `StepChart`, `SparklineRows`, `KpiCard`, `BarChart`, `StackedBarChart`,
210
+ `ComposedChart`, `WaterfallChart`, `FunnelChart`, `BulletChart`, `PyramidChart`,
211
+ `CandlestickChart`, `AreaChart`, `RangeBandChart`, `StreamChart`, `DonutChart`, `RadarChart`,
212
+ `PolarBarChart`, `RadialArcGroup`, `RadialRings`, `GaugeArc`, `MeterChart`, `ScatterChart`,
213
+ `BubbleChart`, `HeatmapChart`, `TreemapChart`, `SankeyChart`, `ActivityGrid`, `CoxcombChart`,
214
+ `WindRose`, `VolvelleChart`, `ChordRing`, `OrbitChart`.
215
+
216
+ Each chart's own props (`xKey`, `valueKey`, `nameKey`…) are typed and documented in its
217
+ `*Props` type. The [repository](https://github.com/ecrespo/silverpoint) holds the API
218
+ specification and the documentation site with the gallery.
219
+
220
+ ## Related packages
221
+
222
+ [`@silverpoint/vue`](https://www.npmjs.com/package/@silverpoint/vue) ·
223
+ [`@silverpoint/angular`](https://www.npmjs.com/package/@silverpoint/angular) ·
224
+ [`@silverpoint/grounds`](https://www.npmjs.com/package/@silverpoint/grounds) ·
225
+ [`@silverpoint/fonts`](https://www.npmjs.com/package/@silverpoint/fonts) ·
226
+ [`@silverpoint/core`](https://www.npmjs.com/package/@silverpoint/core)
227
+
228
+ MIT.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@silverpoint/react",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "React adapter of silverpoint: translates core geometry into JSX, and nothing else.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -426,8 +426,8 @@
426
426
  "provenance": true
427
427
  },
428
428
  "dependencies": {
429
- "@silverpoint/core": "0.1.0",
430
- "@silverpoint/grounds": "0.1.0"
429
+ "@silverpoint/core": "0.1.1",
430
+ "@silverpoint/grounds": "0.1.1"
431
431
  },
432
432
  "peerDependencies": {
433
433
  "react": "^18.2.0 || ^19.0.0",