fabricjs-document-engine 0.5.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 +82 -3
- package/dist/engine/create-document-engine.cjs +107 -4
- package/dist/engine/create-document-engine.d.cts +23 -0
- package/dist/engine/create-document-engine.d.ts +23 -0
- package/dist/engine/create-document-engine.js +107 -4
- package/dist/engine/errors.cjs +1 -0
- package/dist/engine/errors.d.cts +3 -1
- package/dist/engine/errors.d.ts +3 -1
- package/dist/engine/errors.js +1 -0
- package/dist/index.cjs +5 -0
- package/dist/index.d.cts +5 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.js +3 -1
- package/dist/migrations/migrate-document.cjs +65 -0
- package/dist/migrations/migrate-document.d.cts +15 -0
- package/dist/migrations/migrate-document.d.ts +15 -0
- package/dist/migrations/migrate-document.js +63 -0
- 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/dist/storage/key-value-storage.cjs +27 -1
- package/dist/storage/key-value-storage.d.cts +2 -1
- package/dist/storage/key-value-storage.d.ts +2 -1
- package/dist/storage/key-value-storage.js +27 -1
- package/dist/storage.d.cts +2 -1
- package/dist/storage.d.ts +2 -1
- package/dist/versions/document-version.cjs +20 -0
- package/dist/versions/document-version.d.cts +25 -0
- package/dist/versions/document-version.d.ts +25 -0
- package/dist/versions/document-version.js +17 -0
- package/package.json +26 -4
package/dist/engine/errors.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { FontAsset, ImageAsset } from "../assets/asset-manifest.js";
|
|
2
2
|
import { ExportProblem } from "../export/preflight-export.js";
|
|
3
3
|
//#region src/engine/errors.d.ts
|
|
4
|
-
export type DocumentErrorCode = "INVALID_DOCUMENT" | "UNSUPPORTED_SCHEMA" | "UNKNOWN_OBJECT_TYPE" | "INVALID_CUSTOM_OBJECT" | "LOAD_ABORTED" | "LOAD_FAILED" | "MISSING_ASSETS" | "MISSING_FONTS" | "ASSET_UPLOAD_FAILED" | "STORAGE_MISSING" | "SAVE_FAILED" | "SAVE_CONFLICT" | "SAVE_CANCELLED" | "DOCUMENT_NOT_FOUND" | "HISTORY_FAILED" | "RECOVERY_MISSING" | "RECOVERY_NOT_FOUND" | "RECOVERY_FAILED" | "INVALID_EXPORT_OPTIONS" | "EXPORT_BLOCKED" | "EXPORT_FAILED" | "EXPORT_ABORTED" | "ENGINE_DESTROYED";
|
|
4
|
+
export type DocumentErrorCode = "INVALID_DOCUMENT" | "UNSUPPORTED_SCHEMA" | "UNKNOWN_OBJECT_TYPE" | "INVALID_CUSTOM_OBJECT" | "LOAD_ABORTED" | "LOAD_FAILED" | "MISSING_ASSETS" | "MISSING_FONTS" | "ASSET_UPLOAD_FAILED" | "STORAGE_MISSING" | "SAVE_FAILED" | "SAVE_CONFLICT" | "SAVE_CANCELLED" | "DOCUMENT_NOT_FOUND" | "HISTORY_FAILED" | "RECOVERY_MISSING" | "RECOVERY_NOT_FOUND" | "RECOVERY_FAILED" | "MIGRATION_FAILED" | "VERSIONS_UNSUPPORTED" | "VERSION_NOT_FOUND" | "VERSION_FAILED" | "INVALID_EXPORT_OPTIONS" | "EXPORT_BLOCKED" | "EXPORT_FAILED" | "EXPORT_ABORTED" | "ENGINE_DESTROYED";
|
|
5
5
|
export interface DocumentIssue {
|
|
6
6
|
code: DocumentErrorCode;
|
|
7
7
|
path: string;
|
|
@@ -13,6 +13,7 @@ export interface DocumentEngineErrorDetails {
|
|
|
13
13
|
missingAssets?: ImageAsset[];
|
|
14
14
|
missingFonts?: FontAsset[];
|
|
15
15
|
problems?: ExportProblem[];
|
|
16
|
+
migrationFrom?: number;
|
|
16
17
|
cause?: unknown;
|
|
17
18
|
retryable?: boolean;
|
|
18
19
|
}
|
|
@@ -23,6 +24,7 @@ export declare class DocumentEngineError extends Error {
|
|
|
23
24
|
readonly missingAssets: ImageAsset[];
|
|
24
25
|
readonly missingFonts: FontAsset[];
|
|
25
26
|
readonly problems: ExportProblem[];
|
|
27
|
+
readonly migrationFrom: number | undefined;
|
|
26
28
|
readonly cause: unknown;
|
|
27
29
|
readonly retryable: boolean;
|
|
28
30
|
constructor(code: DocumentErrorCode, message: string, details?: DocumentEngineErrorDetails);
|
package/dist/engine/errors.js
CHANGED
|
@@ -9,6 +9,7 @@ var DocumentEngineError = class extends Error {
|
|
|
9
9
|
this.missingAssets = details.missingAssets ?? [];
|
|
10
10
|
this.missingFonts = details.missingFonts ?? [];
|
|
11
11
|
this.problems = details.problems ?? [];
|
|
12
|
+
this.migrationFrom = details.migrationFrom;
|
|
12
13
|
this.cause = details.cause;
|
|
13
14
|
this.retryable = details.retryable ?? false;
|
|
14
15
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -2,16 +2,21 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
2
2
|
const require_errors = require("./engine/errors.cjs");
|
|
3
3
|
const require_document_format = require("./document/document-format.cjs");
|
|
4
4
|
const require_validate_document = require("./document/validate-document.cjs");
|
|
5
|
+
const require_migrate_document = require("./migrations/migrate-document.cjs");
|
|
5
6
|
const require_create_document_engine = require("./engine/create-document-engine.cjs");
|
|
6
7
|
const require_keyboard_shortcuts = require("./history/keyboard-shortcuts.cjs");
|
|
7
8
|
const require_unsaved_changes_warning = require("./save/unsaved-changes-warning.cjs");
|
|
8
9
|
const require_download_export = require("./export/download-export.cjs");
|
|
10
|
+
const require_document_state_store = require("./state/document-state-store.cjs");
|
|
9
11
|
exports.CURRENT_SCHEMA_VERSION = require_document_format.CURRENT_SCHEMA_VERSION;
|
|
10
12
|
exports.DocumentEngineError = require_errors.DocumentEngineError;
|
|
11
13
|
exports.bindKeyboardShortcuts = require_keyboard_shortcuts.bindKeyboardShortcuts;
|
|
12
14
|
exports.bindUnsavedChangesWarning = require_unsaved_changes_warning.bindUnsavedChangesWarning;
|
|
13
15
|
exports.createConflictError = require_errors.createConflictError;
|
|
14
16
|
exports.createDocumentEngine = require_create_document_engine.createDocumentEngine;
|
|
17
|
+
exports.createDocumentStateStore = require_document_state_store.createDocumentStateStore;
|
|
18
|
+
exports.detectSchemaVersion = require_migrate_document.detectSchemaVersion;
|
|
15
19
|
exports.downloadExport = require_download_export.downloadExport;
|
|
16
20
|
exports.isDocumentEngineError = require_errors.isDocumentEngineError;
|
|
21
|
+
exports.migrateDocument = require_migrate_document.migrateDocument;
|
|
17
22
|
exports.validateDocument = require_validate_document.validateDocument;
|
package/dist/index.d.cts
CHANGED
|
@@ -7,6 +7,7 @@ import { ExportPreflight, ExportProblem, ExportProblemCode } from "./export/pref
|
|
|
7
7
|
import { NewDocumentOptions } from "./document/create-document.cjs";
|
|
8
8
|
import { CustomObjectDefinition } from "./fabric/object-registry.cjs";
|
|
9
9
|
import { HistoryOptions, HistoryState } from "./history/create-history.cjs";
|
|
10
|
+
import { DocumentVersion, VersionKind, VersionOptions, VersionStorage, VersionSummary } from "./versions/document-version.cjs";
|
|
10
11
|
import { RecoveryStore } from "./recovery/recovery-store.cjs";
|
|
11
12
|
import { InterruptedLoad, RecoveryOptions, RecoveryRecord } from "./recovery/recovery-controller.cjs";
|
|
12
13
|
import { AutosaveOptions } from "./save/autosave-scheduler.cjs";
|
|
@@ -15,9 +16,11 @@ import { DocumentEngineError, DocumentEngineErrorDetails, DocumentErrorCode, Doc
|
|
|
15
16
|
import { DocumentStorage, SaveContext, SaveResult } from "./storage/storage-contract.cjs";
|
|
16
17
|
import { SaveOptions, SaveRetryEvent, SaveState, SaveStatus } from "./save/save-controller.cjs";
|
|
17
18
|
import { Unsubscribe } from "./engine/event-emitter.cjs";
|
|
18
|
-
import { DocumentEngine, DocumentEngineEvents, DocumentEngineOptions, ExportResult, LoadOptions, createDocumentEngine } from "./engine/create-document-engine.cjs";
|
|
19
|
+
import { DocumentEngine, DocumentEngineEvents, DocumentEngineOptions, ExportResult, ImportOptions, LoadOptions, createDocumentEngine } from "./engine/create-document-engine.cjs";
|
|
19
20
|
import { validateDocument } from "./document/validate-document.cjs";
|
|
20
21
|
import { KeyboardShortcutOptions, UndoRedoTarget, bindKeyboardShortcuts } from "./history/keyboard-shortcuts.cjs";
|
|
21
22
|
import { UnsavedChangesSource, bindUnsavedChangesWarning } from "./save/unsaved-changes-warning.cjs";
|
|
22
23
|
import { DownloadableExport, downloadExport } from "./export/download-export.cjs";
|
|
23
|
-
|
|
24
|
+
import { Migration, MigrationContext, MigrationResult, detectSchemaVersion, migrateDocument } from "./migrations/migrate-document.cjs";
|
|
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
|
@@ -7,6 +7,7 @@ import { ExportPreflight, ExportProblem, ExportProblemCode } from "./export/pref
|
|
|
7
7
|
import { NewDocumentOptions } from "./document/create-document.js";
|
|
8
8
|
import { CustomObjectDefinition } from "./fabric/object-registry.js";
|
|
9
9
|
import { HistoryOptions, HistoryState } from "./history/create-history.js";
|
|
10
|
+
import { DocumentVersion, VersionKind, VersionOptions, VersionStorage, VersionSummary } from "./versions/document-version.js";
|
|
10
11
|
import { RecoveryStore } from "./recovery/recovery-store.js";
|
|
11
12
|
import { InterruptedLoad, RecoveryOptions, RecoveryRecord } from "./recovery/recovery-controller.js";
|
|
12
13
|
import { AutosaveOptions } from "./save/autosave-scheduler.js";
|
|
@@ -15,9 +16,11 @@ import { DocumentEngineError, DocumentEngineErrorDetails, DocumentErrorCode, Doc
|
|
|
15
16
|
import { DocumentStorage, SaveContext, SaveResult } from "./storage/storage-contract.js";
|
|
16
17
|
import { SaveOptions, SaveRetryEvent, SaveState, SaveStatus } from "./save/save-controller.js";
|
|
17
18
|
import { Unsubscribe } from "./engine/event-emitter.js";
|
|
18
|
-
import { DocumentEngine, DocumentEngineEvents, DocumentEngineOptions, ExportResult, LoadOptions, createDocumentEngine } from "./engine/create-document-engine.js";
|
|
19
|
+
import { DocumentEngine, DocumentEngineEvents, DocumentEngineOptions, ExportResult, ImportOptions, LoadOptions, createDocumentEngine } from "./engine/create-document-engine.js";
|
|
19
20
|
import { validateDocument } from "./document/validate-document.js";
|
|
20
21
|
import { KeyboardShortcutOptions, UndoRedoTarget, bindKeyboardShortcuts } from "./history/keyboard-shortcuts.js";
|
|
21
22
|
import { UnsavedChangesSource, bindUnsavedChangesWarning } from "./save/unsaved-changes-warning.js";
|
|
22
23
|
import { DownloadableExport, downloadExport } from "./export/download-export.js";
|
|
23
|
-
|
|
24
|
+
import { Migration, MigrationContext, MigrationResult, detectSchemaVersion, migrateDocument } from "./migrations/migrate-document.js";
|
|
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
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { DocumentEngineError, createConflictError, isDocumentEngineError } from "./engine/errors.js";
|
|
2
2
|
import { CURRENT_SCHEMA_VERSION } from "./document/document-format.js";
|
|
3
3
|
import { validateDocument } from "./document/validate-document.js";
|
|
4
|
+
import { detectSchemaVersion, migrateDocument } from "./migrations/migrate-document.js";
|
|
4
5
|
import { createDocumentEngine } from "./engine/create-document-engine.js";
|
|
5
6
|
import { bindKeyboardShortcuts } from "./history/keyboard-shortcuts.js";
|
|
6
7
|
import { bindUnsavedChangesWarning } from "./save/unsaved-changes-warning.js";
|
|
7
8
|
import { downloadExport } from "./export/download-export.js";
|
|
8
|
-
|
|
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,65 @@
|
|
|
1
|
+
const require_errors = require("../engine/errors.cjs");
|
|
2
|
+
require("../document/document-format.cjs");
|
|
3
|
+
const require_ids = require("../document/ids.cjs");
|
|
4
|
+
//#region src/migrations/migrate-document.ts
|
|
5
|
+
function isPlainObject(value) {
|
|
6
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7
|
+
}
|
|
8
|
+
function positiveNumberOr(value, fallback) {
|
|
9
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : fallback;
|
|
10
|
+
}
|
|
11
|
+
function fromFabricJson(json, context) {
|
|
12
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
13
|
+
const document = {
|
|
14
|
+
schemaVersion: 1,
|
|
15
|
+
id: context.id ?? (typeof json.id === "string" && json.id.length > 0 ? json.id : require_ids.createId()),
|
|
16
|
+
createdAt: now,
|
|
17
|
+
updatedAt: now,
|
|
18
|
+
revision: 0,
|
|
19
|
+
canvas: {
|
|
20
|
+
width: positiveNumberOr(json.width, context.canvasWidth),
|
|
21
|
+
height: positiveNumberOr(json.height, context.canvasHeight),
|
|
22
|
+
...json.background === void 0 ? {} : { background: json.background }
|
|
23
|
+
},
|
|
24
|
+
objects: json.objects,
|
|
25
|
+
metadata: { ...context.metadata }
|
|
26
|
+
};
|
|
27
|
+
if (typeof json.version === "string") document.fabricVersion = json.version;
|
|
28
|
+
return document;
|
|
29
|
+
}
|
|
30
|
+
const migrations = { 0: fromFabricJson };
|
|
31
|
+
function detectSchemaVersion(value) {
|
|
32
|
+
if (!isPlainObject(value)) return void 0;
|
|
33
|
+
if (typeof value.schemaVersion === "number" && Number.isInteger(value.schemaVersion)) return value.schemaVersion;
|
|
34
|
+
if (value.schemaVersion === void 0 && Array.isArray(value.objects)) return 0;
|
|
35
|
+
}
|
|
36
|
+
function migrateDocument(value, context, steps = migrations, targetVersion = 1) {
|
|
37
|
+
const startVersion = detectSchemaVersion(value);
|
|
38
|
+
if (startVersion === void 0 || startVersion >= targetVersion || startVersion < 0) return {
|
|
39
|
+
document: value,
|
|
40
|
+
migratedFrom: void 0
|
|
41
|
+
};
|
|
42
|
+
let document = JSON.parse(JSON.stringify(value));
|
|
43
|
+
for (let version = startVersion; version < targetVersion; version += 1) {
|
|
44
|
+
const step = steps[version];
|
|
45
|
+
if (!step) throw new require_errors.DocumentEngineError("MIGRATION_FAILED", `There is no migration from schema version ${version}`, { migrationFrom: version });
|
|
46
|
+
try {
|
|
47
|
+
document = step(document, context);
|
|
48
|
+
} catch (error) {
|
|
49
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
50
|
+
throw new require_errors.DocumentEngineError("MIGRATION_FAILED", `Could not migrate the document from schema version ${version} to ${version + 1}: ${reason}`, {
|
|
51
|
+
cause: error,
|
|
52
|
+
migrationFrom: version
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
if (document.schemaVersion !== version + 1) throw new require_errors.DocumentEngineError("MIGRATION_FAILED", `The migration from schema version ${version} produced version ${String(document.schemaVersion)} instead of ${version + 1}`, { migrationFrom: version });
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
document,
|
|
59
|
+
migratedFrom: startVersion
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
63
|
+
exports.detectSchemaVersion = detectSchemaVersion;
|
|
64
|
+
exports.migrateDocument = migrateDocument;
|
|
65
|
+
exports.migrations = migrations;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/migrations/migrate-document.d.ts
|
|
2
|
+
export interface MigrationContext {
|
|
3
|
+
canvasWidth: number;
|
|
4
|
+
canvasHeight: number;
|
|
5
|
+
id?: string;
|
|
6
|
+
metadata?: Record<string, unknown>;
|
|
7
|
+
}
|
|
8
|
+
export type Migration = (document: Record<string, unknown>, context: MigrationContext) => Record<string, unknown>;
|
|
9
|
+
export interface MigrationResult {
|
|
10
|
+
document: unknown;
|
|
11
|
+
migratedFrom: number | undefined;
|
|
12
|
+
}
|
|
13
|
+
export declare function detectSchemaVersion(value: unknown): number | undefined;
|
|
14
|
+
export declare function migrateDocument(value: unknown, context: MigrationContext, steps?: Readonly<Record<number, Migration>>, targetVersion?: number): MigrationResult;
|
|
15
|
+
//#endregion
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/migrations/migrate-document.d.ts
|
|
2
|
+
export interface MigrationContext {
|
|
3
|
+
canvasWidth: number;
|
|
4
|
+
canvasHeight: number;
|
|
5
|
+
id?: string;
|
|
6
|
+
metadata?: Record<string, unknown>;
|
|
7
|
+
}
|
|
8
|
+
export type Migration = (document: Record<string, unknown>, context: MigrationContext) => Record<string, unknown>;
|
|
9
|
+
export interface MigrationResult {
|
|
10
|
+
document: unknown;
|
|
11
|
+
migratedFrom: number | undefined;
|
|
12
|
+
}
|
|
13
|
+
export declare function detectSchemaVersion(value: unknown): number | undefined;
|
|
14
|
+
export declare function migrateDocument(value: unknown, context: MigrationContext, steps?: Readonly<Record<number, Migration>>, targetVersion?: number): MigrationResult;
|
|
15
|
+
//#endregion
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { DocumentEngineError } from "../engine/errors.js";
|
|
2
|
+
import "../document/document-format.js";
|
|
3
|
+
import { createId } from "../document/ids.js";
|
|
4
|
+
//#region src/migrations/migrate-document.ts
|
|
5
|
+
function isPlainObject(value) {
|
|
6
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7
|
+
}
|
|
8
|
+
function positiveNumberOr(value, fallback) {
|
|
9
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : fallback;
|
|
10
|
+
}
|
|
11
|
+
function fromFabricJson(json, context) {
|
|
12
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
13
|
+
const document = {
|
|
14
|
+
schemaVersion: 1,
|
|
15
|
+
id: context.id ?? (typeof json.id === "string" && json.id.length > 0 ? json.id : createId()),
|
|
16
|
+
createdAt: now,
|
|
17
|
+
updatedAt: now,
|
|
18
|
+
revision: 0,
|
|
19
|
+
canvas: {
|
|
20
|
+
width: positiveNumberOr(json.width, context.canvasWidth),
|
|
21
|
+
height: positiveNumberOr(json.height, context.canvasHeight),
|
|
22
|
+
...json.background === void 0 ? {} : { background: json.background }
|
|
23
|
+
},
|
|
24
|
+
objects: json.objects,
|
|
25
|
+
metadata: { ...context.metadata }
|
|
26
|
+
};
|
|
27
|
+
if (typeof json.version === "string") document.fabricVersion = json.version;
|
|
28
|
+
return document;
|
|
29
|
+
}
|
|
30
|
+
const migrations = { 0: fromFabricJson };
|
|
31
|
+
function detectSchemaVersion(value) {
|
|
32
|
+
if (!isPlainObject(value)) return void 0;
|
|
33
|
+
if (typeof value.schemaVersion === "number" && Number.isInteger(value.schemaVersion)) return value.schemaVersion;
|
|
34
|
+
if (value.schemaVersion === void 0 && Array.isArray(value.objects)) return 0;
|
|
35
|
+
}
|
|
36
|
+
function migrateDocument(value, context, steps = migrations, targetVersion = 1) {
|
|
37
|
+
const startVersion = detectSchemaVersion(value);
|
|
38
|
+
if (startVersion === void 0 || startVersion >= targetVersion || startVersion < 0) return {
|
|
39
|
+
document: value,
|
|
40
|
+
migratedFrom: void 0
|
|
41
|
+
};
|
|
42
|
+
let document = JSON.parse(JSON.stringify(value));
|
|
43
|
+
for (let version = startVersion; version < targetVersion; version += 1) {
|
|
44
|
+
const step = steps[version];
|
|
45
|
+
if (!step) throw new DocumentEngineError("MIGRATION_FAILED", `There is no migration from schema version ${version}`, { migrationFrom: version });
|
|
46
|
+
try {
|
|
47
|
+
document = step(document, context);
|
|
48
|
+
} catch (error) {
|
|
49
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
50
|
+
throw new DocumentEngineError("MIGRATION_FAILED", `Could not migrate the document from schema version ${version} to ${version + 1}: ${reason}`, {
|
|
51
|
+
cause: error,
|
|
52
|
+
migrationFrom: version
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
if (document.schemaVersion !== version + 1) throw new DocumentEngineError("MIGRATION_FAILED", `The migration from schema version ${version} produced version ${String(document.schemaVersion)} instead of ${version + 1}`, { migrationFrom: version });
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
document,
|
|
59
|
+
migratedFrom: startVersion
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
63
|
+
export { detectSchemaVersion, migrateDocument, migrations };
|
|
@@ -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;
|