147 lines
4.7 KiB
Markdown
147 lines
4.7 KiB
Markdown
# Migrating to @blinksgg/canvas v1.0
|
|
|
|
This guide covers breaking changes and migration steps from v0.x to v1.0.
|
|
|
|
## Requirements
|
|
|
|
- **React 19.0+** — React 18 is not supported (React Compiler, context-as-JSX)
|
|
- **Jotai 2.6+** — Required for atom families and store API
|
|
- **Node 18+** — For ESM support
|
|
|
|
## Breaking Changes Summary
|
|
|
|
### From v0.14+ (Gesture System v2)
|
|
|
|
**`onAction` callback type changed**: `GestureEvent` → `InputEvent`
|
|
|
|
The `Canvas` component's `onAction` prop now receives `InputEvent` (union of pointer + keyboard events) instead of `GestureEvent` (pointer only).
|
|
|
|
```typescript
|
|
// Before (v0.x)
|
|
onAction={(event: GestureEvent, resolution) => {
|
|
const { subject, worldPosition } = event;
|
|
}}
|
|
|
|
// After (v1.0)
|
|
onAction={(event: InputEvent, resolution) => {
|
|
if (event.kind === 'key') return; // skip keyboard events
|
|
const { subject, worldPosition } = event; // narrowed to pointer
|
|
}}
|
|
```
|
|
|
|
**Old gesture config replaced**: The v1 gesture config shape (event-to-action mapping objects) was replaced by the v2 specificity-based binding system.
|
|
|
|
```typescript
|
|
// Before (v0.x) — removed
|
|
<Canvas gestureConfig={{ onNodeDoubleTap: 'fit-to-view' }} />
|
|
|
|
// After (v1.0) — use binding contexts
|
|
import { gesturesV2 } from '@blinksgg/canvas';
|
|
// Bindings are configured via contexts, not flat config
|
|
```
|
|
|
|
### From v0.23+ (Removed Exports)
|
|
|
|
These were deprecated in v0.16 and removed in v0.23:
|
|
|
|
| Removed | Replacement |
|
|
|---------|-------------|
|
|
| `findPortAtPosition()` | Use `hitTestPort()` from `@blinksgg/canvas/utils` |
|
|
| `resolveGestureIntent()` | Use `gesturesV2.resolve()` |
|
|
| `isBackgroundGesture()` | Check `event.subject.kind === 'background'` |
|
|
| `useSupabaseClient()` | Use `CanvasDbProvider` with storage adapter |
|
|
|
|
### From v0.6+ (React 19)
|
|
|
|
- `Context.Provider` syntax → `<Context>` (React 19 style)
|
|
- Manual `React.memo()` / `useCallback()` / `useMemo()` removed — React Compiler handles memoization
|
|
- Ref cleanup functions used instead of `useEffect` return for pointer capture
|
|
|
|
## Import Path Changes
|
|
|
|
All import paths are stable and unchanged since v0.14:
|
|
|
|
```typescript
|
|
import { Canvas, useCanvasSelection, graphAtom } from '@blinksgg/canvas';
|
|
import { commandRegistry } from '@blinksgg/canvas/commands';
|
|
import { graphAtom, selectedNodeIdsAtom } from '@blinksgg/canvas/core';
|
|
import { useNodeDrag, useFitToBounds } from '@blinksgg/canvas/hooks';
|
|
import { gesturesV2 } from '@blinksgg/canvas'; // or from '@blinksgg/canvas/gestures'
|
|
import { CanvasStorageAdapter } from '@blinksgg/canvas/db';
|
|
```
|
|
|
|
## Storage Adapter Migration
|
|
|
|
If you were using the old Supabase provider props:
|
|
|
|
```typescript
|
|
// Before (v0.x) — Supabase-specific props
|
|
<Canvas supabaseUrl="..." supabaseKey="..." />
|
|
|
|
// After (v1.0) — adapter pattern
|
|
import { CanvasDbProvider, SupabaseStorageAdapter } from '@blinksgg/canvas/db';
|
|
|
|
const adapter = new SupabaseStorageAdapter(supabaseClient);
|
|
<CanvasDbProvider adapter={adapter}>
|
|
<Canvas ... />
|
|
</CanvasDbProvider>
|
|
```
|
|
|
|
Or use callback props for simple persistence (no adapter needed):
|
|
|
|
```typescript
|
|
<Canvas
|
|
onNodePersist={async (nodeId, graphId, uiProps) => {
|
|
await saveToYourBackend(nodeId, graphId, uiProps);
|
|
}}
|
|
/>
|
|
```
|
|
|
|
## Peer Dependencies
|
|
|
|
Required:
|
|
- `react` ^19.0.0
|
|
- `react-dom` ^19.0.0
|
|
- `jotai` ^2.6.0
|
|
|
|
Optional (install only if using the feature):
|
|
- `d3-force` ^3.0.0 — for `useForceLayout` hook
|
|
- `@tanstack/react-query` ^5.17.0 — for query-based atoms
|
|
- `jotai-tanstack-query` — for `atomsWithQuery` integration
|
|
- `@blocknote/core`, `@blocknote/react`, `@blocknote/shadcn` ^0.45.0 — for `NoteNode`
|
|
|
|
## Gesture System v1 → v2 Mapping
|
|
|
|
| v1 Gesture Config | v2 Equivalent |
|
|
|-------------------|---------------|
|
|
| `onNodeDoubleTap: 'fit-to-view'` | Default binding: double-tap node → `fit-to-view` |
|
|
| `onBackgroundDoubleTap: 'create-node'` | Default binding: double-tap background → `create-node` |
|
|
| `onNodeRightClick: 'context-menu'` | Default binding: right-click node → `context-menu` |
|
|
| `onNodeLongPress: 'toggle-lock'` | Default binding: long-press node → `toggle-lock` |
|
|
|
|
All default bindings are pre-configured. Override via `gestureConfig` prop or `addGestureRuleAtom`.
|
|
|
|
## Quick Start (v1.0)
|
|
|
|
```tsx
|
|
import { Provider as JotaiProvider } from 'jotai';
|
|
import { Canvas, CanvasStyleProvider, graphAtom } from '@blinksgg/canvas';
|
|
|
|
function App() {
|
|
return (
|
|
<JotaiProvider>
|
|
<CanvasStyleProvider isDark={true}>
|
|
<Canvas
|
|
renderNode={({ node, isSelected }) => (
|
|
<div>{node.label}</div>
|
|
)}
|
|
onAction={(event, resolution) => {
|
|
if (event.kind === 'key') return;
|
|
console.log(resolution.actionId, event.subject);
|
|
}}
|
|
/>
|
|
</CanvasStyleProvider>
|
|
</JotaiProvider>
|
|
);
|
|
}
|
|
```
|