@embedpdf/core 1.0.0 → 1.0.1
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 +37 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -3
- package/dist/index.d.ts +5 -3
- package/dist/index.js +36 -27
- package/dist/index.js.map +1 -1
- package/dist/preact/index.cjs +28 -3
- package/dist/preact/index.cjs.map +1 -1
- package/dist/preact/index.d.cts +7 -1
- package/dist/preact/index.d.ts +7 -1
- package/dist/preact/index.js +28 -4
- package/dist/preact/index.js.map +1 -1
- package/dist/react/index.cjs +28 -3
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +7 -1
- package/dist/react/index.d.ts +7 -1
- package/dist/react/index.js +28 -4
- package/dist/react/index.js.map +1 -1
- package/package.json +3 -3
package/dist/preact/index.d.ts
CHANGED
|
@@ -47,6 +47,12 @@ declare function useRegistry(): PDFContextState;
|
|
|
47
47
|
*/
|
|
48
48
|
declare function useStoreState<T = CoreState>(): StoreState<T> | null;
|
|
49
49
|
|
|
50
|
+
/**
|
|
51
|
+
* Hook that provides access to the current core state
|
|
52
|
+
* and re-renders the component only when the core state changes
|
|
53
|
+
*/
|
|
54
|
+
declare function useCoreState(): CoreState | null;
|
|
55
|
+
|
|
50
56
|
type PluginState<T extends BasePlugin> = {
|
|
51
57
|
plugin: T | null;
|
|
52
58
|
isLoading: boolean;
|
|
@@ -62,4 +68,4 @@ type PluginState<T extends BasePlugin> = {
|
|
|
62
68
|
*/
|
|
63
69
|
declare function usePlugin<T extends BasePlugin>(pluginId: T['id']): PluginState<T>;
|
|
64
70
|
|
|
65
|
-
export { EmbedPDF, PDFContext, type PDFContextState, useCapability, usePlugin, useRegistry, useStoreState };
|
|
71
|
+
export { EmbedPDF, PDFContext, type PDFContextState, useCapability, useCoreState, usePlugin, useRegistry, useStoreState };
|
package/dist/preact/index.js
CHANGED
|
@@ -7,14 +7,17 @@ var PDFContext = createContext({
|
|
|
7
7
|
});
|
|
8
8
|
|
|
9
9
|
// src/preact/components/embed-pdf.tsx
|
|
10
|
-
import { useState, useEffect,
|
|
10
|
+
import { useState, useEffect, useRef } from "preact/hooks";
|
|
11
11
|
import { PluginRegistry } from "@embedpdf/core";
|
|
12
12
|
import { jsx } from "preact/jsx-runtime";
|
|
13
13
|
function EmbedPDF({ engine, onInitialized, plugins, children }) {
|
|
14
14
|
const [registry, setRegistry] = useState(null);
|
|
15
15
|
const [isInitializing, setIsInitializing] = useState(true);
|
|
16
16
|
const [pluginsReady, setPluginsReady] = useState(false);
|
|
17
|
-
const
|
|
17
|
+
const initRef = useRef(onInitialized);
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
initRef.current = onInitialized;
|
|
20
|
+
}, [onInitialized]);
|
|
18
21
|
useEffect(() => {
|
|
19
22
|
const pdfViewer = new PluginRegistry(engine);
|
|
20
23
|
pdfViewer.registerPluginBatch(plugins);
|
|
@@ -23,7 +26,7 @@ function EmbedPDF({ engine, onInitialized, plugins, children }) {
|
|
|
23
26
|
if (pdfViewer.isDestroyed()) {
|
|
24
27
|
return;
|
|
25
28
|
}
|
|
26
|
-
await
|
|
29
|
+
await initRef.current?.(pdfViewer);
|
|
27
30
|
if (pdfViewer.isDestroyed()) {
|
|
28
31
|
return;
|
|
29
32
|
}
|
|
@@ -42,7 +45,7 @@ function EmbedPDF({ engine, onInitialized, plugins, children }) {
|
|
|
42
45
|
setIsInitializing(true);
|
|
43
46
|
setPluginsReady(false);
|
|
44
47
|
};
|
|
45
|
-
}, [engine,
|
|
48
|
+
}, [engine, plugins]);
|
|
46
49
|
return /* @__PURE__ */ jsx(PDFContext.Provider, { value: { registry, isInitializing, pluginsReady }, children: typeof children === "function" ? children({ registry, isInitializing, pluginsReady }) : children });
|
|
47
50
|
}
|
|
48
51
|
|
|
@@ -120,10 +123,31 @@ function useStoreState() {
|
|
|
120
123
|
}, [registry]);
|
|
121
124
|
return state;
|
|
122
125
|
}
|
|
126
|
+
|
|
127
|
+
// src/preact/hooks/use-core-state.ts
|
|
128
|
+
import { useState as useState3, useEffect as useEffect3 } from "preact/hooks";
|
|
129
|
+
import { arePropsEqual } from "@embedpdf/core";
|
|
130
|
+
function useCoreState() {
|
|
131
|
+
const { registry } = useRegistry();
|
|
132
|
+
const [coreState, setCoreState] = useState3(null);
|
|
133
|
+
useEffect3(() => {
|
|
134
|
+
if (!registry) return;
|
|
135
|
+
const store = registry.getStore();
|
|
136
|
+
setCoreState(store.getState().core);
|
|
137
|
+
const unsubscribe = store.subscribe((action, newState, oldState) => {
|
|
138
|
+
if (store.isCoreAction(action) && !arePropsEqual(newState.core, oldState.core)) {
|
|
139
|
+
setCoreState(newState.core);
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
return () => unsubscribe();
|
|
143
|
+
}, [registry]);
|
|
144
|
+
return coreState;
|
|
145
|
+
}
|
|
123
146
|
export {
|
|
124
147
|
EmbedPDF,
|
|
125
148
|
PDFContext,
|
|
126
149
|
useCapability,
|
|
150
|
+
useCoreState,
|
|
127
151
|
usePlugin,
|
|
128
152
|
useRegistry,
|
|
129
153
|
useStoreState
|
package/dist/preact/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/preact/context.ts","../../src/preact/components/embed-pdf.tsx","../../src/preact/hooks/use-registry.ts","../../src/preact/hooks/use-plugin.ts","../../src/preact/hooks/use-capability.ts","../../src/preact/hooks/use-store-state.ts"],"sourcesContent":["import { createContext } from 'preact';\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","/** @jsxImportSource preact */\nimport { h, ComponentChildren } from 'preact';\nimport { useState, useEffect, useCallback } from 'preact/hooks';\nimport { PdfEngine } from '@embedpdf/models';\nimport { PluginRegistry } from '@embedpdf/core';\nimport type { IPlugin, PluginBatchRegistration } from '@embedpdf/core';\n\nimport { PDFContext, PDFContextState } from '../context';\n\ninterface EmbedPDFProps {\n engine: PdfEngine;\n onInitialized: (registry: PluginRegistry) => Promise<void>;\n plugins: PluginBatchRegistration<IPlugin<any>, any>[];\n children: ComponentChildren | ((state: PDFContextState) => ComponentChildren);\n}\n\nexport function EmbedPDF({ engine, onInitialized, plugins, children }: EmbedPDFProps) {\n const [registry, setRegistry] = useState<PluginRegistry | null>(null);\n const [isInitializing, setIsInitializing] = useState<boolean>(true);\n const [pluginsReady, setPluginsReady] = useState<boolean>(false);\n\n const stableOnInit = useCallback(onInitialized, [onInitialized]);\n\n useEffect(() => {\n const pdfViewer = new PluginRegistry(engine);\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 await stableOnInit(pdfViewer);\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, stableOnInit, plugins]);\n\n return (\n <PDFContext.Provider value={{ registry, isInitializing, pluginsReady }}>\n {typeof children === 'function'\n ? children({ registry, isInitializing, pluginsReady })\n : children}\n </PDFContext.Provider>\n );\n}\n","import { useContext } from 'preact/hooks';\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 'preact/hooks';\nimport { CoreState, PluginRegistry, 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"],"mappings":"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","names":["useState","useEffect","useState","useEffect"]}
|
|
1
|
+
{"version":3,"sources":["../../src/preact/context.ts","../../src/preact/components/embed-pdf.tsx","../../src/preact/hooks/use-registry.ts","../../src/preact/hooks/use-plugin.ts","../../src/preact/hooks/use-capability.ts","../../src/preact/hooks/use-store-state.ts","../../src/preact/hooks/use-core-state.ts"],"sourcesContent":["import { createContext } from 'preact';\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","/** @jsxImportSource preact */\nimport { h, ComponentChildren } from 'preact';\nimport { useState, useEffect, useCallback, useRef } from 'preact/hooks';\nimport { PdfEngine } from '@embedpdf/models';\nimport { PluginRegistry } from '@embedpdf/core';\nimport type { IPlugin, PluginBatchRegistration } from '@embedpdf/core';\n\nimport { PDFContext, PDFContextState } from '../context';\n\ninterface EmbedPDFProps {\n engine: PdfEngine;\n onInitialized: (registry: PluginRegistry) => Promise<void>;\n plugins: PluginBatchRegistration<IPlugin<any>, any>[];\n children: ComponentChildren | ((state: PDFContextState) => ComponentChildren);\n}\n\nexport function EmbedPDF({ engine, onInitialized, plugins, children }: 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);\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 await initRef.current?.(pdfViewer);\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 return (\n <PDFContext.Provider value={{ registry, isInitializing, pluginsReady }}>\n {typeof children === 'function'\n ? children({ registry, isInitializing, pluginsReady })\n : children}\n </PDFContext.Provider>\n );\n}\n","import { useContext } from 'preact/hooks';\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 'preact/hooks';\nimport { CoreState, PluginRegistry, 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 'preact/hooks';\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"],"mappings":";AAAA,SAAS,qBAAqB;AASvB,IAAM,aAAa,cAA+B;AAAA,EACvD,UAAU;AAAA,EACV,gBAAgB;AAAA,EAChB,cAAc;AAChB,CAAC;;;ACXD,SAAS,UAAU,WAAwB,cAAc;AAEzD,SAAS,sBAAsB;AA4D3B;AAhDG,SAAS,SAAS,EAAE,QAAQ,eAAe,SAAS,SAAS,GAAkB;AACpF,QAAM,CAAC,UAAU,WAAW,IAAI,SAAgC,IAAI;AACpE,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAAkB,IAAI;AAClE,QAAM,CAAC,cAAc,eAAe,IAAI,SAAkB,KAAK;AAC/D,QAAM,UAAU,OAAuC,aAAa;AAEpE,YAAU,MAAM;AACd,YAAQ,UAAU;AAAA,EACpB,GAAG,CAAC,aAAa,CAAC;AAElB,YAAU,MAAM;AACd,UAAM,YAAY,IAAI,eAAe,MAAM;AAC3C,cAAU,oBAAoB,OAAO;AAErC,UAAM,aAAa,YAAY;AAC7B,YAAM,UAAU,WAAW;AAE3B,UAAI,UAAU,YAAY,GAAG;AAC3B;AAAA,MACF;AACA,YAAM,QAAQ,UAAU,SAAS;AAEjC,UAAI,UAAU,YAAY,GAAG;AAC3B;AAAA,MACF;AAEA,gBAAU,aAAa,EAAE,KAAK,MAAM;AAClC,YAAI,CAAC,UAAU,YAAY,GAAG;AAC5B,0BAAgB,IAAI;AAAA,QACtB;AAAA,MACF,CAAC;AAGD,kBAAY,SAAS;AACrB,wBAAkB,KAAK;AAAA,IACzB;AAEA,eAAW,EAAE,MAAM,QAAQ,KAAK;AAEhC,WAAO,MAAM;AACX,gBAAU,QAAQ;AAClB,kBAAY,IAAI;AAChB,wBAAkB,IAAI;AACtB,sBAAgB,KAAK;AAAA,IACvB;AAAA,EACF,GAAG,CAAC,QAAQ,OAAO,CAAC;AAEpB,SACE,oBAAC,WAAW,UAAX,EAAoB,OAAO,EAAE,UAAU,gBAAgB,aAAa,GAClE,iBAAO,aAAa,aACjB,SAAS,EAAE,UAAU,gBAAgB,aAAa,CAAC,IACnD,UACN;AAEJ;;;ACtEA,SAAS,kBAAkB;AAOpB,SAAS,cAA+B;AAC7C,QAAM,eAAe,WAAW,UAAU;AAG1C,MAAI,iBAAiB,QAAW;AAC9B,UAAM,IAAI,MAAM,yDAAyD;AAAA,EAC3E;AAEA,QAAM,EAAE,UAAU,eAAe,IAAI;AAGrC,MAAI,gBAAgB;AAClB,WAAO;AAAA,EACT;AAGA,MAAI,aAAa,MAAM;AACrB,UAAM,IAAI,MAAM,4CAA4C;AAAA,EAC9D;AAEA,SAAO;AACT;;;ACXO,SAAS,UAAgC,UAAmC;AACjF,QAAM,EAAE,SAAS,IAAI,YAAY;AAEjC,MAAI,aAAa,MAAM;AACrB,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,OAAO,IAAI,QAAQ,MAAM;AAAA,MAAC,CAAC;AAAA,IAC7B;AAAA,EACF;AAEA,QAAM,SAAS,SAAS,UAAa,QAAQ;AAE7C,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,UAAU,QAAQ,YAAY;AAAA,EAChD;AAEA,SAAO;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;AACX,WAAO;AAAA,MACL,UAAU;AAAA,MACV;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,OAAO,UAAU;AACpB,UAAM,IAAI,MAAM,UAAU,QAAQ,gCAAgC;AAAA,EACpE;AAEA,SAAO;AAAA,IACL,UAAU,OAAO,SAAS;AAAA,IAC1B;AAAA,IACA;AAAA,EACF;AACF;;;ACrCA,SAAS,YAAAA,WAAU,aAAAC,kBAAiB;AAQ7B,SAAS,gBAAqD;AACnE,QAAM,EAAE,SAAS,IAAI,YAAY;AACjC,QAAM,CAAC,OAAO,QAAQ,IAAIC,UAA+B,IAAI;AAE7D,EAAAC,WAAU,MAAM;AACd,QAAI,CAAC,SAAU;AAGf,aAAS,SAAS,SAAS,EAAE,SAAS,CAAkB;AAGxD,UAAM,cAAc,SAAS,SAAS,EAAE,UAAU,CAAC,SAAS,aAAa;AACvE,eAAS,QAAyB;AAAA,IACpC,CAAC;AAED,WAAO,MAAM,YAAY;AAAA,EAC3B,GAAG,CAAC,QAAQ,CAAC;AAEb,SAAO;AACT;;;AC3BA,SAAS,YAAAC,WAAU,aAAAC,kBAAiB;AACpC,SAAoB,qBAAqB;AAOlC,SAAS,eAAiC;AAC/C,QAAM,EAAE,SAAS,IAAI,YAAY;AACjC,QAAM,CAAC,WAAW,YAAY,IAAIC,UAA2B,IAAI;AAEjE,EAAAC,WAAU,MAAM;AACd,QAAI,CAAC,SAAU;AAEf,UAAM,QAAQ,SAAS,SAAS;AAGhC,iBAAa,MAAM,SAAS,EAAE,IAAI;AAGlC,UAAM,cAAc,MAAM,UAAU,CAAC,QAAQ,UAAU,aAAa;AAElE,UAAI,MAAM,aAAa,MAAM,KAAK,CAAC,cAAc,SAAS,MAAM,SAAS,IAAI,GAAG;AAC9E,qBAAa,SAAS,IAAI;AAAA,MAC5B;AAAA,IACF,CAAC;AAED,WAAO,MAAM,YAAY;AAAA,EAC3B,GAAG,CAAC,QAAQ,CAAC;AAEb,SAAO;AACT;","names":["useState","useEffect","useState","useEffect","useState","useEffect","useState","useEffect"]}
|
package/dist/react/index.cjs
CHANGED
|
@@ -23,6 +23,7 @@ __export(react_exports, {
|
|
|
23
23
|
EmbedPDF: () => EmbedPDF,
|
|
24
24
|
PDFContext: () => PDFContext,
|
|
25
25
|
useCapability: () => useCapability,
|
|
26
|
+
useCoreState: () => useCoreState,
|
|
26
27
|
usePlugin: () => usePlugin,
|
|
27
28
|
useRegistry: () => useRegistry,
|
|
28
29
|
useStoreState: () => useStoreState
|
|
@@ -45,7 +46,10 @@ function EmbedPDF({ engine, onInitialized, plugins, children }) {
|
|
|
45
46
|
const [registry, setRegistry] = (0, import_react2.useState)(null);
|
|
46
47
|
const [isInitializing, setIsInitializing] = (0, import_react2.useState)(true);
|
|
47
48
|
const [pluginsReady, setPluginsReady] = (0, import_react2.useState)(false);
|
|
48
|
-
const
|
|
49
|
+
const initRef = (0, import_react2.useRef)(onInitialized);
|
|
50
|
+
(0, import_react2.useEffect)(() => {
|
|
51
|
+
initRef.current = onInitialized;
|
|
52
|
+
}, [onInitialized]);
|
|
49
53
|
(0, import_react2.useEffect)(() => {
|
|
50
54
|
const pdfViewer = new import_core.PluginRegistry(engine);
|
|
51
55
|
pdfViewer.registerPluginBatch(plugins);
|
|
@@ -54,7 +58,7 @@ function EmbedPDF({ engine, onInitialized, plugins, children }) {
|
|
|
54
58
|
if (pdfViewer.isDestroyed()) {
|
|
55
59
|
return;
|
|
56
60
|
}
|
|
57
|
-
await
|
|
61
|
+
await initRef.current?.(pdfViewer);
|
|
58
62
|
if (pdfViewer.isDestroyed()) {
|
|
59
63
|
return;
|
|
60
64
|
}
|
|
@@ -73,7 +77,7 @@ function EmbedPDF({ engine, onInitialized, plugins, children }) {
|
|
|
73
77
|
setIsInitializing(true);
|
|
74
78
|
setPluginsReady(false);
|
|
75
79
|
};
|
|
76
|
-
}, [engine,
|
|
80
|
+
}, [engine, plugins]);
|
|
77
81
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PDFContext.Provider, { value: { registry, isInitializing, pluginsReady }, children: typeof children === "function" ? children({ registry, isInitializing, pluginsReady }) : children });
|
|
78
82
|
}
|
|
79
83
|
|
|
@@ -151,11 +155,32 @@ function useStoreState() {
|
|
|
151
155
|
}, [registry]);
|
|
152
156
|
return state;
|
|
153
157
|
}
|
|
158
|
+
|
|
159
|
+
// src/react/hooks/use-core-state.ts
|
|
160
|
+
var import_react5 = require("react");
|
|
161
|
+
var import_core2 = require("@embedpdf/core");
|
|
162
|
+
function useCoreState() {
|
|
163
|
+
const { registry } = useRegistry();
|
|
164
|
+
const [coreState, setCoreState] = (0, import_react5.useState)(null);
|
|
165
|
+
(0, import_react5.useEffect)(() => {
|
|
166
|
+
if (!registry) return;
|
|
167
|
+
const store = registry.getStore();
|
|
168
|
+
setCoreState(store.getState().core);
|
|
169
|
+
const unsubscribe = store.subscribe((action, newState, oldState) => {
|
|
170
|
+
if (store.isCoreAction(action) && !(0, import_core2.arePropsEqual)(newState.core, oldState.core)) {
|
|
171
|
+
setCoreState(newState.core);
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
return () => unsubscribe();
|
|
175
|
+
}, [registry]);
|
|
176
|
+
return coreState;
|
|
177
|
+
}
|
|
154
178
|
// Annotate the CommonJS export names for ESM import in node:
|
|
155
179
|
0 && (module.exports = {
|
|
156
180
|
EmbedPDF,
|
|
157
181
|
PDFContext,
|
|
158
182
|
useCapability,
|
|
183
|
+
useCoreState,
|
|
159
184
|
usePlugin,
|
|
160
185
|
useRegistry,
|
|
161
186
|
useStoreState
|
package/dist/react/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/react/index.ts","../../src/react/context.ts","../../src/react/components/embed-pdf.tsx","../../src/react/hooks/use-registry.ts","../../src/react/hooks/use-plugin.ts","../../src/react/hooks/use-capability.ts","../../src/react/hooks/use-store-state.ts"],"sourcesContent":["export * from './context';\nexport * from './components';\nexport * from './hooks';\n","import { createContext } from 'react';\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 React, { useState, useEffect, useCallback } from 'react';\nimport { PdfEngine } from '@embedpdf/models';\nimport { PluginRegistry } from '@embedpdf/core';\nimport type { IPlugin, PluginBatchRegistration } from '@embedpdf/core';\n\nimport { PDFContext, PDFContextState } from '../context';\n\ninterface EmbedPDFProps {\n engine: PdfEngine;\n onInitialized: (registry: PluginRegistry) => Promise<void>;\n plugins: PluginBatchRegistration<IPlugin<any>, any>[];\n children: React.ReactNode | ((state: PDFContextState) => React.ReactNode);\n}\n\nexport function EmbedPDF({ engine, onInitialized, plugins, children }: EmbedPDFProps) {\n const [registry, setRegistry] = useState<PluginRegistry | null>(null);\n const [isInitializing, setIsInitializing] = useState<boolean>(true);\n const [pluginsReady, setPluginsReady] = useState<boolean>(false);\n\n const stableOnInit = useCallback(onInitialized, [onInitialized]);\n\n useEffect(() => {\n const pdfViewer = new PluginRegistry(engine);\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 await stableOnInit(pdfViewer);\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, stableOnInit, plugins]);\n\n return (\n <PDFContext.Provider value={{ registry, isInitializing, pluginsReady }}>\n {typeof children === 'function'\n ? children({ registry, isInitializing, pluginsReady })\n : children}\n </PDFContext.Provider>\n );\n}\n","import { useContext } from 'react';\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 'react';\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"],"mappings":"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","names":["import_react","import_react","import_react"]}
|
|
1
|
+
{"version":3,"sources":["../../src/react/index.ts","../../src/react/context.ts","../../src/react/components/embed-pdf.tsx","../../src/react/hooks/use-registry.ts","../../src/react/hooks/use-plugin.ts","../../src/react/hooks/use-capability.ts","../../src/react/hooks/use-store-state.ts","../../src/react/hooks/use-core-state.ts"],"sourcesContent":["export * from './context';\nexport * from './components';\nexport * from './hooks';\n","import { createContext } from 'react';\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 React, { useState, useEffect, useCallback, useRef } from 'react';\nimport { PdfEngine } from '@embedpdf/models';\nimport { PluginRegistry } from '@embedpdf/core';\nimport type { IPlugin, PluginBatchRegistration } from '@embedpdf/core';\n\nimport { PDFContext, PDFContextState } from '../context';\n\ninterface EmbedPDFProps {\n engine: PdfEngine;\n onInitialized: (registry: PluginRegistry) => Promise<void>;\n plugins: PluginBatchRegistration<IPlugin<any>, any>[];\n children: React.ReactNode | ((state: PDFContextState) => React.ReactNode);\n}\n\nexport function EmbedPDF({ engine, onInitialized, plugins, children }: 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);\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 return (\n <PDFContext.Provider value={{ registry, isInitializing, pluginsReady }}>\n {typeof children === 'function'\n ? children({ registry, isInitializing, pluginsReady })\n : children}\n </PDFContext.Provider>\n );\n}\n","import { useContext } from 'react';\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 'react';\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 'react';\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"],"mappings":"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","names":["import_react","import_react","import_react","import_react","import_core"]}
|
package/dist/react/index.d.cts
CHANGED
|
@@ -46,6 +46,12 @@ declare function useRegistry(): PDFContextState;
|
|
|
46
46
|
*/
|
|
47
47
|
declare function useStoreState<T = CoreState>(): StoreState<T> | null;
|
|
48
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Hook that provides access to the current core state
|
|
51
|
+
* and re-renders the component only when the core state changes
|
|
52
|
+
*/
|
|
53
|
+
declare function useCoreState(): CoreState | null;
|
|
54
|
+
|
|
49
55
|
type PluginState<T extends BasePlugin> = {
|
|
50
56
|
plugin: T | null;
|
|
51
57
|
isLoading: boolean;
|
|
@@ -61,4 +67,4 @@ type PluginState<T extends BasePlugin> = {
|
|
|
61
67
|
*/
|
|
62
68
|
declare function usePlugin<T extends BasePlugin>(pluginId: T['id']): PluginState<T>;
|
|
63
69
|
|
|
64
|
-
export { EmbedPDF, PDFContext, type PDFContextState, useCapability, usePlugin, useRegistry, useStoreState };
|
|
70
|
+
export { EmbedPDF, PDFContext, type PDFContextState, useCapability, useCoreState, usePlugin, useRegistry, useStoreState };
|
package/dist/react/index.d.ts
CHANGED
|
@@ -46,6 +46,12 @@ declare function useRegistry(): PDFContextState;
|
|
|
46
46
|
*/
|
|
47
47
|
declare function useStoreState<T = CoreState>(): StoreState<T> | null;
|
|
48
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Hook that provides access to the current core state
|
|
51
|
+
* and re-renders the component only when the core state changes
|
|
52
|
+
*/
|
|
53
|
+
declare function useCoreState(): CoreState | null;
|
|
54
|
+
|
|
49
55
|
type PluginState<T extends BasePlugin> = {
|
|
50
56
|
plugin: T | null;
|
|
51
57
|
isLoading: boolean;
|
|
@@ -61,4 +67,4 @@ type PluginState<T extends BasePlugin> = {
|
|
|
61
67
|
*/
|
|
62
68
|
declare function usePlugin<T extends BasePlugin>(pluginId: T['id']): PluginState<T>;
|
|
63
69
|
|
|
64
|
-
export { EmbedPDF, PDFContext, type PDFContextState, useCapability, usePlugin, useRegistry, useStoreState };
|
|
70
|
+
export { EmbedPDF, PDFContext, type PDFContextState, useCapability, useCoreState, usePlugin, useRegistry, useStoreState };
|
package/dist/react/index.js
CHANGED
|
@@ -7,14 +7,17 @@ var PDFContext = createContext({
|
|
|
7
7
|
});
|
|
8
8
|
|
|
9
9
|
// src/react/components/embed-pdf.tsx
|
|
10
|
-
import { useState, useEffect,
|
|
10
|
+
import { useState, useEffect, useRef } from "react";
|
|
11
11
|
import { PluginRegistry } from "@embedpdf/core";
|
|
12
12
|
import { jsx } from "react/jsx-runtime";
|
|
13
13
|
function EmbedPDF({ engine, onInitialized, plugins, children }) {
|
|
14
14
|
const [registry, setRegistry] = useState(null);
|
|
15
15
|
const [isInitializing, setIsInitializing] = useState(true);
|
|
16
16
|
const [pluginsReady, setPluginsReady] = useState(false);
|
|
17
|
-
const
|
|
17
|
+
const initRef = useRef(onInitialized);
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
initRef.current = onInitialized;
|
|
20
|
+
}, [onInitialized]);
|
|
18
21
|
useEffect(() => {
|
|
19
22
|
const pdfViewer = new PluginRegistry(engine);
|
|
20
23
|
pdfViewer.registerPluginBatch(plugins);
|
|
@@ -23,7 +26,7 @@ function EmbedPDF({ engine, onInitialized, plugins, children }) {
|
|
|
23
26
|
if (pdfViewer.isDestroyed()) {
|
|
24
27
|
return;
|
|
25
28
|
}
|
|
26
|
-
await
|
|
29
|
+
await initRef.current?.(pdfViewer);
|
|
27
30
|
if (pdfViewer.isDestroyed()) {
|
|
28
31
|
return;
|
|
29
32
|
}
|
|
@@ -42,7 +45,7 @@ function EmbedPDF({ engine, onInitialized, plugins, children }) {
|
|
|
42
45
|
setIsInitializing(true);
|
|
43
46
|
setPluginsReady(false);
|
|
44
47
|
};
|
|
45
|
-
}, [engine,
|
|
48
|
+
}, [engine, plugins]);
|
|
46
49
|
return /* @__PURE__ */ jsx(PDFContext.Provider, { value: { registry, isInitializing, pluginsReady }, children: typeof children === "function" ? children({ registry, isInitializing, pluginsReady }) : children });
|
|
47
50
|
}
|
|
48
51
|
|
|
@@ -120,10 +123,31 @@ function useStoreState() {
|
|
|
120
123
|
}, [registry]);
|
|
121
124
|
return state;
|
|
122
125
|
}
|
|
126
|
+
|
|
127
|
+
// src/react/hooks/use-core-state.ts
|
|
128
|
+
import { useState as useState3, useEffect as useEffect3 } from "react";
|
|
129
|
+
import { arePropsEqual } from "@embedpdf/core";
|
|
130
|
+
function useCoreState() {
|
|
131
|
+
const { registry } = useRegistry();
|
|
132
|
+
const [coreState, setCoreState] = useState3(null);
|
|
133
|
+
useEffect3(() => {
|
|
134
|
+
if (!registry) return;
|
|
135
|
+
const store = registry.getStore();
|
|
136
|
+
setCoreState(store.getState().core);
|
|
137
|
+
const unsubscribe = store.subscribe((action, newState, oldState) => {
|
|
138
|
+
if (store.isCoreAction(action) && !arePropsEqual(newState.core, oldState.core)) {
|
|
139
|
+
setCoreState(newState.core);
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
return () => unsubscribe();
|
|
143
|
+
}, [registry]);
|
|
144
|
+
return coreState;
|
|
145
|
+
}
|
|
123
146
|
export {
|
|
124
147
|
EmbedPDF,
|
|
125
148
|
PDFContext,
|
|
126
149
|
useCapability,
|
|
150
|
+
useCoreState,
|
|
127
151
|
usePlugin,
|
|
128
152
|
useRegistry,
|
|
129
153
|
useStoreState
|
package/dist/react/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/react/context.ts","../../src/react/components/embed-pdf.tsx","../../src/react/hooks/use-registry.ts","../../src/react/hooks/use-plugin.ts","../../src/react/hooks/use-capability.ts","../../src/react/hooks/use-store-state.ts"],"sourcesContent":["import { createContext } from 'react';\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 React, { useState, useEffect, useCallback } from 'react';\nimport { PdfEngine } from '@embedpdf/models';\nimport { PluginRegistry } from '@embedpdf/core';\nimport type { IPlugin, PluginBatchRegistration } from '@embedpdf/core';\n\nimport { PDFContext, PDFContextState } from '../context';\n\ninterface EmbedPDFProps {\n engine: PdfEngine;\n onInitialized: (registry: PluginRegistry) => Promise<void>;\n plugins: PluginBatchRegistration<IPlugin<any>, any>[];\n children: React.ReactNode | ((state: PDFContextState) => React.ReactNode);\n}\n\nexport function EmbedPDF({ engine, onInitialized, plugins, children }: EmbedPDFProps) {\n const [registry, setRegistry] = useState<PluginRegistry | null>(null);\n const [isInitializing, setIsInitializing] = useState<boolean>(true);\n const [pluginsReady, setPluginsReady] = useState<boolean>(false);\n\n const stableOnInit = useCallback(onInitialized, [onInitialized]);\n\n useEffect(() => {\n const pdfViewer = new PluginRegistry(engine);\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 await stableOnInit(pdfViewer);\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, stableOnInit, plugins]);\n\n return (\n <PDFContext.Provider value={{ registry, isInitializing, pluginsReady }}>\n {typeof children === 'function'\n ? children({ registry, isInitializing, pluginsReady })\n : children}\n </PDFContext.Provider>\n );\n}\n","import { useContext } from 'react';\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 'react';\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"],"mappings":"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","names":["useState","useEffect","useState","useEffect"]}
|
|
1
|
+
{"version":3,"sources":["../../src/react/context.ts","../../src/react/components/embed-pdf.tsx","../../src/react/hooks/use-registry.ts","../../src/react/hooks/use-plugin.ts","../../src/react/hooks/use-capability.ts","../../src/react/hooks/use-store-state.ts","../../src/react/hooks/use-core-state.ts"],"sourcesContent":["import { createContext } from 'react';\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 React, { useState, useEffect, useCallback, useRef } from 'react';\nimport { PdfEngine } from '@embedpdf/models';\nimport { PluginRegistry } from '@embedpdf/core';\nimport type { IPlugin, PluginBatchRegistration } from '@embedpdf/core';\n\nimport { PDFContext, PDFContextState } from '../context';\n\ninterface EmbedPDFProps {\n engine: PdfEngine;\n onInitialized: (registry: PluginRegistry) => Promise<void>;\n plugins: PluginBatchRegistration<IPlugin<any>, any>[];\n children: React.ReactNode | ((state: PDFContextState) => React.ReactNode);\n}\n\nexport function EmbedPDF({ engine, onInitialized, plugins, children }: 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);\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 return (\n <PDFContext.Provider value={{ registry, isInitializing, pluginsReady }}>\n {typeof children === 'function'\n ? children({ registry, isInitializing, pluginsReady })\n : children}\n </PDFContext.Provider>\n );\n}\n","import { useContext } from 'react';\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 'react';\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 'react';\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"],"mappings":"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","names":["useState","useEffect","useState","useEffect","useState","useEffect","useState","useEffect"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@embedpdf/core",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
"@types/react": "^18.2.0"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@embedpdf/models": "1.0.
|
|
32
|
-
"@embedpdf/engines": "1.0.
|
|
31
|
+
"@embedpdf/models": "1.0.1",
|
|
32
|
+
"@embedpdf/engines": "1.0.1"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
35
|
"react": ">=16.8.0",
|