@blueprint-chart/lib 0.2.0 → 0.4.0
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 +19 -0
- package/dist/charts/motion.d.ts +9 -9
- package/dist/charts/plugins/plugin-host.d.ts +16 -0
- package/dist/charts/transition-cache.d.ts +11 -0
- package/dist/charts/value-label-fit.d.ts +11 -0
- package/dist/dsl/serializer.d.ts +1 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.js +4129 -3999
- package/dist/node-backend/browser.js +7 -0
- package/dist/node-backend/errors-poq5BHAK.js +8 -0
- package/dist/node-backend/fonts/DejaVuSans-Bold.ttf +0 -0
- package/dist/node-backend/fonts/DejaVuSans.ttf +0 -0
- package/dist/node-backend/index.js +5372 -0
- package/dist/render/backends/dom-backend.d.ts +2 -0
- package/dist/render/backends/jsdom-env.d.ts +13 -0
- package/dist/render/backends/node-backend.browser.d.ts +5 -0
- package/dist/render/backends/node-backend.d.ts +2 -0
- package/dist/render/backends/rasterize.d.ts +5 -0
- package/dist/render/backends/text-shim.d.ts +12 -0
- package/dist/render/backends/types.d.ts +30 -0
- package/dist/render/errors.d.ts +12 -0
- package/dist/render/index.d.ts +3 -0
- package/dist/render/public-render.d.ts +23 -0
- package/dist/transitions/frame-geometry.d.ts +53 -0
- package/dist/transitions/index.d.ts +3 -0
- package/dist/transitions/interpolate-path.d.ts +11 -0
- package/dist/transitions/types.d.ts +1 -1
- package/package.json +13 -3
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { DOMWindow } from 'jsdom';
|
|
2
|
+
export interface JsdomEnv {
|
|
3
|
+
window: DOMWindow;
|
|
4
|
+
container: HTMLElement;
|
|
5
|
+
serializeSvg: () => string;
|
|
6
|
+
serializeFrame: () => string | undefined;
|
|
7
|
+
cleanup: () => void;
|
|
8
|
+
}
|
|
9
|
+
export interface JsdomEnvOptions {
|
|
10
|
+
width: number;
|
|
11
|
+
height: number;
|
|
12
|
+
}
|
|
13
|
+
export declare function createJsdomEnv(opts: JsdomEnvOptions): JsdomEnv;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { RenderBackend } from './types';
|
|
2
|
+
/** Browser build resolves the node backend to this throwing stub — the heavy
|
|
3
|
+
* native deps must never enter a browser bundle. Reached only if a browser
|
|
4
|
+
* caller forces the Node path. */
|
|
5
|
+
export declare function createNodeBackend(): RenderBackend;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { DOMWindow } from 'jsdom';
|
|
2
|
+
/**
|
|
3
|
+
* Patch jsdom's SVG element prototypes so D3 layout primitives that rely on
|
|
4
|
+
* text measurement (axes, legends, annotations) return realistic widths.
|
|
5
|
+
*
|
|
6
|
+
* jsdom 26 does not expose `SVGTextContentElement` and does not subclass
|
|
7
|
+
* `<svg:text>` from `SVGGraphicsElement` — text elements are plain
|
|
8
|
+
* `SVGElement` instances. We therefore patch `SVGElement.prototype` so the
|
|
9
|
+
* methods exist on the actual prototype chain, while also patching the
|
|
10
|
+
* spec-correct prototypes if they happen to be available.
|
|
11
|
+
*/
|
|
12
|
+
export declare function installTextShim(window: DOMWindow): void;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ChartDefinition } from '../types';
|
|
2
|
+
export interface BackendRenderOptions {
|
|
3
|
+
sceneIndex?: number;
|
|
4
|
+
thumbnail?: boolean;
|
|
5
|
+
theme?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* A render backend abstracts the DOM environment. The DOM backend uses the
|
|
9
|
+
* ambient document; the Node backend provisions jsdom. Both render via the
|
|
10
|
+
* lib's existing renderChart/renderBpc pipeline.
|
|
11
|
+
*/
|
|
12
|
+
export interface RenderBackend {
|
|
13
|
+
readonly kind: 'dom' | 'node';
|
|
14
|
+
/** Create a render target. cleanup() detaches/closes it. */
|
|
15
|
+
createContainer(width: number, height: number): {
|
|
16
|
+
container: HTMLElement;
|
|
17
|
+
cleanup: () => void;
|
|
18
|
+
};
|
|
19
|
+
/** Render the resolved definition into the container (transition disabled). */
|
|
20
|
+
renderToContainer(container: HTMLElement, definition: ChartDefinition, opts: BackendRenderOptions): void;
|
|
21
|
+
/** Serialize the chart SVG markup from a rendered container. */
|
|
22
|
+
serializeSvg(container: HTMLElement): string;
|
|
23
|
+
/** Returns the `.bc-frame` outerHTML; falls back to the chart SVG markup when there is no frame (e.g. thumbnail mode). */
|
|
24
|
+
serializeFrame(container: HTMLElement): string;
|
|
25
|
+
/** Rasterize SVG markup to a PNG byte array. DOM backend throws PngBrowserUnsupportedError. */
|
|
26
|
+
rasterizePng(svg: string, opts: {
|
|
27
|
+
width?: number;
|
|
28
|
+
height?: number;
|
|
29
|
+
}): Promise<Uint8Array>;
|
|
30
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Thrown when a BPC source cannot be parsed/resolved before any output is produced. */
|
|
2
|
+
export declare class ChartParseError extends Error {
|
|
3
|
+
constructor(message: string, options?: ErrorOptions);
|
|
4
|
+
}
|
|
5
|
+
/** Thrown when toPng() is called in a browser environment (PNG export is Node-only in v1). */
|
|
6
|
+
export declare class PngBrowserUnsupportedError extends Error {
|
|
7
|
+
constructor(message?: string);
|
|
8
|
+
}
|
|
9
|
+
/** Thrown when the Node render backend's optional dependencies are missing or failed to install. */
|
|
10
|
+
export declare class MissingNodeRenderDepsError extends Error {
|
|
11
|
+
constructor(message: string);
|
|
12
|
+
}
|
package/dist/render/index.d.ts
CHANGED
|
@@ -3,3 +3,6 @@ export { renderChart } from './render-chart';
|
|
|
3
3
|
export { astToDefinition } from './ast-to-definition';
|
|
4
4
|
export { resolveScene } from './resolve-scene';
|
|
5
5
|
export type { ChartDefinition, RenderOptions, ResolvedChartState } from './types';
|
|
6
|
+
export { render } from './public-render';
|
|
7
|
+
export type { ChartHandle, RenderApiOptions, OutputOptions } from './public-render';
|
|
8
|
+
export { ChartParseError, PngBrowserUnsupportedError, MissingNodeRenderDepsError } from './errors';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { RenderBackend } from './backends/types';
|
|
2
|
+
export interface RenderApiOptions {
|
|
3
|
+
theme?: string;
|
|
4
|
+
scene?: number;
|
|
5
|
+
width?: number;
|
|
6
|
+
height?: number;
|
|
7
|
+
frame?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface OutputOptions {
|
|
10
|
+
width?: number;
|
|
11
|
+
height?: number;
|
|
12
|
+
}
|
|
13
|
+
export interface ChartHandle {
|
|
14
|
+
toSvg: (opts?: OutputOptions) => Promise<string>;
|
|
15
|
+
toHtml: (opts?: OutputOptions) => Promise<string>;
|
|
16
|
+
toPng: (opts?: OutputOptions) => Promise<Uint8Array>;
|
|
17
|
+
mount: (target: HTMLElement | string) => ChartHandle;
|
|
18
|
+
scene: (index: number) => ChartHandle;
|
|
19
|
+
}
|
|
20
|
+
/** Internal; exported for tests. Picks the DOM backend in a browser-like env,
|
|
21
|
+
* else dynamically loads the Node backend via the conditional subpath export. */
|
|
22
|
+
export declare function selectBackend(): Promise<RenderBackend>;
|
|
23
|
+
export declare function render(source: string, options?: RenderApiOptions): Promise<ChartHandle>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { SceneTransition } from './scene-transition';
|
|
2
|
+
/** Plot rectangle in chart-area coordinates: origin + inner size. */
|
|
3
|
+
export interface PlotRect {
|
|
4
|
+
left: number;
|
|
5
|
+
top: number;
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
}
|
|
9
|
+
export interface FrameGeometryOptions {
|
|
10
|
+
/** The chart-area `<g>` whose `transform` carries the plot origin. */
|
|
11
|
+
group: SVGGElement;
|
|
12
|
+
/** The plot clip rect, if any (width/height interpolate with the plot size). */
|
|
13
|
+
clipRect: SVGRectElement | null;
|
|
14
|
+
from: PlotRect;
|
|
15
|
+
to: PlotRect;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Ease the plot frame geometry (chart-area group origin + clip size) from the
|
|
19
|
+
* prior scene's rect to the new one on the orchestrator's `bc-scene` clock.
|
|
20
|
+
*
|
|
21
|
+
* The new render has already placed the group/clip at the NEW geometry, so the
|
|
22
|
+
* tween first resets them to `from` and eases to `to`. The group `transform`
|
|
23
|
+
* uses the point-wise interpolator (d3's default string interp mangles it);
|
|
24
|
+
* clip width/height are numeric and use d3's default attr tween.
|
|
25
|
+
*
|
|
26
|
+
* Registers a buffered flush, so call it during `committing` (e.g. inside
|
|
27
|
+
* `SceneTransition.run`). On the snap path (duration 0 / reduced motion) the
|
|
28
|
+
* geometry is set directly to `to`.
|
|
29
|
+
*/
|
|
30
|
+
export interface PlotFrameOptions {
|
|
31
|
+
/** The chart's `<svg>` (used to find the clip rect by id). */
|
|
32
|
+
svg: SVGSVGElement;
|
|
33
|
+
/** The plot clip-path id (its `rect` size interpolates with the plot). */
|
|
34
|
+
clipId: string;
|
|
35
|
+
/** The chart-area `<g>` whose `transform` carries the plot origin. */
|
|
36
|
+
group: SVGGElement;
|
|
37
|
+
/** The prior scene's plot rect (from the transition cache), if any. */
|
|
38
|
+
from: PlotRect | undefined;
|
|
39
|
+
/** This render's plot rect. */
|
|
40
|
+
to: PlotRect;
|
|
41
|
+
/** Only ease when true (same-type transition with prior marks to tween from). */
|
|
42
|
+
active: boolean;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Renderer-facing wrapper over {@link tweenFrameGeometry}: resolves the clip
|
|
46
|
+
* rect from `svg`/`clipId` and eases from the cached prior plot rect to this
|
|
47
|
+
* render's rect. No-ops unless `active` and a prior rect exist. Using the cached
|
|
48
|
+
* prior rect (rather than reconstructing it from margins) keeps the `from`
|
|
49
|
+
* geometry exact even when a chart's plot height differs from its inner height
|
|
50
|
+
* (e.g. a category-label band) or carries clip inflation.
|
|
51
|
+
*/
|
|
52
|
+
export declare function tweenPlotFrame(orch: SceneTransition, opts: PlotFrameOptions): void;
|
|
53
|
+
export declare function tweenFrameGeometry(orch: SceneTransition, opts: FrameGeometryOptions): void;
|
|
@@ -2,6 +2,9 @@ export { SceneTransition, getSceneTransition } from './scene-transition';
|
|
|
2
2
|
export { BC_TRANSITION_NAME } from './types';
|
|
3
3
|
export type { CommitOptions } from './scene-transition';
|
|
4
4
|
export { featureJoin } from './feature-join';
|
|
5
|
+
export { interpolatePath } from './interpolate-path';
|
|
6
|
+
export { tweenFrameGeometry, tweenPlotFrame } from './frame-geometry';
|
|
7
|
+
export type { PlotRect, FrameGeometryOptions, PlotFrameOptions } from './frame-geometry';
|
|
5
8
|
export { roleScan, tagsCompatible, shouldEscalateToFade, ROLE_MATCH_THRESHOLD } from './role-matcher';
|
|
6
9
|
export { snapshotLiveAttrs } from './snapshot';
|
|
7
10
|
export type { TransitionMode, SceneTransitionState, FeatureRole, FeatureJoinConfig, AttrMap, AttrValue, } from './types';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interpolate two SVG path `d` strings point-wise.
|
|
3
|
+
*
|
|
4
|
+
* d3's default `interpolateString` pairs numbers by document order and
|
|
5
|
+
* fuses/garbles them when the two paths have different counts — observed
|
|
6
|
+
* producing ~1e11 coordinates during area resizes. This splits each path
|
|
7
|
+
* into a command skeleton + number list; when the skeletons match it
|
|
8
|
+
* interpolates the numbers pairwise, otherwise it hard-switches at the
|
|
9
|
+
* midpoint so a malformed blend is never emitted.
|
|
10
|
+
*/
|
|
11
|
+
export declare function interpolatePath(a: string, b: string): (t: number) => string;
|
|
@@ -17,7 +17,7 @@ export type SceneTransitionState = 'idle' | 'committing' | 'animating';
|
|
|
17
17
|
* `'axis-tick.value'`. The role-matcher (future plan) acts on this tag;
|
|
18
18
|
* v1 stores it without acting on it for cross-type.
|
|
19
19
|
*/
|
|
20
|
-
export type FeatureRole = 'mark-per-category' | 'mark-per-cell' | 'series-path' | 'axis-tick.value' | 'axis-tick.category' | 'value-label' | 'annotation.point' | 'annotation.range' | 'annotation.free';
|
|
20
|
+
export type FeatureRole = 'mark-per-category' | 'mark-per-cell' | 'series-path' | 'series-area' | 'series-line' | 'axis-tick.value' | 'axis-tick.category' | 'value-label' | 'annotation.point' | 'annotation.range' | 'annotation.free';
|
|
21
21
|
/** Subset of SVG / HTML attribute values we tween. */
|
|
22
22
|
export type AttrValue = string | number;
|
|
23
23
|
/** Map of attribute name → value. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blueprint-chart/lib",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "DSL-driven charting library built on D3. Define charts as text, render them anywhere.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"chart",
|
|
@@ -32,6 +32,11 @@
|
|
|
32
32
|
"import": "./dist/index.js",
|
|
33
33
|
"default": "./dist/index.js"
|
|
34
34
|
},
|
|
35
|
+
"./internal/node-backend": {
|
|
36
|
+
"node": "./dist/node-backend/index.js",
|
|
37
|
+
"browser": "./dist/node-backend/browser.js",
|
|
38
|
+
"default": "./dist/node-backend/browser.js"
|
|
39
|
+
},
|
|
35
40
|
"./charts.scss": "./src/charts/chart.scss",
|
|
36
41
|
"./src/charts/chart.scss": "./src/charts/chart.scss"
|
|
37
42
|
},
|
|
@@ -56,18 +61,23 @@
|
|
|
56
61
|
"devDependencies": {
|
|
57
62
|
"@types/chroma-js": "^3.1.2",
|
|
58
63
|
"@types/d3": "^7",
|
|
59
|
-
"jsdom": "^
|
|
64
|
+
"@types/jsdom": "^21.1.7",
|
|
60
65
|
"peggy": "^4",
|
|
61
66
|
"typescript": "^5.7",
|
|
62
67
|
"vite": "^6",
|
|
63
68
|
"vite-plugin-dts": "^5.0.0",
|
|
64
69
|
"vitest": "^3"
|
|
65
70
|
},
|
|
71
|
+
"optionalDependencies": {
|
|
72
|
+
"@napi-rs/canvas": "^0.1.100",
|
|
73
|
+
"@resvg/resvg-js": "^2.6.2",
|
|
74
|
+
"jsdom": "^26.1.0"
|
|
75
|
+
},
|
|
66
76
|
"scripts": {
|
|
67
77
|
"generate:parser": "peggy --format es -o src/dsl/grammar.js src/dsl/grammar.peggy",
|
|
68
78
|
"prebuild": "pnpm run generate:parser",
|
|
69
79
|
"pretest": "pnpm run generate:parser",
|
|
70
|
-
"build": "vite build && vite build -c vite.lib.config.ts",
|
|
80
|
+
"build": "vite build && vite build -c vite.lib.config.ts && vite build -c vite.node-backend.config.ts",
|
|
71
81
|
"test": "vitest run"
|
|
72
82
|
}
|
|
73
83
|
}
|