@embedpdf/core 1.5.0 → 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
package/dist/preact/index.js
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import { createContext, Fragment } from "preact";
|
|
2
2
|
import { useMemo, useState, useRef, useEffect, useContext } from "preact/hooks";
|
|
3
3
|
import { jsx, jsxs } from "preact/jsx-runtime";
|
|
4
|
-
import { hasAutoMountElements, PluginRegistry
|
|
4
|
+
import { hasAutoMountElements, PluginRegistry } from "@embedpdf/core";
|
|
5
5
|
const PDFContext = createContext({
|
|
6
6
|
registry: null,
|
|
7
|
+
coreState: null,
|
|
7
8
|
isInitializing: true,
|
|
8
|
-
pluginsReady: false
|
|
9
|
+
pluginsReady: false,
|
|
10
|
+
activeDocumentId: null,
|
|
11
|
+
activeDocument: null,
|
|
12
|
+
documents: {},
|
|
13
|
+
documentStates: []
|
|
9
14
|
});
|
|
10
15
|
function AutoMount({ plugins, children }) {
|
|
11
16
|
const { utilities, wrappers } = useMemo(() => {
|
|
@@ -44,6 +49,7 @@ function EmbedPDF({
|
|
|
44
49
|
autoMountDomElements = true
|
|
45
50
|
}) {
|
|
46
51
|
const [registry, setRegistry] = useState(null);
|
|
52
|
+
const [coreState, setCoreState] = useState(null);
|
|
47
53
|
const [isInitializing, setIsInitializing] = useState(true);
|
|
48
54
|
const [pluginsReady, setPluginsReady] = useState(false);
|
|
49
55
|
const initRef = useRef(onInitialized);
|
|
@@ -59,8 +65,16 @@ function EmbedPDF({
|
|
|
59
65
|
if (pdfViewer.isDestroyed()) {
|
|
60
66
|
return;
|
|
61
67
|
}
|
|
68
|
+
const store = pdfViewer.getStore();
|
|
69
|
+
setCoreState(store.getState().core);
|
|
70
|
+
const unsubscribe = store.subscribe((action, newState, oldState) => {
|
|
71
|
+
if (store.isCoreAction(action) && newState.core !== oldState.core) {
|
|
72
|
+
setCoreState(newState.core);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
62
75
|
await ((_a = initRef.current) == null ? void 0 : _a.call(initRef, pdfViewer));
|
|
63
76
|
if (pdfViewer.isDestroyed()) {
|
|
77
|
+
unsubscribe();
|
|
64
78
|
return;
|
|
65
79
|
}
|
|
66
80
|
pdfViewer.pluginsReady().then(() => {
|
|
@@ -70,17 +84,41 @@ function EmbedPDF({
|
|
|
70
84
|
});
|
|
71
85
|
setRegistry(pdfViewer);
|
|
72
86
|
setIsInitializing(false);
|
|
87
|
+
return unsubscribe;
|
|
73
88
|
};
|
|
74
|
-
|
|
89
|
+
let cleanup;
|
|
90
|
+
initialize().then((unsub) => {
|
|
91
|
+
cleanup = unsub;
|
|
92
|
+
}).catch(console.error);
|
|
75
93
|
return () => {
|
|
94
|
+
cleanup == null ? void 0 : cleanup();
|
|
76
95
|
pdfViewer.destroy();
|
|
77
96
|
setRegistry(null);
|
|
97
|
+
setCoreState(null);
|
|
78
98
|
setIsInitializing(true);
|
|
79
99
|
setPluginsReady(false);
|
|
80
100
|
};
|
|
81
101
|
}, [engine, plugins]);
|
|
82
|
-
const
|
|
83
|
-
|
|
102
|
+
const contextValue = useMemo(() => {
|
|
103
|
+
const activeDocumentId = (coreState == null ? void 0 : coreState.activeDocumentId) ?? null;
|
|
104
|
+
const documents = (coreState == null ? void 0 : coreState.documents) ?? {};
|
|
105
|
+
const documentOrder = (coreState == null ? void 0 : coreState.documentOrder) ?? [];
|
|
106
|
+
const activeDocument = activeDocumentId && documents[activeDocumentId] ? documents[activeDocumentId] : null;
|
|
107
|
+
const documentStates = documentOrder.map((docId) => documents[docId]).filter((doc) => doc !== null && doc !== void 0);
|
|
108
|
+
return {
|
|
109
|
+
registry,
|
|
110
|
+
coreState,
|
|
111
|
+
isInitializing,
|
|
112
|
+
pluginsReady,
|
|
113
|
+
// Convenience accessors (always safe to use)
|
|
114
|
+
activeDocumentId,
|
|
115
|
+
activeDocument,
|
|
116
|
+
documents,
|
|
117
|
+
documentStates
|
|
118
|
+
};
|
|
119
|
+
}, [registry, coreState, isInitializing, pluginsReady]);
|
|
120
|
+
const content = typeof children === "function" ? children(contextValue) : children;
|
|
121
|
+
return /* @__PURE__ */ jsx(PDFContext.Provider, { value: contextValue, children: pluginsReady && autoMountDomElements ? /* @__PURE__ */ jsx(AutoMount, { plugins, children: content }) : content });
|
|
84
122
|
}
|
|
85
123
|
function useRegistry() {
|
|
86
124
|
const contextValue = useContext(PDFContext);
|
|
@@ -148,26 +186,23 @@ function useStoreState() {
|
|
|
148
186
|
return state;
|
|
149
187
|
}
|
|
150
188
|
function useCoreState() {
|
|
151
|
-
const {
|
|
152
|
-
const [coreState, setCoreState] = useState(null);
|
|
153
|
-
useEffect(() => {
|
|
154
|
-
if (!registry) return;
|
|
155
|
-
const store = registry.getStore();
|
|
156
|
-
setCoreState(store.getState().core);
|
|
157
|
-
const unsubscribe = store.subscribe((action, newState, oldState) => {
|
|
158
|
-
if (store.isCoreAction(action) && !arePropsEqual(newState.core, oldState.core)) {
|
|
159
|
-
setCoreState(newState.core);
|
|
160
|
-
}
|
|
161
|
-
});
|
|
162
|
-
return () => unsubscribe();
|
|
163
|
-
}, [registry]);
|
|
189
|
+
const { coreState } = useContext(PDFContext);
|
|
164
190
|
return coreState;
|
|
165
191
|
}
|
|
192
|
+
function useDocumentState(documentId) {
|
|
193
|
+
const coreState = useCoreState();
|
|
194
|
+
const documentState = useMemo(() => {
|
|
195
|
+
if (!coreState || !documentId) return null;
|
|
196
|
+
return coreState.documents[documentId] ?? null;
|
|
197
|
+
}, [coreState, documentId]);
|
|
198
|
+
return documentState;
|
|
199
|
+
}
|
|
166
200
|
export {
|
|
167
201
|
EmbedPDF,
|
|
168
202
|
PDFContext,
|
|
169
203
|
useCapability,
|
|
170
204
|
useCoreState,
|
|
205
|
+
useDocumentState,
|
|
171
206
|
usePlugin,
|
|
172
207
|
useRegistry,
|
|
173
208
|
useStoreState
|
package/dist/preact/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/shared/context.ts","../../src/shared/components/auto-mount.tsx","../../src/shared/components/embed-pdf.tsx","../../src/shared/hooks/use-registry.ts","../../src/shared/hooks/use-plugin.ts","../../src/shared/hooks/use-capability.ts","../../src/shared/hooks/use-store-state.ts","../../src/shared/hooks/use-core-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 { 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 { 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 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, 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","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"],"names":["utilities","wrappers"],"mappings":";;;;AASO,MAAM,aAAa,cAA+B;AAAA,EACvD,UAAU;AAAA,EACV,gBAAgB;AAAA,EAChB,cAAc;AAChB,CAAC;ACJM,SAAS,UAAU,EAAE,SAAS,YAA4B;AAC/D,QAAM,EAAE,WAAW,SAAS,IAAI,QAAQ,MAAM;AAE5C,UAAMA,aAA6B,CAAC;AACpC,UAAMC,YAAqD,CAAC;AAE5D,eAAW,OAAO,SAAS;AACzB,YAAM,MAAM,IAAI;AACZ,UAAA,qBAAqB,GAAG,GAAG;AAC7B,cAAM,WAAW,IAAI,kBAAkB,KAAK,CAAC;AAE7C,mBAAW,WAAW,UAAU;AAC1B,cAAA,QAAQ,SAAS,WAAW;AAC9BD,uBAAU,KAAK,QAAQ,SAAS;AAAA,UAAA,WACvB,QAAQ,SAAS,WAAW;AAErCC,sBAAS,KAAK,QAAQ,SAAS;AAAA,UAAA;AAAA,QACjC;AAAA,MACF;AAAA,IACF;AAEF,WAAO,EAAE,WAAAD,YAAW,UAAAC,UAAS;AAAA,EAAA,GAC5B,CAAC,OAAO,CAAC;AAGZ,QAAM,iBAAiB,SAAS;AAAA,IAC9B,CAAC,SAAS,YAAY,oBAAC,WAAS,UAAQ,SAAA;AAAA,IACxC;AAAA,EACF;AAEA,8BACG,UACE,EAAA,UAAA;AAAA,IAAA;AAAA,IACA,UAAU,IAAI,CAAC,SAAS,0BACtB,SAAa,IAAA,WAAW,CAAC,EAAI,CAC/B;AAAA,EAAA,GACH;AAEJ;ACTO,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,uBAAuB;AACzB,GAAkB;AAChB,QAAM,CAAC,UAAU,WAAW,IAAI,SAAgC,IAAI;AACpE,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAAkB,IAAI;AAClE,QAAM,CAAC,cAAc,eAAe,IAAI,SAAkB,KAAK;AACzD,QAAA,UAAU,OAAuC,aAAa;AAEpE,YAAU,MAAM;AACd,YAAQ,UAAU;AAAA,EAAA,GACjB,CAAC,aAAa,CAAC;AAElB,YAAU,MAAM;AACd,UAAM,YAAY,IAAI,eAAe,QAAQ,EAAE,QAAQ;AACvD,cAAU,oBAAoB,OAAO;AAErC,UAAM,aAAa,YAAY;;AAC7B,YAAM,UAAU,WAAW;AAEvB,UAAA,UAAU,eAAe;AAC3B;AAAA,MAAA;AAII,cAAA,aAAQ,YAAR,iCAAkB;AAGpB,UAAA,UAAU,eAAe;AAC3B;AAAA,MAAA;AAGQ,gBAAA,eAAe,KAAK,MAAM;AAC9B,YAAA,CAAC,UAAU,eAAe;AAC5B,0BAAgB,IAAI;AAAA,QAAA;AAAA,MACtB,CACD;AAGD,kBAAY,SAAS;AACrB,wBAAkB,KAAK;AAAA,IACzB;AAEW,iBAAE,MAAM,QAAQ,KAAK;AAEhC,WAAO,MAAM;AACX,gBAAU,QAAQ;AAClB,kBAAY,IAAI;AAChB,wBAAkB,IAAI;AACtB,sBAAgB,KAAK;AAAA,IACvB;AAAA,EAAA,GACC,CAAC,QAAQ,OAAO,CAAC;AAEd,QAAA,UACJ,OAAO,aAAa,aAChB,SAAS,EAAE,UAAU,gBAAgB,aAAc,CAAA,IACnD;AAEN,6BACG,WAAW,UAAX,EAAoB,OAAO,EAAE,UAAU,gBAAgB,gBACrD,0BAAgB,uBACf,oBAAC,aAAU,SAAmB,UAAA,QAAA,CAAQ,IAEtC,SAEJ;AAEJ;ACtGO,SAAS,cAA+B;AACvC,QAAA,eAAe,WAAW,UAAU;AAG1C,MAAI,iBAAiB,QAAW;AACxB,UAAA,IAAI,MAAM,yDAAyD;AAAA,EAAA;AAGrE,QAAA,EAAE,UAAU,eAAA,IAAmB;AAGrC,MAAI,gBAAgB;AACX,WAAA;AAAA,EAAA;AAIT,MAAI,aAAa,MAAM;AACf,UAAA,IAAI,MAAM,4CAA4C;AAAA,EAAA;AAGvD,SAAA;AACT;ACXO,SAAS,UAAgC,UAAmC;AAC3E,QAAA,EAAE,SAAS,IAAI,YAAY;AAEjC,MAAI,aAAa,MAAM;AACd,WAAA;AAAA,MACL,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,OAAO,IAAI,QAAQ,MAAM;AAAA,MAAE,CAAA;AAAA,IAC7B;AAAA,EAAA;AAGI,QAAA,SAAS,SAAS,UAAa,QAAQ;AAE7C,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,UAAU,QAAQ,YAAY;AAAA,EAAA;AAGzC,SAAA;AAAA,IACL;AAAA,IACA,WAAW;AAAA,IACX,OAAO,OAAO,MAAM;AAAA,EACtB;AACF;ACtBO,SAAS,cAAoC,UAAuC;AACzF,QAAM,EAAE,QAAQ,WAAW,MAAM,IAAI,UAAa,QAAQ;AAE1D,MAAI,CAAC,QAAQ;AACJ,WAAA;AAAA,MACL,UAAU;AAAA,MACV;AAAA,MACA;AAAA,IACF;AAAA,EAAA;AAGE,MAAA,CAAC,OAAO,UAAU;AACpB,UAAM,IAAI,MAAM,UAAU,QAAQ,gCAAgC;AAAA,EAAA;AAG7D,SAAA;AAAA,IACL,UAAU,OAAO,SAAS;AAAA,IAC1B;AAAA,IACA;AAAA,EACF;AACF;AC7BO,SAAS,gBAAqD;AAC7D,QAAA,EAAE,SAAS,IAAI,YAAY;AACjC,QAAM,CAAC,OAAO,QAAQ,IAAI,SAA+B,IAAI;AAE7D,YAAU,MAAM;AACd,QAAI,CAAC,SAAU;AAGf,aAAS,SAAS,SAAW,EAAA,SAAA,CAA2B;AAGxD,UAAM,cAAc,SAAS,SAAA,EAAW,UAAU,CAAC,SAAS,aAAa;AACvE,eAAS,QAAyB;AAAA,IAAA,CACnC;AAED,WAAO,MAAM,YAAY;AAAA,EAAA,GACxB,CAAC,QAAQ,CAAC;AAEN,SAAA;AACT;ACnBO,SAAS,eAAiC;AACzC,QAAA,EAAE,SAAS,IAAI,YAAY;AACjC,QAAM,CAAC,WAAW,YAAY,IAAI,SAA2B,IAAI;AAEjE,YAAU,MAAM;AACd,QAAI,CAAC,SAAU;AAET,UAAA,QAAQ,SAAS,SAAS;AAGnB,iBAAA,MAAM,SAAS,EAAE,IAAI;AAGlC,UAAM,cAAc,MAAM,UAAU,CAAC,QAAQ,UAAU,aAAa;AAE9D,UAAA,MAAM,aAAa,MAAM,KAAK,CAAC,cAAc,SAAS,MAAM,SAAS,IAAI,GAAG;AAC9E,qBAAa,SAAS,IAAI;AAAA,MAAA;AAAA,IAC5B,CACD;AAED,WAAO,MAAM,YAAY;AAAA,EAAA,GACxB,CAAC,QAAQ,CAAC;AAEN,SAAA;AACT;"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/shared/context.ts","../../src/shared/components/auto-mount.tsx","../../src/shared/components/embed-pdf.tsx","../../src/shared/hooks/use-registry.ts","../../src/shared/hooks/use-plugin.ts","../../src/shared/hooks/use-capability.ts","../../src/shared/hooks/use-store-state.ts","../../src/shared/hooks/use-core-state.ts","../../src/shared/hooks/use-document-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 { 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 { 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 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, 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","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 { 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"],"names":["utilities","wrappers"],"mappings":"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"}
|
package/dist/react/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react"),t=require("react/jsx-runtime"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react"),t=require("react/jsx-runtime"),n=require("@embedpdf/core"),r=e.createContext({registry:null,coreState:null,isInitializing:!0,pluginsReady:!1,activeDocumentId:null,activeDocument:null,documents:{},documentStates:[]});function i({plugins:r,children:i}){const{utilities:o,wrappers:u}=e.useMemo(()=>{const e=[],t=[];for(const i of r){const r=i.package;if(n.hasAutoMountElements(r)){const n=r.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}},[r]),s=u.reduce((e,n)=>t.jsx(n,{children:e}),i);return t.jsxs(e.Fragment,{children:[s,o.map((e,n)=>t.jsx(e,{},`utility-${n}`))]})}function o(){const t=e.useContext(r);if(void 0===t)throw new Error("useCapability must be used within a PDFContext.Provider");const{registry:n,isInitializing:i}=t;if(i)return t;if(null===n)throw new Error("PDF registry failed to initialize properly");return t}function u(e){const{registry:t}=o();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 s(){const{coreState:t}=e.useContext(r);return t}exports.EmbedPDF=function({engine:o,logger:u,onInitialized:s,plugins:l,children:c,autoMountDomElements:a=!0}){const[d,g]=e.useState(null),[p,f]=e.useState(null),[y,m]=e.useState(!0),[S,v]=e.useState(!1),x=e.useRef(s);e.useEffect(()=>{x.current=s},[s]),e.useEffect(()=>{const e=new n.PluginRegistry(o,{logger:u});e.registerPluginBatch(l);let t;return(async()=>{var t;if(await e.initialize(),e.isDestroyed())return;const n=e.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==(t=x.current)?void 0:t.call(x,e)),!e.isDestroyed())return e.pluginsReady().then(()=>{e.isDestroyed()||v(!0)}),g(e),m(!1),r;r()})().then(e=>{t=e}).catch(console.error),()=>{null==t||t(),e.destroy(),g(null),f(null),m(!0),v(!1)}},[o,l]);const h=e.useMemo(()=>{const e=(null==p?void 0:p.activeDocumentId)??null,t=(null==p?void 0:p.documents)??{},n=(null==p?void 0:p.documentOrder)??[],r=e&&t[e]?t[e]:null,i=n.map(e=>t[e]).filter(e=>null!=e);return{registry:d,coreState:p,isInitializing:y,pluginsReady:S,activeDocumentId:e,activeDocument:r,documents:t,documentStates:i}},[d,p,y,S]),w="function"==typeof c?c(h):c;return t.jsx(r.Provider,{value:h,children:S&&a?t.jsx(i,{plugins:l,children:w}):w})},exports.PDFContext=r,exports.useCapability=function(e){const{plugin:t,isLoading:n,ready:r}=u(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=s,exports.useDocumentState=function(t){const n=s();return e.useMemo(()=>n&&t?n.documents[t]??null:null,[n,t])},exports.usePlugin=u,exports.useRegistry=o,exports.useStoreState=function(){const{registry:t}=o(),[n,r]=e.useState(null);return e.useEffect(()=>{if(!t)return;r(t.getStore().getState());const e=t.getStore().subscribe((e,t)=>{r(t)});return()=>e()},[t]),n};
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/react/index.cjs.map
CHANGED
|
@@ -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":"oKASaA,EAAaC,EAAAA,cAA+B,CACvDC,SAAU,KACVC,gBAAgB,EAChBC,cAAc,ICHT,SAASC,GAAUC,QAAEA,EAASC,SAAAA,IACnC,MAAMC,UAAEA,EAAWC,SAAAA,GAAaC,WAAQ,KAEtC,MAAMF,EAA6B,GAC7BC,EAAqD,GAE3D,IAAA,MAAWE,KAAOL,EAAS,CACzB,MAAMM,EAAMD,EAAIE,QACZC,GAAAA,EAAAA,qBAAqBF,GAAM,CAC7B,MAAMG,EAAWH,EAAII,qBAAuB,GAE5C,IAAA,MAAWC,KAAWF,EACC,YAAjBE,EAAQC,KACAC,EAAAC,KAAKH,EAAQI,WACG,YAAjBJ,EAAQC,MAERI,EAAAF,KAAKH,EAAQI,UAE1B,CACF,CAEF,MAAO,CAAEb,UAAAA,EAAWC,SAAAA,EAAS,GAC5B,CAACH,IAGEiB,EAAiBd,EAASe,QAC9B,CAACC,EAASC,IAAYC,EAAAA,IAACD,GAASnB,SAAQkB,KACxClB,GAGF,cACGqB,WACE,CAAArB,SAAA,CAAAgB,EACAf,EAAUqB,KAAI,CAACC,EAASC,UACtBD,EAAa,GAAA,WAAWC,SAIjC,CCxCO,SAASC,IACR,MAAAC,EAAeC,aAAWlC,GAGhC,QAAqB,IAAjBiC,EACI,MAAA,IAAIE,MAAM,2DAGZ,MAAAjC,SAAEA,EAAUC,eAAAA,GAAmB8B,EAGrC,GAAI9B,EACK,OAAA8B,EAIT,GAAiB,OAAb/B,EACI,MAAA,IAAIiC,MAAM,8CAGX,OAAAF,CACT,CCXO,SAASG,EAAgCC,GACxC,MAAAnC,SAAEA,GAAa8B,IAErB,GAAiB,OAAb9B,EACK,MAAA,CACLoC,OAAQ,KACRC,WAAW,EACXC,MAAO,IAAIC,SAAQ,UAIjB,MAAAH,EAASpC,EAASwC,UAAaL,GAErC,IAAKC,EACH,MAAM,IAAIH,MAAM,UAAUE,eAGrB,MAAA,CACLC,SACAC,WAAW,EACXC,MAAOF,EAAOE,QAElB,kBCDO,UAAkBG,OACvBA,EAAAC,OACAA,EAAAC,cACAA,EAAAvC,QACAA,EAAAC,SACAA,EAAAuC,qBACAA,GAAuB,IAEvB,MAAO5C,EAAU6C,GAAeC,EAAAA,SAAgC,OACzD7C,EAAgB8C,GAAqBD,EAAAA,UAAkB,IACvD5C,EAAc8C,GAAmBF,EAAAA,UAAkB,GACpDG,EAAUC,SAAuCP,GAEvDQ,EAAAA,WAAU,KACRF,EAAQG,QAAUT,CAAA,GACjB,CAACA,IAEJQ,EAAAA,WAAU,KACR,MAAME,EAAY,IAAIC,EAAAA,eAAeb,EAAQ,CAAEC,WAC/CW,EAAUE,oBAAoBnD,GA8B9B,MA5BmBoD,uBACXH,EAAUI,aAEZJ,EAAUK,sBAKR,OAAAC,EAAAV,EAAQG,cAAU,EAAAO,EAAAC,KAAAX,EAAAI,IAGpBA,EAAUK,gBAIJL,EAAAnD,eAAe2D,MAAK,KACvBR,EAAUK,eACbV,GAAgB,EAAI,IAKxBH,EAAYQ,GACZN,GAAkB,IAAK,KAGZe,MAAMC,QAAQC,OAEpB,KACLX,EAAUY,UACVpB,EAAY,MACZE,GAAkB,GAClBC,GAAgB,EAAK,CACvB,GACC,CAACP,EAAQrC,IAEN,MAAAmB,EACgB,mBAAblB,EACHA,EAAS,CAAEL,WAAUC,iBAAgBC,iBACrCG,eAGHP,EAAWoE,SAAX,CAAoBC,MAAO,CAAEnE,WAAUC,iBAAgBC,gBACrDG,YAAgBuC,EACfnB,MAACtB,GAAUC,UAAmBC,SAAAkB,IAE9BA,GAIR,6CC5FO,SAA6CY,GAClD,MAAMC,OAAEA,EAAQC,UAAAA,EAAAC,MAAWA,GAAUJ,EAAaC,GAElD,IAAKC,EACI,MAAA,CACLgC,SAAU,KACV/B,YACAC,SAIA,IAACF,EAAOgC,SACV,MAAM,IAAInC,MAAM,UAAUE,mCAGrB,MAAA,CACLiC,SAAUhC,EAAOgC,WACjB/B,YACAC,QAEJ,uBC7BO,WACC,MAAAtC,SAAEA,GAAa8B,KACduC,EAAWC,GAAgBxB,EAAAA,SAA2B,MAqBtD,OAnBPK,EAAAA,WAAU,KACR,IAAKnD,EAAU,OAET,MAAAuE,EAAQvE,EAASwE,WAGVF,EAAAC,EAAME,WAAWC,MAG9B,MAAMC,EAAcJ,EAAMK,WAAU,CAACC,EAAQC,EAAUC,KAEjDR,EAAMS,aAAaH,KAAYI,gBAAcH,EAASJ,KAAMK,EAASL,OACvEJ,EAAaQ,EAASJ,KAAI,IAI9B,MAAO,IAAMC,GAAY,GACxB,CAAC3E,IAEGqE,CACT,kECxBO,WACC,MAAArE,SAAEA,GAAa8B,KACdoD,EAAOC,GAAYrC,EAAAA,SAA+B,MAgBlD,OAdPK,EAAAA,WAAU,KACR,IAAKnD,EAAU,OAGfmF,EAASnF,EAASwE,WAAWC,YAG7B,MAAME,EAAc3E,EAASwE,WAAWI,WAAU,CAACQ,EAASN,KAC1DK,EAASL,EAAyB,IAGpC,MAAO,IAAMH,GAAY,GACxB,CAAC3E,IAEGkF,CACT"}
|
|
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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"}
|
package/dist/react/index.js
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { createContext, useMemo, Fragment, useState, useRef, useEffect, useContext } from "react";
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { hasAutoMountElements, PluginRegistry
|
|
3
|
+
import { hasAutoMountElements, PluginRegistry } from "@embedpdf/core";
|
|
4
4
|
const PDFContext = createContext({
|
|
5
5
|
registry: null,
|
|
6
|
+
coreState: null,
|
|
6
7
|
isInitializing: true,
|
|
7
|
-
pluginsReady: false
|
|
8
|
+
pluginsReady: false,
|
|
9
|
+
activeDocumentId: null,
|
|
10
|
+
activeDocument: null,
|
|
11
|
+
documents: {},
|
|
12
|
+
documentStates: []
|
|
8
13
|
});
|
|
9
14
|
function AutoMount({ plugins, children }) {
|
|
10
15
|
const { utilities, wrappers } = useMemo(() => {
|
|
@@ -43,6 +48,7 @@ function EmbedPDF({
|
|
|
43
48
|
autoMountDomElements = true
|
|
44
49
|
}) {
|
|
45
50
|
const [registry, setRegistry] = useState(null);
|
|
51
|
+
const [coreState, setCoreState] = useState(null);
|
|
46
52
|
const [isInitializing, setIsInitializing] = useState(true);
|
|
47
53
|
const [pluginsReady, setPluginsReady] = useState(false);
|
|
48
54
|
const initRef = useRef(onInitialized);
|
|
@@ -58,8 +64,16 @@ function EmbedPDF({
|
|
|
58
64
|
if (pdfViewer.isDestroyed()) {
|
|
59
65
|
return;
|
|
60
66
|
}
|
|
67
|
+
const store = pdfViewer.getStore();
|
|
68
|
+
setCoreState(store.getState().core);
|
|
69
|
+
const unsubscribe = store.subscribe((action, newState, oldState) => {
|
|
70
|
+
if (store.isCoreAction(action) && newState.core !== oldState.core) {
|
|
71
|
+
setCoreState(newState.core);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
61
74
|
await ((_a = initRef.current) == null ? void 0 : _a.call(initRef, pdfViewer));
|
|
62
75
|
if (pdfViewer.isDestroyed()) {
|
|
76
|
+
unsubscribe();
|
|
63
77
|
return;
|
|
64
78
|
}
|
|
65
79
|
pdfViewer.pluginsReady().then(() => {
|
|
@@ -69,17 +83,41 @@ function EmbedPDF({
|
|
|
69
83
|
});
|
|
70
84
|
setRegistry(pdfViewer);
|
|
71
85
|
setIsInitializing(false);
|
|
86
|
+
return unsubscribe;
|
|
72
87
|
};
|
|
73
|
-
|
|
88
|
+
let cleanup;
|
|
89
|
+
initialize().then((unsub) => {
|
|
90
|
+
cleanup = unsub;
|
|
91
|
+
}).catch(console.error);
|
|
74
92
|
return () => {
|
|
93
|
+
cleanup == null ? void 0 : cleanup();
|
|
75
94
|
pdfViewer.destroy();
|
|
76
95
|
setRegistry(null);
|
|
96
|
+
setCoreState(null);
|
|
77
97
|
setIsInitializing(true);
|
|
78
98
|
setPluginsReady(false);
|
|
79
99
|
};
|
|
80
100
|
}, [engine, plugins]);
|
|
81
|
-
const
|
|
82
|
-
|
|
101
|
+
const contextValue = useMemo(() => {
|
|
102
|
+
const activeDocumentId = (coreState == null ? void 0 : coreState.activeDocumentId) ?? null;
|
|
103
|
+
const documents = (coreState == null ? void 0 : coreState.documents) ?? {};
|
|
104
|
+
const documentOrder = (coreState == null ? void 0 : coreState.documentOrder) ?? [];
|
|
105
|
+
const activeDocument = activeDocumentId && documents[activeDocumentId] ? documents[activeDocumentId] : null;
|
|
106
|
+
const documentStates = documentOrder.map((docId) => documents[docId]).filter((doc) => doc !== null && doc !== void 0);
|
|
107
|
+
return {
|
|
108
|
+
registry,
|
|
109
|
+
coreState,
|
|
110
|
+
isInitializing,
|
|
111
|
+
pluginsReady,
|
|
112
|
+
// Convenience accessors (always safe to use)
|
|
113
|
+
activeDocumentId,
|
|
114
|
+
activeDocument,
|
|
115
|
+
documents,
|
|
116
|
+
documentStates
|
|
117
|
+
};
|
|
118
|
+
}, [registry, coreState, isInitializing, pluginsReady]);
|
|
119
|
+
const content = typeof children === "function" ? children(contextValue) : children;
|
|
120
|
+
return /* @__PURE__ */ jsx(PDFContext.Provider, { value: contextValue, children: pluginsReady && autoMountDomElements ? /* @__PURE__ */ jsx(AutoMount, { plugins, children: content }) : content });
|
|
83
121
|
}
|
|
84
122
|
function useRegistry() {
|
|
85
123
|
const contextValue = useContext(PDFContext);
|
|
@@ -147,26 +185,23 @@ function useStoreState() {
|
|
|
147
185
|
return state;
|
|
148
186
|
}
|
|
149
187
|
function useCoreState() {
|
|
150
|
-
const {
|
|
151
|
-
const [coreState, setCoreState] = useState(null);
|
|
152
|
-
useEffect(() => {
|
|
153
|
-
if (!registry) return;
|
|
154
|
-
const store = registry.getStore();
|
|
155
|
-
setCoreState(store.getState().core);
|
|
156
|
-
const unsubscribe = store.subscribe((action, newState, oldState) => {
|
|
157
|
-
if (store.isCoreAction(action) && !arePropsEqual(newState.core, oldState.core)) {
|
|
158
|
-
setCoreState(newState.core);
|
|
159
|
-
}
|
|
160
|
-
});
|
|
161
|
-
return () => unsubscribe();
|
|
162
|
-
}, [registry]);
|
|
188
|
+
const { coreState } = useContext(PDFContext);
|
|
163
189
|
return coreState;
|
|
164
190
|
}
|
|
191
|
+
function useDocumentState(documentId) {
|
|
192
|
+
const coreState = useCoreState();
|
|
193
|
+
const documentState = useMemo(() => {
|
|
194
|
+
if (!coreState || !documentId) return null;
|
|
195
|
+
return coreState.documents[documentId] ?? null;
|
|
196
|
+
}, [coreState, documentId]);
|
|
197
|
+
return documentState;
|
|
198
|
+
}
|
|
165
199
|
export {
|
|
166
200
|
EmbedPDF,
|
|
167
201
|
PDFContext,
|
|
168
202
|
useCapability,
|
|
169
203
|
useCoreState,
|
|
204
|
+
useDocumentState,
|
|
170
205
|
usePlugin,
|
|
171
206
|
useRegistry,
|
|
172
207
|
useStoreState
|
package/dist/react/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/shared/context.ts","../../src/shared/components/auto-mount.tsx","../../src/shared/components/embed-pdf.tsx","../../src/shared/hooks/use-registry.ts","../../src/shared/hooks/use-plugin.ts","../../src/shared/hooks/use-capability.ts","../../src/shared/hooks/use-store-state.ts","../../src/shared/hooks/use-core-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 { 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 { 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 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, 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","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"],"names":["utilities","wrappers"],"mappings":";;;AASO,MAAM,aAAa,cAA+B;AAAA,EACvD,UAAU;AAAA,EACV,gBAAgB;AAAA,EAChB,cAAc;AAChB,CAAC;ACJM,SAAS,UAAU,EAAE,SAAS,YAA4B;AAC/D,QAAM,EAAE,WAAW,SAAS,IAAI,QAAQ,MAAM;AAE5C,UAAMA,aAA6B,CAAC;AACpC,UAAMC,YAAqD,CAAC;AAE5D,eAAW,OAAO,SAAS;AACzB,YAAM,MAAM,IAAI;AACZ,UAAA,qBAAqB,GAAG,GAAG;AAC7B,cAAM,WAAW,IAAI,kBAAkB,KAAK,CAAC;AAE7C,mBAAW,WAAW,UAAU;AAC1B,cAAA,QAAQ,SAAS,WAAW;AAC9BD,uBAAU,KAAK,QAAQ,SAAS;AAAA,UAAA,WACvB,QAAQ,SAAS,WAAW;AAErCC,sBAAS,KAAK,QAAQ,SAAS;AAAA,UAAA;AAAA,QACjC;AAAA,MACF;AAAA,IACF;AAEF,WAAO,EAAE,WAAAD,YAAW,UAAAC,UAAS;AAAA,EAAA,GAC5B,CAAC,OAAO,CAAC;AAGZ,QAAM,iBAAiB,SAAS;AAAA,IAC9B,CAAC,SAAS,YAAY,oBAAC,WAAS,UAAQ,SAAA;AAAA,IACxC;AAAA,EACF;AAEA,8BACG,UACE,EAAA,UAAA;AAAA,IAAA;AAAA,IACA,UAAU,IAAI,CAAC,SAAS,0BACtB,SAAa,IAAA,WAAW,CAAC,EAAI,CAC/B;AAAA,EAAA,GACH;AAEJ;ACTO,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,uBAAuB;AACzB,GAAkB;AAChB,QAAM,CAAC,UAAU,WAAW,IAAI,SAAgC,IAAI;AACpE,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAAkB,IAAI;AAClE,QAAM,CAAC,cAAc,eAAe,IAAI,SAAkB,KAAK;AACzD,QAAA,UAAU,OAAuC,aAAa;AAEpE,YAAU,MAAM;AACd,YAAQ,UAAU;AAAA,EAAA,GACjB,CAAC,aAAa,CAAC;AAElB,YAAU,MAAM;AACd,UAAM,YAAY,IAAI,eAAe,QAAQ,EAAE,QAAQ;AACvD,cAAU,oBAAoB,OAAO;AAErC,UAAM,aAAa,YAAY;;AAC7B,YAAM,UAAU,WAAW;AAEvB,UAAA,UAAU,eAAe;AAC3B;AAAA,MAAA;AAII,cAAA,aAAQ,YAAR,iCAAkB;AAGpB,UAAA,UAAU,eAAe;AAC3B;AAAA,MAAA;AAGQ,gBAAA,eAAe,KAAK,MAAM;AAC9B,YAAA,CAAC,UAAU,eAAe;AAC5B,0BAAgB,IAAI;AAAA,QAAA;AAAA,MACtB,CACD;AAGD,kBAAY,SAAS;AACrB,wBAAkB,KAAK;AAAA,IACzB;AAEW,iBAAE,MAAM,QAAQ,KAAK;AAEhC,WAAO,MAAM;AACX,gBAAU,QAAQ;AAClB,kBAAY,IAAI;AAChB,wBAAkB,IAAI;AACtB,sBAAgB,KAAK;AAAA,IACvB;AAAA,EAAA,GACC,CAAC,QAAQ,OAAO,CAAC;AAEd,QAAA,UACJ,OAAO,aAAa,aAChB,SAAS,EAAE,UAAU,gBAAgB,aAAc,CAAA,IACnD;AAEN,6BACG,WAAW,UAAX,EAAoB,OAAO,EAAE,UAAU,gBAAgB,gBACrD,0BAAgB,uBACf,oBAAC,aAAU,SAAmB,UAAA,QAAA,CAAQ,IAEtC,SAEJ;AAEJ;ACtGO,SAAS,cAA+B;AACvC,QAAA,eAAe,WAAW,UAAU;AAG1C,MAAI,iBAAiB,QAAW;AACxB,UAAA,IAAI,MAAM,yDAAyD;AAAA,EAAA;AAGrE,QAAA,EAAE,UAAU,eAAA,IAAmB;AAGrC,MAAI,gBAAgB;AACX,WAAA;AAAA,EAAA;AAIT,MAAI,aAAa,MAAM;AACf,UAAA,IAAI,MAAM,4CAA4C;AAAA,EAAA;AAGvD,SAAA;AACT;ACXO,SAAS,UAAgC,UAAmC;AAC3E,QAAA,EAAE,SAAS,IAAI,YAAY;AAEjC,MAAI,aAAa,MAAM;AACd,WAAA;AAAA,MACL,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,OAAO,IAAI,QAAQ,MAAM;AAAA,MAAE,CAAA;AAAA,IAC7B;AAAA,EAAA;AAGI,QAAA,SAAS,SAAS,UAAa,QAAQ;AAE7C,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,UAAU,QAAQ,YAAY;AAAA,EAAA;AAGzC,SAAA;AAAA,IACL;AAAA,IACA,WAAW;AAAA,IACX,OAAO,OAAO,MAAM;AAAA,EACtB;AACF;ACtBO,SAAS,cAAoC,UAAuC;AACzF,QAAM,EAAE,QAAQ,WAAW,MAAM,IAAI,UAAa,QAAQ;AAE1D,MAAI,CAAC,QAAQ;AACJ,WAAA;AAAA,MACL,UAAU;AAAA,MACV;AAAA,MACA;AAAA,IACF;AAAA,EAAA;AAGE,MAAA,CAAC,OAAO,UAAU;AACpB,UAAM,IAAI,MAAM,UAAU,QAAQ,gCAAgC;AAAA,EAAA;AAG7D,SAAA;AAAA,IACL,UAAU,OAAO,SAAS;AAAA,IAC1B;AAAA,IACA;AAAA,EACF;AACF;AC7BO,SAAS,gBAAqD;AAC7D,QAAA,EAAE,SAAS,IAAI,YAAY;AACjC,QAAM,CAAC,OAAO,QAAQ,IAAI,SAA+B,IAAI;AAE7D,YAAU,MAAM;AACd,QAAI,CAAC,SAAU;AAGf,aAAS,SAAS,SAAW,EAAA,SAAA,CAA2B;AAGxD,UAAM,cAAc,SAAS,SAAA,EAAW,UAAU,CAAC,SAAS,aAAa;AACvE,eAAS,QAAyB;AAAA,IAAA,CACnC;AAED,WAAO,MAAM,YAAY;AAAA,EAAA,GACxB,CAAC,QAAQ,CAAC;AAEN,SAAA;AACT;ACnBO,SAAS,eAAiC;AACzC,QAAA,EAAE,SAAS,IAAI,YAAY;AACjC,QAAM,CAAC,WAAW,YAAY,IAAI,SAA2B,IAAI;AAEjE,YAAU,MAAM;AACd,QAAI,CAAC,SAAU;AAET,UAAA,QAAQ,SAAS,SAAS;AAGnB,iBAAA,MAAM,SAAS,EAAE,IAAI;AAGlC,UAAM,cAAc,MAAM,UAAU,CAAC,QAAQ,UAAU,aAAa;AAE9D,UAAA,MAAM,aAAa,MAAM,KAAK,CAAC,cAAc,SAAS,MAAM,SAAS,IAAI,GAAG;AAC9E,qBAAa,SAAS,IAAI;AAAA,MAAA;AAAA,IAC5B,CACD;AAED,WAAO,MAAM,YAAY;AAAA,EAAA,GACxB,CAAC,QAAQ,CAAC;AAEN,SAAA;AACT;"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/shared/context.ts","../../src/shared/components/auto-mount.tsx","../../src/shared/components/embed-pdf.tsx","../../src/shared/hooks/use-registry.ts","../../src/shared/hooks/use-plugin.ts","../../src/shared/hooks/use-capability.ts","../../src/shared/hooks/use-store-state.ts","../../src/shared/hooks/use-core-state.ts","../../src/shared/hooks/use-document-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 { 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 { 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 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, 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","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 { 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"],"names":["utilities","wrappers"],"mappings":"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"}
|
package/dist/shared/context.d.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
import { PluginRegistry } from '../index.ts';
|
|
1
|
+
import { CoreState, DocumentState, PluginRegistry } from '../index.ts';
|
|
2
2
|
export interface PDFContextState {
|
|
3
3
|
registry: PluginRegistry | null;
|
|
4
|
+
coreState: CoreState | null;
|
|
4
5
|
isInitializing: boolean;
|
|
5
6
|
pluginsReady: boolean;
|
|
7
|
+
activeDocumentId: string | null;
|
|
8
|
+
activeDocument: DocumentState | null;
|
|
9
|
+
documents: Record<string, DocumentState>;
|
|
10
|
+
documentStates: DocumentState[];
|
|
6
11
|
}
|
|
7
12
|
export declare const PDFContext: import('react').Context<PDFContextState>;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { CoreState } from '../../index.ts';
|
|
2
2
|
/**
|
|
3
|
-
* Hook that provides access to the current core state
|
|
4
|
-
*
|
|
3
|
+
* Hook that provides access to the current core state.
|
|
4
|
+
*
|
|
5
|
+
* Note: This reads from the context which is already subscribed to core state changes
|
|
6
|
+
* in the EmbedPDF component, so there's no additional subscription overhead.
|
|
5
7
|
*/
|
|
6
8
|
export declare function useCoreState(): CoreState | null;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { DocumentState } from '../../index.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Hook that provides reactive access to a specific document's state from the core store.
|
|
4
|
+
*
|
|
5
|
+
* @param documentId The ID of the document to retrieve.
|
|
6
|
+
* @returns The reactive DocumentState object or null if not found.
|
|
7
|
+
*/
|
|
8
|
+
export declare function useDocumentState(documentId: string | null): DocumentState | null;
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
import { PluginRegistry } from '../lib/index.ts';
|
|
1
|
+
import { CoreState, DocumentState, PluginRegistry } from '../lib/index.ts';
|
|
2
2
|
export interface PDFContextState {
|
|
3
3
|
registry: PluginRegistry | null;
|
|
4
|
+
coreState: CoreState | null;
|
|
4
5
|
isInitializing: boolean;
|
|
5
6
|
pluginsReady: boolean;
|
|
7
|
+
activeDocumentId: string | null;
|
|
8
|
+
activeDocument: DocumentState | null;
|
|
9
|
+
documents: Record<string, DocumentState>;
|
|
10
|
+
documentStates: DocumentState[];
|
|
6
11
|
}
|
|
7
12
|
export declare const PDFContext: import('preact').Context<PDFContextState>;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { CoreState } from '../../lib/index.ts';
|
|
2
2
|
/**
|
|
3
|
-
* Hook that provides access to the current core state
|
|
4
|
-
*
|
|
3
|
+
* Hook that provides access to the current core state.
|
|
4
|
+
*
|
|
5
|
+
* Note: This reads from the context which is already subscribed to core state changes
|
|
6
|
+
* in the EmbedPDF component, so there's no additional subscription overhead.
|
|
5
7
|
*/
|
|
6
8
|
export declare function useCoreState(): CoreState | null;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { DocumentState } from '../../lib/index.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Hook that provides reactive access to a specific document's state from the core store.
|
|
4
|
+
*
|
|
5
|
+
* @param documentId The ID of the document to retrieve.
|
|
6
|
+
* @returns The reactive DocumentState object or null if not found.
|
|
7
|
+
*/
|
|
8
|
+
export declare function useDocumentState(documentId: string | null): DocumentState | null;
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
import { PluginRegistry } from '../lib/index.ts';
|
|
1
|
+
import { CoreState, DocumentState, PluginRegistry } from '../lib/index.ts';
|
|
2
2
|
export interface PDFContextState {
|
|
3
3
|
registry: PluginRegistry | null;
|
|
4
|
+
coreState: CoreState | null;
|
|
4
5
|
isInitializing: boolean;
|
|
5
6
|
pluginsReady: boolean;
|
|
7
|
+
activeDocumentId: string | null;
|
|
8
|
+
activeDocument: DocumentState | null;
|
|
9
|
+
documents: Record<string, DocumentState>;
|
|
10
|
+
documentStates: DocumentState[];
|
|
6
11
|
}
|
|
7
12
|
export declare const PDFContext: import('react').Context<PDFContextState>;
|