@embedpdf/core 1.4.1 → 2.0.0-next.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/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +680 -113
- package/dist/index.js.map +1 -1
- package/dist/lib/base/base-plugin.d.ts +52 -0
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/registry/plugin-registry.d.ts +6 -2
- package/dist/lib/store/actions.d.ts +122 -31
- package/dist/lib/store/initial-state.d.ts +22 -6
- package/dist/lib/store/reducer-helpers.d.ts +11 -0
- package/dist/lib/store/selectors.d.ts +21 -3
- package/dist/lib/types/plugin.d.ts +2 -2
- package/dist/lib/utils/event-control.d.ts +37 -2
- package/dist/lib/utils/eventing.d.ts +1 -1
- package/dist/lib/utils/scoped-eventing.d.ts +71 -0
- package/dist/preact/index.cjs +1 -1
- package/dist/preact/index.cjs.map +1 -1
- package/dist/preact/index.js +53 -18
- package/dist/preact/index.js.map +1 -1
- package/dist/react/index.cjs +1 -1
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.js +53 -18
- package/dist/react/index.js.map +1 -1
- package/dist/shared/context.d.ts +6 -1
- package/dist/shared/hooks/index.d.ts +1 -0
- package/dist/shared/hooks/use-core-state.d.ts +4 -2
- package/dist/shared/hooks/use-document-state.d.ts +8 -0
- package/dist/shared-preact/context.d.ts +6 -1
- package/dist/shared-preact/hooks/index.d.ts +1 -0
- package/dist/shared-preact/hooks/use-core-state.d.ts +4 -2
- package/dist/shared-preact/hooks/use-document-state.d.ts +8 -0
- package/dist/shared-react/context.d.ts +6 -1
- package/dist/shared-react/hooks/index.d.ts +1 -0
- package/dist/shared-react/hooks/use-core-state.d.ts +4 -2
- package/dist/shared-react/hooks/use-document-state.d.ts +8 -0
- package/dist/svelte/hooks/index.d.ts +1 -0
- package/dist/svelte/hooks/use-core-state.svelte.d.ts +5 -4
- package/dist/svelte/hooks/use-document-state.svelte.d.ts +9 -0
- package/dist/svelte/hooks/use-registry.svelte.d.ts +6 -1
- package/dist/svelte/index.cjs +1 -1
- package/dist/svelte/index.cjs.map +1 -1
- package/dist/svelte/index.js +55 -17
- package/dist/svelte/index.js.map +1 -1
- package/dist/vue/components/auto-mount.vue.d.ts +3 -2
- package/dist/vue/components/embed-pdf.vue.d.ts +13 -2
- package/dist/vue/components/nested-wrapper.vue.d.ts +3 -2
- package/dist/vue/composables/index.d.ts +1 -0
- package/dist/vue/composables/use-core-state.d.ts +8 -1
- package/dist/vue/composables/use-document-state.d.ts +8 -0
- package/dist/vue/context.d.ts +6 -1
- package/dist/vue/index.cjs +1 -1
- package/dist/vue/index.cjs.map +1 -1
- package/dist/vue/index.js +88 -27
- package/dist/vue/index.js.map +1 -1
- package/package.json +3 -3
|
@@ -2,6 +2,7 @@ import { IPlugin } from '../types/plugin';
|
|
|
2
2
|
import { PluginRegistry } from '../registry/plugin-registry';
|
|
3
3
|
import { Action, CoreAction, CoreState, PluginStore, Store, StoreState } from '../store';
|
|
4
4
|
import { Logger, PdfEngine } from '@embedpdf/models';
|
|
5
|
+
import { DocumentState } from '../store/initial-state';
|
|
5
6
|
export interface StateChangeHandler<TState> {
|
|
6
7
|
(state: TState): void;
|
|
7
8
|
}
|
|
@@ -17,6 +18,11 @@ export declare abstract class BasePlugin<TConfig = unknown, TCapability = unknow
|
|
|
17
18
|
private debouncedTimeouts;
|
|
18
19
|
private unsubscribeFromState;
|
|
19
20
|
private unsubscribeFromCoreStore;
|
|
21
|
+
private unsubscribeFromStartLoadingDocument;
|
|
22
|
+
private unsubscribeFromSetDocumentLoaded;
|
|
23
|
+
private unsubscribeFromCloseDocument;
|
|
24
|
+
private unsubscribeFromSetScale;
|
|
25
|
+
private unsubscribeFromSetRotation;
|
|
20
26
|
private _capability?;
|
|
21
27
|
private readyPromise;
|
|
22
28
|
private readyResolve;
|
|
@@ -96,6 +102,31 @@ export declare abstract class BasePlugin<TConfig = unknown, TCapability = unknow
|
|
|
96
102
|
* @param newState New state
|
|
97
103
|
*/
|
|
98
104
|
protected onCoreStoreUpdated(oldState: StoreState<CoreState>, newState: StoreState<CoreState>): void;
|
|
105
|
+
/**
|
|
106
|
+
* Called when a document is opened
|
|
107
|
+
* Override to initialize per-document state
|
|
108
|
+
* @param documentId The ID of the document that was opened
|
|
109
|
+
*/
|
|
110
|
+
protected onDocumentLoadingStarted(documentId: string): void;
|
|
111
|
+
/**
|
|
112
|
+
* Called when a document is loaded
|
|
113
|
+
* @param documentId The ID of the document that is loaded
|
|
114
|
+
*/
|
|
115
|
+
protected onDocumentLoaded(documentId: string): void;
|
|
116
|
+
/**
|
|
117
|
+
* Called when a document is closed
|
|
118
|
+
* Override to cleanup per-document state
|
|
119
|
+
* @param documentId The ID of the document that was closed
|
|
120
|
+
*/
|
|
121
|
+
protected onDocumentClosed(documentId: string): void;
|
|
122
|
+
/**
|
|
123
|
+
* Called when the active document changes
|
|
124
|
+
* @param previousId The ID of the previous active document
|
|
125
|
+
* @param currentId The ID of the new active document
|
|
126
|
+
*/
|
|
127
|
+
protected onActiveDocumentChanged(previousId: string | null, currentId: string | null): void;
|
|
128
|
+
protected onScaleChanged(documentId: string, scale: number): void;
|
|
129
|
+
protected onRotationChanged(documentId: string, rotation: number): void;
|
|
99
130
|
/**
|
|
100
131
|
* Cleanup method to be called when plugin is being destroyed
|
|
101
132
|
*/
|
|
@@ -112,4 +143,25 @@ export declare abstract class BasePlugin<TConfig = unknown, TCapability = unknow
|
|
|
112
143
|
* Reset the ready state (useful for plugins that need to reinitialize)
|
|
113
144
|
*/
|
|
114
145
|
protected resetReady(): void;
|
|
146
|
+
/**
|
|
147
|
+
* Get the active document ID
|
|
148
|
+
* @throws Error if no active document exists
|
|
149
|
+
*/
|
|
150
|
+
protected getActiveDocumentId(): string;
|
|
151
|
+
/**
|
|
152
|
+
* Get the active document ID or null if none exists
|
|
153
|
+
*/
|
|
154
|
+
protected getActiveDocumentIdOrNull(): string | null;
|
|
155
|
+
/**
|
|
156
|
+
* Get core document state for a specific document
|
|
157
|
+
* @param documentId Document ID (optional, defaults to active document)
|
|
158
|
+
* @returns Document state or null if not found
|
|
159
|
+
*/
|
|
160
|
+
protected getCoreDocument(documentId?: string): DocumentState | null;
|
|
161
|
+
/**
|
|
162
|
+
* Get core document state for a specific document
|
|
163
|
+
* @param documentId Document ID (optional, defaults to active document)
|
|
164
|
+
* @throws Error if document not found
|
|
165
|
+
*/
|
|
166
|
+
protected getCoreDocumentOrThrow(documentId?: string): DocumentState;
|
|
115
167
|
}
|
package/dist/lib/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export * from './store/initial-state';
|
|
|
10
10
|
export * from './store/selectors';
|
|
11
11
|
export * from './utils/event-control';
|
|
12
12
|
export * from './utils/eventing';
|
|
13
|
+
export * from './utils/scoped-eventing';
|
|
13
14
|
export * from './utils/math';
|
|
14
15
|
export * from './utils/typed-object';
|
|
15
16
|
export * from './plugin/builder';
|
|
@@ -51,9 +51,13 @@ export declare class PluginRegistry {
|
|
|
51
51
|
*/
|
|
52
52
|
initialize(): Promise<void>;
|
|
53
53
|
/**
|
|
54
|
-
*
|
|
54
|
+
* Phase 2: Create instance and register capabilities
|
|
55
55
|
*/
|
|
56
|
-
private
|
|
56
|
+
private instantiatePlugin;
|
|
57
|
+
/**
|
|
58
|
+
* Phase 3: Run the initialize method
|
|
59
|
+
*/
|
|
60
|
+
private runPluginInitialization;
|
|
57
61
|
getPluginConfig<TConfig>(pluginId: string): TConfig;
|
|
58
62
|
private validateConfig;
|
|
59
63
|
updatePluginConfig<TConfig>(pluginId: string, config: Partial<TConfig>): Promise<void>;
|
|
@@ -1,51 +1,142 @@
|
|
|
1
|
-
import { PdfDocumentObject, PdfPageObject, Rotation } from '@embedpdf/models';
|
|
2
|
-
export declare const
|
|
1
|
+
import { PdfDocumentObject, PdfErrorCode, PdfPageObject, Rotation } from '@embedpdf/models';
|
|
2
|
+
export declare const START_LOADING_DOCUMENT = "START_LOADING_DOCUMENT";
|
|
3
|
+
export declare const UPDATE_DOCUMENT_LOADING_PROGRESS = "UPDATE_DOCUMENT_LOADING_PROGRESS";
|
|
4
|
+
export declare const SET_DOCUMENT_LOADED = "SET_DOCUMENT_LOADED";
|
|
5
|
+
export declare const SET_DOCUMENT_ERROR = "SET_DOCUMENT_ERROR";
|
|
6
|
+
export declare const RETRY_LOADING_DOCUMENT = "RETRY_LOADING_DOCUMENT";
|
|
7
|
+
export declare const CLOSE_DOCUMENT = "CLOSE_DOCUMENT";
|
|
8
|
+
export declare const SET_ACTIVE_DOCUMENT = "SET_ACTIVE_DOCUMENT";
|
|
9
|
+
export declare const REORDER_DOCUMENTS = "REORDER_DOCUMENTS";
|
|
10
|
+
export declare const MOVE_DOCUMENT = "MOVE_DOCUMENT";
|
|
3
11
|
export declare const REFRESH_DOCUMENT = "REFRESH_DOCUMENT";
|
|
4
12
|
export declare const REFRESH_PAGES = "REFRESH_PAGES";
|
|
5
|
-
export declare const
|
|
6
|
-
export declare const SET_DOCUMENT_ERROR = "SET_DOCUMENT_ERROR";
|
|
13
|
+
export declare const SET_PAGES = "SET_PAGES";
|
|
7
14
|
export declare const SET_SCALE = "SET_SCALE";
|
|
8
15
|
export declare const SET_ROTATION = "SET_ROTATION";
|
|
9
|
-
export declare const
|
|
10
|
-
export declare const
|
|
11
|
-
export
|
|
12
|
-
|
|
16
|
+
export declare const SET_DEFAULT_SCALE = "SET_DEFAULT_SCALE";
|
|
17
|
+
export declare const SET_DEFAULT_ROTATION = "SET_DEFAULT_ROTATION";
|
|
18
|
+
export declare const CORE_ACTION_TYPES: readonly ["START_LOADING_DOCUMENT", "UPDATE_DOCUMENT_LOADING_PROGRESS", "SET_DOCUMENT_LOADED", "CLOSE_DOCUMENT", "SET_ACTIVE_DOCUMENT", "SET_DOCUMENT_ERROR", "RETRY_LOADING_DOCUMENT", "REFRESH_DOCUMENT", "REFRESH_PAGES", "SET_PAGES", "SET_SCALE", "SET_ROTATION", "SET_DEFAULT_SCALE", "SET_DEFAULT_ROTATION", "REORDER_DOCUMENTS", "MOVE_DOCUMENT"];
|
|
19
|
+
export interface StartLoadingDocumentAction {
|
|
20
|
+
type: typeof START_LOADING_DOCUMENT;
|
|
21
|
+
payload: {
|
|
22
|
+
documentId: string;
|
|
23
|
+
name?: string;
|
|
24
|
+
scale?: number;
|
|
25
|
+
rotation?: Rotation;
|
|
26
|
+
passwordProvided?: boolean;
|
|
27
|
+
autoActivate?: boolean;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export interface UpdateDocumentLoadingProgressAction {
|
|
31
|
+
type: typeof UPDATE_DOCUMENT_LOADING_PROGRESS;
|
|
32
|
+
payload: {
|
|
33
|
+
documentId: string;
|
|
34
|
+
progress: number;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export interface SetDocumentLoadedAction {
|
|
38
|
+
type: typeof SET_DOCUMENT_LOADED;
|
|
39
|
+
payload: {
|
|
40
|
+
documentId: string;
|
|
41
|
+
document: PdfDocumentObject;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
export interface SetDocumentErrorAction {
|
|
45
|
+
type: typeof SET_DOCUMENT_ERROR;
|
|
46
|
+
payload: {
|
|
47
|
+
documentId: string;
|
|
48
|
+
error: string;
|
|
49
|
+
errorCode?: PdfErrorCode;
|
|
50
|
+
errorDetails?: any;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export interface RetryLoadingDocumentAction {
|
|
54
|
+
type: typeof RETRY_LOADING_DOCUMENT;
|
|
55
|
+
payload: {
|
|
56
|
+
documentId: string;
|
|
57
|
+
passwordProvided?: boolean;
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export interface CloseDocumentAction {
|
|
61
|
+
type: typeof CLOSE_DOCUMENT;
|
|
62
|
+
payload: {
|
|
63
|
+
documentId: string;
|
|
64
|
+
nextActiveDocumentId?: string | null;
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
export interface SetActiveDocumentAction {
|
|
68
|
+
type: typeof SET_ACTIVE_DOCUMENT;
|
|
69
|
+
payload: string | null;
|
|
70
|
+
}
|
|
71
|
+
export interface ReorderDocumentsAction {
|
|
72
|
+
type: typeof REORDER_DOCUMENTS;
|
|
73
|
+
payload: string[];
|
|
74
|
+
}
|
|
75
|
+
export interface MoveDocumentAction {
|
|
76
|
+
type: typeof MOVE_DOCUMENT;
|
|
77
|
+
payload: {
|
|
78
|
+
documentId: string;
|
|
79
|
+
toIndex: number;
|
|
80
|
+
};
|
|
13
81
|
}
|
|
14
82
|
export interface RefreshDocumentAction {
|
|
15
83
|
type: typeof REFRESH_DOCUMENT;
|
|
16
|
-
payload:
|
|
84
|
+
payload: {
|
|
85
|
+
documentId: string;
|
|
86
|
+
document: PdfDocumentObject;
|
|
87
|
+
};
|
|
17
88
|
}
|
|
18
89
|
export interface RefreshPagesAction {
|
|
19
90
|
type: typeof REFRESH_PAGES;
|
|
20
|
-
payload:
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
payload: PdfDocumentObject;
|
|
91
|
+
payload: {
|
|
92
|
+
documentId: string;
|
|
93
|
+
pageIndexes: number[];
|
|
94
|
+
};
|
|
25
95
|
}
|
|
26
|
-
export interface
|
|
27
|
-
type: typeof
|
|
28
|
-
payload:
|
|
96
|
+
export interface SetPagesAction {
|
|
97
|
+
type: typeof SET_PAGES;
|
|
98
|
+
payload: {
|
|
99
|
+
documentId: string;
|
|
100
|
+
pages: PdfPageObject[][];
|
|
101
|
+
};
|
|
29
102
|
}
|
|
30
103
|
export interface SetScaleAction {
|
|
31
104
|
type: typeof SET_SCALE;
|
|
32
|
-
payload:
|
|
105
|
+
payload: {
|
|
106
|
+
documentId?: string;
|
|
107
|
+
scale: number;
|
|
108
|
+
};
|
|
33
109
|
}
|
|
34
110
|
export interface SetRotationAction {
|
|
35
111
|
type: typeof SET_ROTATION;
|
|
36
|
-
payload:
|
|
112
|
+
payload: {
|
|
113
|
+
documentId?: string;
|
|
114
|
+
rotation: Rotation;
|
|
115
|
+
};
|
|
37
116
|
}
|
|
38
|
-
export interface
|
|
39
|
-
type: typeof
|
|
40
|
-
payload:
|
|
117
|
+
export interface SetDefaultScaleAction {
|
|
118
|
+
type: typeof SET_DEFAULT_SCALE;
|
|
119
|
+
payload: number;
|
|
120
|
+
}
|
|
121
|
+
export interface SetDefaultRotationAction {
|
|
122
|
+
type: typeof SET_DEFAULT_ROTATION;
|
|
123
|
+
payload: Rotation;
|
|
41
124
|
}
|
|
42
|
-
export type DocumentAction =
|
|
125
|
+
export type DocumentAction = StartLoadingDocumentAction | UpdateDocumentLoadingProgressAction | SetDocumentLoadedAction | SetDocumentErrorAction | RetryLoadingDocumentAction | CloseDocumentAction | SetActiveDocumentAction | RefreshDocumentAction | RefreshPagesAction | SetPagesAction | SetScaleAction | SetRotationAction | SetDefaultScaleAction | SetDefaultRotationAction | ReorderDocumentsAction | MoveDocumentAction;
|
|
43
126
|
export type CoreAction = DocumentAction;
|
|
44
|
-
export declare const
|
|
45
|
-
export declare const
|
|
46
|
-
export declare const
|
|
47
|
-
export declare const
|
|
48
|
-
export declare const
|
|
49
|
-
export declare const
|
|
50
|
-
export declare const
|
|
51
|
-
export declare const
|
|
127
|
+
export declare const startLoadingDocument: (documentId: string, name?: string, scale?: number, rotation?: Rotation, passwordProvided?: boolean, autoActivate?: boolean) => CoreAction;
|
|
128
|
+
export declare const updateDocumentLoadingProgress: (documentId: string, progress: number) => CoreAction;
|
|
129
|
+
export declare const setDocumentLoaded: (documentId: string, document: PdfDocumentObject) => CoreAction;
|
|
130
|
+
export declare const setDocumentError: (documentId: string, error: string, errorCode?: PdfErrorCode, errorDetails?: any) => CoreAction;
|
|
131
|
+
export declare const retryLoadingDocument: (documentId: string, passwordProvided?: boolean) => CoreAction;
|
|
132
|
+
export declare const closeDocument: (documentId: string, nextActiveDocumentId?: string | null) => CoreAction;
|
|
133
|
+
export declare const setActiveDocument: (documentId: string | null) => CoreAction;
|
|
134
|
+
export declare const refreshDocument: (documentId: string, document: PdfDocumentObject) => CoreAction;
|
|
135
|
+
export declare const refreshPages: (documentId: string, pageIndexes: number[]) => CoreAction;
|
|
136
|
+
export declare const setPages: (documentId: string, pages: PdfPageObject[][]) => CoreAction;
|
|
137
|
+
export declare const setScale: (scale: number, documentId?: string) => CoreAction;
|
|
138
|
+
export declare const setRotation: (rotation: Rotation, documentId?: string) => CoreAction;
|
|
139
|
+
export declare const setDefaultScale: (scale: number) => CoreAction;
|
|
140
|
+
export declare const setDefaultRotation: (rotation: Rotation) => CoreAction;
|
|
141
|
+
export declare const reorderDocuments: (order: string[]) => CoreAction;
|
|
142
|
+
export declare const moveDocument: (documentId: string, toIndex: number) => CoreAction;
|
|
@@ -1,11 +1,27 @@
|
|
|
1
|
-
import { PdfDocumentObject,
|
|
1
|
+
import { PdfDocumentObject, PdfErrorCode, Rotation } from '@embedpdf/models';
|
|
2
2
|
import { PluginRegistryConfig } from '../types/plugin';
|
|
3
|
-
export
|
|
3
|
+
export type DocumentStatus = 'loading' | 'loaded' | 'error';
|
|
4
|
+
export interface DocumentState {
|
|
5
|
+
id: string;
|
|
6
|
+
name?: string;
|
|
7
|
+
status: DocumentStatus;
|
|
8
|
+
loadingProgress?: number;
|
|
9
|
+
error: string | null;
|
|
10
|
+
errorCode?: PdfErrorCode;
|
|
11
|
+
errorDetails?: any;
|
|
12
|
+
passwordProvided?: boolean;
|
|
13
|
+
document: PdfDocumentObject | null;
|
|
4
14
|
scale: number;
|
|
5
15
|
rotation: Rotation;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
16
|
+
pageRefreshVersions: Record<number, number>;
|
|
17
|
+
loadStartedAt: number;
|
|
18
|
+
loadedAt?: number;
|
|
19
|
+
}
|
|
20
|
+
export interface CoreState {
|
|
21
|
+
documents: Record<string, DocumentState>;
|
|
22
|
+
documentOrder: string[];
|
|
23
|
+
activeDocumentId: string | null;
|
|
24
|
+
defaultScale: number;
|
|
25
|
+
defaultRotation: Rotation;
|
|
10
26
|
}
|
|
11
27
|
export declare const initialCoreState: (config?: PluginRegistryConfig) => CoreState;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { CoreState } from './initial-state';
|
|
2
|
+
/**
|
|
3
|
+
* Calculate the next active document when closing a document.
|
|
4
|
+
* Returns the document to activate, or null if no documents remain.
|
|
5
|
+
*/
|
|
6
|
+
export declare function calculateNextActiveDocument(state: CoreState, closingDocumentId: string, explicitNext?: string | null): string | null;
|
|
7
|
+
/**
|
|
8
|
+
* Reorder a document within the documentOrder array.
|
|
9
|
+
* Returns the new order, or null if the operation is invalid.
|
|
10
|
+
*/
|
|
11
|
+
export declare function moveDocumentInOrder(currentOrder: string[], documentId: string, toIndex: number): string[] | null;
|
|
@@ -1,3 +1,21 @@
|
|
|
1
|
-
import { CoreState } from './initial-state';
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { CoreState, DocumentState } from './initial-state';
|
|
2
|
+
/**
|
|
3
|
+
* Get the active document state
|
|
4
|
+
*/
|
|
5
|
+
export declare const getActiveDocumentState: (state: CoreState) => DocumentState | null;
|
|
6
|
+
/**
|
|
7
|
+
* Get document state by ID
|
|
8
|
+
*/
|
|
9
|
+
export declare const getDocumentState: (state: CoreState, documentId: string) => DocumentState | null;
|
|
10
|
+
/**
|
|
11
|
+
* Get all document IDs
|
|
12
|
+
*/
|
|
13
|
+
export declare const getDocumentIds: (state: CoreState) => string[];
|
|
14
|
+
/**
|
|
15
|
+
* Check if a document is loaded
|
|
16
|
+
*/
|
|
17
|
+
export declare const isDocumentLoaded: (state: CoreState, documentId: string) => boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Get the number of open documents
|
|
20
|
+
*/
|
|
21
|
+
export declare const getDocumentCount: (state: CoreState) => number;
|
|
@@ -14,8 +14,8 @@ export interface BasePluginConfig {
|
|
|
14
14
|
enabled?: boolean;
|
|
15
15
|
}
|
|
16
16
|
export interface PluginRegistryConfig {
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
defaultRotation?: Rotation;
|
|
18
|
+
defaultScale?: number;
|
|
19
19
|
logger?: Logger;
|
|
20
20
|
}
|
|
21
21
|
export interface PluginManifest<TConfig = unknown> {
|
|
@@ -9,15 +9,50 @@ export interface ThrottleOptions extends BaseEventControlOptions {
|
|
|
9
9
|
mode: 'throttle';
|
|
10
10
|
throttleMode?: 'leading-trailing' | 'trailing';
|
|
11
11
|
}
|
|
12
|
-
export
|
|
12
|
+
export interface KeyedDebounceOptions<T> extends BaseEventControlOptions {
|
|
13
|
+
mode: 'debounce';
|
|
14
|
+
keyExtractor: (data: T) => string | number;
|
|
15
|
+
}
|
|
16
|
+
export interface KeyedThrottleOptions<T> extends BaseEventControlOptions {
|
|
17
|
+
mode: 'throttle';
|
|
18
|
+
throttleMode?: 'leading-trailing' | 'trailing';
|
|
19
|
+
keyExtractor: (data: T) => string | number;
|
|
20
|
+
}
|
|
21
|
+
export type EventControlOptions<T = any> = DebounceOptions | ThrottleOptions | KeyedDebounceOptions<T> | KeyedThrottleOptions<T>;
|
|
13
22
|
export declare class EventControl<T> {
|
|
14
23
|
private handler;
|
|
15
24
|
private options;
|
|
16
25
|
private timeoutId?;
|
|
17
26
|
private lastRun;
|
|
18
|
-
constructor(handler: EventHandler<T>, options:
|
|
27
|
+
constructor(handler: EventHandler<T>, options: DebounceOptions | ThrottleOptions);
|
|
19
28
|
handle: (data: T) => void;
|
|
20
29
|
private debounce;
|
|
21
30
|
private throttle;
|
|
22
31
|
destroy(): void;
|
|
23
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Event control with independent debouncing/throttling per key.
|
|
35
|
+
* Useful when events carry a discriminator (like documentId) and
|
|
36
|
+
* you want to debounce/throttle each key's events independently.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* // Debounce viewport resize events independently per document
|
|
40
|
+
* const control = new KeyedEventControl(
|
|
41
|
+
* (event) => recalcZoom(event.documentId),
|
|
42
|
+
* { mode: 'debounce', wait: 150, keyExtractor: (e) => e.documentId }
|
|
43
|
+
* );
|
|
44
|
+
* control.handle(event); // Each documentId gets its own 150ms debounce
|
|
45
|
+
*/
|
|
46
|
+
export declare class KeyedEventControl<T> {
|
|
47
|
+
private handler;
|
|
48
|
+
private options;
|
|
49
|
+
private controls;
|
|
50
|
+
private readonly baseOptions;
|
|
51
|
+
constructor(handler: EventHandler<T>, options: KeyedDebounceOptions<T> | KeyedThrottleOptions<T>);
|
|
52
|
+
handle: (data: T) => void;
|
|
53
|
+
destroy(): void;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Type guard to check if options are keyed
|
|
57
|
+
*/
|
|
58
|
+
export declare function isKeyedOptions<T>(options: EventControlOptions<T>): options is KeyedDebounceOptions<T> | KeyedThrottleOptions<T>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { EventControlOptions } from './event-control';
|
|
2
2
|
export type Listener<T = any> = (value: T) => void;
|
|
3
3
|
export type Unsubscribe = () => void;
|
|
4
|
-
export type EventListener<T> = ((listener: Listener<T>) => Unsubscribe) | ((listener: Listener<T>, options?: EventControlOptions) => Unsubscribe);
|
|
4
|
+
export type EventListener<T> = ((listener: Listener<T>) => Unsubscribe) | ((listener: Listener<T>, options?: EventControlOptions<T>) => Unsubscribe);
|
|
5
5
|
export type EventHook<T = any> = EventListener<T>;
|
|
6
6
|
export interface Emitter<T = any> {
|
|
7
7
|
emit(value?: T): void;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { EventHook } from './eventing';
|
|
2
|
+
/**
|
|
3
|
+
* A scoped behavior emitter that maintains separate cached values
|
|
4
|
+
* and listener sets per scope key.
|
|
5
|
+
*
|
|
6
|
+
* @typeParam TData - The scoped data type (without key context)
|
|
7
|
+
* @typeParam TGlobalEvent - The global event type (includes key context)
|
|
8
|
+
* @typeParam TKey - The key type (string, number, or both)
|
|
9
|
+
*/
|
|
10
|
+
export interface ScopedEmitter<TData = any, TGlobalEvent = {
|
|
11
|
+
key: string;
|
|
12
|
+
data: TData;
|
|
13
|
+
}, TKey extends string | number = string | number> {
|
|
14
|
+
/**
|
|
15
|
+
* Emit an event for a specific scope key.
|
|
16
|
+
*/
|
|
17
|
+
emit(key: TKey, data: TData): void;
|
|
18
|
+
/**
|
|
19
|
+
* Get a scoped event hook that only receives events for this key.
|
|
20
|
+
*/
|
|
21
|
+
forScope(key: TKey): EventHook<TData>;
|
|
22
|
+
/**
|
|
23
|
+
* Global event hook that receives events from all scopes.
|
|
24
|
+
*/
|
|
25
|
+
readonly onGlobal: EventHook<TGlobalEvent>;
|
|
26
|
+
/**
|
|
27
|
+
* Clear all scopes' caches and listeners
|
|
28
|
+
*/
|
|
29
|
+
clear(): void;
|
|
30
|
+
/**
|
|
31
|
+
* Clear a specific scope's cache and listeners
|
|
32
|
+
*/
|
|
33
|
+
clearScope(key: TKey): void;
|
|
34
|
+
/**
|
|
35
|
+
* Get the current cached value for a specific scope
|
|
36
|
+
*/
|
|
37
|
+
getValue(key: TKey): TData | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* Get all active scope keys
|
|
40
|
+
*/
|
|
41
|
+
getScopes(): TKey[];
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Creates a scoped emitter with optional caching behavior.
|
|
45
|
+
*
|
|
46
|
+
* @param toGlobalEvent - Transform function to convert (key, data) into a global event
|
|
47
|
+
* @param options - Configuration options
|
|
48
|
+
* @param options.cache - Whether to cache values per scope (default: true)
|
|
49
|
+
* @param options.equality - Equality function for cached values (default: arePropsEqual)
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```typescript
|
|
53
|
+
* // With caching (stateful) - default behavior
|
|
54
|
+
* const window$ = createScopedEmitter<WindowState, WindowChangeEvent, string>(
|
|
55
|
+
* (documentId, window) => ({ documentId, window })
|
|
56
|
+
* );
|
|
57
|
+
*
|
|
58
|
+
* // Without caching (transient events)
|
|
59
|
+
* const refreshPages$ = createScopedEmitter<number[], RefreshPagesEvent, string>(
|
|
60
|
+
* (documentId, pages) => ({ documentId, pages }),
|
|
61
|
+
* { cache: false }
|
|
62
|
+
* );
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
export declare function createScopedEmitter<TData = any, TGlobalEvent = {
|
|
66
|
+
key: string;
|
|
67
|
+
data: TData;
|
|
68
|
+
}, TKey extends string | number = string | number>(toGlobalEvent: (key: TKey, data: TData) => TGlobalEvent, options?: {
|
|
69
|
+
cache?: boolean;
|
|
70
|
+
equality?: (a: TData, b: TData) => boolean;
|
|
71
|
+
}): ScopedEmitter<TData, TGlobalEvent, TKey>;
|
package/dist/preact/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("preact"),t=require("preact/hooks"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("preact"),t=require("preact/hooks"),n=require("preact/jsx-runtime"),r=require("@embedpdf/core"),i=e.createContext({registry:null,coreState:null,isInitializing:!0,pluginsReady:!1,activeDocumentId:null,activeDocument:null,documents:{},documentStates:[]});function o({plugins:i,children:o}){const{utilities:u,wrappers:s}=t.useMemo(()=>{const e=[],t=[];for(const n of i){const i=n.package;if(r.hasAutoMountElements(i)){const n=i.autoMountElements()||[];for(const r of n)"utility"===r.type?e.push(r.component):"wrapper"===r.type&&t.push(r.component)}}return{utilities:e,wrappers:t}},[i]),l=s.reduce((e,t)=>n.jsx(t,{children:e}),o);return n.jsxs(e.Fragment,{children:[l,u.map((e,t)=>n.jsx(e,{},`utility-${t}`))]})}function u(){const e=t.useContext(i);if(void 0===e)throw new Error("useCapability must be used within a PDFContext.Provider");const{registry:n,isInitializing:r}=e;if(r)return e;if(null===n)throw new Error("PDF registry failed to initialize properly");return e}function s(e){const{registry:t}=u();if(null===t)return{plugin:null,isLoading:!0,ready:new Promise(()=>{})};const n=t.getPlugin(e);if(!n)throw new Error(`Plugin ${e} not found`);return{plugin:n,isLoading:!1,ready:n.ready()}}function l(){const{coreState:e}=t.useContext(i);return e}exports.EmbedPDF=function({engine:e,logger:u,onInitialized:s,plugins:l,children:c,autoMountDomElements:a=!0}){const[d,p]=t.useState(null),[g,f]=t.useState(null),[y,m]=t.useState(!0),[S,v]=t.useState(!1),x=t.useRef(s);t.useEffect(()=>{x.current=s},[s]),t.useEffect(()=>{const t=new r.PluginRegistry(e,{logger:u});t.registerPluginBatch(l);let n;return(async()=>{var e;if(await t.initialize(),t.isDestroyed())return;const n=t.getStore();f(n.getState().core);const r=n.subscribe((e,t,r)=>{n.isCoreAction(e)&&t.core!==r.core&&f(t.core)});if(await(null==(e=x.current)?void 0:e.call(x,t)),!t.isDestroyed())return t.pluginsReady().then(()=>{t.isDestroyed()||v(!0)}),p(t),m(!1),r;r()})().then(e=>{n=e}).catch(console.error),()=>{null==n||n(),t.destroy(),p(null),f(null),m(!0),v(!1)}},[e,l]);const h=t.useMemo(()=>{const e=(null==g?void 0:g.activeDocumentId)??null,t=(null==g?void 0:g.documents)??{},n=(null==g?void 0:g.documentOrder)??[],r=e&&t[e]?t[e]:null,i=n.map(e=>t[e]).filter(e=>null!=e);return{registry:d,coreState:g,isInitializing:y,pluginsReady:S,activeDocumentId:e,activeDocument:r,documents:t,documentStates:i}},[d,g,y,S]),w="function"==typeof c?c(h):c;return n.jsx(i.Provider,{value:h,children:S&&a?n.jsx(o,{plugins:l,children:w}):w})},exports.PDFContext=i,exports.useCapability=function(e){const{plugin:t,isLoading:n,ready:r}=s(e);if(!t)return{provides:null,isLoading:n,ready:r};if(!t.provides)throw new Error(`Plugin ${e} does not provide a capability`);return{provides:t.provides(),isLoading:n,ready:r}},exports.useCoreState=l,exports.useDocumentState=function(e){const n=l();return t.useMemo(()=>n&&e?n.documents[e]??null:null,[n,e])},exports.usePlugin=s,exports.useRegistry=u,exports.useStoreState=function(){const{registry:e}=u(),[n,r]=t.useState(null);return t.useEffect(()=>{if(!e)return;r(e.getStore().getState());const t=e.getStore().subscribe((e,t)=>{r(t)});return()=>t()},[e]),n};
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../../src/shared/context.ts","../../src/shared/components/auto-mount.tsx","../../src/shared/hooks/use-registry.ts","../../src/shared/hooks/use-plugin.ts","../../src/shared/components/embed-pdf.tsx","../../src/shared/hooks/use-capability.ts","../../src/shared/hooks/use-core-state.ts","../../src/shared/hooks/use-store-state.ts"],"sourcesContent":["import { createContext } from '@framework';\nimport type { PluginRegistry } from '@embedpdf/core';\n\nexport interface PDFContextState {\n registry: PluginRegistry | null;\n isInitializing: boolean;\n pluginsReady: boolean;\n}\n\nexport const PDFContext = createContext<PDFContextState>({\n registry: null,\n isInitializing: true,\n pluginsReady: false,\n});\n","import { Fragment, useMemo, ComponentType, ReactNode } from '@framework';\nimport { hasAutoMountElements } from '@embedpdf/core';\nimport type { PluginBatchRegistration, IPlugin } from '@embedpdf/core';\n\ninterface AutoMountProps {\n plugins: PluginBatchRegistration<IPlugin<any>, any>[];\n children: ReactNode;\n}\n\nexport function AutoMount({ plugins, children }: AutoMountProps) {\n const { utilities, wrappers } = useMemo(() => {\n // React-specific types for internal use\n const utilities: ComponentType[] = [];\n const wrappers: ComponentType<{ children: ReactNode }>[] = [];\n\n for (const reg of plugins) {\n const pkg = reg.package;\n if (hasAutoMountElements(pkg)) {\n const elements = pkg.autoMountElements() || [];\n\n for (const element of elements) {\n if (element.type === 'utility') {\n utilities.push(element.component);\n } else if (element.type === 'wrapper') {\n // In React context, we know wrappers need children\n wrappers.push(element.component);\n }\n }\n }\n }\n return { utilities, wrappers };\n }, [plugins]);\n\n // React-specific wrapping logic\n const wrappedContent = wrappers.reduce(\n (content, Wrapper) => <Wrapper>{content}</Wrapper>,\n children,\n );\n\n return (\n <Fragment>\n {wrappedContent}\n {utilities.map((Utility, i) => (\n <Utility key={`utility-${i}`} />\n ))}\n </Fragment>\n );\n}\n","import { useContext } from '@framework';\nimport { PDFContext, PDFContextState } from '../context';\n\n/**\n * Hook to access the PDF registry.\n * @returns The PDF registry or null during initialization\n */\nexport function useRegistry(): PDFContextState {\n const contextValue = useContext(PDFContext);\n\n // Error if used outside of context\n if (contextValue === undefined) {\n throw new Error('useCapability must be used within a PDFContext.Provider');\n }\n\n const { registry, isInitializing } = contextValue;\n\n // During initialization, return null instead of throwing an error\n if (isInitializing) {\n return contextValue;\n }\n\n // At this point, initialization is complete but registry is still null, which is unexpected\n if (registry === null) {\n throw new Error('PDF registry failed to initialize properly');\n }\n\n return contextValue;\n}\n","import type { BasePlugin } from '@embedpdf/core';\nimport { useRegistry } from './use-registry';\n\ntype PluginState<T extends BasePlugin> = {\n plugin: T | null;\n isLoading: boolean;\n ready: Promise<void>;\n};\n\n/**\n * Hook to access a plugin.\n * @param pluginId The ID of the plugin to access\n * @returns The plugin or null during initialization\n * @example\n * // Get zoom plugin\n * const zoom = usePlugin<ZoomPlugin>(ZoomPlugin.id);\n */\nexport function usePlugin<T extends BasePlugin>(pluginId: T['id']): PluginState<T> {\n const { registry } = useRegistry();\n\n if (registry === null) {\n return {\n plugin: null,\n isLoading: true,\n ready: new Promise(() => {}),\n };\n }\n\n const plugin = registry.getPlugin<T>(pluginId);\n\n if (!plugin) {\n throw new Error(`Plugin ${pluginId} not found`);\n }\n\n return {\n plugin,\n isLoading: false,\n ready: plugin.ready(),\n };\n}\n","import { useState, useEffect, useRef, ReactNode } from '@framework';\nimport { Logger, PdfEngine } from '@embedpdf/models';\nimport { PluginRegistry } from '@embedpdf/core';\nimport type { PluginBatchRegistrations } from '@embedpdf/core';\n\nimport { PDFContext, PDFContextState } from '../context';\nimport { AutoMount } from './auto-mount';\n\nexport type { PluginBatchRegistrations };\n\ninterface EmbedPDFProps {\n /**\n * The PDF engine to use for the PDF viewer.\n */\n engine: PdfEngine;\n /**\n * The logger to use for the PDF viewer.\n */\n logger?: Logger;\n /**\n * The callback to call when the PDF viewer is initialized.\n */\n onInitialized?: (registry: PluginRegistry) => Promise<void>;\n /**\n * The plugins to use for the PDF viewer.\n */\n plugins: PluginBatchRegistrations;\n /**\n * The children to render for the PDF viewer.\n */\n children: ReactNode | ((state: PDFContextState) => ReactNode);\n /**\n * Whether to auto-mount specific non-visual DOM elements from plugins.\n * @default true\n */\n autoMountDomElements?: boolean;\n}\n\nexport function EmbedPDF({\n engine,\n logger,\n onInitialized,\n plugins,\n children,\n autoMountDomElements = true,\n}: EmbedPDFProps) {\n const [registry, setRegistry] = useState<PluginRegistry | null>(null);\n const [isInitializing, setIsInitializing] = useState<boolean>(true);\n const [pluginsReady, setPluginsReady] = useState<boolean>(false);\n const initRef = useRef<EmbedPDFProps['onInitialized']>(onInitialized);\n\n useEffect(() => {\n initRef.current = onInitialized; // update without triggering re-runs\n }, [onInitialized]);\n\n useEffect(() => {\n const pdfViewer = new PluginRegistry(engine, { logger });\n pdfViewer.registerPluginBatch(plugins);\n\n const initialize = async () => {\n await pdfViewer.initialize();\n // if the registry is destroyed, don't do anything\n if (pdfViewer.isDestroyed()) {\n return;\n }\n\n /* always call the *latest* callback */\n await initRef.current?.(pdfViewer);\n\n // if the registry is destroyed, don't do anything\n if (pdfViewer.isDestroyed()) {\n return;\n }\n\n pdfViewer.pluginsReady().then(() => {\n if (!pdfViewer.isDestroyed()) {\n setPluginsReady(true);\n }\n });\n\n // Provide the registry to children via context\n setRegistry(pdfViewer);\n setIsInitializing(false);\n };\n\n initialize().catch(console.error);\n\n return () => {\n pdfViewer.destroy();\n setRegistry(null);\n setIsInitializing(true);\n setPluginsReady(false);\n };\n }, [engine, plugins]);\n\n const content =\n typeof children === 'function'\n ? children({ registry, isInitializing, pluginsReady })\n : children;\n\n return (\n <PDFContext.Provider value={{ registry, isInitializing, pluginsReady }}>\n {pluginsReady && autoMountDomElements ? (\n <AutoMount plugins={plugins}>{content}</AutoMount>\n ) : (\n content\n )}\n </PDFContext.Provider>\n );\n}\n","import type { BasePlugin } from '@embedpdf/core';\nimport { usePlugin } from './use-plugin';\n\ntype CapabilityState<T extends BasePlugin> = {\n provides: ReturnType<NonNullable<T['provides']>> | null;\n isLoading: boolean;\n ready: Promise<void>;\n};\n\n/**\n * Hook to access a plugin's capability.\n * @param pluginId The ID of the plugin to access\n * @returns The capability provided by the plugin or null during initialization\n * @example\n * // Get zoom capability\n * const zoom = useCapability<ZoomPlugin>(ZoomPlugin.id);\n */\nexport function useCapability<T extends BasePlugin>(pluginId: T['id']): CapabilityState<T> {\n const { plugin, isLoading, ready } = usePlugin<T>(pluginId);\n\n if (!plugin) {\n return {\n provides: null,\n isLoading,\n ready,\n };\n }\n\n if (!plugin.provides) {\n throw new Error(`Plugin ${pluginId} does not provide a capability`);\n }\n\n return {\n provides: plugin.provides() as ReturnType<NonNullable<T['provides']>>,\n isLoading,\n ready,\n };\n}\n","import { useState, useEffect } from '@framework';\nimport { CoreState, arePropsEqual } from '@embedpdf/core';\nimport { useRegistry } from './use-registry';\n\n/**\n * Hook that provides access to the current core state\n * and re-renders the component only when the core state changes\n */\nexport function useCoreState(): CoreState | null {\n const { registry } = useRegistry();\n const [coreState, setCoreState] = useState<CoreState | null>(null);\n\n useEffect(() => {\n if (!registry) return;\n\n const store = registry.getStore();\n\n // Get initial core state\n setCoreState(store.getState().core);\n\n // Create a single subscription that handles all core actions\n const unsubscribe = store.subscribe((action, newState, oldState) => {\n // Only update if it's a core action and the core state changed\n if (store.isCoreAction(action) && !arePropsEqual(newState.core, oldState.core)) {\n setCoreState(newState.core);\n }\n });\n\n return () => unsubscribe();\n }, [registry]);\n\n return coreState;\n}\n","import { useState, useEffect } from '@framework';\nimport { CoreState, StoreState } from '@embedpdf/core';\nimport { useRegistry } from './use-registry';\n\n/**\n * Hook that provides access to the current global store state\n * and re-renders the component when the state changes\n */\nexport function useStoreState<T = CoreState>(): StoreState<T> | null {\n const { registry } = useRegistry();\n const [state, setState] = useState<StoreState<T> | null>(null);\n\n useEffect(() => {\n if (!registry) return;\n\n // Get initial state\n setState(registry.getStore().getState() as StoreState<T>);\n\n // Subscribe to store changes\n const unsubscribe = registry.getStore().subscribe((_action, newState) => {\n setState(newState as StoreState<T>);\n });\n\n return () => unsubscribe();\n }, [registry]);\n\n return state;\n}\n"],"names":["PDFContext","createContext","registry","isInitializing","pluginsReady","AutoMount","plugins","children","utilities","wrappers","useMemo","reg","pkg","package","hasAutoMountElements","elements","autoMountElements","element","type","utilities2","push","component","wrappers2","wrappedContent","reduce","content","Wrapper","jsx","Fragment","map","Utility","i","useRegistry","contextValue","useContext","Error","usePlugin","pluginId","plugin","isLoading","ready","Promise","getPlugin","engine","logger","onInitialized","autoMountDomElements","setRegistry","useState","setIsInitializing","setPluginsReady","initRef","useRef","useEffect","current","pdfViewer","PluginRegistry","registerPluginBatch","async","initialize","isDestroyed","_a","call","then","catch","console","error","destroy","Provider","value","provides","coreState","setCoreState","store","getStore","getState","core","unsubscribe","subscribe","action","newState","oldState","isCoreAction","arePropsEqual","state","setState","_action"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../src/shared/context.ts","../../src/shared/components/auto-mount.tsx","../../src/shared/hooks/use-registry.ts","../../src/shared/hooks/use-plugin.ts","../../src/shared/hooks/use-core-state.ts","../../src/shared/components/embed-pdf.tsx","../../src/shared/hooks/use-capability.ts","../../src/shared/hooks/use-document-state.ts","../../src/shared/hooks/use-store-state.ts"],"sourcesContent":["import { createContext } from '@framework';\nimport type { CoreState, DocumentState, PluginRegistry } from '@embedpdf/core';\n\nexport interface PDFContextState {\n registry: PluginRegistry | null;\n coreState: CoreState | null;\n isInitializing: boolean;\n pluginsReady: boolean;\n\n // Convenience accessors (always safe to use)\n activeDocumentId: string | null;\n activeDocument: DocumentState | null;\n documents: Record<string, DocumentState>;\n documentStates: DocumentState[];\n}\n\nexport const PDFContext = createContext<PDFContextState>({\n registry: null,\n coreState: null,\n isInitializing: true,\n pluginsReady: false,\n activeDocumentId: null,\n activeDocument: null,\n documents: {},\n documentStates: [],\n});\n","import { Fragment, useMemo, ComponentType, ReactNode } from '@framework';\nimport { hasAutoMountElements } from '@embedpdf/core';\nimport type { PluginBatchRegistration, IPlugin } from '@embedpdf/core';\n\ninterface AutoMountProps {\n plugins: PluginBatchRegistration<IPlugin<any>, any>[];\n children: ReactNode;\n}\n\nexport function AutoMount({ plugins, children }: AutoMountProps) {\n const { utilities, wrappers } = useMemo(() => {\n // React-specific types for internal use\n const utilities: ComponentType[] = [];\n const wrappers: ComponentType<{ children: ReactNode }>[] = [];\n\n for (const reg of plugins) {\n const pkg = reg.package;\n if (hasAutoMountElements(pkg)) {\n const elements = pkg.autoMountElements() || [];\n\n for (const element of elements) {\n if (element.type === 'utility') {\n utilities.push(element.component);\n } else if (element.type === 'wrapper') {\n // In React context, we know wrappers need children\n wrappers.push(element.component);\n }\n }\n }\n }\n return { utilities, wrappers };\n }, [plugins]);\n\n // React-specific wrapping logic\n const wrappedContent = wrappers.reduce(\n (content, Wrapper) => <Wrapper>{content}</Wrapper>,\n children,\n );\n\n return (\n <Fragment>\n {wrappedContent}\n {utilities.map((Utility, i) => (\n <Utility key={`utility-${i}`} />\n ))}\n </Fragment>\n );\n}\n","import { useContext } from '@framework';\nimport { PDFContext, PDFContextState } from '../context';\n\n/**\n * Hook to access the PDF registry.\n * @returns The PDF registry or null during initialization\n */\nexport function useRegistry(): PDFContextState {\n const contextValue = useContext(PDFContext);\n\n // Error if used outside of context\n if (contextValue === undefined) {\n throw new Error('useCapability must be used within a PDFContext.Provider');\n }\n\n const { registry, isInitializing } = contextValue;\n\n // During initialization, return null instead of throwing an error\n if (isInitializing) {\n return contextValue;\n }\n\n // At this point, initialization is complete but registry is still null, which is unexpected\n if (registry === null) {\n throw new Error('PDF registry failed to initialize properly');\n }\n\n return contextValue;\n}\n","import type { BasePlugin } from '@embedpdf/core';\nimport { useRegistry } from './use-registry';\n\ntype PluginState<T extends BasePlugin> = {\n plugin: T | null;\n isLoading: boolean;\n ready: Promise<void>;\n};\n\n/**\n * Hook to access a plugin.\n * @param pluginId The ID of the plugin to access\n * @returns The plugin or null during initialization\n * @example\n * // Get zoom plugin\n * const zoom = usePlugin<ZoomPlugin>(ZoomPlugin.id);\n */\nexport function usePlugin<T extends BasePlugin>(pluginId: T['id']): PluginState<T> {\n const { registry } = useRegistry();\n\n if (registry === null) {\n return {\n plugin: null,\n isLoading: true,\n ready: new Promise(() => {}),\n };\n }\n\n const plugin = registry.getPlugin<T>(pluginId);\n\n if (!plugin) {\n throw new Error(`Plugin ${pluginId} not found`);\n }\n\n return {\n plugin,\n isLoading: false,\n ready: plugin.ready(),\n };\n}\n","import { useContext } from '@framework';\nimport { CoreState } from '@embedpdf/core';\nimport { PDFContext } from '../context';\n\n/**\n * Hook that provides access to the current core state.\n *\n * Note: This reads from the context which is already subscribed to core state changes\n * in the EmbedPDF component, so there's no additional subscription overhead.\n */\nexport function useCoreState(): CoreState | null {\n const { coreState } = useContext(PDFContext);\n return coreState;\n}\n","import { useState, useEffect, useRef, useMemo, ReactNode } from '@framework';\nimport { Logger, PdfEngine } from '@embedpdf/models';\nimport { PluginRegistry, CoreState, DocumentState } from '@embedpdf/core';\nimport type { PluginBatchRegistrations } from '@embedpdf/core';\n\nimport { PDFContext, PDFContextState } from '../context';\nimport { AutoMount } from './auto-mount';\n\nexport type { PluginBatchRegistrations };\n\ninterface EmbedPDFProps {\n /**\n * The PDF engine to use for the PDF viewer.\n */\n engine: PdfEngine;\n /**\n * The logger to use for the PDF viewer.\n */\n logger?: Logger;\n /**\n * The callback to call when the PDF viewer is initialized.\n */\n onInitialized?: (registry: PluginRegistry) => Promise<void>;\n /**\n * The plugins to use for the PDF viewer.\n */\n plugins: PluginBatchRegistrations;\n /**\n * The children to render for the PDF viewer.\n */\n children: ReactNode | ((state: PDFContextState) => ReactNode);\n /**\n * Whether to auto-mount specific non-visual DOM elements from plugins.\n * @default true\n */\n autoMountDomElements?: boolean;\n}\n\nexport function EmbedPDF({\n engine,\n logger,\n onInitialized,\n plugins,\n children,\n autoMountDomElements = true,\n}: EmbedPDFProps) {\n const [registry, setRegistry] = useState<PluginRegistry | null>(null);\n const [coreState, setCoreState] = useState<CoreState | null>(null);\n const [isInitializing, setIsInitializing] = useState<boolean>(true);\n const [pluginsReady, setPluginsReady] = useState<boolean>(false);\n const initRef = useRef<EmbedPDFProps['onInitialized']>(onInitialized);\n\n useEffect(() => {\n initRef.current = onInitialized;\n }, [onInitialized]);\n\n useEffect(() => {\n const pdfViewer = new PluginRegistry(engine, { logger });\n pdfViewer.registerPluginBatch(plugins);\n\n const initialize = async () => {\n await pdfViewer.initialize();\n\n if (pdfViewer.isDestroyed()) {\n return;\n }\n\n const store = pdfViewer.getStore();\n setCoreState(store.getState().core);\n\n const unsubscribe = store.subscribe((action, newState, oldState) => {\n // Only update if it's a core action and the core state changed\n if (store.isCoreAction(action) && newState.core !== oldState.core) {\n setCoreState(newState.core);\n }\n });\n\n /* always call the *latest* callback */\n await initRef.current?.(pdfViewer);\n\n if (pdfViewer.isDestroyed()) {\n unsubscribe();\n return;\n }\n\n pdfViewer.pluginsReady().then(() => {\n if (!pdfViewer.isDestroyed()) {\n setPluginsReady(true);\n }\n });\n\n // Provide the registry to children via context\n setRegistry(pdfViewer);\n setIsInitializing(false);\n\n // Return cleanup function\n return unsubscribe;\n };\n\n let cleanup: (() => void) | undefined;\n initialize()\n .then((unsub) => {\n cleanup = unsub;\n })\n .catch(console.error);\n\n return () => {\n cleanup?.();\n pdfViewer.destroy();\n setRegistry(null);\n setCoreState(null);\n setIsInitializing(true);\n setPluginsReady(false);\n };\n }, [engine, plugins]);\n\n // Compute convenience accessors\n const contextValue: PDFContextState = useMemo(() => {\n const activeDocumentId = coreState?.activeDocumentId ?? null;\n const documents = coreState?.documents ?? {};\n const documentOrder = coreState?.documentOrder ?? [];\n\n // Compute active document\n const activeDocument =\n activeDocumentId && documents[activeDocumentId] ? documents[activeDocumentId] : null;\n\n // Compute open documents in order\n const documentStates = documentOrder\n .map((docId) => documents[docId])\n .filter((doc): doc is DocumentState => doc !== null && doc !== undefined);\n\n return {\n registry,\n coreState,\n isInitializing,\n pluginsReady,\n // Convenience accessors (always safe to use)\n activeDocumentId,\n activeDocument,\n documents,\n documentStates,\n };\n }, [registry, coreState, isInitializing, pluginsReady]);\n\n const content = typeof children === 'function' ? children(contextValue) : children;\n\n return (\n <PDFContext.Provider value={contextValue}>\n {pluginsReady && autoMountDomElements ? (\n <AutoMount plugins={plugins}>{content}</AutoMount>\n ) : (\n content\n )}\n </PDFContext.Provider>\n );\n}\n","import type { BasePlugin } from '@embedpdf/core';\nimport { usePlugin } from './use-plugin';\n\ntype CapabilityState<T extends BasePlugin> = {\n provides: ReturnType<NonNullable<T['provides']>> | null;\n isLoading: boolean;\n ready: Promise<void>;\n};\n\n/**\n * Hook to access a plugin's capability.\n * @param pluginId The ID of the plugin to access\n * @returns The capability provided by the plugin or null during initialization\n * @example\n * // Get zoom capability\n * const zoom = useCapability<ZoomPlugin>(ZoomPlugin.id);\n */\nexport function useCapability<T extends BasePlugin>(pluginId: T['id']): CapabilityState<T> {\n const { plugin, isLoading, ready } = usePlugin<T>(pluginId);\n\n if (!plugin) {\n return {\n provides: null,\n isLoading,\n ready,\n };\n }\n\n if (!plugin.provides) {\n throw new Error(`Plugin ${pluginId} does not provide a capability`);\n }\n\n return {\n provides: plugin.provides() as ReturnType<NonNullable<T['provides']>>,\n isLoading,\n ready,\n };\n}\n","import { useMemo } from '@framework';\nimport { DocumentState } from '@embedpdf/core';\nimport { useCoreState } from './use-core-state';\n\n/**\n * Hook that provides reactive access to a specific document's state from the core store.\n *\n * @param documentId The ID of the document to retrieve.\n * @returns The reactive DocumentState object or null if not found.\n */\nexport function useDocumentState(documentId: string | null): DocumentState | null {\n const coreState = useCoreState();\n\n const documentState = useMemo(() => {\n if (!coreState || !documentId) return null;\n return coreState.documents[documentId] ?? null;\n }, [coreState, documentId]);\n\n return documentState;\n}\n","import { useState, useEffect } from '@framework';\nimport { CoreState, StoreState } from '@embedpdf/core';\nimport { useRegistry } from './use-registry';\n\n/**\n * Hook that provides access to the current global store state\n * and re-renders the component when the state changes\n */\nexport function useStoreState<T = CoreState>(): StoreState<T> | null {\n const { registry } = useRegistry();\n const [state, setState] = useState<StoreState<T> | null>(null);\n\n useEffect(() => {\n if (!registry) return;\n\n // Get initial state\n setState(registry.getStore().getState() as StoreState<T>);\n\n // Subscribe to store changes\n const unsubscribe = registry.getStore().subscribe((_action, newState) => {\n setState(newState as StoreState<T>);\n });\n\n return () => unsubscribe();\n }, [registry]);\n\n return state;\n}\n"],"names":["PDFContext","createContext","registry","coreState","isInitializing","pluginsReady","activeDocumentId","activeDocument","documents","documentStates","AutoMount","plugins","children","utilities","wrappers","useMemo","reg","pkg","package","hasAutoMountElements","elements","autoMountElements","element","type","push","component","wrappedContent","reduce","content","Wrapper","jsx","Fragment","map","Utility","i","useRegistry","contextValue","useContext","Error","usePlugin","pluginId","plugin","isLoading","ready","Promise","getPlugin","useCoreState","engine","logger","onInitialized","autoMountDomElements","setRegistry","useState","setCoreState","setIsInitializing","setPluginsReady","initRef","useRef","useEffect","current","pdfViewer","PluginRegistry","registerPluginBatch","cleanup","async","initialize","isDestroyed","store","getStore","getState","core","unsubscribe","subscribe","action","newState","oldState","isCoreAction","_a","call","then","unsub","catch","console","error","destroy","documentOrder","docId","filter","doc","Provider","value","provides","documentId","state","setState","_action"],"mappings":"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"}
|