@weasyprint-tsx/ui 0.1.6 → 0.1.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/README.md CHANGED
@@ -276,3 +276,77 @@ LaTeX equation rendering via KaTeX.
276
276
  | `displayMode` | `boolean` | `false` | Render as block-level equation |
277
277
  | `aligned` | `boolean` | `false` | Wrap in `\begin{aligned}…\end{aligned}` |
278
278
  | `chemical` | `boolean` | `false` | Wrap in `\ce{…}` for chemical notation |
279
+
280
+ ---
281
+
282
+ ## Chart
283
+
284
+ Renders a [chart.js](https://www.chartjs.org/) chart server-side as a base64-encoded PNG `<img>`.
285
+
286
+ ### `Chart`
287
+
288
+ ```tsx
289
+ import type { ChartConfiguration } from "chart.js";
290
+ import { Chart } from "@weasyprint-tsx/ui";
291
+
292
+ const config: ChartConfiguration = {
293
+ type: "bar",
294
+ data: {
295
+ labels: ["Jan", "Feb", "Mar"],
296
+ datasets: [{ label: "Sales", data: [12, 8, 21] }],
297
+ },
298
+ };
299
+
300
+ <Chart config={config} width={600} height={300} />
301
+ ```
302
+
303
+ | Prop | Type | Default | Description |
304
+ |------|------|---------|-------------|
305
+ | `config` | `ChartConfiguration` | — | chart.js configuration object |
306
+ | `width` | `number` | `800` | Canvas width in pixels |
307
+ | `height` | `number` | `500` | Canvas height in pixels |
308
+ | `...rest` | `Omit<ComponentProps<"img">, "src">` | — | All standard `<img>` attributes except `src` |
309
+
310
+ ---
311
+
312
+ ### `chartFunction`
313
+
314
+ Samples a numeric function into a data array for chart datasets. Produces `sample + 1` values evaluated at `n * step` for `n` in `0..sample`.
315
+
316
+ ```ts
317
+ chartFunction(func, options?)
318
+ ```
319
+
320
+ | Param | Type | Default | Description |
321
+ |-------|------|---------|-------------|
322
+ | `func` | `(n: number) => number` | — | Function to sample |
323
+ | `options.step` | `number` | `1` | Multiplier applied to the index before calling `func` |
324
+ | `options.sample` | `number` | `100` | Number of intervals (yields `sample + 1` points) |
325
+
326
+ ```tsx
327
+ import { Chart, chartFunction } from "@weasyprint-tsx/ui";
328
+
329
+ <Chart config={{
330
+ type: "line",
331
+ data: {
332
+ labels: chartFunction(n => n, { step: 0.1 }),
333
+ datasets: [{ label: "sin(x)", data: chartFunction(Math.sin, { step: 0.1 }) }],
334
+ },
335
+ }} />
336
+ ```
337
+
338
+ ---
339
+
340
+ ### `labelFunction`
341
+
342
+ Same as `chartFunction` but the sampling function may return a `number` or `string`. Use to generate axis labels.
343
+
344
+ ```ts
345
+ labelFunction(func, options?)
346
+ ```
347
+
348
+ | Param | Type | Default | Description |
349
+ |-------|------|---------|-------------|
350
+ | `func` | `(n: number) => number \| string` | — | Function to sample |
351
+ | `options.step` | `number` | `1` | Multiplier applied to the index |
352
+ | `options.sample` | `number` | `100` | Number of intervals (yields `sample + 1` values) |
package/package.json CHANGED
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "name": "@weasyprint-tsx/ui",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "exports": {
5
5
  ".": "./src/index.ts"
6
6
  },
7
7
  "types": "./src/index.ts",
8
8
  "dependencies": {
9
+ "@napi-rs/canvas": "^1.0.0",
10
+ "chart.js": "^4.5.1",
9
11
  "highlight.js": "11.11.1",
10
12
  "katex": "^0.16.47"
11
13
  }
package/src/Chart.tsx ADDED
@@ -0,0 +1,54 @@
1
+ import { createCanvas } from "@napi-rs/canvas";
2
+ import type { ChartConfiguration } from "chart.js";
3
+ import { Chart as ChartJS } from "chart.js/auto";
4
+ import { ComponentProps } from "preact";
5
+
6
+ export interface ChartProps extends Omit<ComponentProps<"img">, "src"> {
7
+ config: ChartConfiguration;
8
+ width?: number;
9
+ height?: number;
10
+ }
11
+
12
+ export function Chart({
13
+ config,
14
+ width = 800,
15
+ height = 500,
16
+ ...props
17
+ }: ChartProps) {
18
+ const canvas = createCanvas(width, height);
19
+
20
+ const chart = new ChartJS(canvas as unknown as HTMLCanvasElement, {
21
+ ...config,
22
+ options: {
23
+ ...config.options,
24
+ animation: false,
25
+ responsive: false,
26
+ },
27
+ });
28
+
29
+ const dataUrl = `data:image/png;base64,${canvas.toBuffer("image/png").toString("base64")}`;
30
+ chart.destroy();
31
+
32
+ return <img src={dataUrl} width={width} height={height} {...props} />;
33
+ }
34
+
35
+ type FunctionOptions = {
36
+ step?: number;
37
+ sample?: number;
38
+ };
39
+
40
+ export function chartFunction(
41
+ func: (n: number) => number,
42
+ options?: FunctionOptions,
43
+ ) {
44
+ const { sample = 100, step = 1 } = options ?? {};
45
+ return Array.from({ length: sample + 1 }, (_, n) => func(n * step));
46
+ }
47
+
48
+ export function labelFunction(
49
+ func: (n: number) => number | string,
50
+ options?: FunctionOptions
51
+ ) {
52
+ const { sample = 100, step = 1 } = options ?? {};
53
+ return Array.from({ length: sample + 1 }, (_, n) => func(n * step));
54
+ }
@@ -1,5 +1,5 @@
1
1
  .ol {
2
- & > .li {
2
+ .li {
3
3
  counter-increment: list-items;
4
4
  &::before {
5
5
  content: var(--ol-marker-pre, "") counter(list-items, decimal)
package/src/index.ts CHANGED
@@ -1,3 +1,5 @@
1
+ export { Chart, chartFunction, labelFunction } from "./Chart";
2
+ export type { ChartProps } from "./Chart";
1
3
  export { Block, BlockBox } from "./BlockBox";
2
4
  export type { BlockBoxProps, BlockProps } from "./BlockBox";
3
5
  export { CodeBlock } from "./CodeBlock";