@delacour/react-native-charts 0.1.0-alpha.20260925053522
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 +98 -0
- package/package.json +61 -0
- package/src/animation/AGENTS.md +40 -0
- package/src/animation/animation.types.ts +16 -0
- package/src/animation/index.ts +2 -0
- package/src/animation/use-animated-path.ts +74 -0
- package/src/cartesian/AGENTS.md +110 -0
- package/src/cartesian/axes/chart-x-axis.tsx +52 -0
- package/src/cartesian/axes/chart-y-axis.tsx +56 -0
- package/src/cartesian/cartesian-chart.context.tsx +43 -0
- package/src/cartesian/cartesian-chart.tsx +132 -0
- package/src/cartesian/cartesian-chart.types.ts +181 -0
- package/src/cartesian/hooks/use-canvas-size.ts +37 -0
- package/src/cartesian/hooks/use-chart-model.ts +278 -0
- package/src/cartesian/index.ts +41 -0
- package/src/cartesian/marks/chart-area.tsx +83 -0
- package/src/cartesian/marks/chart-bar-group.tsx +132 -0
- package/src/cartesian/marks/chart-bar-stack.tsx +209 -0
- package/src/cartesian/marks/chart-bar.tsx +195 -0
- package/src/cartesian/marks/chart-candlestick.tsx +148 -0
- package/src/cartesian/marks/chart-cursor.tsx +168 -0
- package/src/cartesian/marks/chart-grid.tsx +46 -0
- package/src/cartesian/marks/chart-line.tsx +73 -0
- package/src/cartesian/marks/chart-scatter.tsx +71 -0
- package/src/core/AGENTS.md +77 -0
- package/src/core/animation/morph-strategy.test.ts +38 -0
- package/src/core/animation/morph-strategy.ts +53 -0
- package/src/core/animation/resample-points.test.ts +68 -0
- package/src/core/animation/resample-points.ts +64 -0
- package/src/core/chart.types.ts +62 -0
- package/src/core/curve/build-area.test.ts +48 -0
- package/src/core/curve/build-area.ts +58 -0
- package/src/core/curve/build-line.test.ts +64 -0
- package/src/core/curve/build-line.ts +53 -0
- package/src/core/curve/curves.test.ts +20 -0
- package/src/core/curve/curves.ts +48 -0
- package/src/core/geometry/band.test.ts +79 -0
- package/src/core/geometry/band.ts +111 -0
- package/src/core/geometry/category-domain.test.ts +33 -0
- package/src/core/geometry/category-domain.ts +18 -0
- package/src/core/geometry/chart-bounds.test.ts +36 -0
- package/src/core/geometry/chart-bounds.ts +47 -0
- package/src/core/geometry/chart-layout.test.ts +230 -0
- package/src/core/geometry/chart-layout.ts +162 -0
- package/src/core/geometry/domain.test.ts +87 -0
- package/src/core/geometry/domain.ts +94 -0
- package/src/core/geometry/grid-lines.test.ts +48 -0
- package/src/core/geometry/grid-lines.ts +43 -0
- package/src/core/geometry/stack.test.ts +151 -0
- package/src/core/geometry/stack.ts +109 -0
- package/src/core/geometry/step.test.ts +34 -0
- package/src/core/geometry/step.ts +21 -0
- package/src/core/geometry/transform-input-data.test.ts +105 -0
- package/src/core/geometry/transform-input-data.ts +88 -0
- package/src/core/geometry/x-values.test.ts +37 -0
- package/src/core/geometry/x-values.ts +36 -0
- package/src/core/index.ts +109 -0
- package/src/core/interaction/closest-index.test.ts +36 -0
- package/src/core/interaction/closest-index.ts +27 -0
- package/src/core/interaction/path-segments.test.ts +60 -0
- package/src/core/interaction/path-segments.ts +155 -0
- package/src/core/interaction/y-for-x.test.ts +135 -0
- package/src/core/interaction/y-for-x.ts +106 -0
- package/src/core/polar/build-slice-path.test.ts +173 -0
- package/src/core/polar/build-slice-path.ts +98 -0
- package/src/core/polar/label-position.test.ts +41 -0
- package/src/core/polar/label-position.ts +18 -0
- package/src/core/polar/pie-input.test.ts +36 -0
- package/src/core/polar/pie-input.ts +32 -0
- package/src/core/polar/polar-point.test.ts +55 -0
- package/src/core/polar/polar-point.ts +29 -0
- package/src/core/polar/polar.types.ts +47 -0
- package/src/core/polar/resolve-layout.test.ts +63 -0
- package/src/core/polar/resolve-layout.ts +55 -0
- package/src/core/polar/resolve-slices.test.ts +89 -0
- package/src/core/polar/resolve-slices.ts +58 -0
- package/src/core/polar/slice-index-at.test.ts +52 -0
- package/src/core/polar/slice-index-at.ts +42 -0
- package/src/core/polar/slice-opacity.test.ts +29 -0
- package/src/core/polar/slice-opacity.ts +12 -0
- package/src/core/scale/make-scale.test.ts +55 -0
- package/src/core/scale/make-scale.ts +78 -0
- package/src/core/scale/scale.test.ts +76 -0
- package/src/core/scale/scale.ts +65 -0
- package/src/core/scale/scale.types.ts +30 -0
- package/src/core/shape/build-bars.test.ts +203 -0
- package/src/core/shape/build-bars.ts +167 -0
- package/src/core/shape/build-candles.test.ts +156 -0
- package/src/core/shape/build-candles.ts +153 -0
- package/src/core/shape/build-scatter.test.ts +103 -0
- package/src/core/shape/build-scatter.ts +81 -0
- package/src/core/shape/rect-path.test.ts +61 -0
- package/src/core/shape/rect-path.ts +69 -0
- package/src/core/text/axis-gutters.test.ts +70 -0
- package/src/core/text/axis-gutters.ts +70 -0
- package/src/core/text/bar-label.test.ts +92 -0
- package/src/core/text/bar-label.ts +61 -0
- package/src/core/text/format-tick.test.ts +87 -0
- package/src/core/text/format-tick.ts +76 -0
- package/src/core/text/label-anchor.test.ts +59 -0
- package/src/core/text/label-anchor.ts +62 -0
- package/src/core/ticks/build-ticks.test.ts +38 -0
- package/src/core/ticks/build-ticks.ts +36 -0
- package/src/core/ticks/linear-ticks.test.ts +56 -0
- package/src/core/ticks/linear-ticks.ts +67 -0
- package/src/core/ticks/tick-count.test.ts +46 -0
- package/src/core/ticks/tick-count.ts +35 -0
- package/src/core/ticks/tick.types.ts +7 -0
- package/src/core/ticks/time-ticks.test.ts +61 -0
- package/src/core/ticks/time-ticks.ts +22 -0
- package/src/core/util/as-number.test.ts +45 -0
- package/src/core/util/as-number.ts +22 -0
- package/src/core/util/clamp.test.ts +21 -0
- package/src/core/util/clamp.ts +16 -0
- package/src/core/util/extent.test.ts +33 -0
- package/src/core/util/extent.ts +37 -0
- package/src/core/util/read-at.test.ts +14 -0
- package/src/core/util/read-at.ts +14 -0
- package/src/core/util/sided-number.test.ts +28 -0
- package/src/core/util/sided-number.ts +34 -0
- package/src/docs.test.ts +45 -0
- package/src/flat-worklet.test.ts +130 -0
- package/src/gesture/AGENTS.md +84 -0
- package/src/gesture/gesture-overlay.tsx +21 -0
- package/src/gesture/gesture.types.ts +143 -0
- package/src/gesture/index.ts +12 -0
- package/src/gesture/use-chart-scrub.ts +44 -0
- package/src/gesture/use-scrub-gesture.ts +162 -0
- package/src/index.ts +6 -0
- package/src/no-classname.test.ts +27 -0
- package/src/polar/AGENTS.md +55 -0
- package/src/polar/hooks/use-polar-model.ts +88 -0
- package/src/polar/index.ts +14 -0
- package/src/polar/marks/pie-inset.tsx +70 -0
- package/src/polar/marks/pie-label.tsx +71 -0
- package/src/polar/marks/pie-slice.tsx +82 -0
- package/src/polar/marks/pie-slices.tsx +60 -0
- package/src/polar/polar-chart.context.tsx +37 -0
- package/src/polar/polar-chart.tsx +91 -0
- package/src/polar/polar-chart.types.ts +82 -0
- package/src/purity.test.ts +75 -0
- package/src/skia/AGENTS.md +39 -0
- package/src/skia/build-path.ts +22 -0
- package/src/skia/font.ts +78 -0
- package/src/skia/index.ts +9 -0
- package/src/source-tree.test.ts +33 -0
package/src/skia/font.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { matchFont, type SkFont } from "@shopify/react-native-skia";
|
|
2
|
+
import { useMemo } from "react";
|
|
3
|
+
import type { LabelMetrics } from "../core/text/label-anchor";
|
|
4
|
+
|
|
5
|
+
/** Re-exported so a consumer can hold a font without importing Skia itself. */
|
|
6
|
+
export type ChartFont = SkFont;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A font from a family the operating system already has.
|
|
10
|
+
*
|
|
11
|
+
* No asset ships with this package, and none needs to: `matchFont` resolves
|
|
12
|
+
* against the system font manager, so a chart is legible with no `expo-font`,
|
|
13
|
+
* no config plugin and no Metro asset resolver in the consuming app.
|
|
14
|
+
*
|
|
15
|
+
* The trade is that iOS's system font is not Android's, so the same labels
|
|
16
|
+
* measure differently and the plot rect differs by a few points across
|
|
17
|
+
* platforms. That is correct behaviour rather than a bug — but it does mean a
|
|
18
|
+
* screenshot baseline has to be per-platform, and an app that needs identical
|
|
19
|
+
* layout on both must load and pass its own font.
|
|
20
|
+
*
|
|
21
|
+
* An `undefined` family means the platform default. `matchFont` spreads the
|
|
22
|
+
* style it is given over its own defaults, so a `fontFamily: undefined` key
|
|
23
|
+
* would erase the default rather than fall through to it and throw "Value is
|
|
24
|
+
* undefined, expected a String" from inside Skia — which is why the key is
|
|
25
|
+
* omitted rather than passed.
|
|
26
|
+
*/
|
|
27
|
+
export function useSystemFont(family: string | undefined, size: number): SkFont {
|
|
28
|
+
return useMemo(
|
|
29
|
+
() => matchFont(family === undefined ? { fontSize: size } : { fontFamily: family, fontSize: size }),
|
|
30
|
+
[family, size]
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The advance width of `text`, in points.
|
|
36
|
+
*
|
|
37
|
+
* Glyph advances summed, rather than `measureText`. `measureText` returns the
|
|
38
|
+
* *drawn* bounds, which exclude side bearings — a tick reading "10" measures
|
|
39
|
+
* narrower than the space it actually occupies, and the axis gutter comes out
|
|
40
|
+
* a point or two too tight on every label. `getTextWidth` gives the advance
|
|
41
|
+
* directly but is deprecated in Skia 2.x.
|
|
42
|
+
*/
|
|
43
|
+
export function measureLabelWidth(font: SkFont | null, text: string): number {
|
|
44
|
+
if (font === null || text === "") return 0;
|
|
45
|
+
let total = 0;
|
|
46
|
+
for (const advance of font.getGlyphWidths(font.getGlyphIDs(text))) total += advance;
|
|
47
|
+
return total;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Advance widths for a whole axis' worth of labels. */
|
|
51
|
+
export function measureLabelWidths(font: SkFont | null, labels: readonly string[]): number[] {
|
|
52
|
+
return labels.map((label) => measureLabelWidth(font, label));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Line height, from the font's own metrics.
|
|
57
|
+
*
|
|
58
|
+
* `ascent` is negative and `descent` positive, so the span between them is the
|
|
59
|
+
* full glyph box — which is what an axis gutter has to reserve, not the
|
|
60
|
+
* nominal point size.
|
|
61
|
+
*/
|
|
62
|
+
export function fontLineHeight(font: SkFont | null): number {
|
|
63
|
+
const { ascent, descent } = fontMetrics(font);
|
|
64
|
+
return ascent + descent;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* A font's ascent and descent, both as positive distances from the baseline.
|
|
69
|
+
*
|
|
70
|
+
* Skia reports `ascent` negative (it is a y offset in a downward-positive
|
|
71
|
+
* space) and `descent` positive. Normalising both to magnitudes here is what
|
|
72
|
+
* lets `anchorY` read as geometry rather than as sign juggling.
|
|
73
|
+
*/
|
|
74
|
+
export function fontMetrics(font: SkFont | null): LabelMetrics {
|
|
75
|
+
if (font === null) return { ascent: 0, descent: 0 };
|
|
76
|
+
const metrics = font.getMetrics();
|
|
77
|
+
return { ascent: Math.abs(metrics.ascent), descent: Math.abs(metrics.descent) };
|
|
78
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { readdirSync, readFileSync, statSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
/** Every `.ts`/`.tsx` under `dir`, tests included unless `skipTests`. */
|
|
5
|
+
export function sourceFiles(dir: string, options: { skipTests?: boolean } = {}): string[] {
|
|
6
|
+
const found: string[] = [];
|
|
7
|
+
const walk = (current: string): void => {
|
|
8
|
+
for (const entry of readdirSync(current)) {
|
|
9
|
+
const path = join(current, entry);
|
|
10
|
+
if (statSync(path).isDirectory()) {
|
|
11
|
+
walk(path);
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
if (!/\.tsx?$/.test(entry)) continue;
|
|
15
|
+
if (options.skipTests && /\.test\.tsx?$/.test(entry)) continue;
|
|
16
|
+
found.push(path);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
walk(dir);
|
|
20
|
+
return found;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const SRC = import.meta.dir;
|
|
24
|
+
export const PACKAGE_ROOT = join(SRC, "..");
|
|
25
|
+
|
|
26
|
+
export function read(path: string): string {
|
|
27
|
+
return readFileSync(path, "utf8");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** `path` relative to the package, for a failure message that can be acted on. */
|
|
31
|
+
export function relative(path: string): string {
|
|
32
|
+
return path.slice(PACKAGE_ROOT.length + 1);
|
|
33
|
+
}
|