canvas/CHANGELOG.md
2026-03-11 18:42:08 -07:00

52 KiB

Changelog

All notable changes to @blinksgg/canvas will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[3.0.0] - 2026-03-11 — "React Compiler"

BREAKING

  • Peer dependencies now require react / react-dom ^19.2.0 (was ^19.0.0)
  • Removed all manual useCallback / useMemo wrappers — React Compiler auto-optimizes

Changed

  • Integrated React Compiler (babel-plugin-react-compiler) into Vitest pipeline
  • Added @vitejs/plugin-react for Babel transform support
  • Removed useCallback from useGestureSystem.ts (4), GestureProvider.tsx (1), useGestureResolver.ts (1)
  • Removed useMemo from useGestureSystem.ts (1), GestureProvider.tsx (1), keyboard.ts (1)
  • Replaced useMemo(() => nextOwnerId++, []) with useState(() => nextOwnerId++) in GestureProvider.tsx

Tests

  • All 761 passing tests remain green — zero regressions

[2.5.0] - 2026-03-11 — "Hook Integration"

Changed

  • Exported easeInOutCubic from useAnimatedLayout.ts for independent testing

Added

  • animated-layout.test.ts — 9 tests: easeInOutCubic boundary values, monotonicity, range
  • useActionExecutor-hook.test.ts — 6 tests: renderHook integration, return shape
  • usePlugin-hook.test.ts — 5 tests: register/unregister lifecycle, re-render stability
  • useLayout-hook.test.ts — 4 tests: useLayout, useGetGraphBounds, useFitToBounds

Tests

  • 24 new tests across 4 new test files (first React hook integration tests)
  • Total passing: 473 across 54 test files

[2.4.0] - 2026-03-11 — "Deep Logic"

Added

  • drag-state-machine.test.ts — 11 tests: buildDragPositions, computeDragUpdates, isDragPrevented
  • action-types-enums.test.ts — 9 tests: ActionCategory enum, BuiltInActionId uniqueness
  • event-types-enums.test.ts — 10 tests: CanvasEventType, EVENT_TYPE_INFO completeness
  • gesture-rules-types.test.ts — 6 tests: GestureDescriptor/Pattern/Rule shapes

Tests

  • 36 new tests across 4 new test files
  • Total passing: 449 across 50 test files

[2.3.0] - 2026-03-11 — "Edge Coverage"

Added

  • actions-node.test.ts — 8 tests: selection + node action registration verification
  • actions-viewport.test.ts — 6 tests: viewport + history action registration
  • modifier-helpers.test.ts — 9 tests: isRepeatBlocked, getSelectedNodeIds, resolveFocusableNodeId, getCurrentSubject
  • pointer-bindings-v2.test.ts — 6 tests: array integrity, unique IDs, pattern types
  • plugin-types.test.ts — 5 tests: PluginError construction, CanvasPlugin interface shape

Tests

  • 34 new tests across 5 new test files
  • Total passing: 413 across 46 test files

[2.2.0] - 2026-03-11 — "Total Coverage"

Changed

  • Split built-in-actions.ts (342L) into actions-node.ts and actions-viewport.ts; original slimmed to 44L barrel

Added

  • keyboard-bindings.test.ts — 6 tests: array integrity, unique IDs, standard shortcuts
  • gesture-classification.test.ts — 3 tests: findNearestNode contract, empty graph
  • viewport-commands.test.ts — 7 tests: command shapes, registration, descriptions
  • serialization-commands.test.ts — 5 tests: export/import shapes, registration
  • store-atoms.test.ts — 13 tests: default values, isCommandActive, currentInput, commandProgress
  • command-executor.test.ts — 4 tests: collectInput rejection, cancelCommand

Tests

  • 38 new tests across 6 new test files
  • Total passing: 379 across 41 test files

[2.1.0] - 2026-03-11 — "Store & Adapter"

Added

  • command-line-store.test.ts — 11 tests covering open/close, search, select command, provide/skip/goBack input, error state
  • storage-adapter.test.ts — 10 tests covering InMemoryStorageAdapter CRUD for nodes/edges, batch ops, error handling

Tests

  • 21 new tests across 2 new test files
  • Total passing: 341 across 35 test files

[2.0.0] - 2026-03-11 — "Clean Architecture"

⚠ BREAKING CHANGES

  • Removed deprecated re-exports addEdgeToLocalGraphAtom and removeEdgeFromLocalGraphAtom from graph-mutations.ts — import from graph-mutations-edges instead
  • Renamed gesturesV2gestures namespace export in main barrel

Changed

  • CANVAS_VERSION bumped to '2.0.0'
  • Updated 4 source files and 16 test files to import edge atoms from graph-mutations-edges

Added

  • action-executor.test.ts — 8 tests covering createActionContext, createActionContextFromTouchEvent
  • settings-store.test.ts — 12 tests covering default state, setEventMapping, resetSettings, togglePanel, virtualization, hasUnsavedChanges

Tests

  • 20 new tests across 2 new test files
  • Total passing: 320 across 33 test files

[1.98.0] - 2026-03-11 — "Commands & Dispatch"

Added

  • dispatcher.test.ts — 10 tests covering registerAction/unregisterAction, dispatch simple and phase handlers, none action
  • clipboard-commands.test.ts — 10 tests covering copy/cut/paste/duplicate/deleteSelected definitions and registration
  • group-commands.test.ts — 10 tests covering group/ungroup/collapse/expand definitions and registration

Tests

  • 30 new tests across 3 new test files
  • Total passing: 300 across 31 test files

[1.95.0] - 2026-03-11 — "Final Polish"

Added

  • port-types.test.ts — 16 tests covering calculatePortPosition, getNodePorts, canPortAcceptConnection, arePortsCompatible
  • command-registry.test.ts — 11 tests covering register/unregister, get/has, search, aliases, sorting
  • keyboard-contexts.test.ts — 7 tests covering unique IDs, priorities, arrow key and nudge bindings
  • canvas-styles.test.ts — 7 tests covering theme structure, mergeWithDefaults, light/dark differences

Tests

  • 44 new tests across 4 new test files
  • Total passing: 270 across 28 test files

[1.9.0] - 2026-03-11 — "Derived & Types"

Added

  • event-types.ts — CanvasEventType enum, EventTypeInfo, EVENT_TYPE_INFO lookup
  • action-types.ts — ActionCategory enum, BuiltInActionId, ActionContext, ActionHelpers, ActionDefinition
  • settings-state-types.ts — EventActionMapping, SettingsPreset, CanvasSettingsState, DEFAULT_MAPPINGS
  • graph-derived-atoms.test.ts — 8 tests covering highestZIndex, nodeKeys, edgeKeys, reactivity
  • settings-types.test.ts — 10 tests covering enum integrity, EVENT_TYPE_INFO coverage, action ID uniqueness
  • canvas-serializer-validation.test.ts — 7 tests covering missing fields, wrong version, invalid nodes
  • viewport-store-actions.test.ts — 8 tests covering zoom/pan defaults, reset, coordinate transforms

Changed

  • settings-types.ts — re-export barrel (419→~40L)

Tests

  • 33 new tests across 4 new test files
  • Total passing: 226 across 24 test files

[1.8.0] - 2026-03-11 — "Pipeline Polish"

Added

  • gesture-provider-utils.ts — isEditableTarget, setHeldKeyValue, applyHeldKeyDelta, getCurrentSubject, getSubjectPosition, buildGuardContext
  • gesture-provider-utils.test.ts — 13 tests covering DOM detection, held-key immutability, key delta application
  • timed-state-runner.test.ts — 8 tests covering state transitions, tap, double-tap, long-press, cancel, destroy
  • contexts.test.ts — 5 tests covering PALM_REJECTION and ACTIVE_INTERACTION context priorities and integrity
  • command-store.test.ts — 5 tests covering open/close command line, phase transitions

Changed

  • GestureProvider.tsx — delegates to gesture-provider-utils (347→~215L)

Tests

  • 31 new tests across 4 new test files
  • Total passing: 193 across 20 test files

[1.7.0] - 2026-03-11 — "Gesture Refine"

Added

  • keyboard-bindings.ts — 24 keyboard shortcut bindings extracted from DEFAULT_CONTEXT
  • pointer-bindings.ts — 22 pointer/touch gesture bindings extracted from DEFAULT_CONTEXT
  • minimap-utils.ts — computeGraphBounds, getMinimapTransform, minimapToWorld
  • pointer-contexts.test.ts — 12 tests covering binding integrity, no duplicate IDs, pick mode contexts
  • minimap-utils.test.ts — 8 tests covering bounds calculation, transform, world conversion
  • canvas-serializer-roundtrip.test.ts — 9 tests covering export/import round-trip, viewport, offset, validation

Changed

  • pointer-contexts.ts — assembles DEFAULT_CONTEXT from imported arrays (346→~120L)
  • Minimap.tsx — delegates to minimap-utils (310→~278L)

Tests

  • 30 new tests across 3 new test files
  • Total passing: 162 across 16 test files

[1.6.0] - 2026-03-11 — "Hook Coverage"

Added

  • useCanvasGraph.test.ts — 6 tests covering nodeKeys, edgeKeys, getNodeAttributes
  • useCanvasSelection.test.ts — 8 tests covering select, deselect, toggle, add, remove, edge selection
  • useCanvasViewport.test.ts — 7 tests covering zoom, pan, viewportRect, constants
  • useCanvasHistory.test.ts — 6 tests covering recordSnapshot, undo, redo, clear, labels
  • useVirtualization.test.ts — 5 tests covering metrics, enable/disable/toggle
  • useCanvasSettings.test.ts — 8 tests covering mappings, presets, panel toggle, reset
  • plugin-registry.test.ts — 12 tests covering register/unregister, dependencies, conflicts, lifecycle
  • useDragStateMachine.ts — buildDragPositions, computeDragUpdates, isDragPrevented
  • useDragConstraints.ts — snapToGrid, clampToBounds, applyDragConstraints
  • modifier-helpers.ts — isRepeatBlocked, getSelectedNodeIds, getCurrentSubject, updateKeySubject
  • gesture-classification.ts — findNearestNode, cycleFocus, navigateFocus, activateFocusedNode

Changed

  • useNodeDrag.ts — delegates to useDragStateMachine helpers (367→~310L)
  • input-action-helpers.ts — delegates to modifier-helpers + gesture-classification (374→~210L)

Tests

  • 52 new tests across 7 new test files
  • Total passing: 132 across 13 test files

[1.5.0] - 2026-03-11 — "Test & Harden"

Added

  • graph-mutations.test.ts — 10 tests covering addNode, deleteNode, deleteEdge, loadGraphFromDb, drag lifecycle
  • clipboard-store.test.ts — 10 tests covering copy, cut, paste, duplicate, edge remapping, guards
  • group-store.test.ts — 12 tests covering collapse/expand, parent/child, circular guard, moveToGroup
  • history-store.test.ts — 10 tests covering push, undo, redo, clear, labels, edge cases
  • built-in-actions.test.ts — 14 tests covering registration, all 18 handler delegations, guards
  • ContextMenuAction — standalone touch-friendly action row component
  • ContextMenuDivider — section header/separator component
  • ComboboxOption — option row with icon, label, description, highlight
  • ComboboxSearch — search input with ARIA combobox role
  • EdgePath — drag handle visual indicator (44px touch target)
  • EdgeLabel — inline edge label positioning component

Changed

  • NodeContextMenu.tsx — delegates to ContextMenuAction + ContextMenuDivider (367→~310L)
  • NodeTypeCombobox.tsx — delegates to ComboboxOption + ComboboxSearch (374→~310L)
  • EdgeOverlay.tsx — delegates handle to EdgePath (349→~310L)

Tests

  • 57 new tests across 5 new test files
  • Total passing: 97 across 8 test files

[1.4.0] - 2026-03-11 — "Stable DB"

Added

  • Adapter conformance test harnessrunAdapterConformanceTests(name, factory) validates any CanvasStorageAdapter implementation against the full CRUD + batch contract (15 tests)
  • Batch operations — optional createNodes, deleteNodes, createEdges, deleteEdges on CanvasStorageAdapter with sequential fallback in InMemoryStorageAdapter
  • PortHandle — standalone port handle component with drag, hover, and compatibility highlighting
  • SettingsPresets — preset management component (apply, save-as, delete, reset)
  • SettingsEventMap — event-to-action mapping table component
  • CollectorInputPhase — progress/prompt display for command input collection
  • CollectorSelectInput / CollectorBooleanInput — extracted select option and boolean input components with shared ShortcutButton

Changed

  • @blinksgg/canvas/db — promoted from Beta → Stable
  • NodePorts.tsx — refactored from 406L → ~110L, delegates to PortBar + PortHandle
  • CommandInputCollector.tsx — refactored from 397L → ~165L, delegates to CollectorInputPhase + CollectorSelectInput
  • SettingsPanel.tsx — refactored from 392L → ~125L, delegates to SettingsPresets + SettingsEventMap
  • storage-adapter.test.ts — refactored to use conformance harness; retains only atom-level tests

Tests

  • adapter-conformance.test.ts — 14 CRUD + 2 batch tests against InMemoryStorageAdapter
  • storage-adapter.test.ts — 3 atom integration tests

[1.3.0] - 2026-03-11 — "Serialize"

Added

  • Canvas serializationexportGraph(store) / importGraph(store, snapshot) for full JSON snapshots of nodes, edges, positions, groups, and viewport state
  • CanvasSnapshot type — portable JSON schema (version 1) with SerializedNode, SerializedEdge, SerializedGroup, viewport, and metadata fields
  • validateSnapshot(data) — runtime schema validation with detailed error reporting
  • Import optionsclearExisting (default true), offsetPosition for paste-at-cursor, remapIds for UUID regeneration to avoid conflicts
  • Headless API integrationexportSnapshot(), importSnapshot(), validateSnapshot() on CanvasAPI
  • Built-in commandsexportCanvas (alias: export) copies graph JSON to clipboard; importCanvas (alias: import) reads, validates, and loads from clipboard
  • createWheelHandler(config) — extracted wheel zoom logic into a standalone, testable pure function
  • createPinchHandlers(config) — extracted pinch zoom logic (simultaneous pan, velocity sampling, inertia) into a standalone, testable pure function

Changed

  • useCanvasGestures.ts — refactored from 518 lines to ~370 lines by delegating wheel and pinch zoom to extracted modules
  • gestures/index.ts — exports createWheelHandler, WheelZoomConfig, createPinchHandlers, PinchZoomConfig
  • builtins/index.ts — registers serialization-commands alongside existing built-in command sets

Tests

  • canvas-serializer.test.ts — 18 tests: export (7), import (8), round-trip (1), validation (9)
  • useWheelZoom.test.ts — 7 tests: zoom in/out, min/max clamp, guard conditions
  • usePinchZoom.test.ts — 5 tests: start/update/end lifecycle, disabled state

[1.2.0] - 2026-03-10 — "Plugin API"

Added

  • Plugin system — unified CanvasPlugin interface bundles node types, commands, actions, gesture contexts, and edge path calculators into a single declarative manifest
  • plugin-types.tsCanvasPlugin, PluginContext, PluginRegistration, PluginError class with typed error codes (ALREADY_REGISTERED, NOT_FOUND, MISSING_DEPENDENCY, CONFLICT, LIFECYCLE_ERROR)
  • plugin-registry.tsregisterPlugin() / unregisterPlugin() with dependency resolution, cross-plugin conflict detection, atomic registration with rollback, and lifecycle hooks (onRegister → cleanup)
  • edge-path-registry.ts — extensible custom edge path calculator registry; plugins can register new edge path types beyond the 8 built-ins
  • usePlugin() / usePlugins() hooks — React integration for plugin lifecycle (register on mount, unregister on unmount, dependency-order cleanup)
  • unregisterNodeType() — per-type removal for clean plugin teardown
  • 2 new test suitesplugin-registry (28 tests), edge-path-registry (8 tests)
    • Registration, duplicate detection, dependency resolution, conflict detection across all subsystems
    • Atomic rollback on lifecycle error, cleanup verification, query functions
    • Custom edge path precedence over built-ins, clear/unregister behavior

Changed

  • Canvas.renderNode is now optional — when omitted, the node type registry auto-resolves components by node.dbData.node_type, including those registered by plugins. Falls back to FallbackNodeTypeComponent for unknown types.
  • Barrel exports updated — plugin types, registry, hooks, and edge path registry all exported from core/, hooks/, and utils/ entry points

[1.1.0] - 2026-03-10 — "Gesture Modular"

Changed

  • Split useRegisterInputActions.ts (528L → 259L): extracted input-action-helpers.ts (~370L) with all pure store helper functions (navigation, selection, mutation, escape logic)
  • Split useCanvasGestures.ts (667L → 518L): extracted useGuardContext.ts (~70L) and useInertia.ts (~170L)
  • 3 new modules — all exported from @blinksgg/canvas/gestures:
    • input-action-helpers.tsfindNearestNode, cycleFocus, nudgeSelection, deleteSelection, escapeInput, etc.
    • useGuardContext.ts — guard context atom reads + stable ref for gesture callbacks
    • useInertia.ts — pan/zoom inertia engines, velocity samplers, pinch tracking

Added

  • 2 new test suitesinput-action-helpers (28 tests), useInertia (5 tests)
    • Navigation: findNearestNode in all 4 directions, axis preference, fallback behavior
    • Focus: cycleFocus forward/backward, activateFocusedNode
    • Mutations: nudgeSelection, deleteSelection, selectAll
    • Guards: isRepeatBlocked, getCurrentSubject, clearSelectionState
    • Zoom: snapZoom threshold behavior, constant validation

Fixed

  • WeakMap for module-level caches_prevUiNodes, _edgeCache, _positionCache now use WeakMap<object, ...> keyed by Graph instance, preventing cross-store contamination in multi-Canvas setups
  • clearAllPendingMutations() on graph switch — mutation queue is now cleared when switching graphs, preventing stale inFlight flags from blocking new mutations
  • hasPendingMutations() checks queuedUiProperties — was only checking queuedPosition, missing queued UI property updates
  • collectInput rejects immediately — was returning a never-resolving Promise, now throws with a descriptive error message
  • startMutation() count includes descendants — was only counting selected nodes, not their group descendants, causing imbalanced completeMutation() calls
  • Timed-state config threadingonUp now receives config parameter and uses config.multiTapWindowMs instead of hardcoded default
  • localStorage key namespaced'canvas-settings''@blinksgg/canvas/settings' to prevent cross-application collisions
  • Singleton keyboard routing documentedGestureProvider.tsx now has a comment explaining the intentional global activeOwnerId pattern

[1.0.0] - 2026-03-10 — "Stable Canvas"

First stable release. All APIs are now covered by semver guarantees.

Added

  • API stability documentdocs/api-stability.md classifying all exports as Stable, Beta, or Experimental
  • Migration guidedocs/migration-v1.md covering v0.x → v1.0 breaking changes
  • 3 new hook test suitesuseNodeDrag-atoms, useNodeResize-atoms, useForceLayout-atoms
  • peerDependenciesMeta — d3-force, @tanstack/react-query, @blocknote/* marked as optional

Changed

  • Version bump — 0.36.0 → 1.0.0
  • onAction callback type — Now accepts InputEvent (pointer + keyboard union) instead of GestureEvent (pointer only). Use event.kind === 'key' guard to narrow.

Highlights

  • 72+ test suites, 219+ exported atoms, zero TODO/FIXME comments
  • 8 entry points: root, core, hooks, components, commands, gestures, db, utils
  • React 19 native with React Compiler auto-memoization
  • Touch-first gesture pipeline with specificity-scored binding resolution
  • Local-first with optional Supabase sync via storage adapter
  • Full headless API for programmatic control without React

[0.36.0] - 2026-03-09 — "Gesture Pipeline"

Changed

  • Split contexts.ts (614L → 100L): extracted keyboard-contexts.ts (~200L) + pointer-contexts.ts (~280L)

Added

  • 3 new test suitesgesture-specificity (12), gesture-mapper (10), gesture-dispatcher (10)
    • Specificity scoring: type/subject/source/modifier/button/key matching
    • Mapper: context indexing, priority resolution, consumeInput, guards
    • Dispatcher: handler registry, phase routing, none/unknown handling

[0.35.0] - 2026-03-09 — "Gesture Polish"

Added

  • 3 new test suitesgesture-inertia (12), timed-state (10), gesture-normalize (4)
    • VelocitySampler, PanInertia, ZoomInertia fully tested
    • Timed state machine: tap/double-tap/triple-tap/long-press/cancel
    • Modifier extraction from pointer events

[0.34.0] - 2026-03-09 — "Layout Hooks"

Changed

  • Split useNodeDrag.ts — extracted DragMemo + UseNodeDragOptions into hooks/drag-types.ts (~32L)

Added

  • 2 new test suitesgesture-rules-defaults (8), keyboard-shortcuts (5)

[0.33.0] - 2026-03-09 — "Settings & Config"

Changed

  • Split settings-store.ts — extracted presets + utility into settings-presets.ts (~85L)

Added

  • 1 new test suitesettings-presets (9 tests: preset config, uniqueness, event coverage, utility)

[0.32.0] - 2026-03-09 — "Core Stores"

Changed

  • Split history-store.ts — extracted pure delta functions into history-actions.ts (~160L):
    • applyDelta, invertDelta, createSnapshot now exported standalone

Added

  • 2 new test suiteshistory-actions (14), group-store-utils (7)

[0.31.0] - 2026-03-09 — "Command System"

Changed

  • Split commands/store.ts (343L) into 2 modules:
    • store-atoms.ts — core state + derived atoms (~95L)
    • store.ts — action atoms + helpers (~260L)

Added

  • 3 new test suitescommands-registry (13), commands-executor (3), commands-store (15)
    • Total: 670 tests across 54 files

[0.30.0] - 2026-03-09 — "Gesture Engine"

Changed

  • Split gesture-rules.ts (473L) into 3 focused modules:
    • gesture-rules.ts — scoring, resolver, index (~200L)
    • gesture-rules-types.ts — all type definitions (~117L)
    • gesture-rules-defaults.ts — default rules, labels, merge (~190L)

Added

  • 3 new test suitessync-store (14), gesture-rule-store (12), gesture-configs (6)
    • Total: 639 tests across 51 files

[0.29.0] - 2026-03-09 — "Registry Split"

Changed

  • Split action-registry.ts (449L) into 2 modules:
    • action-registry.ts — registry CRUD + utilities (~120L)
    • built-in-actions.ts — all 20+ built-in action definitions (~340L)

Added

  • 4 new test suitesgraph-mutations-edges (10), graph-mutations-advanced (8), debug (8), component-registry (6)
    • Total: 607 tests across 48 files

[0.28.0] - 2026-03-09 — "Modular Mutations"

Changed

  • Split graph-mutations.ts (524L) into 3 focused modules:
    • graph-mutations.ts — node CRUD, drag lifecycle, DB sync
    • graph-mutations-edges.ts — edge CRUD, animation, label editing
    • graph-mutations-advanced.ts — split/merge nodes, drop target

Added

  • 4 new test suiteslayout (11), hit-test (4), action-executor (8), mutation-queue (7)
    • Total: 575 tests across 44 files

[0.27.0] - 2026-03-09 — "Deep Test"

Added

  • 4 new test suitessettings-store (12), edge-path-calculators (12), snap-store (16), locked-node-store (10)
    • Total: 542 tests across 40 files
  • history-types.ts — extracted HistoryDelta, HistoryEntry, HistoryState, GraphSnapshot from history-store.ts

[0.26.0] - 2026-03-09 — "Improve Core"

Added

  • Minimap edge drawing — edges render as thin lines between node centers; new edgeColor prop
  • Fuzzy multi-token search — split query by whitespace, all tokens must match (order-independent); exported fuzzyMatch helper
  • Edge search — search now matches edge labels and types; searchEdgeResultsAtom, searchEdgeResultCountAtom, searchTotalResultCountAtom
  • Smart alignment guides — node-to-node edge/center snapping; findAlignmentGuides, alignmentGuidesAtom, AlignmentGuides component
  • 2 new test suitesalignment-guides.test.ts (8 tests), 7 fuzzy tests added to search-store.test.ts
    • Total: 489 tests across 36 files

Changed

  • Clipboard cutcutToClipboardAtom now actually deletes selected nodes (with undo support via pushHistoryAtom)
  • Edge search dimmingEdgeRenderer keeps matched edges visible during search (checks searchEdgeResultsAtom)

[0.25.0] - 2026-03-09 — "Test & Harden"

Added

  • 8 new test suites (65 tests) — graph-mutations, graph-derived, graph-position, action-registry, interaction-store, reduced-motion-store, external-keyboard-store, toast-store
    • Total: 474 tests across 35 files

Changed

  • Split TouchActionButton — 559-line monolith → 3 files: icons.tsx (7 SVGs), RadialMenu.tsx (layout + items), index.tsx (orchestrator)

[0.24.0] - 2026-03-09 — "iPad First"

Added

  • prefers-reduced-motion support — new prefersReducedMotionAtom + watchReducedMotionAtom; pan/zoom inertia, animated layouts, and edge fade animations respect the OS setting
  • CSS prefers-reduced-motion — all canvas keyframe animations (search pulse, drop target, edge enter/exit, tap pulse) disabled when active
  • Undo/redo in TouchActionButton — primary FAB actions on touch devices (with UndoIcon / RedoIcon)
  • External keyboard detectionhasExternalKeyboardAtom; hides TouchActionButton when modifier keys are available
  • Cursor hiding on touch@media (pointer: coarse) resets all cursors to default via data-canvas-root
  • data-canvas-root attribute on Viewport for CSS targeting

Changed

  • Safe-area marginsViewportControls and TouchActionButton use max(16px, env(safe-area-inset-*)) instead of hardcoded 16px

[0.23.0] - 2026-03-09 — "Clean Barrel"

Changed

  • Slimmed core/index.ts barrel — 458 → 85 lines (replaced 33 named export blocks with export *)
  • Renamed CanvasToast interface → CanvasToastData to resolve name collision with CanvasToast component

Removed

  • findPortAtPosition (deprecated in v0.20) — use hitTestPort from utils/hit-test
  • resolveGestureIntent / isBackgroundGesture (deprecated in v0.14) — use resolveGestureIndexed from gesture-rules
  • gesture-resolver.test.ts — tests for removed functions
  • All @deprecated markers cleared from production code

[0.22.0] - 2026-03-09 — "Modular Core"

Changed

  • Split graph-store.ts (914 → 68 lines) into 4 focused modules:
    • graph-store.ts — core atoms (graphAtom, graphUpdateVersionAtom, drag/edge creation state)
    • graph-position.ts — position management (nodePositionAtomFamily, updateNodePositionAtom, cleanup)
    • graph-derived.ts — read-only UI state (uiNodesAtom, nodeFamilyAtom, edgeFamilyAtom)
    • graph-mutations.ts — write atoms (CRUD, split/merge, edge animations, DB sync)
  • Zero public API changes — all exports still available from core/index.ts barrel
  • Rewrote 51 import sites (25 production, 24 test, 2 dynamic)

[0.21.0] - 2026-03-09 — "Debug"

Changed

  • Unified logging — migrated all 33 raw console.* calls to createDebug with debug package namespaces
  • createDebug extended — now returns debug(), .warn(), .error() sub-loggers
    • .warn() and .error() are always enabled (bypass DEBUG filter)
    • .warn() routes to console.warn, .error() to console.error
    • Enable verbose logging: localStorage.debug = 'canvas:*'

Files migrated

  • useForceLayout.ts (9 calls), db/queries/nodes.ts (5), db/queries/edges.ts (4)
  • action-executor.ts (6), settings-store.ts (3), history-store.ts (2)
  • NodeErrorBoundary.tsx (1), NodeTypeCombobox.tsx (1), useAnimatedLayout.ts (1), NoteNode.tsx (2)

[0.20.1] - 2026-03-09

Added

  • hitTestNode / hitTestPort — testable hit-test utilities replacing 5 direct document.elementFromPoint calls
  • setHitTestProvider — swap DOM hit-testing for mocks in tests or SSR

Changed

  • findPortAtPosition deprecated — delegates to hitTestPort

[0.20.0] - 2026-03-09 — "Maintain"

Fixed

  • atomFamily deprecation — migrated from deprecated jotai/utils to jotai-family package (prepares for jotai v3, eliminates deprecation warnings)
  • Corrupt graphology install — force-reinstalled pnpm store to fix missing dist files

Removed

  • Dead CanvasConfig type — stale interface with supabaseUrl/supabaseAnonKey fields (unused, unexported)

[0.17.0] - 2026-03-09 — "Connect"

Added

  • EdgePreviewLine — animated SVG bezier preview during edge creation (dashed line with color states for idle/valid/snapped)
  • Drag-from-port — click a port in NodePorts to initiate edge creation (previously only available via EdgeOverlay handle)
  • Port snap visual — port dots scale up (1.3x) and glow when a drag is hovering over a compatible port
  • canConnect validation — new callback prop on EdgeOverlay to reject invalid connections before edge creation

Changed

  • EdgeOverlayProps — added optional canConnect callback
  • NodePorts / PortBar — port elements now have onPointerDown for drag initiation

[0.16.0] - 2026-03-09 — "Harden"

Removed (breaking)

  • resolveGestureIntent — removed from public API; use resolveGestureIndexed from gesture-rules instead
  • isBackgroundGesture — removed from public API
  • nodeGestureConfig / viewportGestureConfig — removed deprecated constants; use getNodeGestureConfig(source) / getViewportGestureConfig(source) functions
  • useSupabaseClient / supabaseClientAtom — removed from public API; use useStorageAdapter() instead
  • Legacy Supabase propsCanvasDbProvider and CanvasProvider no longer accept supabaseUrl / supabaseAnonKey; pass an adapter prop instead

Changed

  • CanvasProviderProps.adapter — now required (was optional)
  • CanvasDbProviderProps — simplified to single interface (was discriminated union)
  • utils/index.ts — exports getNodeGestureConfig / getViewportGestureConfig functions instead of deprecated constants
  • README.md — refreshed with v0.14 Gesture System v2 and v0.15 Performance sections; updated architecture diagram and state management table

[0.15.0] - 2026-03-07 — "Perform"

Added

  • Spatial grid indexSpatialGrid class with fixed-cell bucketing for O(visible) viewport culling; replaces O(N) linear scan in visibleNodeKeysAtom
  • spatialIndexAtom — Jotai atom rebuilding the grid on graph structure and position changes
  • Performance instrumentationcanvasMark / canvasWrap helpers with performance.mark/performance.measure; opt-in via setPerfEnabled(true) or window.__canvasPerf?.(true)
  • perfEnabledAtom — Jotai atom for perf toggle; setPerfEnabled imperative API
  • Gestures subpath export@blinksgg/canvas/gestures for code-splitting the gesture pipeline
  • 17 new tests covering SpatialGrid (12) and perf instrumentation (5)

Changed

  • edgeFamilyAtom — structural equality cache (_edgeCache) prevents re-renders when source/target positions and attributes haven't changed
  • uiNodesAtom — structural equality check: returns previous array reference when all entries match by id, position, and isDragging
  • updateNodePositionAtom — wrapped with canvasMark('drag-frame') for profiling the drag hot path
  • visibleNodeKeysAtom — uses SpatialGrid.query() + canvasMark('virtualization-cull') instead of linear Array.filter
  • virtualization-store — removed standalone isNodeVisible function in favor of spatial grid AABB intersection

[0.14.0] - 2026-03-07 — "Unify"

Added

  • Gesture System v2 — unified pointer + keyboard input pipeline with 4-layer architecture: Normalize → Recognize → Resolve → Dispatch
  • Specificity-scored binding resolution — patterns scored by type (128), key (64), subjectKind (32), modifier (16/8), source (4), button (2); highest score wins across priority-sorted context stack
  • Keyboard as parallel input streamKeyInputEvent type shares resolver and dispatcher with PointerGestureEvent via InputEvent union; InputPattern matches both kinds
  • Built-in mapping contextsPALM_REJECTION_CONTEXT (pri 0), ACTIVE_INTERACTION_CONTEXT (pri 15), SEARCH_CONTEXT (pri 25), KEYBOARD_MANIPULATE_CONTEXT (pri 30), KEYBOARD_NAVIGATE_CONTEXT (pri 40), DEFAULT_CONTEXT (pri 100)
  • Held keysHeldKeysState tracks pressed keyboard keys; pointer events carry heldKeys for patterns like Space+drag → pan
  • Custom modifiersModifiers.custom?: Record<string, boolean> for non-keyboard flags (iPad toolbar buttons, stylus buttons); scored identically to standard modifiers
  • Phase-aware action handlersPhaseHandler interface routes onStart/onMove/onEnd/onInstant/onCancel for pointer and onDown/onUp for keyboard; simple function handlers fire on start/instant/down
  • consumeInput flag — bindings can block lower-priority contexts from matching the same event
  • useGestureSystem hook — manages context stack, palm rejection toggle, held key state; produces pre-built MappingIndex for O(1) event bucketing
  • useCanvasGestures hook — wires pointer events from a viewport ref through the full pipeline with inertia support
  • useNodeGestures hook — per-node pointer event handlers feeding the pipeline with { kind: 'node', nodeId } subject
  • useRegisterInputActions hook — registers all built-in action handlers (selection, viewport, clipboard, history, layout, navigation, search)
  • useInputModeGestureContext hook — auto-pushes/removes input mode contexts (pickNode, pickNodes, pickPoint)
  • GestureProvider / InputProvider — React context provider wrapping the gesture system for tree-wide access
  • Keyboard shortcuts in gesture pipeline/ (command line), Escape, Delete/Backspace, Ctrl/Cmd+C/X/V/D/A/Z/Y/F/M all routed through binding resolution instead of ad-hoc key handlers
  • Keyboard navigate mode — Arrow keys move focus, Enter enters manipulate mode, Space activates, Tab cycles nodes
  • Keyboard manipulate mode — Arrow keys nudge selected nodes (Shift = large nudge), Escape exits
  • Search keyboard bindingsEnter/Shift+Enter and Ctrl/Cmd+G cycle search results within gesture pipeline
  • SplitNode, GroupNodes, MergeNodes — added to BuiltInActionId enum; registered as proper pipeline actions with ActionHelpers callbacks
  • Pan inertiaPanInertia class with friction-based deceleration after drag release
  • Timed state machineTimedStateRunner for tap counting, long-press detection, double/triple-tap recognition with configurable thresholds
  • Interactive demoGestureV2Demo with Binding Composer (pointer/keyboard), Event Composer (pointer/keyboard), held key simulation, real-time event log with input kind badges
  • Architecture docspackages/canvas/docs/arch-gesture-system-v2.md, plan-gesture-system-v2.md, plan-keyboard-gesture-integration.md
  • 5 new test suites — specificity (16 tests), mapper (12), timed-state (8), palm-rejection (5), inertia (4)

Changed

  • keyboard.ts — shortcut handling simplified; most key bindings moved to gesture pipeline contexts
  • Viewport.tsx — gesture intent resolution delegated to v2 pipeline when available
  • Node.tsx — pointer events can route through useNodeGestures pipeline
  • settings-types.tsActionContext gains optional selectedNodeIds; ActionHelpers gains optional splitNode, groupNodes, mergeNodes
  • interaction-store.ts — added KeyboardInteractionMode type ('navigate' | 'manipulate') and keyboardInteractionModeAtom
  • selection-path-store.ts — exported isSelectingAtom for guard context access

[0.13.0] - 2026-03-05 — "Refine"

Added

  • Undo/redo for structural operationssplitNodeAtom, mergeNodesAtom, nestNodesOnDropAtom, groupSelectedNodesAtom, ungroupNodesAtom now push history snapshots with descriptive labels; all fully undoable
  • Undo/redo toast feedbackcanvasToastAtom, showToastAtom in toast-store.ts; CanvasToast overlay component shows "Undo: {label}" / "Redo: {label}" for 2 seconds after Ctrl+Z/Y
  • Tree layoutuseTreeLayout hook: BFS depth assignment, root detection, top-down/left-right direction; treeLayout and horizontalLayout commands
  • Grid layoutuseGridLayout hook: spatial-order-preserving grid with auto column count; gridLayout command
  • Animated layout transitionsuseAnimatedLayout shared hook: RAF loop with cubic easing, history snapshot before animation, persistence callback
  • Zoom inertia — pinch-to-zoom continues with momentum after fingers lift (friction=0.88, velocity tracking)
  • Snap-to-100% zoom detent — zoom snaps to 1.0 when within 0.03 threshold (both wheel and pinch)
  • Simultaneous pan during pinch — tracks finger midpoint movement frame-to-frame for fluid two-finger gestures
  • Tap pulse animationcanvas-tap-pulse CSS keyframe on ViewportControls buttons for tactile feedback
  • 19 new tests (404 total) covering undo for split/merge/nest/group/ungroup, tree layout algorithm, grid layout algorithm

Changed

  • CommandProvider — wires useTreeLayout and useGridLayout into CommandContext.layout
  • useCanvasHistory — shows toast with operation label on undo/redo
  • Viewport — zoom inertia loop, snap-to-100% in onWheel/onPinch, simultaneous pan tracking in onPinch
  • ViewportControls — ControlButton applies canvas-tap-pulse class on click
  • CanvasAnimations — added canvas-tap-pulse keyframe

[0.12.0] - 2026-03-05 — "Reshape"

Added

  • Drag-to-nest — drag a node over another to nest it as a child; visual drop-target highlight with pulsing blue outline; dropTargetNodeIdAtom, nestNodesOnDropAtom
  • Two-finger split — two fingers diverging on a node (80px threshold) splits it into two copies with all edges duplicated; splitNodeAtom, useSplitGesture hook
  • Merge nodesCtrl+M or command palette merges 2+ selected nodes; edges re-routed to survivor, internal edges discarded; mergeNodesAtom, mergeNodesCommand
  • split-node gesture intent — added to GestureIntent type; pinch-on-node now maps to split-node instead of zoom
  • .canvas-drop-target CSS — pulsing blue outline animation for drop target feedback
  • 18 new tests (385 total) covering nest-on-drop, split-node, merge-nodes

Changed

  • useNodeDrag — detects drop target via elementFromPoint during drag; nests nodes on drop end
  • Node — integrates useSplitGesture for two-finger split; shows drop-target highlight
  • useGlobalKeyboard — added Ctrl+M shortcut for merge

[0.11.0] - 2026-03-05 — "Interactive"

Added

  • Nested group drag — dragging a group node now moves all its descendants (children, nested groups) together via getNodeDescendants helper
  • Edge deletion animationsremoveEdgeWithAnimationAtom snapshots edge state before removal and renders a fade-out animation via departingEdgesAtom; DepartingEdgeItem renders the exit animation
  • Edge creation animations — CSS fade-in animation class .canvas-edge-enter for newly created edges
  • Edge label editing — double-click an edge label to open an inline <input> overlay; editingEdgeLabelAtom + updateEdgeLabelAtom manage state; EdgeLabelEditor component positioned at label world coords
  • EdgeLabelEditor component — HTML input overlay for inline edge label editing, included automatically in Canvas
  • 14 new tests (367 total) covering nested group drag, departing edges, edge label editing

Changed

  • useNodeDrag — on first drag frame, expands initialPositions to include all descendants of group nodes being dragged
  • edgeFamilyAtom — now depends on graphUpdateVersionAtom for non-position attribute reactivity (label, color changes)
  • EdgeRenderer — renders departing edges with exit animation; edge labels support double-click to edit
  • CanvasAnimations — added canvas-edge-fade-in, canvas-edge-fade-out keyframes and .canvas-edge-enter, .canvas-edge-exit CSS classes

[0.10.0] - 2026-03-05 — "Polish"

Added

  • Edge re-routingcollapsedEdgeRemapAtom maps collapsed children to their outermost collapsed ancestor; edges visually re-route to the group node instead of disappearing
  • Group auto-resizeautoResizeGroupAtom recomputes group bounding box from children with padding; triggered automatically when drag ends on a child node
  • Search keyboard shortcutsCtrl+F opens search, Enter/Shift+Enter cycle results, Ctrl+G/Ctrl+Shift+G alternative navigation, Escape clears search before clearing selection
  • Edge search dimming — edges dim to opacity: 0.2 when search is active and neither endpoint matches, with 150ms CSS transition
  • Search highlight pulse — currently highlighted search result gets an animated amber box-shadow pulse (canvas-search-highlight CSS class)
  • CanvasAnimations component — injects CSS keyframes for search pulse and edge transitions
  • 11 new tests (353 total) covering edge remap, internal edge hiding, cross-boundary edges, auto-resize, and drag-triggered resize

Changed

  • visibleEdgeKeysAtom — now remap-aware: resolves effective endpoints through collapsedEdgeRemapAtom, hides internal edges (both endpoints in same collapsed group)
  • edgeFamilyAtom — uses remapped positions when source/target is inside a collapsed group
  • endNodeDragAtom — triggers autoResizeGroupAtom for the parent group after drag ends
  • useGlobalKeyboardEscape now clears search first (before clearing selection)

[0.9.0] - 2026-03-05 — "Full Stack"

Added

  • Abstract persistenceCanvasStorageAdapter interface with SupabaseStorageAdapter implementation and InMemoryStorageAdapter. CanvasDbProvider now accepts an adapter prop for any backend
  • storageAdapterAtom — Jotai atom for global adapter access; useStorageAdapter() hook
  • Node groupingparentId attribute on graph nodes, collapsible container groups with GroupNode component
  • group-storecollapsedGroupsAtom, toggleGroupCollapseAtom, nodeChildrenAtom, nodeParentAtom, setNodeParentAtom, groupSelectedNodesAtom, ungroupNodesAtom, isNodeCollapsed() utility
  • Group commandsgroupNodes, ungroupNodes, collapseGroup, expandGroup registered in command palette
  • Search & filtersearchQueryAtom, searchResultsAtom (case-insensitive substring match on label/type/id), highlightedSearchIndexAtom with next/prev navigation
  • Search commandssearchNodes (aliases: find, search) and clearSearch commands
  • Node dimming — non-matching nodes rendered with opacity: 0.2 and pointerEvents: none when search filter is active
  • Component tests — 39 new React component tests (Canvas, Node, Viewport, Minimap, SelectionOverlay, GroupNode) using @testing-library/react
  • 89 new tests (342 total)

Changed

  • uiNodesAtom — filters out nodes whose ancestor group is collapsed (walks parent chain)
  • CanvasDbProvider — accepts union props: { adapter } (primary) or { supabaseUrl, supabaseAnonKey } (legacy, deprecated)
  • CanvasProvider — accepts optional adapter prop alongside deprecated supabase credential props

[0.8.0] - 2026-03-05 — "Full Picture"

Added

  • Minimap<canvas>-based overview component showing all nodes with draggable viewport rectangle. Click/drag to pan. Configurable position, size, and colors
  • Lasso selection — pencil drag on background draws freeform lasso path; nodes whose center falls inside the polygon are selected
  • Rect selection — Shift+drag on background draws rectangular selection box; nodes overlapping the rect (AABB intersection) are selected
  • SelectionOverlay — SVG component rendering the active lasso/rect path with configurable colors
  • selection-path-store — new core store with startSelectionAtom, updateSelectionAtom, endSelectionAtom, selectionPathAtom, selectionRectAtom
  • pointInPolygon() — ray-casting utility for lasso selection, exported from core
  • Zoom animationsanimateZoomToNodeAtom and animateFitToBoundsAtom write atoms for smooth animated viewport transitions with cubic ease-in-out
  • useZoomTransition — hook driving requestAnimationFrame-based zoom/pan animation loop
  • zoomAnimationTargetAtom — stores current animation target (start/end zoom/pan, duration)
  • 39 new tests (253 total) covering selection paths, point-in-polygon, and zoom animation atoms

Changed

  • Viewport.tsx — now resolves gesture intent once at drag start (with modifier key state) and stores it in a ref, fixing Shift+drag rect-select and pencil lasso
  • TODO.md — marked v0.7 completions, updated roadmap for v0.9+

[0.7.0] - 2026-03-05 — "Solid Ground"

Added

  • Headless Canvas APIcreateCanvasAPI(store) factory provides all canvas operations (selection, viewport, graph, history, clipboard, snap, virtualization, actions) without React
  • buildActionHelpers(store) — pure Jotai store-based ActionHelpers construction, extracted from useActionExecutor for headless use
  • fitToBoundsAtom — headless write atom for fitting viewport to graph or selection bounds
  • centerOnNodeAtom — headless write atom for centering viewport on a specific node
  • Arrow key navigation — spatial keyboard navigation between nodes (Arrow keys = directional focus, Enter/Space = select, Tab = cycle by z-index)
  • focusedNodeIdAtom — keyboard focus state, distinct from selection, with visual focus ring
  • useArrowKeyNavigation hook — React hook for enabling keyboard navigation
  • useCanvasGraph hook — convenience hook for graph structure access (nodeCount, edgeCount, getNode, getEdge)
  • 214 unit tests — comprehensive coverage for graph-store, selection-store, history-store, clipboard-store, viewport-store, virtualization-store, and canvas-api (up from 47)

Changed

  • Edge re-render optimizationedgeFamilyAtom no longer depends on nodePositionUpdateCounterAtom (global counter). Reactivity flows through nodePositionAtomFamily with structural equality caching. Performance: O(connected edges) per drag frame instead of O(all edges)
  • useActionExecutor simplified — refactored to use buildActionHelpers internally (~30 lines from ~160)
  • useFitToBounds simplified — delegates to fitToBoundsAtom instead of inline computation
  • Position atom cachingnodePositionAtomFamily returns same object reference for unchanged positions via _positionCache Map

Fixed

  • Position atom cleanup now also clears the position cache to prevent stale references

[0.6.0] - 2026-03-03

Changed

  • React Compiler integration — automatic memoization replaces 110 useCallback, 25 useMemo, 2 React.memo
  • Context as JSX — 3 providers modernized (CanvasStyleProvider, CommandProvider, CanvasDbProvider)
  • Ref cleanupCanvasStyleProvider uses ref callback with cleanup for CSS variable lifecycle

Removed

  • Dropped React 18 — peerDependencies require react@^19.0.0

[0.5.0] - 2026-03-03

Added

  • NodeClick event type — single-click events on nodes now flow through the action executor
  • EdgeHover / EdgeLeave observability callbacks on Canvas
  • React.memo on EdgeItem component for render optimization

Fixed

  • ConnectedNodeRenderer virtualization — switched from nodeKeysAtom to visibleNodeKeysAtom
  • ConnectedNode forwards onClick, onHover, onLeave props correctly
  • history-store typed assertion for delta type checking

[0.4.0] - 2026-03-03

Added

  • Edge eventsEdgeClick, EdgeDoubleClick, EdgeRightClick with callback props on Canvas
  • Observability callbacksonSelectionChange, onViewportChange, onDragStart, onDragEnd, onNodeHover, onNodeLeave
  • Strong type contractsUINodeProperties replaces Record<string, unknown>, UINodeState replaces any in event callbacks
  • SelectEdge built-in action in the action registry

[0.3.0] - 2026-03-03

Added

  • All 8 event-action mappings fully wired (NodeRightClick, NodeLongPress, BackgroundClick)
  • BackgroundClick routed through action executor when onBackgroundClick prop is provided

Fixed

  • centerOnNode viewport calculation — correctly reads node position from graph store

[0.2.x] - 2025-01-14

Added

Settings Panel

  • CanvasEventType enum for all canvas events (double-click, triple-click, right-click, long-press)
  • ActionRegistry with registerAction() for custom actions
  • Built-in actions: selection, viewport, node, layout, history (17 total)
  • useCanvasSettings() hook, useActionExecutor() hook
  • SettingsPanel headless UI component
  • Three built-in presets: Default, Minimal, Power User
  • localStorage persistence via atomWithStorage

Layout System

  • useFitToBounds(), useGetGraphBounds(), useSelectionBounds(), useForceLayout()
  • Layout utilities: calculateBounds(), checkNodesOverlap(), getNodeCenter()

Command Palette

  • @blinksgg/canvas/commands subpath export
  • CommandProvider, CommandLine, CommandSearch, CommandInputCollector, CommandFeedbackOverlay
  • registerBuiltinCommands(), registerCommand(), useCommandLine(), useGlobalKeyboard()
  • Keyboard shortcuts: /, Cmd+K, Escape

Clipboard

  • Local-first copy/cut/paste/duplicate (Ctrl+C/X/V/D)

Virtualization

  • Viewport culling (+200px buffer)

Connection Ports

  • PortDefinition, NodePorts component, calculatePortPosition(), arePortsCompatible()

Input System

  • classifyPointer() for finger/pencil/mouse classification
  • resolveGestureIntent() with palm rejection
  • Touch/stylus support with device-aware thresholds

Other

  • d3-force added as peer dependency

[0.2.0] - 2025-01-07

Added

  • Subscription hooks for reactive state access:
    • useCanvasSelection(), useCanvasViewport(), useCanvasDrag()
  • New subpath export @blinksgg/canvas/hooks
  • Configurable edge paths with 8 path types:
    • bezier (default), bezier-vertical, bezier-smart
    • straight, step, step-vertical, step-smart, smooth-step
  • Edge path calculator utilities from @blinksgg/canvas/utils

Changed

  • EdgeRenderer uses configurable path calculators instead of hardcoded bezier curves

[0.1.0] - 2025-01-01

Added

  • Initial release
  • Core state management with Jotai atoms
  • Node drag, resize, and selection
  • Edge creation and management
  • Viewport pan/zoom with gesture support
  • Supabase sync integration
  • Style theming system with CSS variables
  • Undo/redo history support

Breaking Changes Guide

Upgrading to 0.6.0

  • React 18 is no longer supported. Update to React 19.
  • No API changes — the React Compiler handles memoization automatically.

Upgrading to 0.2.0

No breaking changes. Subscription hooks are recommended over direct atom imports:

// Before
import { selectedNodeIdsAtom } from '@blinksgg/canvas/core';
const selectedNodeIds = useAtomValue(selectedNodeIdsAtom);

// After (recommended)
import { useCanvasSelection } from '@blinksgg/canvas/hooks';
const { selectedNodeIds, count, hasSelection } = useCanvasSelection();

Version Policy

  • MAJOR version: Breaking changes (removed/renamed exports, changed return types)
  • MINOR version: New features (new hooks, components, options)
  • PATCH version: Bug fixes (no API changes)