fabricjs-document-engine 0.6.0 → 0.7.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/README.md +46 -2
- package/dist/engine/create-document-engine.cjs +2 -0
- package/dist/engine/create-document-engine.d.cts +3 -0
- package/dist/engine/create-document-engine.d.ts +3 -0
- package/dist/engine/create-document-engine.js +2 -0
- package/dist/index.cjs +2 -0
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/react/engine-context.cjs +12 -0
- package/dist/react/engine-context.d.cts +10 -0
- package/dist/react/engine-context.d.ts +10 -0
- package/dist/react/engine-context.js +11 -0
- package/dist/react/use-document-engine.cjs +23 -0
- package/dist/react/use-document-engine.d.cts +6 -0
- package/dist/react/use-document-engine.d.ts +6 -0
- package/dist/react/use-document-engine.js +23 -0
- package/dist/react/use-document-event.cjs +12 -0
- package/dist/react/use-document-event.d.cts +4 -0
- package/dist/react/use-document-event.d.ts +4 -0
- package/dist/react/use-document-event.js +12 -0
- package/dist/react/use-document-state.cjs +11 -0
- package/dist/react/use-document-state.d.cts +5 -0
- package/dist/react/use-document-state.d.ts +5 -0
- package/dist/react/use-document-state.js +11 -0
- package/dist/react.cjs +11 -0
- package/dist/react.d.cts +6 -0
- package/dist/react.d.ts +6 -0
- package/dist/react.js +6 -0
- package/dist/state/document-state-store.cjs +114 -0
- package/dist/state/document-state-store.d.cts +28 -0
- package/dist/state/document-state-store.d.ts +28 -0
- package/dist/state/document-state-store.js +114 -0
- package/package.json +26 -4
package/README.md
CHANGED
|
@@ -15,6 +15,7 @@ Fabric already draws objects, handles interaction and serializes to JSON. This p
|
|
|
15
15
|
- **Dependable export.** PNG, JPEG, WebP, SVG and editable JSON. You choose the area, scale and background. A preflight check means an export either succeeds or tells you exactly which image or font prevents it.
|
|
16
16
|
- **Versions and migration.** Keep named versions, restore any of them as a new revision, and open plain Fabric JSON or documents saved by older versions of this package.
|
|
17
17
|
- **Reliable undo and redo.** One user action is one undo step. Transactions group several code changes into one labelled step, and ids survive undo and redo.
|
|
18
|
+
- **React ready, framework free.** Hooks for React, and a small state store for any other framework. Your toolbar and UI stay yours.
|
|
18
19
|
- **Fabric 6 and 7.** Every release is tested against both.
|
|
19
20
|
|
|
20
21
|
## Install
|
|
@@ -40,6 +41,42 @@ localStorage.setItem(document.id, JSON.stringify(document));
|
|
|
40
41
|
await engine.loadDocument(JSON.parse(localStorage.getItem(document.id)!));
|
|
41
42
|
```
|
|
42
43
|
|
|
44
|
+
## React
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
import { useDocumentEngine, useDocumentState, DocumentEngineProvider, useEngine } from 'fabricjs-document-engine/react';
|
|
48
|
+
|
|
49
|
+
function Editor({ canvas }: { canvas: Canvas | null }) {
|
|
50
|
+
const engine = useDocumentEngine(canvas, { storage, autosave: true });
|
|
51
|
+
return (
|
|
52
|
+
<DocumentEngineProvider engine={engine}>
|
|
53
|
+
<YourToolbar />
|
|
54
|
+
</DocumentEngineProvider>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function YourToolbar() {
|
|
59
|
+
const engine = useEngine();
|
|
60
|
+
const state = useDocumentState(engine);
|
|
61
|
+
if (!engine || !state) return null;
|
|
62
|
+
return (
|
|
63
|
+
<>
|
|
64
|
+
<button disabled={!state.canUndo} onClick={() => engine.undo()}>Undo {state.undoLabel}</button>
|
|
65
|
+
<button disabled={!state.isDirty} onClick={() => engine.save()}>Save</button>
|
|
66
|
+
<span>{state.saveStatus}</span>
|
|
67
|
+
</>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
- `useDocumentEngine(canvas, options)` creates the engine once your Fabric canvas exists and destroys it on unmount. It returns `null` until then. Options are read when the engine is created.
|
|
73
|
+
- `useDocumentState(engine)` returns `{ documentId, isLoading, loadError, saveStatus, isDirty, isSaving, revision, lastSavedAt, saveError, canUndo, canRedo, undoLabel, redoLabel, assetWarnings }` and re-renders when any of them change.
|
|
74
|
+
- `useDocumentEvent(engine, 'save:error', handler)` subscribes to any event with the latest handler.
|
|
75
|
+
- `DocumentEngineProvider` and `useEngine()` pass the engine to deeply nested toolbars.
|
|
76
|
+
- The React entry is marked `'use client'` for Next.js. React is an optional peer dependency, so the core never imports it.
|
|
77
|
+
|
|
78
|
+
For other frameworks, `createDocumentStateStore(engine)` gives the same state as `{ getSnapshot, subscribe }`, which fits Svelte stores, Vue's `shallowRef` and similar tools.
|
|
79
|
+
|
|
43
80
|
## Saving and loading through storage
|
|
44
81
|
|
|
45
82
|
The built-in adapters are the quickest way to start:
|
|
@@ -59,6 +96,8 @@ await engine.save();
|
|
|
59
96
|
|
|
60
97
|
Both adapters also have `listDocuments()` and `deleteDocument(id)`. To build on another key-value store, use `createKeyValueStorage({ read, write, remove, keys }, prefix)`.
|
|
61
98
|
|
|
99
|
+
More adapters, including a REST API with revision checks and image uploads, are in [docs/storage-examples.md](https://github.com/re-sohail/fabricjs-document-engine/blob/main/docs/storage-examples.md).
|
|
100
|
+
|
|
62
101
|
### Your own backend
|
|
63
102
|
|
|
64
103
|
A storage adapter is two functions:
|
|
@@ -398,8 +437,9 @@ Keep project data such as titles, owners and tags in `metadata` with `engine.upd
|
|
|
398
437
|
| `engine.getHistory()` | Returns `{ undo, redo }` label lists, newest first. |
|
|
399
438
|
| `engine.clearHistory()` | Forgets all steps. Loading a document or starting a new one also does this. |
|
|
400
439
|
| `bindKeyboardShortcuts(engine, { target? })` | Adds the undo and redo shortcuts. Returns an unbind function. |
|
|
401
|
-
| `engine.on(event, handler)` | Listens to `load:start`, `load:success`, `load:error`, `save:start`, `save:success`, `save:error`, `save:retry`, `save:status`, `assets:warning`, `recovery:checkpoint`, `recovery:restored`, `recovery:error`, `export:success`, `export:error`, `version:created`, `version:restored`, `version:error`, `history:change` or `history:error`. Returns an unsubscribe function. |
|
|
440
|
+
| `engine.on(event, handler)` | Listens to `load:start`, `document:change`, `load:success`, `load:error`, `save:start`, `save:success`, `save:error`, `save:retry`, `save:status`, `assets:warning`, `recovery:checkpoint`, `recovery:restored`, `recovery:error`, `export:success`, `export:error`, `version:created`, `version:restored`, `version:error`, `history:change` or `history:error`. Returns an unsubscribe function. |
|
|
402
441
|
| `engine.destroy()` | Stops listening to the canvas and cancels a running load. |
|
|
442
|
+
| `createDocumentStateStore(engine)` | Framework-free `{ getSnapshot, subscribe, destroy }` state for toolbars. |
|
|
403
443
|
| `validateDocument(value)` | Returns a list of issues with the exact path of each problem. |
|
|
404
444
|
|
|
405
445
|
## Errors
|
|
@@ -449,10 +489,14 @@ A failed load never clears or half-fills your canvas.
|
|
|
449
489
|
| 5 | Recovery after a refresh or crash | 0.4.0 |
|
|
450
490
|
| 6 | PNG, JPEG, SVG and JSON export with preflight checks | 0.5.0 |
|
|
451
491
|
| 7 | Named versions and schema migrations | 0.6.0 |
|
|
452
|
-
| 8 | React adapter and examples | |
|
|
492
|
+
| 8 | React adapter and examples | 0.7.0 |
|
|
453
493
|
| 9 | Hardening and benchmarks | |
|
|
454
494
|
| 10 | Stable API | 1.0.0 |
|
|
455
495
|
|
|
496
|
+
## Troubleshooting
|
|
497
|
+
|
|
498
|
+
Common problems and fixes are in [docs/troubleshooting.md](https://github.com/re-sohail/fabricjs-document-engine/blob/main/docs/troubleshooting.md).
|
|
499
|
+
|
|
456
500
|
## License
|
|
457
501
|
|
|
458
502
|
MIT
|
|
@@ -201,6 +201,7 @@ function createDocumentEngine(options) {
|
|
|
201
201
|
saving.startSession(document.revision ?? 0);
|
|
202
202
|
canvas.requestRenderAll();
|
|
203
203
|
if (warnings.length > 0) events.emit("assets:warning", { warnings });
|
|
204
|
+
events.emit("document:change", { documentId: document.id });
|
|
204
205
|
events.emit("load:success", {
|
|
205
206
|
document,
|
|
206
207
|
warnings,
|
|
@@ -338,6 +339,7 @@ function createDocumentEngine(options) {
|
|
|
338
339
|
history.reset();
|
|
339
340
|
recovery?.cancel();
|
|
340
341
|
saving.startSession(0);
|
|
342
|
+
events.emit("document:change", { documentId: documentInfo.id });
|
|
341
343
|
}
|
|
342
344
|
function getObjectById(id) {
|
|
343
345
|
ensureUsable();
|
|
@@ -201,6 +201,7 @@ function createDocumentEngine(options) {
|
|
|
201
201
|
saving.startSession(document.revision ?? 0);
|
|
202
202
|
canvas.requestRenderAll();
|
|
203
203
|
if (warnings.length > 0) events.emit("assets:warning", { warnings });
|
|
204
|
+
events.emit("document:change", { documentId: document.id });
|
|
204
205
|
events.emit("load:success", {
|
|
205
206
|
document,
|
|
206
207
|
warnings,
|
|
@@ -338,6 +339,7 @@ function createDocumentEngine(options) {
|
|
|
338
339
|
history.reset();
|
|
339
340
|
recovery?.cancel();
|
|
340
341
|
saving.startSession(0);
|
|
342
|
+
events.emit("document:change", { documentId: documentInfo.id });
|
|
341
343
|
}
|
|
342
344
|
function getObjectById(id) {
|
|
343
345
|
ensureUsable();
|
package/dist/index.cjs
CHANGED
|
@@ -7,12 +7,14 @@ const require_create_document_engine = require("./engine/create-document-engine.
|
|
|
7
7
|
const require_keyboard_shortcuts = require("./history/keyboard-shortcuts.cjs");
|
|
8
8
|
const require_unsaved_changes_warning = require("./save/unsaved-changes-warning.cjs");
|
|
9
9
|
const require_download_export = require("./export/download-export.cjs");
|
|
10
|
+
const require_document_state_store = require("./state/document-state-store.cjs");
|
|
10
11
|
exports.CURRENT_SCHEMA_VERSION = require_document_format.CURRENT_SCHEMA_VERSION;
|
|
11
12
|
exports.DocumentEngineError = require_errors.DocumentEngineError;
|
|
12
13
|
exports.bindKeyboardShortcuts = require_keyboard_shortcuts.bindKeyboardShortcuts;
|
|
13
14
|
exports.bindUnsavedChangesWarning = require_unsaved_changes_warning.bindUnsavedChangesWarning;
|
|
14
15
|
exports.createConflictError = require_errors.createConflictError;
|
|
15
16
|
exports.createDocumentEngine = require_create_document_engine.createDocumentEngine;
|
|
17
|
+
exports.createDocumentStateStore = require_document_state_store.createDocumentStateStore;
|
|
16
18
|
exports.detectSchemaVersion = require_migrate_document.detectSchemaVersion;
|
|
17
19
|
exports.downloadExport = require_download_export.downloadExport;
|
|
18
20
|
exports.isDocumentEngineError = require_errors.isDocumentEngineError;
|
package/dist/index.d.cts
CHANGED
|
@@ -22,4 +22,5 @@ import { KeyboardShortcutOptions, UndoRedoTarget, bindKeyboardShortcuts } from "
|
|
|
22
22
|
import { UnsavedChangesSource, bindUnsavedChangesWarning } from "./save/unsaved-changes-warning.cjs";
|
|
23
23
|
import { DownloadableExport, downloadExport } from "./export/download-export.cjs";
|
|
24
24
|
import { Migration, MigrationContext, MigrationResult, detectSchemaVersion, migrateDocument } from "./migrations/migrate-document.cjs";
|
|
25
|
-
|
|
25
|
+
import { DocumentState, DocumentStateStore, createDocumentStateStore } from "./state/document-state-store.cjs";
|
|
26
|
+
export { type AssetManifest, type AssetOptions, type AssetReport, type AssetWarning, type AssetWarningCode, type AutosaveOptions, CURRENT_SCHEMA_VERSION, type CustomObjectDefinition, type DocumentCanvas, type DocumentEngine, DocumentEngineError, type DocumentEngineErrorDetails, type DocumentEngineEvents, type DocumentEngineOptions, type DocumentErrorCode, type DocumentInfo, type DocumentIssue, type DocumentState, type DocumentStateStore, type DocumentStorage, type DocumentVersion, type DownloadableExport, type ExportArea, type ExportBackground, type ExportFormat, type ExportOptions, type ExportPreflight, type ExportProblem, type ExportProblemCode, type ExportRect, type ExportResult, type FabricDocument, type FontAsset, type FontLoader, type HistoryOptions, type HistoryState, type ImageAsset, type ImportOptions, type InterruptedLoad, type KeyboardShortcutOptions, type LoadOptions, type Migration, type MigrationContext, type MigrationResult, type NewDocumentOptions, type RecoveryOptions, type RecoveryRecord, type RecoveryStore, type RetryOptions, type SaveContext, type SaveOptions, type SaveResult, type SaveRetryEvent, type SaveState, type SaveStatus, type SerializedFabricObject, type UndoRedoTarget, type UnsavedChangesSource, type Unsubscribe, type UploadRequest, type VersionKind, type VersionOptions, type VersionStorage, type VersionSummary, bindKeyboardShortcuts, bindUnsavedChangesWarning, createConflictError, createDocumentEngine, createDocumentStateStore, detectSchemaVersion, downloadExport, isDocumentEngineError, migrateDocument, validateDocument };
|
package/dist/index.d.ts
CHANGED
|
@@ -22,4 +22,5 @@ import { KeyboardShortcutOptions, UndoRedoTarget, bindKeyboardShortcuts } from "
|
|
|
22
22
|
import { UnsavedChangesSource, bindUnsavedChangesWarning } from "./save/unsaved-changes-warning.js";
|
|
23
23
|
import { DownloadableExport, downloadExport } from "./export/download-export.js";
|
|
24
24
|
import { Migration, MigrationContext, MigrationResult, detectSchemaVersion, migrateDocument } from "./migrations/migrate-document.js";
|
|
25
|
-
|
|
25
|
+
import { DocumentState, DocumentStateStore, createDocumentStateStore } from "./state/document-state-store.js";
|
|
26
|
+
export { type AssetManifest, type AssetOptions, type AssetReport, type AssetWarning, type AssetWarningCode, type AutosaveOptions, CURRENT_SCHEMA_VERSION, type CustomObjectDefinition, type DocumentCanvas, type DocumentEngine, DocumentEngineError, type DocumentEngineErrorDetails, type DocumentEngineEvents, type DocumentEngineOptions, type DocumentErrorCode, type DocumentInfo, type DocumentIssue, type DocumentState, type DocumentStateStore, type DocumentStorage, type DocumentVersion, type DownloadableExport, type ExportArea, type ExportBackground, type ExportFormat, type ExportOptions, type ExportPreflight, type ExportProblem, type ExportProblemCode, type ExportRect, type ExportResult, type FabricDocument, type FontAsset, type FontLoader, type HistoryOptions, type HistoryState, type ImageAsset, type ImportOptions, type InterruptedLoad, type KeyboardShortcutOptions, type LoadOptions, type Migration, type MigrationContext, type MigrationResult, type NewDocumentOptions, type RecoveryOptions, type RecoveryRecord, type RecoveryStore, type RetryOptions, type SaveContext, type SaveOptions, type SaveResult, type SaveRetryEvent, type SaveState, type SaveStatus, type SerializedFabricObject, type UndoRedoTarget, type UnsavedChangesSource, type Unsubscribe, type UploadRequest, type VersionKind, type VersionOptions, type VersionStorage, type VersionSummary, bindKeyboardShortcuts, bindUnsavedChangesWarning, createConflictError, createDocumentEngine, createDocumentStateStore, detectSchemaVersion, downloadExport, isDocumentEngineError, migrateDocument, validateDocument };
|
package/dist/index.js
CHANGED
|
@@ -6,4 +6,5 @@ import { createDocumentEngine } from "./engine/create-document-engine.js";
|
|
|
6
6
|
import { bindKeyboardShortcuts } from "./history/keyboard-shortcuts.js";
|
|
7
7
|
import { bindUnsavedChangesWarning } from "./save/unsaved-changes-warning.js";
|
|
8
8
|
import { downloadExport } from "./export/download-export.js";
|
|
9
|
-
|
|
9
|
+
import { createDocumentStateStore } from "./state/document-state-store.js";
|
|
10
|
+
export { CURRENT_SCHEMA_VERSION, DocumentEngineError, bindKeyboardShortcuts, bindUnsavedChangesWarning, createConflictError, createDocumentEngine, createDocumentStateStore, detectSchemaVersion, downloadExport, isDocumentEngineError, migrateDocument, validateDocument };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
let react = require("react");
|
|
2
|
+
//#region src/react/engine-context.ts
|
|
3
|
+
const EngineContext = (0, react.createContext)(null);
|
|
4
|
+
function DocumentEngineProvider({ engine, children }) {
|
|
5
|
+
return (0, react.createElement)(EngineContext.Provider, { value: engine }, children);
|
|
6
|
+
}
|
|
7
|
+
function useEngine() {
|
|
8
|
+
return (0, react.useContext)(EngineContext);
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
exports.DocumentEngineProvider = DocumentEngineProvider;
|
|
12
|
+
exports.useEngine = useEngine;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { DocumentEngine } from "../engine/create-document-engine.cjs";
|
|
2
|
+
import { ReactNode } from "react";
|
|
3
|
+
//#region src/react/engine-context.d.ts
|
|
4
|
+
export interface DocumentEngineProviderProps {
|
|
5
|
+
engine: DocumentEngine | null;
|
|
6
|
+
children?: ReactNode;
|
|
7
|
+
}
|
|
8
|
+
export declare function DocumentEngineProvider({ engine, children }: DocumentEngineProviderProps): ReactNode;
|
|
9
|
+
export declare function useEngine(): DocumentEngine | null;
|
|
10
|
+
//#endregion
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { DocumentEngine } from "../engine/create-document-engine.js";
|
|
2
|
+
import { ReactNode } from "react";
|
|
3
|
+
//#region src/react/engine-context.d.ts
|
|
4
|
+
export interface DocumentEngineProviderProps {
|
|
5
|
+
engine: DocumentEngine | null;
|
|
6
|
+
children?: ReactNode;
|
|
7
|
+
}
|
|
8
|
+
export declare function DocumentEngineProvider({ engine, children }: DocumentEngineProviderProps): ReactNode;
|
|
9
|
+
export declare function useEngine(): DocumentEngine | null;
|
|
10
|
+
//#endregion
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createContext, createElement, useContext } from "react";
|
|
2
|
+
//#region src/react/engine-context.ts
|
|
3
|
+
const EngineContext = createContext(null);
|
|
4
|
+
function DocumentEngineProvider({ engine, children }) {
|
|
5
|
+
return createElement(EngineContext.Provider, { value: engine }, children);
|
|
6
|
+
}
|
|
7
|
+
function useEngine() {
|
|
8
|
+
return useContext(EngineContext);
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
export { DocumentEngineProvider, useEngine };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const require_create_document_engine = require("../engine/create-document-engine.cjs");
|
|
2
|
+
let react = require("react");
|
|
3
|
+
//#region src/react/use-document-engine.ts
|
|
4
|
+
function useDocumentEngine(canvas, options = {}) {
|
|
5
|
+
const latestOptions = (0, react.useRef)(options);
|
|
6
|
+
latestOptions.current = options;
|
|
7
|
+
const [engine, setEngine] = (0, react.useState)(null);
|
|
8
|
+
(0, react.useEffect)(() => {
|
|
9
|
+
if (!canvas) return void 0;
|
|
10
|
+
const created = require_create_document_engine.createDocumentEngine({
|
|
11
|
+
...latestOptions.current,
|
|
12
|
+
canvas
|
|
13
|
+
});
|
|
14
|
+
setEngine(created);
|
|
15
|
+
return () => {
|
|
16
|
+
created.destroy();
|
|
17
|
+
setEngine((current) => current === created ? null : current);
|
|
18
|
+
};
|
|
19
|
+
}, [canvas]);
|
|
20
|
+
return engine;
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
exports.useDocumentEngine = useDocumentEngine;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { DocumentEngine, DocumentEngineOptions } from "../engine/create-document-engine.cjs";
|
|
2
|
+
import { StaticCanvas } from "fabric";
|
|
3
|
+
//#region src/react/use-document-engine.d.ts
|
|
4
|
+
export type ReactEngineOptions = Omit<DocumentEngineOptions, "canvas">;
|
|
5
|
+
export declare function useDocumentEngine(canvas: StaticCanvas | null | undefined, options?: ReactEngineOptions): DocumentEngine | null;
|
|
6
|
+
//#endregion
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { DocumentEngine, DocumentEngineOptions } from "../engine/create-document-engine.js";
|
|
2
|
+
import { StaticCanvas } from "fabric";
|
|
3
|
+
//#region src/react/use-document-engine.d.ts
|
|
4
|
+
export type ReactEngineOptions = Omit<DocumentEngineOptions, "canvas">;
|
|
5
|
+
export declare function useDocumentEngine(canvas: StaticCanvas | null | undefined, options?: ReactEngineOptions): DocumentEngine | null;
|
|
6
|
+
//#endregion
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { createDocumentEngine } from "../engine/create-document-engine.js";
|
|
2
|
+
import { useEffect, useRef, useState } from "react";
|
|
3
|
+
//#region src/react/use-document-engine.ts
|
|
4
|
+
function useDocumentEngine(canvas, options = {}) {
|
|
5
|
+
const latestOptions = useRef(options);
|
|
6
|
+
latestOptions.current = options;
|
|
7
|
+
const [engine, setEngine] = useState(null);
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
if (!canvas) return void 0;
|
|
10
|
+
const created = createDocumentEngine({
|
|
11
|
+
...latestOptions.current,
|
|
12
|
+
canvas
|
|
13
|
+
});
|
|
14
|
+
setEngine(created);
|
|
15
|
+
return () => {
|
|
16
|
+
created.destroy();
|
|
17
|
+
setEngine((current) => current === created ? null : current);
|
|
18
|
+
};
|
|
19
|
+
}, [canvas]);
|
|
20
|
+
return engine;
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
export { useDocumentEngine };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
let react = require("react");
|
|
2
|
+
//#region src/react/use-document-event.ts
|
|
3
|
+
function useDocumentEvent(engine, name, handler) {
|
|
4
|
+
const latestHandler = (0, react.useRef)(handler);
|
|
5
|
+
latestHandler.current = handler;
|
|
6
|
+
(0, react.useEffect)(() => {
|
|
7
|
+
if (!engine) return void 0;
|
|
8
|
+
return engine.on(name, (payload) => latestHandler.current(payload));
|
|
9
|
+
}, [engine, name]);
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
exports.useDocumentEvent = useDocumentEvent;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { DocumentEngine, DocumentEngineEvents } from "../engine/create-document-engine.cjs";
|
|
2
|
+
//#region src/react/use-document-event.d.ts
|
|
3
|
+
export declare function useDocumentEvent<Name extends keyof DocumentEngineEvents>(engine: DocumentEngine | null | undefined, name: Name, handler: (payload: DocumentEngineEvents[Name]) => void): void;
|
|
4
|
+
//#endregion
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { DocumentEngine, DocumentEngineEvents } from "../engine/create-document-engine.js";
|
|
2
|
+
//#region src/react/use-document-event.d.ts
|
|
3
|
+
export declare function useDocumentEvent<Name extends keyof DocumentEngineEvents>(engine: DocumentEngine | null | undefined, name: Name, handler: (payload: DocumentEngineEvents[Name]) => void): void;
|
|
4
|
+
//#endregion
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { useEffect, useRef } from "react";
|
|
2
|
+
//#region src/react/use-document-event.ts
|
|
3
|
+
function useDocumentEvent(engine, name, handler) {
|
|
4
|
+
const latestHandler = useRef(handler);
|
|
5
|
+
latestHandler.current = handler;
|
|
6
|
+
useEffect(() => {
|
|
7
|
+
if (!engine) return void 0;
|
|
8
|
+
return engine.on(name, (payload) => latestHandler.current(payload));
|
|
9
|
+
}, [engine, name]);
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
export { useDocumentEvent };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const require_document_state_store = require("../state/document-state-store.cjs");
|
|
2
|
+
let react = require("react");
|
|
3
|
+
//#region src/react/use-document-state.ts
|
|
4
|
+
const subscribeToNothing = () => () => void 0;
|
|
5
|
+
const nothing = () => null;
|
|
6
|
+
function useDocumentState(engine) {
|
|
7
|
+
const store = (0, react.useMemo)(() => engine ? require_document_state_store.createDocumentStateStore(engine) : null, [engine]);
|
|
8
|
+
return (0, react.useSyncExternalStore)(store ? store.subscribe : subscribeToNothing, store ? store.getSnapshot : nothing, nothing);
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
exports.useDocumentState = useDocumentState;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { DocumentEngine } from "../engine/create-document-engine.cjs";
|
|
2
|
+
import { DocumentState } from "../state/document-state-store.cjs";
|
|
3
|
+
//#region src/react/use-document-state.d.ts
|
|
4
|
+
export declare function useDocumentState(engine: DocumentEngine | null | undefined): DocumentState | null;
|
|
5
|
+
//#endregion
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { DocumentEngine } from "../engine/create-document-engine.js";
|
|
2
|
+
import { DocumentState } from "../state/document-state-store.js";
|
|
3
|
+
//#region src/react/use-document-state.d.ts
|
|
4
|
+
export declare function useDocumentState(engine: DocumentEngine | null | undefined): DocumentState | null;
|
|
5
|
+
//#endregion
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createDocumentStateStore } from "../state/document-state-store.js";
|
|
2
|
+
import { useMemo, useSyncExternalStore } from "react";
|
|
3
|
+
//#region src/react/use-document-state.ts
|
|
4
|
+
const subscribeToNothing = () => () => void 0;
|
|
5
|
+
const nothing = () => null;
|
|
6
|
+
function useDocumentState(engine) {
|
|
7
|
+
const store = useMemo(() => engine ? createDocumentStateStore(engine) : null, [engine]);
|
|
8
|
+
return useSyncExternalStore(store ? store.subscribe : subscribeToNothing, store ? store.getSnapshot : nothing, nothing);
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
export { useDocumentState };
|
package/dist/react.cjs
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const require_use_document_engine = require("./react/use-document-engine.cjs");
|
|
4
|
+
const require_use_document_state = require("./react/use-document-state.cjs");
|
|
5
|
+
const require_use_document_event = require("./react/use-document-event.cjs");
|
|
6
|
+
const require_engine_context = require("./react/engine-context.cjs");
|
|
7
|
+
exports.DocumentEngineProvider = require_engine_context.DocumentEngineProvider;
|
|
8
|
+
exports.useDocumentEngine = require_use_document_engine.useDocumentEngine;
|
|
9
|
+
exports.useDocumentEvent = require_use_document_event.useDocumentEvent;
|
|
10
|
+
exports.useDocumentState = require_use_document_state.useDocumentState;
|
|
11
|
+
exports.useEngine = require_engine_context.useEngine;
|
package/dist/react.d.cts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { DocumentState } from "./state/document-state-store.cjs";
|
|
2
|
+
import { ReactEngineOptions, useDocumentEngine } from "./react/use-document-engine.cjs";
|
|
3
|
+
import { useDocumentState } from "./react/use-document-state.cjs";
|
|
4
|
+
import { useDocumentEvent } from "./react/use-document-event.cjs";
|
|
5
|
+
import { DocumentEngineProvider, DocumentEngineProviderProps, useEngine } from "./react/engine-context.cjs";
|
|
6
|
+
export { DocumentEngineProvider, type DocumentEngineProviderProps, type DocumentState, type ReactEngineOptions, useDocumentEngine, useDocumentEvent, useDocumentState, useEngine };
|
package/dist/react.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { DocumentState } from "./state/document-state-store.js";
|
|
2
|
+
import { ReactEngineOptions, useDocumentEngine } from "./react/use-document-engine.js";
|
|
3
|
+
import { useDocumentState } from "./react/use-document-state.js";
|
|
4
|
+
import { useDocumentEvent } from "./react/use-document-event.js";
|
|
5
|
+
import { DocumentEngineProvider, DocumentEngineProviderProps, useEngine } from "./react/engine-context.js";
|
|
6
|
+
export { DocumentEngineProvider, type DocumentEngineProviderProps, type DocumentState, type ReactEngineOptions, useDocumentEngine, useDocumentEvent, useDocumentState, useEngine };
|
package/dist/react.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useDocumentEngine } from "./react/use-document-engine.js";
|
|
3
|
+
import { useDocumentState } from "./react/use-document-state.js";
|
|
4
|
+
import { useDocumentEvent } from "./react/use-document-event.js";
|
|
5
|
+
import { DocumentEngineProvider, useEngine } from "./react/engine-context.js";
|
|
6
|
+
export { DocumentEngineProvider, useDocumentEngine, useDocumentEvent, useDocumentState, useEngine };
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
//#region src/state/document-state-store.ts
|
|
2
|
+
function initialState(engine) {
|
|
3
|
+
const saveState = engine.getSaveState();
|
|
4
|
+
const history = engine.getHistory();
|
|
5
|
+
return {
|
|
6
|
+
documentId: engine.getDocumentInfo().id,
|
|
7
|
+
isLoading: false,
|
|
8
|
+
loadError: void 0,
|
|
9
|
+
saveStatus: saveState.status,
|
|
10
|
+
isDirty: saveState.isDirty,
|
|
11
|
+
isSaving: saveState.isSaving,
|
|
12
|
+
revision: saveState.revision,
|
|
13
|
+
lastSavedAt: saveState.lastSavedAt,
|
|
14
|
+
saveError: saveState.error,
|
|
15
|
+
canUndo: history.undo.length > 0,
|
|
16
|
+
canRedo: history.redo.length > 0,
|
|
17
|
+
undoLabel: history.undo[0],
|
|
18
|
+
redoLabel: history.redo[0],
|
|
19
|
+
assetWarnings: []
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function withLiveEngineValues(engine, previous) {
|
|
23
|
+
return {
|
|
24
|
+
...previous,
|
|
25
|
+
...initialState(engine),
|
|
26
|
+
isLoading: previous.isLoading,
|
|
27
|
+
loadError: previous.loadError,
|
|
28
|
+
assetWarnings: previous.assetWarnings
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function isSameState(first, second) {
|
|
32
|
+
return Object.keys(first).every((key) => first[key] === second[key]);
|
|
33
|
+
}
|
|
34
|
+
function createDocumentStateStore(engine) {
|
|
35
|
+
let state = initialState(engine);
|
|
36
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
37
|
+
let detachFromEngine;
|
|
38
|
+
function update(changes) {
|
|
39
|
+
const next = {
|
|
40
|
+
...state,
|
|
41
|
+
...changes
|
|
42
|
+
};
|
|
43
|
+
if (isSameState(state, next)) return;
|
|
44
|
+
state = next;
|
|
45
|
+
for (const listener of [...listeners]) listener();
|
|
46
|
+
}
|
|
47
|
+
function attachToEngine() {
|
|
48
|
+
const unsubscribers = [
|
|
49
|
+
engine.on("load:start", () => update({
|
|
50
|
+
isLoading: true,
|
|
51
|
+
loadError: void 0
|
|
52
|
+
})),
|
|
53
|
+
engine.on("load:success", ({ warnings }) => update({
|
|
54
|
+
isLoading: false,
|
|
55
|
+
assetWarnings: warnings
|
|
56
|
+
})),
|
|
57
|
+
engine.on("load:error", ({ error }) => {
|
|
58
|
+
if (error.code !== "LOAD_ABORTED") update({
|
|
59
|
+
isLoading: false,
|
|
60
|
+
loadError: error
|
|
61
|
+
});
|
|
62
|
+
}),
|
|
63
|
+
engine.on("document:change", ({ documentId }) => update({
|
|
64
|
+
documentId,
|
|
65
|
+
loadError: void 0
|
|
66
|
+
})),
|
|
67
|
+
engine.on("assets:warning", ({ warnings }) => update({ assetWarnings: warnings })),
|
|
68
|
+
engine.on("save:status", (saveState) => update({
|
|
69
|
+
saveStatus: saveState.status,
|
|
70
|
+
isDirty: saveState.isDirty,
|
|
71
|
+
isSaving: saveState.isSaving,
|
|
72
|
+
revision: saveState.revision,
|
|
73
|
+
lastSavedAt: saveState.lastSavedAt,
|
|
74
|
+
saveError: saveState.error
|
|
75
|
+
})),
|
|
76
|
+
engine.on("history:change", (history) => update({
|
|
77
|
+
canUndo: history.canUndo,
|
|
78
|
+
canRedo: history.canRedo,
|
|
79
|
+
undoLabel: history.undoLabel,
|
|
80
|
+
redoLabel: history.redoLabel
|
|
81
|
+
}))
|
|
82
|
+
];
|
|
83
|
+
return () => unsubscribers.forEach((unsubscribe) => unsubscribe());
|
|
84
|
+
}
|
|
85
|
+
function refreshWhileDetached() {
|
|
86
|
+
if (detachFromEngine) return;
|
|
87
|
+
const fresh = withLiveEngineValues(engine, state);
|
|
88
|
+
if (!isSameState(state, fresh)) state = fresh;
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
getSnapshot() {
|
|
92
|
+
refreshWhileDetached();
|
|
93
|
+
return state;
|
|
94
|
+
},
|
|
95
|
+
subscribe(listener) {
|
|
96
|
+
refreshWhileDetached();
|
|
97
|
+
listeners.add(listener);
|
|
98
|
+
detachFromEngine ?? (detachFromEngine = attachToEngine());
|
|
99
|
+
return () => {
|
|
100
|
+
listeners.delete(listener);
|
|
101
|
+
if (listeners.size > 0) return;
|
|
102
|
+
detachFromEngine?.();
|
|
103
|
+
detachFromEngine = void 0;
|
|
104
|
+
};
|
|
105
|
+
},
|
|
106
|
+
destroy() {
|
|
107
|
+
listeners.clear();
|
|
108
|
+
detachFromEngine?.();
|
|
109
|
+
detachFromEngine = void 0;
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
//#endregion
|
|
114
|
+
exports.createDocumentStateStore = createDocumentStateStore;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { AssetWarning } from "../assets/asset-pipeline.cjs";
|
|
2
|
+
import { DocumentEngineError } from "../engine/errors.cjs";
|
|
3
|
+
import { SaveStatus } from "../save/save-controller.cjs";
|
|
4
|
+
import { DocumentEngine } from "../engine/create-document-engine.cjs";
|
|
5
|
+
//#region src/state/document-state-store.d.ts
|
|
6
|
+
export interface DocumentState {
|
|
7
|
+
documentId: string;
|
|
8
|
+
isLoading: boolean;
|
|
9
|
+
loadError: DocumentEngineError | undefined;
|
|
10
|
+
saveStatus: SaveStatus;
|
|
11
|
+
isDirty: boolean;
|
|
12
|
+
isSaving: boolean;
|
|
13
|
+
revision: number;
|
|
14
|
+
lastSavedAt: string | undefined;
|
|
15
|
+
saveError: DocumentEngineError | undefined;
|
|
16
|
+
canUndo: boolean;
|
|
17
|
+
canRedo: boolean;
|
|
18
|
+
undoLabel: string | undefined;
|
|
19
|
+
redoLabel: string | undefined;
|
|
20
|
+
assetWarnings: AssetWarning[];
|
|
21
|
+
}
|
|
22
|
+
export interface DocumentStateStore {
|
|
23
|
+
getSnapshot(): DocumentState;
|
|
24
|
+
subscribe(listener: () => void): () => void;
|
|
25
|
+
destroy(): void;
|
|
26
|
+
}
|
|
27
|
+
export declare function createDocumentStateStore(engine: DocumentEngine): DocumentStateStore;
|
|
28
|
+
//#endregion
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { AssetWarning } from "../assets/asset-pipeline.js";
|
|
2
|
+
import { DocumentEngineError } from "../engine/errors.js";
|
|
3
|
+
import { SaveStatus } from "../save/save-controller.js";
|
|
4
|
+
import { DocumentEngine } from "../engine/create-document-engine.js";
|
|
5
|
+
//#region src/state/document-state-store.d.ts
|
|
6
|
+
export interface DocumentState {
|
|
7
|
+
documentId: string;
|
|
8
|
+
isLoading: boolean;
|
|
9
|
+
loadError: DocumentEngineError | undefined;
|
|
10
|
+
saveStatus: SaveStatus;
|
|
11
|
+
isDirty: boolean;
|
|
12
|
+
isSaving: boolean;
|
|
13
|
+
revision: number;
|
|
14
|
+
lastSavedAt: string | undefined;
|
|
15
|
+
saveError: DocumentEngineError | undefined;
|
|
16
|
+
canUndo: boolean;
|
|
17
|
+
canRedo: boolean;
|
|
18
|
+
undoLabel: string | undefined;
|
|
19
|
+
redoLabel: string | undefined;
|
|
20
|
+
assetWarnings: AssetWarning[];
|
|
21
|
+
}
|
|
22
|
+
export interface DocumentStateStore {
|
|
23
|
+
getSnapshot(): DocumentState;
|
|
24
|
+
subscribe(listener: () => void): () => void;
|
|
25
|
+
destroy(): void;
|
|
26
|
+
}
|
|
27
|
+
export declare function createDocumentStateStore(engine: DocumentEngine): DocumentStateStore;
|
|
28
|
+
//#endregion
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
//#region src/state/document-state-store.ts
|
|
2
|
+
function initialState(engine) {
|
|
3
|
+
const saveState = engine.getSaveState();
|
|
4
|
+
const history = engine.getHistory();
|
|
5
|
+
return {
|
|
6
|
+
documentId: engine.getDocumentInfo().id,
|
|
7
|
+
isLoading: false,
|
|
8
|
+
loadError: void 0,
|
|
9
|
+
saveStatus: saveState.status,
|
|
10
|
+
isDirty: saveState.isDirty,
|
|
11
|
+
isSaving: saveState.isSaving,
|
|
12
|
+
revision: saveState.revision,
|
|
13
|
+
lastSavedAt: saveState.lastSavedAt,
|
|
14
|
+
saveError: saveState.error,
|
|
15
|
+
canUndo: history.undo.length > 0,
|
|
16
|
+
canRedo: history.redo.length > 0,
|
|
17
|
+
undoLabel: history.undo[0],
|
|
18
|
+
redoLabel: history.redo[0],
|
|
19
|
+
assetWarnings: []
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function withLiveEngineValues(engine, previous) {
|
|
23
|
+
return {
|
|
24
|
+
...previous,
|
|
25
|
+
...initialState(engine),
|
|
26
|
+
isLoading: previous.isLoading,
|
|
27
|
+
loadError: previous.loadError,
|
|
28
|
+
assetWarnings: previous.assetWarnings
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function isSameState(first, second) {
|
|
32
|
+
return Object.keys(first).every((key) => first[key] === second[key]);
|
|
33
|
+
}
|
|
34
|
+
function createDocumentStateStore(engine) {
|
|
35
|
+
let state = initialState(engine);
|
|
36
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
37
|
+
let detachFromEngine;
|
|
38
|
+
function update(changes) {
|
|
39
|
+
const next = {
|
|
40
|
+
...state,
|
|
41
|
+
...changes
|
|
42
|
+
};
|
|
43
|
+
if (isSameState(state, next)) return;
|
|
44
|
+
state = next;
|
|
45
|
+
for (const listener of [...listeners]) listener();
|
|
46
|
+
}
|
|
47
|
+
function attachToEngine() {
|
|
48
|
+
const unsubscribers = [
|
|
49
|
+
engine.on("load:start", () => update({
|
|
50
|
+
isLoading: true,
|
|
51
|
+
loadError: void 0
|
|
52
|
+
})),
|
|
53
|
+
engine.on("load:success", ({ warnings }) => update({
|
|
54
|
+
isLoading: false,
|
|
55
|
+
assetWarnings: warnings
|
|
56
|
+
})),
|
|
57
|
+
engine.on("load:error", ({ error }) => {
|
|
58
|
+
if (error.code !== "LOAD_ABORTED") update({
|
|
59
|
+
isLoading: false,
|
|
60
|
+
loadError: error
|
|
61
|
+
});
|
|
62
|
+
}),
|
|
63
|
+
engine.on("document:change", ({ documentId }) => update({
|
|
64
|
+
documentId,
|
|
65
|
+
loadError: void 0
|
|
66
|
+
})),
|
|
67
|
+
engine.on("assets:warning", ({ warnings }) => update({ assetWarnings: warnings })),
|
|
68
|
+
engine.on("save:status", (saveState) => update({
|
|
69
|
+
saveStatus: saveState.status,
|
|
70
|
+
isDirty: saveState.isDirty,
|
|
71
|
+
isSaving: saveState.isSaving,
|
|
72
|
+
revision: saveState.revision,
|
|
73
|
+
lastSavedAt: saveState.lastSavedAt,
|
|
74
|
+
saveError: saveState.error
|
|
75
|
+
})),
|
|
76
|
+
engine.on("history:change", (history) => update({
|
|
77
|
+
canUndo: history.canUndo,
|
|
78
|
+
canRedo: history.canRedo,
|
|
79
|
+
undoLabel: history.undoLabel,
|
|
80
|
+
redoLabel: history.redoLabel
|
|
81
|
+
}))
|
|
82
|
+
];
|
|
83
|
+
return () => unsubscribers.forEach((unsubscribe) => unsubscribe());
|
|
84
|
+
}
|
|
85
|
+
function refreshWhileDetached() {
|
|
86
|
+
if (detachFromEngine) return;
|
|
87
|
+
const fresh = withLiveEngineValues(engine, state);
|
|
88
|
+
if (!isSameState(state, fresh)) state = fresh;
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
getSnapshot() {
|
|
92
|
+
refreshWhileDetached();
|
|
93
|
+
return state;
|
|
94
|
+
},
|
|
95
|
+
subscribe(listener) {
|
|
96
|
+
refreshWhileDetached();
|
|
97
|
+
listeners.add(listener);
|
|
98
|
+
detachFromEngine ?? (detachFromEngine = attachToEngine());
|
|
99
|
+
return () => {
|
|
100
|
+
listeners.delete(listener);
|
|
101
|
+
if (listeners.size > 0) return;
|
|
102
|
+
detachFromEngine?.();
|
|
103
|
+
detachFromEngine = void 0;
|
|
104
|
+
};
|
|
105
|
+
},
|
|
106
|
+
destroy() {
|
|
107
|
+
listeners.clear();
|
|
108
|
+
detachFromEngine?.();
|
|
109
|
+
detachFromEngine = void 0;
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
//#endregion
|
|
114
|
+
export { createDocumentStateStore };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fabricjs-document-engine",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Turn an existing Fabric.js canvas into a dependable editable document: stable object ids, versioned save and load, undo and redo, safe autosave with conflict protection, custom objects and clear errors.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"fabric",
|
|
@@ -19,7 +19,9 @@
|
|
|
19
19
|
"editor",
|
|
20
20
|
"typescript",
|
|
21
21
|
"storage",
|
|
22
|
-
"recovery"
|
|
22
|
+
"recovery",
|
|
23
|
+
"react",
|
|
24
|
+
"react hooks"
|
|
23
25
|
],
|
|
24
26
|
"license": "MIT",
|
|
25
27
|
"author": "Sohail Khan (https://me.jscrate.dev)",
|
|
@@ -64,10 +66,20 @@
|
|
|
64
66
|
"default": "./dist/recovery.cjs"
|
|
65
67
|
}
|
|
66
68
|
},
|
|
69
|
+
"./react": {
|
|
70
|
+
"import": {
|
|
71
|
+
"types": "./dist/react.d.ts",
|
|
72
|
+
"default": "./dist/react.js"
|
|
73
|
+
},
|
|
74
|
+
"require": {
|
|
75
|
+
"types": "./dist/react.d.cts",
|
|
76
|
+
"default": "./dist/react.cjs"
|
|
77
|
+
}
|
|
78
|
+
},
|
|
67
79
|
"./package.json": "./package.json"
|
|
68
80
|
},
|
|
69
81
|
"scripts": {
|
|
70
|
-
"build": "tsdown && npm run lint:publint && npm run lint:attw",
|
|
82
|
+
"build": "tsdown && node scripts/verify-build.mjs && npm run lint:publint && npm run lint:attw",
|
|
71
83
|
"dev": "tsdown --watch",
|
|
72
84
|
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.tools.json",
|
|
73
85
|
"test": "vitest run",
|
|
@@ -80,7 +92,8 @@
|
|
|
80
92
|
"release": "changeset publish"
|
|
81
93
|
},
|
|
82
94
|
"peerDependencies": {
|
|
83
|
-
"fabric": "^6.0.0 || ^7.0.0"
|
|
95
|
+
"fabric": "^6.0.0 || ^7.0.0",
|
|
96
|
+
"react": "^18.0.0 || ^19.0.0"
|
|
84
97
|
},
|
|
85
98
|
"publishConfig": {
|
|
86
99
|
"access": "public",
|
|
@@ -101,13 +114,22 @@
|
|
|
101
114
|
"@arethetypeswrong/cli": "^0.18.5",
|
|
102
115
|
"@changesets/cli": "^3.0.3",
|
|
103
116
|
"@types/node": "^22.20.4",
|
|
117
|
+
"@types/react": "^19.3.0",
|
|
118
|
+
"@types/react-dom": "^19.3.0",
|
|
104
119
|
"@vitest/browser-playwright": "^5.0.2",
|
|
105
120
|
"fabric": "^7.4.0",
|
|
106
121
|
"fabric6": "npm:fabric@^6.9.1",
|
|
107
122
|
"playwright": "^1.63.0",
|
|
108
123
|
"publint": "^0.3.24",
|
|
124
|
+
"react": "^19.3.0",
|
|
125
|
+
"react-dom": "^19.3.0",
|
|
109
126
|
"tsdown": "^0.23.0",
|
|
110
127
|
"typescript": "^5.9.3",
|
|
111
128
|
"vitest": "^5.0.2"
|
|
129
|
+
},
|
|
130
|
+
"peerDependenciesMeta": {
|
|
131
|
+
"react": {
|
|
132
|
+
"optional": true
|
|
133
|
+
}
|
|
112
134
|
}
|
|
113
135
|
}
|