@invinite-org/chartlang-adapter-kit 1.4.0 → 1.6.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/CHANGELOG.md +158 -0
- package/dist/base/bufferingAdapter.d.ts +1 -0
- package/dist/base/bufferingAdapter.d.ts.map +1 -1
- package/dist/base/bufferingAdapter.js +1 -0
- package/dist/base/bufferingAdapter.js.map +1 -1
- package/dist/base/passThroughAdapter.d.ts +1 -0
- package/dist/base/passThroughAdapter.d.ts.map +1 -1
- package/dist/base/passThroughAdapter.js +1 -0
- package/dist/base/passThroughAdapter.js.map +1 -1
- package/dist/canvas/glyphs.d.ts +209 -0
- package/dist/canvas/glyphs.d.ts.map +1 -0
- package/dist/canvas/glyphs.js +219 -0
- package/dist/canvas/glyphs.js.map +1 -0
- package/dist/canvas/index.d.ts +2 -0
- package/dist/canvas/index.d.ts.map +1 -1
- package/dist/canvas/index.js +1 -0
- package/dist/canvas/index.js.map +1 -1
- package/dist/canvas/mockContext.d.ts +42 -0
- package/dist/canvas/mockContext.d.ts.map +1 -1
- package/dist/canvas/mockContext.js +50 -0
- package/dist/canvas/mockContext.js.map +1 -1
- package/dist/canvas/renderCtx.d.ts +6 -0
- package/dist/canvas/renderCtx.d.ts.map +1 -1
- package/dist/canvas/renderCtx.js.map +1 -1
- package/dist/capabilities/capabilities.d.ts +16 -0
- package/dist/capabilities/capabilities.d.ts.map +1 -1
- package/dist/capabilities/capabilities.js +16 -0
- package/dist/capabilities/capabilities.js.map +1 -1
- package/dist/defineAdapter.d.ts +2 -0
- package/dist/defineAdapter.d.ts.map +1 -1
- package/dist/defineAdapter.js +1 -0
- package/dist/defineAdapter.js.map +1 -1
- package/dist/geometry/index.d.ts +3 -0
- package/dist/geometry/index.d.ts.map +1 -1
- package/dist/geometry/index.js +2 -0
- package/dist/geometry/index.js.map +1 -1
- package/dist/geometry/renderOrder.d.ts +52 -0
- package/dist/geometry/renderOrder.d.ts.map +1 -0
- package/dist/geometry/renderOrder.js +35 -0
- package/dist/geometry/renderOrder.js.map +1 -0
- package/dist/geometry/shift.d.ts +117 -0
- package/dist/geometry/shift.d.ts.map +1 -0
- package/dist/geometry/shift.js +141 -0
- package/dist/geometry/shift.js.map +1 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/interaction/domWiring.d.ts +90 -0
- package/dist/interaction/domWiring.d.ts.map +1 -0
- package/dist/interaction/domWiring.js +113 -0
- package/dist/interaction/domWiring.js.map +1 -0
- package/dist/interaction/index.d.ts +5 -0
- package/dist/interaction/index.d.ts.map +1 -0
- package/dist/interaction/index.js +5 -0
- package/dist/interaction/index.js.map +1 -0
- package/dist/interaction/viewController.d.ts +132 -0
- package/dist/interaction/viewController.d.ts.map +1 -0
- package/dist/interaction/viewController.js +133 -0
- package/dist/interaction/viewController.js.map +1 -0
- package/dist/mocks/mockCandleSource.d.ts +12 -0
- package/dist/mocks/mockCandleSource.d.ts.map +1 -1
- package/dist/mocks/mockCandleSource.js +13 -4
- package/dist/mocks/mockCandleSource.js.map +1 -1
- package/dist/types.d.ts +91 -8
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/validation/validateEmission.d.ts.map +1 -1
- package/dist/validation/validateEmission.js +10 -0
- package/dist/validation/validateEmission.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
// Copyright (c) 2026 Invinite. Licensed under the MIT License.
|
|
2
|
+
// See the LICENSE file in the repo root for full license text.
|
|
3
|
+
// Shared, model-free glyph geometry for the canvas-family adapters (uplot
|
|
4
|
+
// draw-hook, lightweight-charts overlay). Promoted out of the canvas2d
|
|
5
|
+
// reference adapter's `render/{shape,character,arrow,marker,label}.ts` so the
|
|
6
|
+
// `shape` / `character` / `arrow` / `marker` / `label` geometry is written ONCE
|
|
7
|
+
// instead of hand-ported per consumer (the bug class the `shift.ts` /
|
|
8
|
+
// `renderOrder.ts` promotions exist to kill). Each helper draws onto a
|
|
9
|
+
// `RenderCtx` and takes a plain `fallbackColor: string` (the null-color
|
|
10
|
+
// default), so it carries no palette / library / model types — the move is a
|
|
11
|
+
// pure RenderCtx-based promotion. canvas2d keeps its own `Palette`-taking
|
|
12
|
+
// local renderers (re-consume deferred).
|
|
13
|
+
const OFFSET_RATIO = 1.25;
|
|
14
|
+
const TWO_PI = Math.PI * 2;
|
|
15
|
+
const DEFAULT_LABEL_FONT = "10px sans-serif";
|
|
16
|
+
function anchoredShapeY(args) {
|
|
17
|
+
switch (args.location ?? "absolute") {
|
|
18
|
+
case "above":
|
|
19
|
+
return args.y - args.size * OFFSET_RATIO;
|
|
20
|
+
case "below":
|
|
21
|
+
return args.y + args.size * OFFSET_RATIO;
|
|
22
|
+
case "absolute":
|
|
23
|
+
return args.y;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Render a `shape` glyph at a plot anchor. The five filled-marker shapes
|
|
28
|
+
* (`circle` / `triangle-up` / `triangle-down` / `square` / `diamond`)
|
|
29
|
+
* delegate to {@link drawMarker}; `cross` / `xcross` / `flag` stroke their
|
|
30
|
+
* geometry directly. A null `color` falls back to `fallbackColor`.
|
|
31
|
+
*
|
|
32
|
+
* @since 1.7
|
|
33
|
+
* @stable
|
|
34
|
+
* @example
|
|
35
|
+
* declare const ctx: RenderCtx;
|
|
36
|
+
* drawShape(ctx, { x: 10, y: 20, shape: "cross", size: 8, color: null }, "#90caf9");
|
|
37
|
+
*/
|
|
38
|
+
export function drawShape(ctx, args, fallbackColor) {
|
|
39
|
+
const y = anchoredShapeY(args);
|
|
40
|
+
if (args.shape === "circle" ||
|
|
41
|
+
args.shape === "triangle-up" ||
|
|
42
|
+
args.shape === "triangle-down" ||
|
|
43
|
+
args.shape === "square" ||
|
|
44
|
+
args.shape === "diamond") {
|
|
45
|
+
drawMarker(ctx, { ...args, y, shape: args.shape }, fallbackColor);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
ctx.strokeStyle = args.color ?? fallbackColor;
|
|
49
|
+
ctx.lineWidth = 1;
|
|
50
|
+
const half = args.size / 2;
|
|
51
|
+
switch (args.shape) {
|
|
52
|
+
case "cross":
|
|
53
|
+
ctx.beginPath();
|
|
54
|
+
ctx.moveTo(args.x - half, y);
|
|
55
|
+
ctx.lineTo(args.x + half, y);
|
|
56
|
+
ctx.moveTo(args.x, y - half);
|
|
57
|
+
ctx.lineTo(args.x, y + half);
|
|
58
|
+
ctx.stroke();
|
|
59
|
+
return;
|
|
60
|
+
case "xcross":
|
|
61
|
+
ctx.beginPath();
|
|
62
|
+
ctx.moveTo(args.x - half, y - half);
|
|
63
|
+
ctx.lineTo(args.x + half, y + half);
|
|
64
|
+
ctx.moveTo(args.x + half, y - half);
|
|
65
|
+
ctx.lineTo(args.x - half, y + half);
|
|
66
|
+
ctx.stroke();
|
|
67
|
+
return;
|
|
68
|
+
case "flag":
|
|
69
|
+
ctx.beginPath();
|
|
70
|
+
ctx.moveTo(args.x - half, y + half);
|
|
71
|
+
ctx.lineTo(args.x - half, y - half);
|
|
72
|
+
ctx.lineTo(args.x + half, y - half / 2);
|
|
73
|
+
ctx.lineTo(args.x - half, y);
|
|
74
|
+
ctx.stroke();
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Render a discrete marker glyph at (`x`, `y`). The renderer sets `fillStyle`
|
|
80
|
+
* once, then dispatches on `shape`:
|
|
81
|
+
*
|
|
82
|
+
* - `circle` → `arc` → `closePath` → `fill`.
|
|
83
|
+
* - `square` → single `fillRect` (`size x size`, centred on the anchor).
|
|
84
|
+
* - `triangle-up` / `triangle-down` / `diamond` → polygon via `beginPath` +
|
|
85
|
+
* `moveTo` + `lineTo`s + `closePath` + `fill`.
|
|
86
|
+
*
|
|
87
|
+
* A null `color` falls back to `fallbackColor`.
|
|
88
|
+
*
|
|
89
|
+
* @since 1.7
|
|
90
|
+
* @stable
|
|
91
|
+
* @example
|
|
92
|
+
* declare const ctx: RenderCtx;
|
|
93
|
+
* drawMarker(ctx, { x: 100, y: 50, shape: "circle", size: 6, color: "#26a69a" }, "#90caf9");
|
|
94
|
+
*/
|
|
95
|
+
export function drawMarker(ctx, args, fallbackColor) {
|
|
96
|
+
ctx.fillStyle = args.color ?? fallbackColor;
|
|
97
|
+
const half = args.size / 2;
|
|
98
|
+
switch (args.shape) {
|
|
99
|
+
case "circle":
|
|
100
|
+
ctx.beginPath();
|
|
101
|
+
ctx.arc(args.x, args.y, half, 0, TWO_PI);
|
|
102
|
+
ctx.closePath();
|
|
103
|
+
ctx.fill();
|
|
104
|
+
return;
|
|
105
|
+
case "square":
|
|
106
|
+
ctx.fillRect(args.x - half, args.y - half, args.size, args.size);
|
|
107
|
+
return;
|
|
108
|
+
case "triangle-up":
|
|
109
|
+
ctx.beginPath();
|
|
110
|
+
ctx.moveTo(args.x, args.y - half);
|
|
111
|
+
ctx.lineTo(args.x + half, args.y + half);
|
|
112
|
+
ctx.lineTo(args.x - half, args.y + half);
|
|
113
|
+
ctx.closePath();
|
|
114
|
+
ctx.fill();
|
|
115
|
+
return;
|
|
116
|
+
case "triangle-down":
|
|
117
|
+
ctx.beginPath();
|
|
118
|
+
ctx.moveTo(args.x, args.y + half);
|
|
119
|
+
ctx.lineTo(args.x + half, args.y - half);
|
|
120
|
+
ctx.lineTo(args.x - half, args.y - half);
|
|
121
|
+
ctx.closePath();
|
|
122
|
+
ctx.fill();
|
|
123
|
+
return;
|
|
124
|
+
case "diamond":
|
|
125
|
+
ctx.beginPath();
|
|
126
|
+
ctx.moveTo(args.x, args.y - half);
|
|
127
|
+
ctx.lineTo(args.x + half, args.y);
|
|
128
|
+
ctx.lineTo(args.x, args.y + half);
|
|
129
|
+
ctx.lineTo(args.x - half, args.y);
|
|
130
|
+
ctx.closePath();
|
|
131
|
+
ctx.fill();
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function characterAnchor(args) {
|
|
136
|
+
switch (args.location ?? "absolute") {
|
|
137
|
+
case "above":
|
|
138
|
+
return { y: args.y - args.size, baseline: "bottom" };
|
|
139
|
+
case "below":
|
|
140
|
+
return { y: args.y + args.size, baseline: "top" };
|
|
141
|
+
case "absolute":
|
|
142
|
+
return { y: args.y, baseline: "middle" };
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Render a `character` glyph (Pine `plotchar`) as centred canvas text. A null
|
|
147
|
+
* `color` falls back to `fallbackColor`.
|
|
148
|
+
*
|
|
149
|
+
* @since 1.7
|
|
150
|
+
* @stable
|
|
151
|
+
* @example
|
|
152
|
+
* declare const ctx: RenderCtx;
|
|
153
|
+
* drawCharacter(ctx, { x: 10, y: 20, char: "A", size: 12, color: null }, "#90caf9");
|
|
154
|
+
*/
|
|
155
|
+
export function drawCharacter(ctx, args, fallbackColor) {
|
|
156
|
+
const resolved = characterAnchor(args);
|
|
157
|
+
ctx.fillStyle = args.color ?? fallbackColor;
|
|
158
|
+
ctx.font = `${args.size}px sans-serif`;
|
|
159
|
+
ctx.textAlign = "center";
|
|
160
|
+
ctx.textBaseline = resolved.baseline;
|
|
161
|
+
ctx.fillText(args.char, args.x, resolved.y);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Render an `arrow` glyph (Pine `plotarrow`) as a filled directional triangle.
|
|
165
|
+
* A null `color` falls back to `fallbackColor`.
|
|
166
|
+
*
|
|
167
|
+
* @since 1.7
|
|
168
|
+
* @stable
|
|
169
|
+
* @example
|
|
170
|
+
* declare const ctx: RenderCtx;
|
|
171
|
+
* drawArrow(ctx, { x: 10, y: 20, direction: "up", size: 10, color: null }, "#90caf9");
|
|
172
|
+
*/
|
|
173
|
+
export function drawArrow(ctx, args, fallbackColor) {
|
|
174
|
+
const half = args.size / 2;
|
|
175
|
+
ctx.fillStyle = args.color ?? fallbackColor;
|
|
176
|
+
ctx.beginPath();
|
|
177
|
+
if (args.direction === "up") {
|
|
178
|
+
ctx.moveTo(args.x, args.y - half);
|
|
179
|
+
ctx.lineTo(args.x + half, args.y + half);
|
|
180
|
+
ctx.lineTo(args.x - half, args.y + half);
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
ctx.moveTo(args.x, args.y + half);
|
|
184
|
+
ctx.lineTo(args.x + half, args.y - half);
|
|
185
|
+
ctx.lineTo(args.x - half, args.y - half);
|
|
186
|
+
}
|
|
187
|
+
ctx.closePath();
|
|
188
|
+
ctx.fill();
|
|
189
|
+
}
|
|
190
|
+
function labelBaseline(position) {
|
|
191
|
+
switch (position) {
|
|
192
|
+
case "above":
|
|
193
|
+
return "bottom";
|
|
194
|
+
case "below":
|
|
195
|
+
return "top";
|
|
196
|
+
case "anchor":
|
|
197
|
+
return "middle";
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Render a single text annotation at (`x`, `y`). The renderer sets `fillStyle`,
|
|
202
|
+
* `font`, `textAlign = "center"`, and a `position`-dependent `textBaseline`,
|
|
203
|
+
* then calls `fillText`. A null `color` falls back to `fallbackColor`; an
|
|
204
|
+
* omitted `font` falls back to `"10px sans-serif"`.
|
|
205
|
+
*
|
|
206
|
+
* @since 1.7
|
|
207
|
+
* @stable
|
|
208
|
+
* @example
|
|
209
|
+
* declare const ctx: RenderCtx;
|
|
210
|
+
* drawLabel(ctx, { x: 100, y: 50, text: "PEAK", position: "above", color: "#26a69a" }, "#90caf9");
|
|
211
|
+
*/
|
|
212
|
+
export function drawLabel(ctx, args, fallbackColor) {
|
|
213
|
+
ctx.fillStyle = args.color ?? fallbackColor;
|
|
214
|
+
ctx.font = args.font ?? DEFAULT_LABEL_FONT;
|
|
215
|
+
ctx.textAlign = "center";
|
|
216
|
+
ctx.textBaseline = labelBaseline(args.position);
|
|
217
|
+
ctx.fillText(args.text, args.x, args.y);
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=glyphs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glyphs.js","sourceRoot":"","sources":["../../src/canvas/glyphs.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n\nimport type { RenderCtx } from \"./renderCtx.js\";\n\n// Shared, model-free glyph geometry for the canvas-family adapters (uplot\n// draw-hook, lightweight-charts overlay). Promoted out of the canvas2d\n// reference adapter's `render/{shape,character,arrow,marker,label}.ts` so the\n// `shape` / `character` / `arrow` / `marker` / `label` geometry is written ONCE\n// instead of hand-ported per consumer (the bug class the `shift.ts` /\n// `renderOrder.ts` promotions exist to kill). Each helper draws onto a\n// `RenderCtx` and takes a plain `fallbackColor: string` (the null-color\n// default), so it carries no palette / library / model types — the move is a\n// pure RenderCtx-based promotion. canvas2d keeps its own `Palette`-taking\n// local renderers (re-consume deferred).\n\nconst OFFSET_RATIO = 1.25;\nconst TWO_PI = Math.PI * 2;\nconst DEFAULT_LABEL_FONT = \"10px sans-serif\";\n\n/**\n * Vertical anchoring mode shared by the `shape` / `character` glyphs.\n * `above` / `below` offset the glyph relative to the plot value; `absolute`\n * pins it at the value.\n *\n * @since 1.7\n * @stable\n * @example\n * const location: GlyphLocation = \"below\";\n * void location;\n */\nexport type GlyphLocation = \"above\" | \"below\" | \"absolute\";\n\n/**\n * Inventory of `shape` glyphs (Pine `plotshape`). The first five reuse the\n * filled {@link drawMarker} geometry; `cross` / `xcross` / `flag` are\n * stroke-only.\n *\n * @since 1.7\n * @stable\n * @example\n * const glyph: ShapeGlyph = \"cross\";\n * void glyph;\n */\nexport type ShapeGlyph =\n | \"circle\"\n | \"triangle-up\"\n | \"triangle-down\"\n | \"square\"\n | \"diamond\"\n | \"cross\"\n | \"xcross\"\n | \"flag\";\n\n/**\n * Inputs for {@link drawShape}. World-space `x` / `y` are pixels the caller\n * derives via `timeToX` / `priceToY`; `size` is the glyph bounding-box edge\n * length in pixels.\n *\n * @since 1.7\n * @stable\n * @example\n * const args: ShapeArgs = { x: 10, y: 20, shape: \"cross\", size: 8, color: null };\n * void args;\n */\nexport type ShapeArgs = {\n readonly x: number;\n readonly y: number;\n readonly shape: ShapeGlyph;\n readonly size: number;\n readonly location?: GlyphLocation;\n readonly color: string | null;\n};\n\n/**\n * Discrete marker glyph. Matches the `marker` variant of `PlotStyle.shape`.\n *\n * @since 1.7\n * @stable\n * @example\n * const s: MarkerShape = \"triangle-up\";\n * void s;\n */\nexport type MarkerShape = \"circle\" | \"triangle-up\" | \"triangle-down\" | \"square\" | \"diamond\";\n\n/**\n * Inputs for {@link drawMarker}. World-space `x` / `y` are pixels the caller\n * derives via `timeToX` / `priceToY`; `size` is the glyph's bounding-box edge\n * length in pixels (the circle uses `size` as its diameter).\n *\n * @since 1.7\n * @stable\n * @example\n * const args: MarkerArgs = { x: 100, y: 50, shape: \"triangle-up\", size: 8, color: \"#26a69a\" };\n * void args;\n */\nexport type MarkerArgs = {\n readonly x: number;\n readonly y: number;\n readonly shape: MarkerShape;\n readonly size: number;\n readonly color: string | null;\n};\n\n/**\n * Inputs for {@link drawCharacter}. World-space `x` / `y` are pixels the\n * caller derives via `timeToX` / `priceToY`; `size` is the font px size.\n *\n * @since 1.7\n * @stable\n * @example\n * const args: CharacterArgs = { x: 10, y: 20, char: \"A\", size: 12, color: null };\n * void args;\n */\nexport type CharacterArgs = {\n readonly x: number;\n readonly y: number;\n readonly char: string;\n readonly size: number;\n readonly location?: GlyphLocation;\n readonly color: string | null;\n};\n\n/**\n * Inputs for {@link drawArrow}. World-space `x` / `y` are pixels the caller\n * derives via `timeToX` / `priceToY`; `size` is the triangle bounding-box edge\n * length in pixels.\n *\n * @since 1.7\n * @stable\n * @example\n * const args: ArrowArgs = { x: 10, y: 20, direction: \"up\", size: 10, color: null };\n * void args;\n */\nexport type ArrowArgs = {\n readonly x: number;\n readonly y: number;\n readonly direction: \"up\" | \"down\";\n readonly size: number;\n readonly color: string | null;\n};\n\n/**\n * Position the label sits in relative to the (`x`, `y`) anchor.\n *\n * - `above` → text sits above the anchor (`textBaseline = \"bottom\"`).\n * - `below` → text sits below the anchor (`textBaseline = \"top\"`).\n * - `anchor` → text is vertically centred on the anchor (`textBaseline =\n * \"middle\"`).\n *\n * @since 1.7\n * @stable\n * @example\n * const p: LabelPosition = \"above\";\n * void p;\n */\nexport type LabelPosition = \"above\" | \"below\" | \"anchor\";\n\n/**\n * Inputs for {@link drawLabel}. World-space `x` / `y` are pixels the caller\n * derives via `timeToX` / `priceToY`. `font` defaults to `\"10px sans-serif\"`\n * when omitted.\n *\n * @since 1.7\n * @stable\n * @example\n * const args: LabelArgs = { x: 100, y: 50, text: \"PEAK\", position: \"above\", color: \"#26a69a\" };\n * void args;\n */\nexport type LabelArgs = {\n readonly x: number;\n readonly y: number;\n readonly text: string;\n readonly position: LabelPosition;\n readonly color: string | null;\n readonly font?: string;\n};\n\nfunction anchoredShapeY(args: ShapeArgs): number {\n switch (args.location ?? \"absolute\") {\n case \"above\":\n return args.y - args.size * OFFSET_RATIO;\n case \"below\":\n return args.y + args.size * OFFSET_RATIO;\n case \"absolute\":\n return args.y;\n }\n}\n\n/**\n * Render a `shape` glyph at a plot anchor. The five filled-marker shapes\n * (`circle` / `triangle-up` / `triangle-down` / `square` / `diamond`)\n * delegate to {@link drawMarker}; `cross` / `xcross` / `flag` stroke their\n * geometry directly. A null `color` falls back to `fallbackColor`.\n *\n * @since 1.7\n * @stable\n * @example\n * declare const ctx: RenderCtx;\n * drawShape(ctx, { x: 10, y: 20, shape: \"cross\", size: 8, color: null }, \"#90caf9\");\n */\nexport function drawShape(ctx: RenderCtx, args: ShapeArgs, fallbackColor: string): void {\n const y = anchoredShapeY(args);\n if (\n args.shape === \"circle\" ||\n args.shape === \"triangle-up\" ||\n args.shape === \"triangle-down\" ||\n args.shape === \"square\" ||\n args.shape === \"diamond\"\n ) {\n drawMarker(ctx, { ...args, y, shape: args.shape }, fallbackColor);\n return;\n }\n\n ctx.strokeStyle = args.color ?? fallbackColor;\n ctx.lineWidth = 1;\n const half = args.size / 2;\n switch (args.shape) {\n case \"cross\":\n ctx.beginPath();\n ctx.moveTo(args.x - half, y);\n ctx.lineTo(args.x + half, y);\n ctx.moveTo(args.x, y - half);\n ctx.lineTo(args.x, y + half);\n ctx.stroke();\n return;\n case \"xcross\":\n ctx.beginPath();\n ctx.moveTo(args.x - half, y - half);\n ctx.lineTo(args.x + half, y + half);\n ctx.moveTo(args.x + half, y - half);\n ctx.lineTo(args.x - half, y + half);\n ctx.stroke();\n return;\n case \"flag\":\n ctx.beginPath();\n ctx.moveTo(args.x - half, y + half);\n ctx.lineTo(args.x - half, y - half);\n ctx.lineTo(args.x + half, y - half / 2);\n ctx.lineTo(args.x - half, y);\n ctx.stroke();\n return;\n }\n}\n\n/**\n * Render a discrete marker glyph at (`x`, `y`). The renderer sets `fillStyle`\n * once, then dispatches on `shape`:\n *\n * - `circle` → `arc` → `closePath` → `fill`.\n * - `square` → single `fillRect` (`size x size`, centred on the anchor).\n * - `triangle-up` / `triangle-down` / `diamond` → polygon via `beginPath` +\n * `moveTo` + `lineTo`s + `closePath` + `fill`.\n *\n * A null `color` falls back to `fallbackColor`.\n *\n * @since 1.7\n * @stable\n * @example\n * declare const ctx: RenderCtx;\n * drawMarker(ctx, { x: 100, y: 50, shape: \"circle\", size: 6, color: \"#26a69a\" }, \"#90caf9\");\n */\nexport function drawMarker(ctx: RenderCtx, args: MarkerArgs, fallbackColor: string): void {\n ctx.fillStyle = args.color ?? fallbackColor;\n const half = args.size / 2;\n switch (args.shape) {\n case \"circle\":\n ctx.beginPath();\n ctx.arc(args.x, args.y, half, 0, TWO_PI);\n ctx.closePath();\n ctx.fill();\n return;\n case \"square\":\n ctx.fillRect(args.x - half, args.y - half, args.size, args.size);\n return;\n case \"triangle-up\":\n ctx.beginPath();\n ctx.moveTo(args.x, args.y - half);\n ctx.lineTo(args.x + half, args.y + half);\n ctx.lineTo(args.x - half, args.y + half);\n ctx.closePath();\n ctx.fill();\n return;\n case \"triangle-down\":\n ctx.beginPath();\n ctx.moveTo(args.x, args.y + half);\n ctx.lineTo(args.x + half, args.y - half);\n ctx.lineTo(args.x - half, args.y - half);\n ctx.closePath();\n ctx.fill();\n return;\n case \"diamond\":\n ctx.beginPath();\n ctx.moveTo(args.x, args.y - half);\n ctx.lineTo(args.x + half, args.y);\n ctx.lineTo(args.x, args.y + half);\n ctx.lineTo(args.x - half, args.y);\n ctx.closePath();\n ctx.fill();\n return;\n }\n}\n\nfunction characterAnchor(args: CharacterArgs): {\n readonly y: number;\n readonly baseline: RenderCtx[\"textBaseline\"];\n} {\n switch (args.location ?? \"absolute\") {\n case \"above\":\n return { y: args.y - args.size, baseline: \"bottom\" };\n case \"below\":\n return { y: args.y + args.size, baseline: \"top\" };\n case \"absolute\":\n return { y: args.y, baseline: \"middle\" };\n }\n}\n\n/**\n * Render a `character` glyph (Pine `plotchar`) as centred canvas text. A null\n * `color` falls back to `fallbackColor`.\n *\n * @since 1.7\n * @stable\n * @example\n * declare const ctx: RenderCtx;\n * drawCharacter(ctx, { x: 10, y: 20, char: \"A\", size: 12, color: null }, \"#90caf9\");\n */\nexport function drawCharacter(ctx: RenderCtx, args: CharacterArgs, fallbackColor: string): void {\n const resolved = characterAnchor(args);\n ctx.fillStyle = args.color ?? fallbackColor;\n ctx.font = `${args.size}px sans-serif`;\n ctx.textAlign = \"center\";\n ctx.textBaseline = resolved.baseline;\n ctx.fillText(args.char, args.x, resolved.y);\n}\n\n/**\n * Render an `arrow` glyph (Pine `plotarrow`) as a filled directional triangle.\n * A null `color` falls back to `fallbackColor`.\n *\n * @since 1.7\n * @stable\n * @example\n * declare const ctx: RenderCtx;\n * drawArrow(ctx, { x: 10, y: 20, direction: \"up\", size: 10, color: null }, \"#90caf9\");\n */\nexport function drawArrow(ctx: RenderCtx, args: ArrowArgs, fallbackColor: string): void {\n const half = args.size / 2;\n ctx.fillStyle = args.color ?? fallbackColor;\n ctx.beginPath();\n if (args.direction === \"up\") {\n ctx.moveTo(args.x, args.y - half);\n ctx.lineTo(args.x + half, args.y + half);\n ctx.lineTo(args.x - half, args.y + half);\n } else {\n ctx.moveTo(args.x, args.y + half);\n ctx.lineTo(args.x + half, args.y - half);\n ctx.lineTo(args.x - half, args.y - half);\n }\n ctx.closePath();\n ctx.fill();\n}\n\nfunction labelBaseline(position: LabelPosition): \"top\" | \"middle\" | \"bottom\" {\n switch (position) {\n case \"above\":\n return \"bottom\";\n case \"below\":\n return \"top\";\n case \"anchor\":\n return \"middle\";\n }\n}\n\n/**\n * Render a single text annotation at (`x`, `y`). The renderer sets `fillStyle`,\n * `font`, `textAlign = \"center\"`, and a `position`-dependent `textBaseline`,\n * then calls `fillText`. A null `color` falls back to `fallbackColor`; an\n * omitted `font` falls back to `\"10px sans-serif\"`.\n *\n * @since 1.7\n * @stable\n * @example\n * declare const ctx: RenderCtx;\n * drawLabel(ctx, { x: 100, y: 50, text: \"PEAK\", position: \"above\", color: \"#26a69a\" }, \"#90caf9\");\n */\nexport function drawLabel(ctx: RenderCtx, args: LabelArgs, fallbackColor: string): void {\n ctx.fillStyle = args.color ?? fallbackColor;\n ctx.font = args.font ?? DEFAULT_LABEL_FONT;\n ctx.textAlign = \"center\";\n ctx.textBaseline = labelBaseline(args.position);\n ctx.fillText(args.text, args.x, args.y);\n}\n"]}
|
package/dist/canvas/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export { drawArrow, drawCharacter, drawLabel, drawMarker, drawShape } from "./glyphs.js";
|
|
2
|
+
export type { ArrowArgs, CharacterArgs, GlyphLocation, LabelArgs, LabelPosition, MarkerArgs, MarkerShape, ShapeArgs, ShapeGlyph, } from "./glyphs.js";
|
|
1
3
|
export { hashCallLog, MockCanvasContext } from "./mockContext.js";
|
|
2
4
|
export type { RecordedCall } from "./mockContext.js";
|
|
3
5
|
export { paintPrimitive } from "./paintPrimitive.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/canvas/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAClE,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/canvas/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACzF,YAAY,EACR,SAAS,EACT,aAAa,EACb,aAAa,EACb,SAAS,EACT,aAAa,EACb,UAAU,EACV,WAAW,EACX,SAAS,EACT,UAAU,GACb,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAClE,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/canvas/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Copyright (c) 2026 Invinite. Licensed under the MIT License.
|
|
2
2
|
// See the LICENSE file in the repo root for full license text.
|
|
3
|
+
export { drawArrow, drawCharacter, drawLabel, drawMarker, drawShape } from "./glyphs.js";
|
|
3
4
|
export { hashCallLog, MockCanvasContext } from "./mockContext.js";
|
|
4
5
|
export { paintPrimitive } from "./paintPrimitive.js";
|
|
5
6
|
//# sourceMappingURL=index.js.map
|
package/dist/canvas/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/canvas/index.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,+DAA+D;AAE/D,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAElE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC","sourcesContent":["// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n\nexport { hashCallLog, MockCanvasContext } from \"./mockContext.js\";\nexport type { RecordedCall } from \"./mockContext.js\";\nexport { paintPrimitive } from \"./paintPrimitive.js\";\nexport type { RenderCtx } from \"./renderCtx.js\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/canvas/index.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,+DAA+D;AAE/D,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAYzF,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAElE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC","sourcesContent":["// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n\nexport { drawArrow, drawCharacter, drawLabel, drawMarker, drawShape } from \"./glyphs.js\";\nexport type {\n ArrowArgs,\n CharacterArgs,\n GlyphLocation,\n LabelArgs,\n LabelPosition,\n MarkerArgs,\n MarkerShape,\n ShapeArgs,\n ShapeGlyph,\n} from \"./glyphs.js\";\nexport { hashCallLog, MockCanvasContext } from \"./mockContext.js\";\nexport type { RecordedCall } from \"./mockContext.js\";\nexport { paintPrimitive } from \"./paintPrimitive.js\";\nexport type { RenderCtx } from \"./renderCtx.js\";\n"]}
|
|
@@ -34,8 +34,32 @@ export type RecordedCall = {
|
|
|
34
34
|
readonly kind: "lineTo";
|
|
35
35
|
readonly x: number;
|
|
36
36
|
readonly y: number;
|
|
37
|
+
} | {
|
|
38
|
+
readonly kind: "bezierCurveTo";
|
|
39
|
+
readonly c1x: number;
|
|
40
|
+
readonly c1y: number;
|
|
41
|
+
readonly c2x: number;
|
|
42
|
+
readonly c2y: number;
|
|
43
|
+
readonly x: number;
|
|
44
|
+
readonly y: number;
|
|
37
45
|
} | {
|
|
38
46
|
readonly kind: "stroke";
|
|
47
|
+
} | {
|
|
48
|
+
readonly kind: "rect";
|
|
49
|
+
readonly x: number;
|
|
50
|
+
readonly y: number;
|
|
51
|
+
readonly w: number;
|
|
52
|
+
readonly h: number;
|
|
53
|
+
} | {
|
|
54
|
+
readonly kind: "clip";
|
|
55
|
+
} | {
|
|
56
|
+
readonly kind: "setTransform";
|
|
57
|
+
readonly a: number;
|
|
58
|
+
readonly b: number;
|
|
59
|
+
readonly c: number;
|
|
60
|
+
readonly d: number;
|
|
61
|
+
readonly e: number;
|
|
62
|
+
readonly f: number;
|
|
39
63
|
} | {
|
|
40
64
|
readonly kind: "fillRect";
|
|
41
65
|
readonly x: number;
|
|
@@ -73,6 +97,14 @@ export type RecordedCall = {
|
|
|
73
97
|
readonly kind: "set";
|
|
74
98
|
readonly prop: "lineWidth";
|
|
75
99
|
readonly value: number;
|
|
100
|
+
} | {
|
|
101
|
+
readonly kind: "set";
|
|
102
|
+
readonly prop: "lineJoin";
|
|
103
|
+
readonly value: string;
|
|
104
|
+
} | {
|
|
105
|
+
readonly kind: "set";
|
|
106
|
+
readonly prop: "lineCap";
|
|
107
|
+
readonly value: string;
|
|
76
108
|
} | {
|
|
77
109
|
readonly kind: "set";
|
|
78
110
|
readonly prop: "globalAlpha";
|
|
@@ -115,6 +147,8 @@ export declare class MockCanvasContext {
|
|
|
115
147
|
private _strokeStyle;
|
|
116
148
|
private _fillStyle;
|
|
117
149
|
private _lineWidth;
|
|
150
|
+
private _lineJoin;
|
|
151
|
+
private _lineCap;
|
|
118
152
|
private _globalAlpha;
|
|
119
153
|
private _font;
|
|
120
154
|
private _textAlign;
|
|
@@ -126,7 +160,11 @@ export declare class MockCanvasContext {
|
|
|
126
160
|
beginPath(): void;
|
|
127
161
|
moveTo(x: number, y: number): void;
|
|
128
162
|
lineTo(x: number, y: number): void;
|
|
163
|
+
bezierCurveTo(c1x: number, c1y: number, c2x: number, c2y: number, x: number, y: number): void;
|
|
129
164
|
stroke(): void;
|
|
165
|
+
rect(x: number, y: number, w: number, h: number): void;
|
|
166
|
+
clip(): void;
|
|
167
|
+
setTransform(a: number, b: number, c: number, d: number, e: number, f: number): void;
|
|
130
168
|
fillRect(x: number, y: number, w: number, h: number): void;
|
|
131
169
|
fill(): void;
|
|
132
170
|
arc(x: number, y: number, radius: number, start: number, end: number): void;
|
|
@@ -139,6 +177,10 @@ export declare class MockCanvasContext {
|
|
|
139
177
|
set fillStyle(value: string);
|
|
140
178
|
get lineWidth(): number;
|
|
141
179
|
set lineWidth(value: number);
|
|
180
|
+
get lineJoin(): "round" | "bevel" | "miter";
|
|
181
|
+
set lineJoin(value: "round" | "bevel" | "miter");
|
|
182
|
+
get lineCap(): "butt" | "round" | "square";
|
|
183
|
+
set lineCap(value: "butt" | "round" | "square");
|
|
142
184
|
get globalAlpha(): number;
|
|
143
185
|
set globalAlpha(value: number);
|
|
144
186
|
get font(): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mockContext.d.ts","sourceRoot":"","sources":["../../src/canvas/mockContext.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"mockContext.d.ts","sourceRoot":"","sources":["../../src/canvas/mockContext.ts"],"names":[],"mappings":"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"}
|
|
@@ -26,6 +26,8 @@ export class MockCanvasContext {
|
|
|
26
26
|
_strokeStyle = "#000000";
|
|
27
27
|
_fillStyle = "#000000";
|
|
28
28
|
_lineWidth = 1;
|
|
29
|
+
_lineJoin = "miter";
|
|
30
|
+
_lineCap = "butt";
|
|
29
31
|
_globalAlpha = 1;
|
|
30
32
|
_font = "10px sans-serif";
|
|
31
33
|
_textAlign = "start";
|
|
@@ -51,9 +53,21 @@ export class MockCanvasContext {
|
|
|
51
53
|
lineTo(x, y) {
|
|
52
54
|
this.calls.push({ kind: "lineTo", x, y });
|
|
53
55
|
}
|
|
56
|
+
bezierCurveTo(c1x, c1y, c2x, c2y, x, y) {
|
|
57
|
+
this.calls.push({ kind: "bezierCurveTo", c1x, c1y, c2x, c2y, x, y });
|
|
58
|
+
}
|
|
54
59
|
stroke() {
|
|
55
60
|
this.calls.push({ kind: "stroke" });
|
|
56
61
|
}
|
|
62
|
+
rect(x, y, w, h) {
|
|
63
|
+
this.calls.push({ kind: "rect", x, y, w, h });
|
|
64
|
+
}
|
|
65
|
+
clip() {
|
|
66
|
+
this.calls.push({ kind: "clip" });
|
|
67
|
+
}
|
|
68
|
+
setTransform(a, b, c, d, e, f) {
|
|
69
|
+
this.calls.push({ kind: "setTransform", a, b, c, d, e, f });
|
|
70
|
+
}
|
|
57
71
|
fillRect(x, y, w, h) {
|
|
58
72
|
this.calls.push({ kind: "fillRect", x, y, w, h });
|
|
59
73
|
}
|
|
@@ -93,6 +107,20 @@ export class MockCanvasContext {
|
|
|
93
107
|
this._lineWidth = value;
|
|
94
108
|
this.calls.push({ kind: "set", prop: "lineWidth", value });
|
|
95
109
|
}
|
|
110
|
+
get lineJoin() {
|
|
111
|
+
return this._lineJoin;
|
|
112
|
+
}
|
|
113
|
+
set lineJoin(value) {
|
|
114
|
+
this._lineJoin = value;
|
|
115
|
+
this.calls.push({ kind: "set", prop: "lineJoin", value });
|
|
116
|
+
}
|
|
117
|
+
get lineCap() {
|
|
118
|
+
return this._lineCap;
|
|
119
|
+
}
|
|
120
|
+
set lineCap(value) {
|
|
121
|
+
this._lineCap = value;
|
|
122
|
+
this.calls.push({ kind: "set", prop: "lineCap", value });
|
|
123
|
+
}
|
|
96
124
|
get globalAlpha() {
|
|
97
125
|
return this._globalAlpha;
|
|
98
126
|
}
|
|
@@ -132,6 +160,7 @@ function canonicalise(call) {
|
|
|
132
160
|
switch (call.kind) {
|
|
133
161
|
case "clearRect":
|
|
134
162
|
case "fillRect":
|
|
163
|
+
case "rect":
|
|
135
164
|
return {
|
|
136
165
|
kind: call.kind,
|
|
137
166
|
x: roundFloat(call.x),
|
|
@@ -143,6 +172,16 @@ function canonicalise(call) {
|
|
|
143
172
|
case "lineTo":
|
|
144
173
|
case "translate":
|
|
145
174
|
return { kind: call.kind, x: roundFloat(call.x), y: roundFloat(call.y) };
|
|
175
|
+
case "bezierCurveTo":
|
|
176
|
+
return {
|
|
177
|
+
kind: call.kind,
|
|
178
|
+
c1x: roundFloat(call.c1x),
|
|
179
|
+
c1y: roundFloat(call.c1y),
|
|
180
|
+
c2x: roundFloat(call.c2x),
|
|
181
|
+
c2y: roundFloat(call.c2y),
|
|
182
|
+
x: roundFloat(call.x),
|
|
183
|
+
y: roundFloat(call.y),
|
|
184
|
+
};
|
|
146
185
|
case "arc":
|
|
147
186
|
return {
|
|
148
187
|
kind: call.kind,
|
|
@@ -152,6 +191,16 @@ function canonicalise(call) {
|
|
|
152
191
|
start: roundFloat(call.start),
|
|
153
192
|
end: roundFloat(call.end),
|
|
154
193
|
};
|
|
194
|
+
case "setTransform":
|
|
195
|
+
return {
|
|
196
|
+
kind: call.kind,
|
|
197
|
+
a: roundFloat(call.a),
|
|
198
|
+
b: roundFloat(call.b),
|
|
199
|
+
c: roundFloat(call.c),
|
|
200
|
+
d: roundFloat(call.d),
|
|
201
|
+
e: roundFloat(call.e),
|
|
202
|
+
f: roundFloat(call.f),
|
|
203
|
+
};
|
|
155
204
|
case "setLineDash":
|
|
156
205
|
return { kind: call.kind, segments: call.segments.map((s) => roundFloat(s)) };
|
|
157
206
|
case "fillText":
|
|
@@ -171,6 +220,7 @@ function canonicalise(call) {
|
|
|
171
220
|
case "stroke":
|
|
172
221
|
case "fill":
|
|
173
222
|
case "closePath":
|
|
223
|
+
case "clip":
|
|
174
224
|
return { kind: call.kind };
|
|
175
225
|
}
|
|
176
226
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mockContext.js","sourceRoot":"","sources":["../../src/canvas/mockContext.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n\nimport { createHash } from \"node:crypto\";\n\n/**\n * One recorded call against {@link MockCanvasContext}. Tests inspect\n * the array to assert a paint sequence. The union covers every method\n * and setter on {@link import(\"./renderCtx\").RenderCtx}; adding a new\n * draw call means extending both the mock and this union together.\n *\n * @since 1.3\n * @stable\n * @example\n * const call: RecordedCall = { kind: \"clearRect\", x: 0, y: 0, w: 100, h: 100 };\n * void call;\n */\nexport type RecordedCall =\n | {\n readonly kind: \"clearRect\";\n readonly x: number;\n readonly y: number;\n readonly w: number;\n readonly h: number;\n }\n | { readonly kind: \"translate\"; readonly x: number; readonly y: number }\n | { readonly kind: \"save\" }\n | { readonly kind: \"restore\" }\n | { readonly kind: \"beginPath\" }\n | { readonly kind: \"moveTo\"; readonly x: number; readonly y: number }\n | { readonly kind: \"lineTo\"; readonly x: number; readonly y: number }\n | { readonly kind: \"stroke\" }\n | {\n readonly kind: \"fillRect\";\n readonly x: number;\n readonly y: number;\n readonly w: number;\n readonly h: number;\n }\n | { readonly kind: \"fill\" }\n | {\n readonly kind: \"arc\";\n readonly x: number;\n readonly y: number;\n readonly radius: number;\n readonly start: number;\n readonly end: number;\n }\n | { readonly kind: \"closePath\" }\n | { readonly kind: \"setLineDash\"; readonly segments: ReadonlyArray<number> }\n | { readonly kind: \"fillText\"; readonly text: string; readonly x: number; readonly y: number }\n | { readonly kind: \"set\"; readonly prop: \"strokeStyle\"; readonly value: string }\n | { readonly kind: \"set\"; readonly prop: \"fillStyle\"; readonly value: string }\n | { readonly kind: \"set\"; readonly prop: \"lineWidth\"; readonly value: number }\n | { readonly kind: \"set\"; readonly prop: \"globalAlpha\"; readonly value: number }\n | { readonly kind: \"set\"; readonly prop: \"font\"; readonly value: string }\n | { readonly kind: \"set\"; readonly prop: \"textAlign\"; readonly value: string }\n | { readonly kind: \"set\"; readonly prop: \"textBaseline\"; readonly value: string };\n\n/**\n * Hand-rolled Canvas 2D mock that satisfies the canvas sink's\n * {@link import(\"./renderCtx\").RenderCtx} structural type. Every method\n * and setter appends a typed record to `calls` so tests can assert the\n * exact paint sequence without standing up `node-canvas` or a real\n * browser. The canvas2d adapter re-exports this class as\n * `MockCanvas2DContext` (implementation shared, public name unchanged).\n *\n * Property setters are tracked via accessor pairs — the mock stores the\n * most recent value in private fields so `ctx.strokeStyle = \"#x\"` both\n * records the call and survives a subsequent read.\n *\n * @since 1.3\n * @stable\n * @example\n * const ctx = new MockCanvasContext();\n * ctx.clearRect(0, 0, 100, 100);\n * // ctx.calls[0] === { kind: \"clearRect\", x: 0, y: 0, w: 100, h: 100 }\n * void ctx;\n */\nexport class MockCanvasContext {\n readonly calls: RecordedCall[] = [];\n private _strokeStyle = \"#000000\";\n private _fillStyle = \"#000000\";\n private _lineWidth = 1;\n private _globalAlpha = 1;\n private _font = \"10px sans-serif\";\n private _textAlign: \"start\" | \"center\" | \"end\" | \"left\" | \"right\" = \"start\";\n private _textBaseline: \"top\" | \"middle\" | \"bottom\" | \"alphabetic\" | \"hanging\" = \"alphabetic\";\n\n clearRect(x: number, y: number, w: number, h: number): void {\n this.calls.push({ kind: \"clearRect\", x, y, w, h });\n }\n\n translate(x: number, y: number): void {\n this.calls.push({ kind: \"translate\", x, y });\n }\n\n save(): void {\n this.calls.push({ kind: \"save\" });\n }\n\n restore(): void {\n this.calls.push({ kind: \"restore\" });\n }\n\n beginPath(): void {\n this.calls.push({ kind: \"beginPath\" });\n }\n\n moveTo(x: number, y: number): void {\n this.calls.push({ kind: \"moveTo\", x, y });\n }\n\n lineTo(x: number, y: number): void {\n this.calls.push({ kind: \"lineTo\", x, y });\n }\n\n stroke(): void {\n this.calls.push({ kind: \"stroke\" });\n }\n\n fillRect(x: number, y: number, w: number, h: number): void {\n this.calls.push({ kind: \"fillRect\", x, y, w, h });\n }\n\n fill(): void {\n this.calls.push({ kind: \"fill\" });\n }\n\n arc(x: number, y: number, radius: number, start: number, end: number): void {\n this.calls.push({ kind: \"arc\", x, y, radius, start, end });\n }\n\n closePath(): void {\n this.calls.push({ kind: \"closePath\" });\n }\n\n setLineDash(segments: ReadonlyArray<number>): void {\n this.calls.push({ kind: \"setLineDash\", segments: segments.slice() });\n }\n\n fillText(text: string, x: number, y: number): void {\n this.calls.push({ kind: \"fillText\", text, x, y });\n }\n\n get strokeStyle(): string {\n return this._strokeStyle;\n }\n\n set strokeStyle(value: string) {\n this._strokeStyle = value;\n this.calls.push({ kind: \"set\", prop: \"strokeStyle\", value });\n }\n\n get fillStyle(): string {\n return this._fillStyle;\n }\n\n set fillStyle(value: string) {\n this._fillStyle = value;\n this.calls.push({ kind: \"set\", prop: \"fillStyle\", value });\n }\n\n get lineWidth(): number {\n return this._lineWidth;\n }\n\n set lineWidth(value: number) {\n this._lineWidth = value;\n this.calls.push({ kind: \"set\", prop: \"lineWidth\", value });\n }\n\n get globalAlpha(): number {\n return this._globalAlpha;\n }\n\n set globalAlpha(value: number) {\n this._globalAlpha = value;\n this.calls.push({ kind: \"set\", prop: \"globalAlpha\", value });\n }\n\n get font(): string {\n return this._font;\n }\n\n set font(value: string) {\n this._font = value;\n this.calls.push({ kind: \"set\", prop: \"font\", value });\n }\n\n get textAlign(): \"start\" | \"center\" | \"end\" | \"left\" | \"right\" {\n return this._textAlign;\n }\n\n set textAlign(value: \"start\" | \"center\" | \"end\" | \"left\" | \"right\") {\n this._textAlign = value;\n this.calls.push({ kind: \"set\", prop: \"textAlign\", value });\n }\n\n get textBaseline(): \"top\" | \"middle\" | \"bottom\" | \"alphabetic\" | \"hanging\" {\n return this._textBaseline;\n }\n\n set textBaseline(value: \"top\" | \"middle\" | \"bottom\" | \"alphabetic\" | \"hanging\") {\n this._textBaseline = value;\n this.calls.push({ kind: \"set\", prop: \"textBaseline\", value });\n }\n}\n\nconst FLOAT_DECIMALS = 4;\n\nfunction roundFloat(n: number): number | string {\n if (!Number.isFinite(n)) return String(n);\n return Number(n.toFixed(FLOAT_DECIMALS));\n}\n\nfunction canonicalise(call: RecordedCall): Record<string, unknown> {\n switch (call.kind) {\n case \"clearRect\":\n case \"fillRect\":\n return {\n kind: call.kind,\n x: roundFloat(call.x),\n y: roundFloat(call.y),\n w: roundFloat(call.w),\n h: roundFloat(call.h),\n };\n case \"moveTo\":\n case \"lineTo\":\n case \"translate\":\n return { kind: call.kind, x: roundFloat(call.x), y: roundFloat(call.y) };\n case \"arc\":\n return {\n kind: call.kind,\n x: roundFloat(call.x),\n y: roundFloat(call.y),\n radius: roundFloat(call.radius),\n start: roundFloat(call.start),\n end: roundFloat(call.end),\n };\n case \"setLineDash\":\n return { kind: call.kind, segments: call.segments.map((s) => roundFloat(s)) };\n case \"fillText\":\n return {\n kind: call.kind,\n text: call.text,\n x: roundFloat(call.x),\n y: roundFloat(call.y),\n };\n case \"set\": {\n const value = typeof call.value === \"number\" ? roundFloat(call.value) : call.value;\n return { kind: call.kind, prop: call.prop, value };\n }\n case \"beginPath\":\n case \"save\":\n case \"restore\":\n case \"stroke\":\n case \"fill\":\n case \"closePath\":\n return { kind: call.kind };\n }\n}\n\n/**\n * Hash a recorded call log into a stable SHA-256 hex string. Floats are\n * rounded to four decimal places and re-serialised in canonical-key\n * JSON so a microscopic floating-point drift does not re-hash the log.\n * Pass `mock.calls`. Adapters pin their integration render output\n * against a single golden constant with this.\n *\n * @since 1.3\n * @stable\n * @example\n * const ctx = new MockCanvasContext();\n * ctx.clearRect(0, 0, 100, 100);\n * const h = hashCallLog(ctx.calls);\n * // h is a 64-char hex string\n * void h;\n */\nexport function hashCallLog(calls: ReadonlyArray<RecordedCall>): string {\n const payload = calls.map(canonicalise);\n const serialised = JSON.stringify(payload);\n return createHash(\"sha256\").update(serialised).digest(\"hex\");\n}\n"]}
|
|
1
|
+
{"version":3,"file":"mockContext.js","sourceRoot":"","sources":["../../src/canvas/mockContext.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n\nimport { createHash } from \"node:crypto\";\n\n/**\n * One recorded call against {@link MockCanvasContext}. Tests inspect\n * the array to assert a paint sequence. The union covers every method\n * and setter on {@link import(\"./renderCtx\").RenderCtx}; adding a new\n * draw call means extending both the mock and this union together.\n *\n * @since 1.3\n * @stable\n * @example\n * const call: RecordedCall = { kind: \"clearRect\", x: 0, y: 0, w: 100, h: 100 };\n * void call;\n */\nexport type RecordedCall =\n | {\n readonly kind: \"clearRect\";\n readonly x: number;\n readonly y: number;\n readonly w: number;\n readonly h: number;\n }\n | { readonly kind: \"translate\"; readonly x: number; readonly y: number }\n | { readonly kind: \"save\" }\n | { readonly kind: \"restore\" }\n | { readonly kind: \"beginPath\" }\n | { readonly kind: \"moveTo\"; readonly x: number; readonly y: number }\n | { readonly kind: \"lineTo\"; readonly x: number; readonly y: number }\n | {\n readonly kind: \"bezierCurveTo\";\n readonly c1x: number;\n readonly c1y: number;\n readonly c2x: number;\n readonly c2y: number;\n readonly x: number;\n readonly y: number;\n }\n | { readonly kind: \"stroke\" }\n | {\n readonly kind: \"rect\";\n readonly x: number;\n readonly y: number;\n readonly w: number;\n readonly h: number;\n }\n | { readonly kind: \"clip\" }\n | {\n readonly kind: \"setTransform\";\n readonly a: number;\n readonly b: number;\n readonly c: number;\n readonly d: number;\n readonly e: number;\n readonly f: number;\n }\n | {\n readonly kind: \"fillRect\";\n readonly x: number;\n readonly y: number;\n readonly w: number;\n readonly h: number;\n }\n | { readonly kind: \"fill\" }\n | {\n readonly kind: \"arc\";\n readonly x: number;\n readonly y: number;\n readonly radius: number;\n readonly start: number;\n readonly end: number;\n }\n | { readonly kind: \"closePath\" }\n | { readonly kind: \"setLineDash\"; readonly segments: ReadonlyArray<number> }\n | { readonly kind: \"fillText\"; readonly text: string; readonly x: number; readonly y: number }\n | { readonly kind: \"set\"; readonly prop: \"strokeStyle\"; readonly value: string }\n | { readonly kind: \"set\"; readonly prop: \"fillStyle\"; readonly value: string }\n | { readonly kind: \"set\"; readonly prop: \"lineWidth\"; readonly value: number }\n | { readonly kind: \"set\"; readonly prop: \"lineJoin\"; readonly value: string }\n | { readonly kind: \"set\"; readonly prop: \"lineCap\"; readonly value: string }\n | { readonly kind: \"set\"; readonly prop: \"globalAlpha\"; readonly value: number }\n | { readonly kind: \"set\"; readonly prop: \"font\"; readonly value: string }\n | { readonly kind: \"set\"; readonly prop: \"textAlign\"; readonly value: string }\n | { readonly kind: \"set\"; readonly prop: \"textBaseline\"; readonly value: string };\n\n/**\n * Hand-rolled Canvas 2D mock that satisfies the canvas sink's\n * {@link import(\"./renderCtx\").RenderCtx} structural type. Every method\n * and setter appends a typed record to `calls` so tests can assert the\n * exact paint sequence without standing up `node-canvas` or a real\n * browser. The canvas2d adapter re-exports this class as\n * `MockCanvas2DContext` (implementation shared, public name unchanged).\n *\n * Property setters are tracked via accessor pairs — the mock stores the\n * most recent value in private fields so `ctx.strokeStyle = \"#x\"` both\n * records the call and survives a subsequent read.\n *\n * @since 1.3\n * @stable\n * @example\n * const ctx = new MockCanvasContext();\n * ctx.clearRect(0, 0, 100, 100);\n * // ctx.calls[0] === { kind: \"clearRect\", x: 0, y: 0, w: 100, h: 100 }\n * void ctx;\n */\nexport class MockCanvasContext {\n readonly calls: RecordedCall[] = [];\n private _strokeStyle = \"#000000\";\n private _fillStyle = \"#000000\";\n private _lineWidth = 1;\n private _lineJoin: \"round\" | \"bevel\" | \"miter\" = \"miter\";\n private _lineCap: \"butt\" | \"round\" | \"square\" = \"butt\";\n private _globalAlpha = 1;\n private _font = \"10px sans-serif\";\n private _textAlign: \"start\" | \"center\" | \"end\" | \"left\" | \"right\" = \"start\";\n private _textBaseline: \"top\" | \"middle\" | \"bottom\" | \"alphabetic\" | \"hanging\" = \"alphabetic\";\n\n clearRect(x: number, y: number, w: number, h: number): void {\n this.calls.push({ kind: \"clearRect\", x, y, w, h });\n }\n\n translate(x: number, y: number): void {\n this.calls.push({ kind: \"translate\", x, y });\n }\n\n save(): void {\n this.calls.push({ kind: \"save\" });\n }\n\n restore(): void {\n this.calls.push({ kind: \"restore\" });\n }\n\n beginPath(): void {\n this.calls.push({ kind: \"beginPath\" });\n }\n\n moveTo(x: number, y: number): void {\n this.calls.push({ kind: \"moveTo\", x, y });\n }\n\n lineTo(x: number, y: number): void {\n this.calls.push({ kind: \"lineTo\", x, y });\n }\n\n bezierCurveTo(c1x: number, c1y: number, c2x: number, c2y: number, x: number, y: number): void {\n this.calls.push({ kind: \"bezierCurveTo\", c1x, c1y, c2x, c2y, x, y });\n }\n\n stroke(): void {\n this.calls.push({ kind: \"stroke\" });\n }\n\n rect(x: number, y: number, w: number, h: number): void {\n this.calls.push({ kind: \"rect\", x, y, w, h });\n }\n\n clip(): void {\n this.calls.push({ kind: \"clip\" });\n }\n\n setTransform(a: number, b: number, c: number, d: number, e: number, f: number): void {\n this.calls.push({ kind: \"setTransform\", a, b, c, d, e, f });\n }\n\n fillRect(x: number, y: number, w: number, h: number): void {\n this.calls.push({ kind: \"fillRect\", x, y, w, h });\n }\n\n fill(): void {\n this.calls.push({ kind: \"fill\" });\n }\n\n arc(x: number, y: number, radius: number, start: number, end: number): void {\n this.calls.push({ kind: \"arc\", x, y, radius, start, end });\n }\n\n closePath(): void {\n this.calls.push({ kind: \"closePath\" });\n }\n\n setLineDash(segments: ReadonlyArray<number>): void {\n this.calls.push({ kind: \"setLineDash\", segments: segments.slice() });\n }\n\n fillText(text: string, x: number, y: number): void {\n this.calls.push({ kind: \"fillText\", text, x, y });\n }\n\n get strokeStyle(): string {\n return this._strokeStyle;\n }\n\n set strokeStyle(value: string) {\n this._strokeStyle = value;\n this.calls.push({ kind: \"set\", prop: \"strokeStyle\", value });\n }\n\n get fillStyle(): string {\n return this._fillStyle;\n }\n\n set fillStyle(value: string) {\n this._fillStyle = value;\n this.calls.push({ kind: \"set\", prop: \"fillStyle\", value });\n }\n\n get lineWidth(): number {\n return this._lineWidth;\n }\n\n set lineWidth(value: number) {\n this._lineWidth = value;\n this.calls.push({ kind: \"set\", prop: \"lineWidth\", value });\n }\n\n get lineJoin(): \"round\" | \"bevel\" | \"miter\" {\n return this._lineJoin;\n }\n\n set lineJoin(value: \"round\" | \"bevel\" | \"miter\") {\n this._lineJoin = value;\n this.calls.push({ kind: \"set\", prop: \"lineJoin\", value });\n }\n\n get lineCap(): \"butt\" | \"round\" | \"square\" {\n return this._lineCap;\n }\n\n set lineCap(value: \"butt\" | \"round\" | \"square\") {\n this._lineCap = value;\n this.calls.push({ kind: \"set\", prop: \"lineCap\", value });\n }\n\n get globalAlpha(): number {\n return this._globalAlpha;\n }\n\n set globalAlpha(value: number) {\n this._globalAlpha = value;\n this.calls.push({ kind: \"set\", prop: \"globalAlpha\", value });\n }\n\n get font(): string {\n return this._font;\n }\n\n set font(value: string) {\n this._font = value;\n this.calls.push({ kind: \"set\", prop: \"font\", value });\n }\n\n get textAlign(): \"start\" | \"center\" | \"end\" | \"left\" | \"right\" {\n return this._textAlign;\n }\n\n set textAlign(value: \"start\" | \"center\" | \"end\" | \"left\" | \"right\") {\n this._textAlign = value;\n this.calls.push({ kind: \"set\", prop: \"textAlign\", value });\n }\n\n get textBaseline(): \"top\" | \"middle\" | \"bottom\" | \"alphabetic\" | \"hanging\" {\n return this._textBaseline;\n }\n\n set textBaseline(value: \"top\" | \"middle\" | \"bottom\" | \"alphabetic\" | \"hanging\") {\n this._textBaseline = value;\n this.calls.push({ kind: \"set\", prop: \"textBaseline\", value });\n }\n}\n\nconst FLOAT_DECIMALS = 4;\n\nfunction roundFloat(n: number): number | string {\n if (!Number.isFinite(n)) return String(n);\n return Number(n.toFixed(FLOAT_DECIMALS));\n}\n\nfunction canonicalise(call: RecordedCall): Record<string, unknown> {\n switch (call.kind) {\n case \"clearRect\":\n case \"fillRect\":\n case \"rect\":\n return {\n kind: call.kind,\n x: roundFloat(call.x),\n y: roundFloat(call.y),\n w: roundFloat(call.w),\n h: roundFloat(call.h),\n };\n case \"moveTo\":\n case \"lineTo\":\n case \"translate\":\n return { kind: call.kind, x: roundFloat(call.x), y: roundFloat(call.y) };\n case \"bezierCurveTo\":\n return {\n kind: call.kind,\n c1x: roundFloat(call.c1x),\n c1y: roundFloat(call.c1y),\n c2x: roundFloat(call.c2x),\n c2y: roundFloat(call.c2y),\n x: roundFloat(call.x),\n y: roundFloat(call.y),\n };\n case \"arc\":\n return {\n kind: call.kind,\n x: roundFloat(call.x),\n y: roundFloat(call.y),\n radius: roundFloat(call.radius),\n start: roundFloat(call.start),\n end: roundFloat(call.end),\n };\n case \"setTransform\":\n return {\n kind: call.kind,\n a: roundFloat(call.a),\n b: roundFloat(call.b),\n c: roundFloat(call.c),\n d: roundFloat(call.d),\n e: roundFloat(call.e),\n f: roundFloat(call.f),\n };\n case \"setLineDash\":\n return { kind: call.kind, segments: call.segments.map((s) => roundFloat(s)) };\n case \"fillText\":\n return {\n kind: call.kind,\n text: call.text,\n x: roundFloat(call.x),\n y: roundFloat(call.y),\n };\n case \"set\": {\n const value = typeof call.value === \"number\" ? roundFloat(call.value) : call.value;\n return { kind: call.kind, prop: call.prop, value };\n }\n case \"beginPath\":\n case \"save\":\n case \"restore\":\n case \"stroke\":\n case \"fill\":\n case \"closePath\":\n case \"clip\":\n return { kind: call.kind };\n }\n}\n\n/**\n * Hash a recorded call log into a stable SHA-256 hex string. Floats are\n * rounded to four decimal places and re-serialised in canonical-key\n * JSON so a microscopic floating-point drift does not re-hash the log.\n * Pass `mock.calls`. Adapters pin their integration render output\n * against a single golden constant with this.\n *\n * @since 1.3\n * @stable\n * @example\n * const ctx = new MockCanvasContext();\n * ctx.clearRect(0, 0, 100, 100);\n * const h = hashCallLog(ctx.calls);\n * // h is a 64-char hex string\n * void h;\n */\nexport function hashCallLog(calls: ReadonlyArray<RecordedCall>): string {\n const payload = calls.map(canonicalise);\n const serialised = JSON.stringify(payload);\n return createHash(\"sha256\").update(serialised).digest(\"hex\");\n}\n"]}
|
|
@@ -22,7 +22,11 @@ export type RenderCtx = {
|
|
|
22
22
|
beginPath(): void;
|
|
23
23
|
moveTo(x: number, y: number): void;
|
|
24
24
|
lineTo(x: number, y: number): void;
|
|
25
|
+
bezierCurveTo(c1x: number, c1y: number, c2x: number, c2y: number, x: number, y: number): void;
|
|
25
26
|
stroke(): void;
|
|
27
|
+
rect(x: number, y: number, w: number, h: number): void;
|
|
28
|
+
clip(): void;
|
|
29
|
+
setTransform(a: number, b: number, c: number, d: number, e: number, f: number): void;
|
|
26
30
|
fillRect(x: number, y: number, w: number, h: number): void;
|
|
27
31
|
fill(): void;
|
|
28
32
|
arc(x: number, y: number, radius: number, start: number, end: number): void;
|
|
@@ -32,6 +36,8 @@ export type RenderCtx = {
|
|
|
32
36
|
strokeStyle: string;
|
|
33
37
|
fillStyle: string;
|
|
34
38
|
lineWidth: number;
|
|
39
|
+
lineJoin: "round" | "bevel" | "miter";
|
|
40
|
+
lineCap: "butt" | "round" | "square";
|
|
35
41
|
globalAlpha: number;
|
|
36
42
|
font: string;
|
|
37
43
|
textAlign: "start" | "center" | "end" | "left" | "right";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderCtx.d.ts","sourceRoot":"","sources":["../../src/canvas/renderCtx.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,SAAS,GAAG;IACpB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5D,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,IAAI,IAAI,IAAI,CAAC;IACb,OAAO,IAAI,IAAI,CAAC;IAChB,SAAS,IAAI,IAAI,CAAC;IAClB,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"renderCtx.d.ts","sourceRoot":"","sources":["../../src/canvas/renderCtx.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,SAAS,GAAG;IACpB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5D,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,IAAI,IAAI,IAAI,CAAC;IACb,OAAO,IAAI,IAAI,CAAC;IAChB,SAAS,IAAI,IAAI,CAAC;IAClB,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAMnC,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9F,MAAM,IAAI,IAAI,CAAC;IAOf,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvD,IAAI,IAAI,IAAI,CAAC;IAKb,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrF,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3D,IAAI,IAAI,IAAI,CAAC;IACb,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5E,SAAS,IAAI,IAAI,CAAC;IAClB,WAAW,CAAC,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IACnD,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnD,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;IACtC,OAAO,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC;IACzD,YAAY,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,GAAG,YAAY,GAAG,SAAS,CAAC;CACxE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderCtx.js","sourceRoot":"","sources":["../../src/canvas/renderCtx.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,+DAA+D","sourcesContent":["// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n\n/**\n * Minimal `CanvasRenderingContext2D` subset the canvas-family sink\n * touches. Declared here (and re-used by {@link import(\"./paintPrimitive\").paintPrimitive}\n * and {@link import(\"./mockContext\").MockCanvasContext}) so production\n * `CanvasRenderingContext2D`, `OffscreenCanvasRenderingContext2D`, and\n * the test `MockCanvasContext` all satisfy one structural type. Moved\n * from the canvas2d adapter's `render/clear.ts` so lightweight-charts /\n * uplot / canvas2d share one painter and one mock.\n *\n * @since 1.3\n * @stable\n * @example\n * declare const ctx: RenderCtx;\n * ctx.clearRect(0, 0, 1, 1);\n * void ctx;\n */\nexport type RenderCtx = {\n clearRect(x: number, y: number, w: number, h: number): void;\n translate(x: number, y: number): void;\n save(): void;\n restore(): void;\n beginPath(): void;\n moveTo(x: number, y: number): void;\n lineTo(x: number, y: number): void;\n stroke(): void;\n fillRect(x: number, y: number, w: number, h: number): void;\n fill(): void;\n arc(x: number, y: number, radius: number, start: number, end: number): void;\n closePath(): void;\n setLineDash(segments: ReadonlyArray<number>): void;\n fillText(text: string, x: number, y: number): void;\n strokeStyle: string;\n fillStyle: string;\n lineWidth: number;\n globalAlpha: number;\n font: string;\n textAlign: \"start\" | \"center\" | \"end\" | \"left\" | \"right\";\n textBaseline: \"top\" | \"middle\" | \"bottom\" | \"alphabetic\" | \"hanging\";\n};\n"]}
|
|
1
|
+
{"version":3,"file":"renderCtx.js","sourceRoot":"","sources":["../../src/canvas/renderCtx.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,+DAA+D","sourcesContent":["// Copyright (c) 2026 Invinite. Licensed under the MIT License.\n// See the LICENSE file in the repo root for full license text.\n\n/**\n * Minimal `CanvasRenderingContext2D` subset the canvas-family sink\n * touches. Declared here (and re-used by {@link import(\"./paintPrimitive\").paintPrimitive}\n * and {@link import(\"./mockContext\").MockCanvasContext}) so production\n * `CanvasRenderingContext2D`, `OffscreenCanvasRenderingContext2D`, and\n * the test `MockCanvasContext` all satisfy one structural type. Moved\n * from the canvas2d adapter's `render/clear.ts` so lightweight-charts /\n * uplot / canvas2d share one painter and one mock.\n *\n * @since 1.3\n * @stable\n * @example\n * declare const ctx: RenderCtx;\n * ctx.clearRect(0, 0, 1, 1);\n * void ctx;\n */\nexport type RenderCtx = {\n clearRect(x: number, y: number, w: number, h: number): void;\n translate(x: number, y: number): void;\n save(): void;\n restore(): void;\n beginPath(): void;\n moveTo(x: number, y: number): void;\n lineTo(x: number, y: number): void;\n // Append a cubic Bézier from the current point to `(x, y)` with control\n // points `(c1x, c1y)` / `(c2x, c2y)`. A self-scaled adapter uses this to\n // stroke a monotone-cubic curve through a plot series' points instead of\n // straight segments, so an MA line reads as a smooth curve at any bar\n // density rather than a faceted polyline.\n bezierCurveTo(c1x: number, c1y: number, c2x: number, c2y: number, x: number, y: number): void;\n stroke(): void;\n // Path-`rect` (adds a rectangle to the current path) + `clip` (intersects\n // the clip region with the current path). Distinct from `fillRect` — these\n // two compose into the standard `beginPath()` → `rect()` → `clip()` idiom\n // an adapter uses to confine a hand-rolled draw pass to a plotting-area\n // box (the uplot candle/hline/drawing overlay clips to uPlot's plot bbox\n // so off-window marks do not spill into the axis gutters).\n rect(x: number, y: number, w: number, h: number): void;\n clip(): void;\n // Replace the current transform with the matrix `[a, b, c, d, e, f]`. A\n // self-scaled canvas adapter uses `setTransform(dpr, 0, 0, dpr, 0, 0)` to\n // draw in CSS-pixel space while backing a HiDPI canvas, so absolute sizes\n // (line widths, fonts) render at the right thickness on retina displays.\n setTransform(a: number, b: number, c: number, d: number, e: number, f: number): void;\n fillRect(x: number, y: number, w: number, h: number): void;\n fill(): void;\n arc(x: number, y: number, radius: number, start: number, end: number): void;\n closePath(): void;\n setLineDash(segments: ReadonlyArray<number>): void;\n fillText(text: string, x: number, y: number): void;\n strokeStyle: string;\n fillStyle: string;\n lineWidth: number;\n lineJoin: \"round\" | \"bevel\" | \"miter\";\n lineCap: \"butt\" | \"round\" | \"square\";\n globalAlpha: number;\n font: string;\n textAlign: \"start\" | \"center\" | \"end\" | \"left\" | \"right\";\n textBaseline: \"top\" | \"middle\" | \"bottom\" | \"alphabetic\" | \"hanging\";\n};\n"]}
|