@grundyjs/algiviz 0.11.1 → 0.11.2
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 +11 -0
- package/dist/canvas/index.d.ts +3 -3
- package/dist/canvas/index.js +18 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.11.2 — 2026-11-05
|
|
4
|
+
|
|
5
|
+
- Avoid argument-count limits when scaling large arrays in the Canvas renderer.
|
|
6
|
+
- Isolate Canvas composite, filter and shadow settings alongside transform/alpha;
|
|
7
|
+
restore caller settings even when drawing throws.
|
|
8
|
+
- Reject invalid frame progress before drawing; preserve the zero-sized bitmap no-op.
|
|
9
|
+
- Require a valid light/dark theme at runtime and allow explicitly undefined colors
|
|
10
|
+
with exactOptionalPropertyTypes. Preserve the createSortRenderer compatibility alias.
|
|
11
|
+
- Document Canvas coordinates, context ownership, scene adaptation, color priority
|
|
12
|
+
and error behavior in English and Russian; add renderer and packed-consumer regressions.
|
|
13
|
+
|
|
3
14
|
## 0.11.1 — 2026-11-05
|
|
4
15
|
|
|
5
16
|
- Validate both numeric positions in array swap/shift before reading or mutating
|
package/dist/canvas/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export type ArrayObjects = {
|
|
|
8
8
|
held: boolean;
|
|
9
9
|
};
|
|
10
10
|
};
|
|
11
|
-
/** Adapts array
|
|
11
|
+
/** Adapts immutable array snapshots; freezes scene wrappers but retains Item references. */
|
|
12
12
|
export declare function arrayScene(state: ArraySnapshot): Scene<ArrayObjects>;
|
|
13
13
|
/** Canvas color strings for the semantic roles in the array renderer. */
|
|
14
14
|
export interface ArrayPalette {
|
|
@@ -25,10 +25,10 @@ export type ArrayPaletteOverrides = {
|
|
|
25
25
|
};
|
|
26
26
|
export interface ArrayRendererOptions {
|
|
27
27
|
readonly theme: "light" | "dark";
|
|
28
|
-
readonly colors?: ArrayPaletteOverrides;
|
|
28
|
+
readonly colors?: ArrayPaletteOverrides | undefined;
|
|
29
29
|
}
|
|
30
30
|
export { createArrayRenderer as createSortRenderer };
|
|
31
|
-
/**
|
|
31
|
+
/** Full-frame bitmap renderer; the caller owns sizing and must provide an unclipped context. */
|
|
32
32
|
export declare function createArrayRenderer(options: ArrayRendererOptions): Readonly<{
|
|
33
33
|
render(ctx: CanvasRenderingContext2D, frame: ArrayFrame): void;
|
|
34
34
|
}>;
|
package/dist/canvas/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createSceneRenderer, createSceneProjector } from "../scene/index.js";
|
|
2
|
-
/** Adapts array
|
|
2
|
+
/** Adapts immutable array snapshots; freezes scene wrappers but retains Item references. */
|
|
3
3
|
export function arrayScene(state) {
|
|
4
4
|
return Object.freeze({
|
|
5
5
|
objects: Object.freeze([...positions(state)].map(([id, data]) => Object.freeze({ id, type: "bar", data: Object.freeze(data) })))
|
|
@@ -34,9 +34,12 @@ function positions(state) {
|
|
|
34
34
|
result.set(state.held.id, { item: state.held, index: state.slots.indexOf(null), held: true });
|
|
35
35
|
return result;
|
|
36
36
|
}
|
|
37
|
-
/**
|
|
37
|
+
/** Full-frame bitmap renderer; the caller owns sizing and must provide an unclipped context. */
|
|
38
38
|
export function createArrayRenderer(options) {
|
|
39
|
-
const
|
|
39
|
+
const theme = options?.theme;
|
|
40
|
+
if (theme !== "light" && theme !== "dark")
|
|
41
|
+
throw new TypeError("Array renderer theme must be light or dark");
|
|
42
|
+
const colors = { ...palettes[theme] };
|
|
40
43
|
for (const key of Object.keys(colors)) {
|
|
41
44
|
const color = options.colors?.[key];
|
|
42
45
|
if (color !== undefined)
|
|
@@ -48,6 +51,9 @@ export function createArrayRenderer(options) {
|
|
|
48
51
|
const { width, height } = ctx.canvas;
|
|
49
52
|
if (width <= 0 || height <= 0)
|
|
50
53
|
return;
|
|
54
|
+
if (!Number.isFinite(frame.progress) || frame.progress < 0 || frame.progress > 1) {
|
|
55
|
+
throw new RangeError("Array frame progress must be between zero and one");
|
|
56
|
+
}
|
|
51
57
|
const projected = projectFrame(frame);
|
|
52
58
|
const items = projected.current.objects;
|
|
53
59
|
const count = frame.current.slots.length;
|
|
@@ -55,7 +61,9 @@ export function createArrayRenderer(options) {
|
|
|
55
61
|
const cell = (width - 2 * margin) / Math.max(count, 1);
|
|
56
62
|
const barWidth = cell * 0.7;
|
|
57
63
|
const available = height * 0.48;
|
|
58
|
-
|
|
64
|
+
let maxMagnitude = 1;
|
|
65
|
+
for (const { data } of items)
|
|
66
|
+
maxMagnitude = Math.max(maxMagnitude, Math.abs(data.item.value));
|
|
59
67
|
const baseline = height * 0.69;
|
|
60
68
|
const fontSize = Math.max(9, Math.min(20, cell * 0.45, width * 0.035));
|
|
61
69
|
const progress = frame.progress;
|
|
@@ -65,6 +73,12 @@ export function createArrayRenderer(options) {
|
|
|
65
73
|
try {
|
|
66
74
|
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
67
75
|
ctx.globalAlpha = 1;
|
|
76
|
+
ctx.globalCompositeOperation = "source-over";
|
|
77
|
+
ctx.filter = "none";
|
|
78
|
+
ctx.shadowColor = "rgba(0, 0, 0, 0)";
|
|
79
|
+
ctx.shadowBlur = 0;
|
|
80
|
+
ctx.shadowOffsetX = 0;
|
|
81
|
+
ctx.shadowOffsetY = 0;
|
|
68
82
|
ctx.fillStyle = colors.background;
|
|
69
83
|
ctx.fillRect(0, 0, width, height);
|
|
70
84
|
ctx.font = `${Math.max(12, Math.min(24, width * 0.045))}px sans-serif`;
|