f1ow 0.1.3 → 0.1.5
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/README.md +126 -9
- package/dist/f1ow.js +12519 -7316
- package/dist/f1ow.umd.cjs +15399 -10
- package/dist/lib/FlowCanvasProps.d.ts +22 -0
- package/dist/lib/index.d.ts +2 -0
- package/dist/utils/elementRegistry.d.ts +146 -0
- package/package.json +99 -94
package/README.md
CHANGED
|
@@ -30,6 +30,8 @@
|
|
|
30
30
|
- **Undo / Redo** — 100-step history snapshot system.
|
|
31
31
|
- **Export** — Export canvas to PNG, SVG, or JSON.
|
|
32
32
|
- **Real-Time Collaboration** — Optional CRDT via Yjs (experimental) with cursor presence.
|
|
33
|
+
- **Plugin / Extension System** — Register custom element types with per-type validation and default values.
|
|
34
|
+
- **Element Validation** — Every mutation path (add, update, import) is validated; invalid elements are rejected gracefully.
|
|
33
35
|
- **Fully Themeable** — Dark mode, custom colors, all via props.
|
|
34
36
|
- **Zero CSS Dependencies** — No external stylesheets required. Inline styled.
|
|
35
37
|
- **TypeScript** — Full type safety with strict mode.
|
|
@@ -37,14 +39,25 @@
|
|
|
37
39
|
## 📦 Installation
|
|
38
40
|
|
|
39
41
|
```bash
|
|
40
|
-
npm
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
#
|
|
44
|
-
|
|
42
|
+
# npm
|
|
43
|
+
npm install f1ow konva react-konva zustand
|
|
44
|
+
|
|
45
|
+
# pnpm
|
|
46
|
+
pnpm add f1ow konva react-konva zustand
|
|
47
|
+
|
|
48
|
+
# yarn
|
|
49
|
+
yarn add f1ow konva react-konva zustand
|
|
45
50
|
```
|
|
46
51
|
|
|
47
|
-
>
|
|
52
|
+
> `react` and `react-dom` are assumed to already be in your project. If not, add them too:
|
|
53
|
+
> ```bash
|
|
54
|
+
> npm install react react-dom
|
|
55
|
+
> ```
|
|
56
|
+
|
|
57
|
+
> **Optional — Collaboration only:** install these when using the `collaboration` prop:
|
|
58
|
+
> ```bash
|
|
59
|
+
> npm install yjs y-websocket
|
|
60
|
+
> ```
|
|
48
61
|
|
|
49
62
|
### Next.js / Non-Vite Bundlers
|
|
50
63
|
|
|
@@ -98,6 +111,7 @@ That's it — you get a full-featured canvas editor with a toolbar, style panel,
|
|
|
98
111
|
| `width` / `height` | `number \| string` | `'100%'` | Canvas dimensions |
|
|
99
112
|
| `tools` | `ToolType[]` | all | Visible tools in toolbar |
|
|
100
113
|
| `defaultTool` | `ToolType` | `'select'` | Default active tool on mount |
|
|
114
|
+
| `defaultStyle` | `Partial<ElementStyle>` | — | Default drawing style for new elements |
|
|
101
115
|
| `toolbarPosition` | `'top' \| 'bottom' \| 'hidden'` | `'bottom'` | Position of the main toolbar |
|
|
102
116
|
| `showToolbar` | `boolean` | `true` | Show toolbar (legacy, use `toolbarPosition`) |
|
|
103
117
|
| `showStylePanel` | `boolean` | `true` | Show style panel |
|
|
@@ -109,6 +123,7 @@ That's it — you get a full-featured canvas editor with a toolbar, style panel,
|
|
|
109
123
|
| `className` | `string` | — | Root container CSS class |
|
|
110
124
|
| `contextMenuItems` | `ContextMenuItem[]` or `(ctx) => ContextMenuItem[]` | — | Extra context menu items |
|
|
111
125
|
| `renderContextMenu` | `(ctx) => ReactNode` | — | Replace built-in context menu |
|
|
126
|
+
| `customElementTypes` | `CustomElementConfig[]` | — | Register custom element types ([docs](#-custom-element-types--plugins)) |
|
|
112
127
|
| `collaboration` | `CollaborationConfig` | — | Enable real-time collaboration |
|
|
113
128
|
| `workerConfig` | `{ elbowWorkerUrl?: string, exportWorkerUrl?: string, disabled?: boolean }` | — | Worker URLs for Next.js ([docs](docs/NEXTJS_INTEGRATION.md)) |
|
|
114
129
|
|
|
@@ -135,6 +150,7 @@ const ref = useRef<FlowCanvasRef>(null);
|
|
|
135
150
|
| `setSelectedIds(ids)` | — | Set selection |
|
|
136
151
|
| `clearSelection()` | — | Deselect all |
|
|
137
152
|
| `setActiveTool(tool)` | — | Switch tool |
|
|
153
|
+
| `getActiveTool()` | `ToolType` | Get current active tool |
|
|
138
154
|
| `undo()` / `redo()` | — | History navigation |
|
|
139
155
|
| `zoomTo(scale)` | — | Set zoom level |
|
|
140
156
|
| `resetView()` | — | Reset pan & zoom |
|
|
@@ -199,12 +215,23 @@ Append custom items or fully replace the built-in menu:
|
|
|
199
215
|
|
|
200
216
|
## 🤝 Collaboration (Experimental)
|
|
201
217
|
|
|
218
|
+
First install the optional peer dependencies:
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
npm install yjs y-websocket
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Then pass a `CollaborationConfig` to the `collaboration` prop:
|
|
225
|
+
|
|
202
226
|
```tsx
|
|
203
227
|
<FlowCanvas
|
|
204
228
|
collaboration={{
|
|
205
|
-
|
|
206
|
-
|
|
229
|
+
serverUrl: "wss://my-yjs-server.example.com",
|
|
230
|
+
roomName: "my-room",
|
|
207
231
|
user: { id: "user-1", name: "Alice", color: "#e03131" },
|
|
232
|
+
// authToken: "...", // optional auth token
|
|
233
|
+
// syncDebounceMs: 50, // local→remote debounce (ms)
|
|
234
|
+
// awarenessThrottleMs: 100 // cursor sharing throttle (ms)
|
|
208
235
|
}}
|
|
209
236
|
/>
|
|
210
237
|
```
|
|
@@ -213,7 +240,7 @@ Provides CRDT-based real-time sync with cursor presence overlay. Requires a [Yjs
|
|
|
213
240
|
|
|
214
241
|
## 🧩 Element Types
|
|
215
242
|
|
|
216
|
-
`CanvasElement` is a discriminated union of 8 types:
|
|
243
|
+
`CanvasElement` is a discriminated union of 8 built-in types:
|
|
217
244
|
|
|
218
245
|
- **Shapes** — `rectangle`, `ellipse`, `diamond`
|
|
219
246
|
- **Connectors** — `line`, `arrow` (with bindings, routing, arrowheads)
|
|
@@ -221,8 +248,98 @@ Provides CRDT-based real-time sync with cursor presence overlay. Requires a [Yjs
|
|
|
221
248
|
|
|
222
249
|
All elements share: `id`, `x`, `y`, `width`, `height`, `rotation`, `style`, `isLocked`, `isVisible`, `boundElements`, `groupIds`.
|
|
223
250
|
|
|
251
|
+
Custom types can be added via the plugin system — see [Custom Element Types](#-custom-element-types--plugins).
|
|
252
|
+
|
|
224
253
|
> Full type definitions are bundled in the package `.d.ts` files.
|
|
225
254
|
|
|
255
|
+
## 🔌 Custom Element Types / Plugins
|
|
256
|
+
|
|
257
|
+
f1ow supports registering custom element types. Every element passing through `addElement`, `updateElement`, `setElements`, or `importJSON` is validated — both built-in and custom types.
|
|
258
|
+
|
|
259
|
+
### Option 1 — Global registration (before rendering)
|
|
260
|
+
|
|
261
|
+
Register once at module level so the type is available across all `<FlowCanvas>` instances:
|
|
262
|
+
|
|
263
|
+
```ts
|
|
264
|
+
import { registerCustomElement } from 'f1ow';
|
|
265
|
+
|
|
266
|
+
registerCustomElement({
|
|
267
|
+
type: 'sticky-note',
|
|
268
|
+
displayName: 'Sticky Note',
|
|
269
|
+
|
|
270
|
+
// Called after base-field validation passes.
|
|
271
|
+
// Return true = valid, or a string = error message.
|
|
272
|
+
validate: (el) => typeof el.content === 'string' || 'content must be a string',
|
|
273
|
+
|
|
274
|
+
// Default field values — only fills gaps, never overwrites.
|
|
275
|
+
defaults: { content: '', color: '#ffeb3b' },
|
|
276
|
+
});
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### Option 2 — Per-component registration (via prop)
|
|
280
|
+
|
|
281
|
+
Types are registered once when `<FlowCanvas>` mounts. Keep the array reference stable (module constant or `useMemo`) — changes after mount have no effect.
|
|
282
|
+
|
|
283
|
+
```tsx
|
|
284
|
+
import { FlowCanvas } from 'f1ow';
|
|
285
|
+
import type { CustomElementConfig } from 'f1ow';
|
|
286
|
+
|
|
287
|
+
// ✅ Define outside the component (or useMemo) — stable reference
|
|
288
|
+
const MY_TYPES: CustomElementConfig[] = [
|
|
289
|
+
{
|
|
290
|
+
type: 'sticky-note',
|
|
291
|
+
displayName: 'Sticky Note',
|
|
292
|
+
validate: (el) => typeof el.content === 'string' || 'content must be a string',
|
|
293
|
+
defaults: { content: '', color: '#ffeb3b' },
|
|
294
|
+
},
|
|
295
|
+
];
|
|
296
|
+
|
|
297
|
+
function App() {
|
|
298
|
+
return <FlowCanvas customElementTypes={MY_TYPES} />;
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### `CustomElementConfig` reference
|
|
303
|
+
|
|
304
|
+
| Field | Type | Description |
|
|
305
|
+
| --- | --- | --- |
|
|
306
|
+
| `type` | `string` | **Required.** Unique type identifier (must not clash with built-ins unless `allowOverride: true`) |
|
|
307
|
+
| `displayName` | `string` | Human-readable name used in warnings. Defaults to `type` |
|
|
308
|
+
| `validate` | `(el: Record<string, unknown>) => true \| string` | Extra validation after base-field checks. Return `true` = valid, string = error message |
|
|
309
|
+
| `defaults` | `Partial<T>` | Default field values applied on `addElement`. Existing fields take priority |
|
|
310
|
+
| `allowOverride` | `boolean` | Allow replacing an existing registration. Default `false` |
|
|
311
|
+
|
|
312
|
+
### Using the registry directly
|
|
313
|
+
|
|
314
|
+
```ts
|
|
315
|
+
import { elementRegistry } from 'f1ow';
|
|
316
|
+
|
|
317
|
+
// Check if a type is registered
|
|
318
|
+
elementRegistry.isRegistered('sticky-note'); // true / false
|
|
319
|
+
|
|
320
|
+
// Validate any element manually
|
|
321
|
+
const result = elementRegistry.validateElement(myElement);
|
|
322
|
+
if (!result.valid) console.error(result.error);
|
|
323
|
+
|
|
324
|
+
// All registered types
|
|
325
|
+
elementRegistry.getRegisteredTypes();
|
|
326
|
+
// → ['rectangle', 'ellipse', ..., 'sticky-note']
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### Built-in validation rules
|
|
330
|
+
|
|
331
|
+
Every element is validated on every write regardless of type:
|
|
332
|
+
|
|
333
|
+
| Field | Rule |
|
|
334
|
+
| --- | --- |
|
|
335
|
+
| `id` | Non-empty string |
|
|
336
|
+
| `type` | Must be a registered type |
|
|
337
|
+
| `x`, `y`, `rotation` | Finite number |
|
|
338
|
+
| `width`, `height` | Finite number ≥ 0 |
|
|
339
|
+
| `style.opacity` | Number in `[0, 1]` |
|
|
340
|
+
| `style.strokeWidth`, `style.fontSize` | Finite number > 0 |
|
|
341
|
+
| `id` / `type` in updates | Blocked — use `convertElementType` for type changes |
|
|
342
|
+
|
|
226
343
|
## 🛠️ Development
|
|
227
344
|
|
|
228
345
|
```bash
|