@grundyjs/algiviz 0.11.0 → 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 +23 -0
- package/README.md +2 -2
- package/dist/array/trace.d.ts +3 -2
- package/dist/array/trace.js +4 -1
- package/dist/canvas/index.d.ts +3 -3
- package/dist/canvas/index.js +18 -4
- package/package.json +1 -1
- package/ru/README.md +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
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
|
+
|
|
14
|
+
## 0.11.1 — 2026-11-05
|
|
15
|
+
|
|
16
|
+
- Validate both numeric positions in array swap/shift before reading or mutating
|
|
17
|
+
the trace, rejecting invalid JavaScript arguments without losing item identities
|
|
18
|
+
or changing snapshots, counters, markers or the next step index.
|
|
19
|
+
- Allow explicitly undefined sorted-region inputs with exactOptionalPropertyTypes,
|
|
20
|
+
matching the existing runtime behavior of preserving the current marker.
|
|
21
|
+
- Document array guarantees in English and Russian: fixed length, one held item,
|
|
22
|
+
trace-local IDs, immutable snapshots, counters and author-supplied sorted markers.
|
|
23
|
+
- Add an application-owned object lifecycle example and expand playback completion,
|
|
24
|
+
strict type and installed-package consumer checks. No new public exports.
|
|
25
|
+
|
|
3
26
|
## 0.11.0 — 2026-11-02
|
|
4
27
|
|
|
5
28
|
- Add createStatePlayer() for lazy playback of plain immutable states without
|
package/README.md
CHANGED
|
@@ -102,8 +102,8 @@ the [local setup instructions](https://github.com/urffin/algiviz/blob/master/doc
|
|
|
102
102
|
- **Scene:** describes objects with stable IDs, types and application-owned data.
|
|
103
103
|
- **Handler:** chooses geometry and drawing behavior, including interpolation.
|
|
104
104
|
|
|
105
|
-
Do not mutate emitted states.
|
|
106
|
-
|
|
105
|
+
Do not mutate emitted states. `createStatePlayer` completes on source exhaustion;
|
|
106
|
+
`createPlayer` requires an explicit terminal step. Call `dispose()` when removing a visualization. Algorithms, layouts and animation
|
|
107
107
|
scheduling belong to the application.
|
|
108
108
|
|
|
109
109
|
## Playback modes
|
package/dist/array/trace.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Item, ArrayStep } from "./types.js";
|
|
2
|
+
/** Omitted or undefined markers preserve their current values. */
|
|
2
3
|
export interface SortedRegions {
|
|
3
|
-
readonly sortedPrefixLength?: number;
|
|
4
|
-
readonly sortedSuffixLength?: number;
|
|
4
|
+
readonly sortedPrefixLength?: number | undefined;
|
|
5
|
+
readonly sortedSuffixLength?: number | undefined;
|
|
5
6
|
}
|
|
6
7
|
export interface ArrayTrace {
|
|
7
8
|
readonly length: number;
|
package/dist/array/trace.js
CHANGED
|
@@ -54,6 +54,8 @@ export function createArrayTrace(values) {
|
|
|
54
54
|
},
|
|
55
55
|
swap(left, right, update) {
|
|
56
56
|
active();
|
|
57
|
+
index(left);
|
|
58
|
+
index(right);
|
|
57
59
|
const a = item(left), b = item(right);
|
|
58
60
|
if (left === right)
|
|
59
61
|
throw new RangeError("Swap requires distinct positions");
|
|
@@ -74,8 +76,9 @@ export function createArrayTrace(values) {
|
|
|
74
76
|
},
|
|
75
77
|
shift(from, to, update) {
|
|
76
78
|
active();
|
|
77
|
-
|
|
79
|
+
index(from);
|
|
78
80
|
index(to);
|
|
81
|
+
const moved = item(from);
|
|
79
82
|
if (slots[to] !== null)
|
|
80
83
|
throw new Error("Shift destination must be empty");
|
|
81
84
|
regions(update);
|
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`;
|
package/package.json
CHANGED
package/ru/README.md
CHANGED
|
@@ -100,7 +100,8 @@ document.querySelector('#next').onclick = () => player.nextStep();
|
|
|
100
100
|
- **Сцена** описывает объекты: стабильный `id`, тип и собственные данные.
|
|
101
101
|
- **Обработчик** выбирает геометрию и способ рисования. Плавность — его решение.
|
|
102
102
|
|
|
103
|
-
Состояния после выдачи нельзя изменять.
|
|
103
|
+
Состояния после выдачи нельзя изменять. `createStatePlayer` завершается при исчерпании
|
|
104
|
+
источника; `createPlayer` требует явного завершающего шага;
|
|
104
105
|
при удалении визуализации вызовите `dispose()`. Алгоритмы, раскладка и цикл
|
|
105
106
|
анимации принадлежат приложению.
|
|
106
107
|
|