@grundyjs/algiviz 0.5.1 → 0.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 CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.6.0 — 2026-10-14
4
+
5
+ - Add an application-owned graph BFS example with custom vertices, edges and queue
6
+ entries, shortest distances, disconnected components and both playback modes.
7
+ - Add createStepEmitter to /playback for per-iterator step numbering and frozen
8
+ wrappers; snapshot copying and state/event immutability remain author-owned.
9
+ - Use the helper in graph and merge examples, and document custom graph integration.
10
+
3
11
  ## 0.5.1 — 2026-10-14
4
12
 
5
13
  - Update the README around the current public API and examples; remove migration
package/README.md CHANGED
@@ -5,7 +5,7 @@ algorithm and define your objects; AlgiViz provides array operations, playback,
5
5
  typed scene dispatch and a ready-made Canvas array renderer. No runtime dependencies.
6
6
  Playback works without DOM, React or Next.js. ESM only, with TypeScript declarations.
7
7
 
8
- This README describes version 0.5.1.
8
+ This README describes version 0.6.0.
9
9
 
10
10
  ## Install
11
11
 
@@ -123,6 +123,28 @@ Custom array events or tree/graph operations can use this contract and a custom
123
123
  renderer. The scene API below dispatches individual objects; there is no built-in
124
124
  graph/tree algorithm or operation set.
125
125
 
126
+ ### Step emission helper (since 0.6.0)
127
+
128
+ Version 0.6.0 adds `createStepEmitter` from `/playback`. It removes manual step numbering and freezes the step wrapper:
129
+
130
+ ```js
131
+ import { createStepEmitter } from '@grundyjs/algiviz/playback';
132
+
133
+ function* counter() {
134
+ let count = 0;
135
+ const emit = createStepEmitter(() => Object.freeze({ count }));
136
+ yield emit('start');
137
+ count++;
138
+ yield emit('done');
139
+ }
140
+ ```
141
+
142
+ Create the emitter inside each iterator. Its callback runs once per emission;
143
+ indices start at zero and failed captures do not consume an index. The helper
144
+ does not clone or freeze state/event data, infer terminal events or store history.
145
+ The callback must produce isolated immutable snapshots; immutable shared structures
146
+ can be reused. Returning a mutable workspace directly does not make it a snapshot.
147
+
126
148
  ### User-defined objects and visualizations
127
149
 
128
150
  Define a type map with your own data, then
@@ -311,6 +333,7 @@ included in the npm archive.
311
333
  | [Sorting lab](examples/index.html) | Insertion and bubble sort using the array operations and renderer |
312
334
  | [Merge sort](examples/merge.html) | Custom state and a two-row scene for the main array and buffer |
313
335
  | [Quick sort partitions](examples/quick.html) | Lomuto and three-way partitioning with custom state and scene |
336
+ | [Graph BFS](examples/graph.html) | Cycles, disconnected components, shortest distances and an animated queue |
314
337
  | [Tree traversal](examples/tree.html) | Custom nodes, edges and pointer with Canvas and retained SVG backends |
315
338
 
316
339
  All examples reuse [demo-player.mjs](examples/demo-player.mjs) and
@@ -353,6 +376,18 @@ switches between Canvas and SVG without restarting playback.
353
376
  and removes stale elements even after seeking skips exit transitions.
354
377
  No tree-specific algorithm or renderer is added to the package.
355
378
 
379
+ ### Graph breadth-first search
380
+
381
+ Open [examples/graph.html](examples/graph.html) and choose a start vertex.
382
+ The example explores only its connected component, marks vertices when enqueued
383
+ and shows shortest unweighted distances. Its custom vertex, connection and queue
384
+ entry types are projected from immutable algorithm state. Both playback modes use
385
+ the same generator; changing the start creates a new traversal.
386
+
387
+ See [Building a custom graph example](docs/custom-graph-example.md) for the
388
+ algorithm, projection and renderer boundaries. This example uses the existing
389
+ public APIs and adds no graph-specific package exports.
390
+
356
391
  ## Development
357
392
 
358
393
  Requires Node.js 22 or later and npm.
@@ -392,7 +427,7 @@ candidate commit.
392
427
 
393
428
  The [publish workflow](.github/workflows/npm-publish.yml) runs when a stable GitHub
394
429
  Release is published. Drafts, prereleases and tag pushes alone do not publish.
395
- Use `v` followed by the exact package version, such as `v0.5.1`, at the tested commit.
430
+ Use `v` followed by the exact package version, such as `v0.6.0`, at the tested commit.
396
431
 
397
432
  The workflow uses Node.js 24 and npm 11, checks the version and packed consumer,
398
433
  then publishes with provenance through npm trusted publishing (OIDC).
@@ -2,3 +2,4 @@ export { createPlayer } from "./player.js";
2
2
  export type { Player } from "./player.js";
3
3
  export { createTimeline } from "./timeline.js";
4
4
  export type { Step, Frame, Timeline } from "./types.js";
5
+ export { createStepEmitter } from "./step-emitter.js";
@@ -1,2 +1,3 @@
1
1
  export { createPlayer } from "./player.js";
2
2
  export { createTimeline } from "./timeline.js";
3
+ export { createStepEmitter } from "./step-emitter.js";
@@ -0,0 +1,6 @@
1
+ import type { Step } from "./types.js";
2
+ /**
3
+ * Capture state in a frozen, consecutively indexed step. Use one emitter per iterator.
4
+ * The callback owns snapshot isolation; state and event are not cloned or frozen.
5
+ */
6
+ export declare function createStepEmitter<State>(snapshot: () => State): <Event>(event: Event) => Step<State, Event>;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Capture state in a frozen, consecutively indexed step. Use one emitter per iterator.
3
+ * The callback owns snapshot isolation; state and event are not cloned or frozen.
4
+ */
5
+ export function createStepEmitter(snapshot) {
6
+ let index = 0;
7
+ return (event) => {
8
+ const state = snapshot();
9
+ const step = Object.freeze({ index, state, event });
10
+ index++;
11
+ return step;
12
+ };
13
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grundyjs/algiviz",
3
- "version": "0.5.1",
3
+ "version": "0.6.0",
4
4
  "description": "Deterministic algorithm steps for educational visualizations",
5
5
  "type": "module",
6
6
  "files": [