@rhc-office/sdk 6.6.268 → 6.6.351

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.
Files changed (78) hide show
  1. package/README.md +1 -5
  2. package/dist/api/annotation-tool.d.ts +162 -102
  3. package/dist/api/annotation-tool.d.ts.map +1 -1
  4. package/dist/api/callbacks.d.ts +32 -6
  5. package/dist/api/callbacks.d.ts.map +1 -1
  6. package/dist/api/document-sdk.d.ts +6 -5
  7. package/dist/api/document-sdk.d.ts.map +1 -1
  8. package/dist/api/document-tool.d.ts +16 -11
  9. package/dist/api/document-tool.d.ts.map +1 -1
  10. package/dist/api/menu-visibility.d.ts +6 -1
  11. package/dist/api/menu-visibility.d.ts.map +1 -1
  12. package/dist/api/page-arrange-tool.d.ts +28 -0
  13. package/dist/api/page-arrange-tool.d.ts.map +1 -0
  14. package/dist/api/security-tool.d.ts +21 -0
  15. package/dist/api/security-tool.d.ts.map +1 -0
  16. package/dist/api/ui-tool.d.ts +19 -0
  17. package/dist/api/ui-tool.d.ts.map +1 -1
  18. package/dist/browser/document-viewer.js +1 -1
  19. package/dist/browser/document-viewer.js.map +1 -1
  20. package/dist/index.d.ts +2 -0
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +446 -360
  23. package/dist/index.js.map +1 -1
  24. package/dist/index.umd.cjs +1 -1
  25. package/dist/index.umd.cjs.map +1 -1
  26. package/dist/tools/AnnotationToolImpl.d.ts +5 -27
  27. package/dist/tools/AnnotationToolImpl.d.ts.map +1 -1
  28. package/dist/tools/DigitalSignToolImpl.d.ts.map +1 -1
  29. package/dist/tools/DocumentToolImpl.d.ts.map +1 -1
  30. package/dist/tools/PageArrangeToolImpl.d.ts +21 -0
  31. package/dist/tools/PageArrangeToolImpl.d.ts.map +1 -0
  32. package/dist/tools/SecurityToolImpl.d.ts +12 -0
  33. package/dist/tools/SecurityToolImpl.d.ts.map +1 -0
  34. package/dist/tools/UIToolImpl.d.ts +13 -0
  35. package/dist/tools/UIToolImpl.d.ts.map +1 -1
  36. package/dist/tools/index.d.ts +2 -1
  37. package/dist/tools/index.d.ts.map +1 -1
  38. package/dist/viewer/AdapterProtocol.d.ts +3 -1
  39. package/dist/viewer/AdapterProtocol.d.ts.map +1 -1
  40. package/dist/viewer/BridgeToolAdapter.d.ts +1 -0
  41. package/dist/viewer/BridgeToolAdapter.d.ts.map +1 -1
  42. package/dist/viewer/DocumentSDK.d.ts +7 -4
  43. package/dist/viewer/DocumentSDK.d.ts.map +1 -1
  44. package/dist/viewer/ReaderBridgeClient.d.ts +3 -0
  45. package/dist/viewer/ReaderBridgeClient.d.ts.map +1 -1
  46. package/dist/viewer/ReaderConfiguration.d.ts +0 -1
  47. package/dist/viewer/ReaderConfiguration.d.ts.map +1 -1
  48. package/dist/viewer/ReaderStateStore.d.ts +2 -0
  49. package/dist/viewer/ReaderStateStore.d.ts.map +1 -1
  50. package/dist/viewer/SdkCallbackRegistry.d.ts +2 -2
  51. package/dist/viewer/SdkCallbackRegistry.d.ts.map +1 -1
  52. package/package.json +2 -2
  53. package/src/api/annotation-tool.ts +232 -146
  54. package/src/api/callbacks.ts +48 -7
  55. package/src/api/document-sdk.ts +9 -5
  56. package/src/api/document-tool.ts +25 -13
  57. package/src/api/menu-visibility.ts +10 -1
  58. package/src/api/page-arrange-tool.ts +67 -0
  59. package/src/api/security-tool.ts +32 -0
  60. package/src/api/ui-tool.ts +33 -0
  61. package/src/index.ts +2 -0
  62. package/src/tools/AnnotationToolImpl.ts +71 -165
  63. package/src/tools/DigitalSignToolImpl.ts +13 -2
  64. package/src/tools/DocumentToolImpl.ts +8 -4
  65. package/src/tools/PageArrangeToolImpl.ts +99 -0
  66. package/src/tools/SecurityToolImpl.ts +48 -0
  67. package/src/tools/UIToolImpl.ts +98 -12
  68. package/src/tools/index.ts +2 -1
  69. package/src/viewer/AdapterProtocol.ts +4 -0
  70. package/src/viewer/BridgeToolAdapter.ts +11 -2
  71. package/src/viewer/DocumentSDK.ts +58 -30
  72. package/src/viewer/ReaderBridgeClient.ts +9 -0
  73. package/src/viewer/ReaderConfiguration.ts +0 -2
  74. package/src/viewer/ReaderStateStore.ts +13 -1
  75. package/src/viewer/SdkCallbackRegistry.ts +75 -6
  76. package/dist/tools/Phase1ToolPlaceholder.d.ts +0 -5
  77. package/dist/tools/Phase1ToolPlaceholder.d.ts.map +0 -1
  78. package/src/tools/Phase1ToolPlaceholder.ts +0 -35
@@ -0,0 +1,48 @@
1
+ import type { SecurityTool } from '../api/security-tool';
2
+ import {
3
+ createBridgeToolAdapter,
4
+ type BridgeToolAdapterContext,
5
+ type BridgeToolDescriptor,
6
+ } from '../viewer/BridgeToolAdapter';
7
+
8
+ const SECURITY_TOOL_DESCRIPTOR: BridgeToolDescriptor = {
9
+ getSecuritySettings: { kind: 'query' },
10
+ isSecuritySettingsLocalEditable: { kind: 'query' },
11
+ setSecuritySettingsLocalEditable: { kind: 'query' },
12
+ setSecuritySettings: { kind: 'query' },
13
+ openSecuritySettingsDialog: { kind: 'command' },
14
+ };
15
+
16
+ export class SecurityToolImpl implements SecurityTool {
17
+ private readonly adapter: SecurityTool;
18
+
19
+ constructor(context: BridgeToolAdapterContext) {
20
+ this.adapter = createBridgeToolAdapter<SecurityTool>(
21
+ 'security',
22
+ SECURITY_TOOL_DESCRIPTOR,
23
+ context,
24
+ );
25
+ }
26
+
27
+ getSecuritySettings: SecurityTool['getSecuritySettings'] = () => {
28
+ return this.adapter.getSecuritySettings();
29
+ };
30
+
31
+ setSecuritySettings: SecurityTool['setSecuritySettings'] = (update) => {
32
+ return this.adapter.setSecuritySettings(update);
33
+ };
34
+
35
+ isSecuritySettingsLocalEditable: SecurityTool['isSecuritySettingsLocalEditable'] = () => {
36
+ return this.adapter.isSecuritySettingsLocalEditable();
37
+ };
38
+
39
+ setSecuritySettingsLocalEditable: SecurityTool['setSecuritySettingsLocalEditable'] = (
40
+ editable,
41
+ ) => {
42
+ return this.adapter.setSecuritySettingsLocalEditable(editable);
43
+ };
44
+
45
+ openSecuritySettingsDialog: SecurityTool['openSecuritySettingsDialog'] = () => {
46
+ return this.adapter.openSecuritySettingsDialog();
47
+ };
48
+ }
@@ -22,10 +22,22 @@ const createUIToolDescriptor = (context: BridgeToolAdapterContext): BridgeToolDe
22
22
  hideRibbonMenuItem: { kind: 'command' },
23
23
  showRibbonTitleBar: { kind: 'command' },
24
24
  hideRibbonTitleBar: { kind: 'command' },
25
+ showRibbonTabs: { kind: 'command' },
26
+ hideRibbonTabs: { kind: 'command' },
25
27
  selectRibbonMenu: { kind: 'command' },
28
+ setupRibbonMenuTab: { kind: 'command' },
29
+ showRibbonMenuTab: { kind: 'command' },
30
+ hideRibbonMenuTab: { kind: 'command' },
31
+ enableRibbonMenuTab: { kind: 'command' },
32
+ disableRibbonMenuTab: { kind: 'command' },
33
+ setupRibbonMenuItemState: { kind: 'command' },
34
+ enableRibbonMenuItem: { kind: 'command' },
35
+ disableRibbonMenuItem: { kind: 'command' },
26
36
  setRibbonMenuButtonStyle: { kind: 'command' },
27
37
  setWatermark: { kind: 'command' },
28
38
  setCompactMode: { kind: 'command' },
39
+ setRulerVisible: { kind: 'command' },
40
+ toggleSidebar: { kind: 'command' },
29
41
  enterBookViewMode: {
30
42
  kind: 'callbackQuery',
31
43
  mapCallbackResult: () => [],
@@ -48,35 +60,53 @@ export class UIToolImpl implements UITool {
48
60
  }
49
61
 
50
62
  showToolbarMenu: UITool['showToolbarMenu'] = () => {
51
- return this.adapter.showToolbarMenu();
63
+ this.warnLegacyRibbonMethod('showToolbarMenu', 'showRibbonMenu');
64
+ return this.showRibbonMenu();
52
65
  };
53
66
 
54
67
  hideToolbarMenu: UITool['hideToolbarMenu'] = () => {
55
- return this.adapter.hideToolbarMenu();
68
+ this.warnLegacyRibbonMethod('hideToolbarMenu', 'hideRibbonMenu');
69
+ return this.hideRibbonMenu();
56
70
  };
57
71
 
58
72
  setupToolbarMenu: UITool['setupToolbarMenu'] = (opt) => {
59
- return this.adapter.setupToolbarMenu(opt);
73
+ this.warnLegacyRibbonMethod(
74
+ 'setupToolbarMenu',
75
+ 'showRibbonMenu/hideRibbonMenu/setupRibbonMenuTab',
76
+ );
77
+ return this.setupRibbonMenu(opt);
60
78
  };
61
79
 
62
80
  showToolbarMenuItem: UITool['showToolbarMenuItem'] = (menuId) => {
63
- return this.adapter.showToolbarMenuItem(menuId);
81
+ this.warnLegacyRibbonMethod('showToolbarMenuItem', 'showRibbonMenuItem');
82
+ return this.showRibbonMenuItem(menuId);
64
83
  };
65
84
 
66
85
  hideToolbarMenuItem: UITool['hideToolbarMenuItem'] = (menuId) => {
67
- return this.adapter.hideToolbarMenuItem(menuId);
86
+ this.warnLegacyRibbonMethod('hideToolbarMenuItem', 'hideRibbonMenuItem');
87
+ return this.hideRibbonMenuItem(menuId);
68
88
  };
69
89
 
70
90
  setupRibbonMenu: UITool['setupRibbonMenu'] = (opt) => {
71
- return this.adapter.setupRibbonMenu(opt);
91
+ this.warnLegacyRibbonMethod(
92
+ 'setupRibbonMenu',
93
+ 'showRibbonMenu/hideRibbonMenu/setupRibbonMenuTab',
94
+ );
95
+ if (typeof opt === 'boolean') {
96
+ return opt ? this.showRibbonMenu() : this.hideRibbonMenu();
97
+ }
98
+
99
+ return this.setupRibbonMenuTab(opt.menu, { visible: opt.visible });
72
100
  };
73
101
 
74
102
  setupRibbonMenuItem: UITool['setupRibbonMenuItem'] = (menuId, visible, config) => {
75
- return this.adapter.setupRibbonMenuItem(menuId, visible, config);
103
+ this.warnLegacyRibbonMethod('setupRibbonMenuItem', 'setupRibbonMenuItemState');
104
+ return this.setupRibbonMenuItemState(menuId, { visible, config });
76
105
  };
77
106
 
78
107
  setupRibbonTitleBar: UITool['setupRibbonTitleBar'] = (visible) => {
79
- return this.adapter.setupRibbonTitleBar(visible);
108
+ this.warnLegacyRibbonMethod('setupRibbonTitleBar', 'showRibbonTabs/hideRibbonTabs');
109
+ return visible ? this.showRibbonTabs() : this.hideRibbonTabs();
80
110
  };
81
111
 
82
112
  showRibbonMenu: UITool['showRibbonMenu'] = () => {
@@ -88,25 +118,69 @@ export class UIToolImpl implements UITool {
88
118
  };
89
119
 
90
120
  showRibbonMenuItem: UITool['showRibbonMenuItem'] = (menuId, config) => {
91
- return this.adapter.showRibbonMenuItem(menuId, config);
121
+ this.warnLegacyRibbonMethod('showRibbonMenuItem', 'setupRibbonMenuItemState');
122
+ return this.setupRibbonMenuItemState(menuId, { visible: true, config });
92
123
  };
93
124
 
94
125
  hideRibbonMenuItem: UITool['hideRibbonMenuItem'] = (menuId, config) => {
95
- return this.adapter.hideRibbonMenuItem(menuId, config);
126
+ this.warnLegacyRibbonMethod('hideRibbonMenuItem', 'setupRibbonMenuItemState');
127
+ return this.setupRibbonMenuItemState(menuId, { visible: false, config });
96
128
  };
97
129
 
98
130
  showRibbonTitleBar: UITool['showRibbonTitleBar'] = () => {
99
- return this.adapter.showRibbonTitleBar();
131
+ this.warnLegacyRibbonMethod('showRibbonTitleBar', 'showRibbonTabs');
132
+ return this.showRibbonTabs();
100
133
  };
101
134
 
102
135
  hideRibbonTitleBar: UITool['hideRibbonTitleBar'] = () => {
103
- return this.adapter.hideRibbonTitleBar();
136
+ this.warnLegacyRibbonMethod('hideRibbonTitleBar', 'hideRibbonTabs');
137
+ return this.hideRibbonTabs();
138
+ };
139
+
140
+ showRibbonTabs: UITool['showRibbonTabs'] = () => {
141
+ return this.adapter.showRibbonTabs();
142
+ };
143
+
144
+ hideRibbonTabs: UITool['hideRibbonTabs'] = () => {
145
+ return this.adapter.hideRibbonTabs();
104
146
  };
105
147
 
106
148
  selectRibbonMenu: UITool['selectRibbonMenu'] = (menuId) => {
107
149
  return this.adapter.selectRibbonMenu(menuId);
108
150
  };
109
151
 
152
+ setupRibbonMenuTab: UITool['setupRibbonMenuTab'] = (menuId, state) => {
153
+ return this.adapter.setupRibbonMenuTab(menuId, state);
154
+ };
155
+
156
+ showRibbonMenuTab: UITool['showRibbonMenuTab'] = (menuId) => {
157
+ return this.adapter.showRibbonMenuTab(menuId);
158
+ };
159
+
160
+ hideRibbonMenuTab: UITool['hideRibbonMenuTab'] = (menuId) => {
161
+ return this.adapter.hideRibbonMenuTab(menuId);
162
+ };
163
+
164
+ enableRibbonMenuTab: UITool['enableRibbonMenuTab'] = (menuId) => {
165
+ return this.adapter.enableRibbonMenuTab(menuId);
166
+ };
167
+
168
+ disableRibbonMenuTab: UITool['disableRibbonMenuTab'] = (menuId) => {
169
+ return this.adapter.disableRibbonMenuTab(menuId);
170
+ };
171
+
172
+ setupRibbonMenuItemState: UITool['setupRibbonMenuItemState'] = (menuId, state) => {
173
+ return this.adapter.setupRibbonMenuItemState(menuId, state);
174
+ };
175
+
176
+ enableRibbonMenuItem: UITool['enableRibbonMenuItem'] = (menuId, config) => {
177
+ return this.setupRibbonMenuItemState(menuId, { disabled: false, config });
178
+ };
179
+
180
+ disableRibbonMenuItem: UITool['disableRibbonMenuItem'] = (menuId, config) => {
181
+ return this.setupRibbonMenuItemState(menuId, { disabled: true, config });
182
+ };
183
+
110
184
  setRibbonMenuButtonStyle: UITool['setRibbonMenuButtonStyle'] = (buttonId, buttonStyle) => {
111
185
  return this.adapter.setRibbonMenuButtonStyle(buttonId, buttonStyle);
112
186
  };
@@ -119,6 +193,14 @@ export class UIToolImpl implements UITool {
119
193
  return this.adapter.setCompactMode(compact);
120
194
  };
121
195
 
196
+ setRulerVisible: UITool['setRulerVisible'] = (visible) => {
197
+ return this.adapter.setRulerVisible(visible);
198
+ };
199
+
200
+ toggleSidebar: UITool['toggleSidebar'] = () => {
201
+ return this.adapter.toggleSidebar();
202
+ };
203
+
122
204
  enterBookViewMode: UITool['enterBookViewMode'] = (callback) => {
123
205
  return this.adapter.enterBookViewMode(callback);
124
206
  };
@@ -142,4 +224,8 @@ export class UIToolImpl implements UITool {
142
224
  invalidateView: UITool['invalidateView'] = () => {
143
225
  return this.adapter.invalidateView();
144
226
  };
227
+
228
+ private warnLegacyRibbonMethod(methodName: string, replacement: string): void {
229
+ console.warn(`[RHC Office SDK] ui.${methodName} is deprecated. Use ui.${replacement} instead.`);
230
+ }
145
231
  }
@@ -4,10 +4,11 @@ export * from './DigitalSignToolImpl';
4
4
  export * from './DocumentToolImpl';
5
5
  export * from './FindToolImpl';
6
6
  export * from './NetworkingToolImpl';
7
+ export * from './PageArrangeToolImpl';
7
8
  export * from './PageToolImpl';
8
9
  export * from './PdfFormFillerImpl';
9
- export * from './Phase1ToolPlaceholder';
10
10
  export * from './SDKValueObjects';
11
+ export * from './SecurityToolImpl';
11
12
  export * from './SignServerToolImpl';
12
13
  export * from './SymbologyToolImpl';
13
14
  export * from './TemplateSignToolImpl';
@@ -8,9 +8,11 @@ export const RHC_OFFICE_READER_ID_ATTRIBUTE = 'data-rhc-office-reader-id';
8
8
  export type AdapterToolName =
9
9
  | 'document'
10
10
  | 'page'
11
+ | 'pageArrange'
11
12
  | 'ui'
12
13
  | 'find'
13
14
  | 'annotation'
15
+ | 'security'
14
16
  | 'digitalSign'
15
17
  | 'signServer'
16
18
  | 'review'
@@ -82,6 +84,8 @@ export interface AdapterStatePatch {
82
84
  documentType?: string;
83
85
  annotationMode?: string;
84
86
  annotationEnabled?: boolean;
87
+ annotations?: unknown[];
88
+ digitalSignatures?: unknown[];
85
89
  extensionState?: 'connected' | 'disconnected';
86
90
  }
87
91
 
@@ -15,6 +15,7 @@ export interface BridgeToolMethodDescriptor {
15
15
  callback?: (callbacks: SdkCallbackRegistry, args: unknown[]) => void;
16
16
  mapCallbackResult?: (result: unknown) => unknown[];
17
17
  kind: BridgeMethodKind;
18
+ returnsResult?: boolean;
18
19
  state?: (state: ReturnType<ReaderStateStore['snapshot']>, args: unknown[]) => unknown;
19
20
  }
20
21
 
@@ -100,9 +101,17 @@ export const createBridgeToolAdapter = <T extends object>(
100
101
  return undefined;
101
102
  }
102
103
 
103
- void context.bridge
104
+ const commandRequest = context.bridge
104
105
  .request(tool, adapterMethod, normalizeParams(args))
105
- .catch(context.onAsyncError);
106
+ .catch((error): undefined => {
107
+ context.onAsyncError(error);
108
+ return undefined;
109
+ });
110
+ if (methodDescriptor.returnsResult) {
111
+ return commandRequest;
112
+ }
113
+
114
+ void commandRequest;
106
115
  return undefined;
107
116
  };
108
117
  },
@@ -1,12 +1,14 @@
1
1
  import type { AnnotationTool } from '../api/annotation-tool';
2
2
  import type { CryptoTool } from '../api/crypto-tool';
3
3
  import type { ReaderReadyCallback, ReaderUnloadCallback } from '../api/callbacks';
4
- import type { IDocumentSDK, IReaderEmbedOptions } from '../api/document-sdk';
4
+ import type { IDocumentSDK, ReaderThemeMode } from '../api/document-sdk';
5
5
  import type { DocumentTool } from '../api/document-tool';
6
6
  import type { FindTool } from '../api/find-tool';
7
7
  import type { NetworkingTool } from '../api/networking-tool';
8
+ import type { PageArrangeTool } from '../api/page-arrange-tool';
8
9
  import type { PageTool } from '../api/page-tool';
9
10
  import type { PdfFormFiller } from '../api/pdf-formfiller';
11
+ import type { SecurityTool } from '../api/security-tool';
10
12
  import type { SignServerTool } from '../api/sign-server';
11
13
  import type { DigitalSignTool } from '../api/sign-tool';
12
14
  import type { SymbologyTool } from '../api/symbology-tool';
@@ -18,9 +20,11 @@ import { DigitalSignToolImpl } from '../tools/DigitalSignToolImpl';
18
20
  import { DocumentToolImpl } from '../tools/DocumentToolImpl';
19
21
  import { FindToolImpl } from '../tools/FindToolImpl';
20
22
  import { NetworkingToolImpl } from '../tools/NetworkingToolImpl';
23
+ import { PageArrangeToolImpl } from '../tools/PageArrangeToolImpl';
21
24
  import { PageToolImpl } from '../tools/PageToolImpl';
22
25
  import { PdfFormFillerImpl } from '../tools/PdfFormFillerImpl';
23
26
  import { DigitalSignOptions, KVField } from '../tools/SDKValueObjects';
27
+ import { SecurityToolImpl } from '../tools/SecurityToolImpl';
24
28
  import { SignServerToolImpl } from '../tools/SignServerToolImpl';
25
29
  import { SymbologyToolImpl } from '../tools/SymbologyToolImpl';
26
30
  import { TemplateSignToolImpl } from '../tools/TemplateSignToolImpl';
@@ -45,8 +49,8 @@ type ReaderEventListener = Parameters<IDocumentSDK['setReaderEventListener']>[0]
45
49
  type ReaderEventPayload = Parameters<NonNullable<ReaderEventListener>>[1];
46
50
 
47
51
  interface DocumentSDKRuntimeOptions {
48
- adapterReadyTimeoutMs?: number;
49
- adapterRequestTimeoutMs?: number;
52
+ readyTimeoutMs?: number;
53
+ requestTimeoutMs?: number;
50
54
  }
51
55
 
52
56
  type NativeReaderEventName = 'documentLoaded' | 'documentStateChange' | 'documentError';
@@ -151,36 +155,25 @@ const removeMediaQueryListener = (
151
155
  }
152
156
  };
153
157
 
154
- const applyReaderElementLayout = (
155
- readerElement: HTMLElement,
156
- configuration: NormalizedReaderEmbedOptions,
157
- ): void => {
158
- if (configuration.style) {
159
- readerElement.style.cssText = configuration.style;
160
- }
161
-
158
+ const applyReaderElementLayout = (readerElement: HTMLElement): void => {
162
159
  if (!readerElement.style.display) {
163
160
  readerElement.style.display = 'block';
164
161
  }
165
162
 
166
163
  if (!readerElement.style.width) {
167
- readerElement.style.width = configuration.width ?? '100%';
168
- } else if (configuration.width) {
169
- readerElement.style.width = configuration.width;
164
+ readerElement.style.width = '100%';
170
165
  }
171
166
 
172
167
  if (!readerElement.style.height) {
173
- readerElement.style.height = configuration.height ?? '100%';
174
- } else if (configuration.height) {
175
- readerElement.style.height = configuration.height;
168
+ readerElement.style.height = '100%';
176
169
  }
177
170
  };
178
171
 
179
172
  const bindReaderElementTheme = (
180
173
  readerElement: HTMLElement,
181
- configuration: NormalizedReaderEmbedOptions,
174
+ theme: ReaderThemeMode | undefined,
182
175
  ): ReaderThemeCleanup | null => {
183
- const configuredTheme = configuration.theme;
176
+ const configuredTheme = theme;
184
177
  if (!configuredTheme) {
185
178
  readerElement.removeAttribute('theme');
186
179
  return null;
@@ -230,6 +223,7 @@ export class DocumentSDK implements IDocumentSDK {
230
223
  private readonly documentTool = new DocumentToolImpl(this.bridgeToolContext);
231
224
  private readonly uiTool = new UIToolImpl(this.bridgeToolContext);
232
225
  private readonly pageTool = new PageToolImpl(this.bridgeToolContext);
226
+ private readonly pageArrangeTool = new PageArrangeToolImpl(this.bridgeToolContext);
233
227
  private readonly findTool = new FindToolImpl(this.bridgeToolContext);
234
228
  private readonly signServerTool = new SignServerToolImpl(this.bridgeToolContext);
235
229
  private readonly digitalSignTool = new DigitalSignToolImpl(this.bridgeToolContext);
@@ -239,6 +233,7 @@ export class DocumentSDK implements IDocumentSDK {
239
233
  private readonly pdfFormFiller = new PdfFormFillerImpl(this.bridgeToolContext);
240
234
  private readonly networkingTool = new NetworkingToolImpl(this.bridgeToolContext);
241
235
  private readonly cryptoTool = new CryptoToolImpl(this.bridgeToolContext);
236
+ private readonly securityTool = new SecurityToolImpl(this.bridgeToolContext);
242
237
 
243
238
  private readonly readyCallbacks: ReaderReadyCallback[] = [];
244
239
  private readonly unloadCallbacks: ReaderUnloadCallback[] = [];
@@ -255,14 +250,13 @@ export class DocumentSDK implements IDocumentSDK {
255
250
  private normalizedConfiguration: NormalizedReaderEmbedOptions | null = null;
256
251
  private sessionUser?: Parameters<IDocumentSDK['setSessionUser']>[0];
257
252
  private sessionData?: string;
258
- private license?: { license: string; feature: string };
259
253
  private readonly nativeEventCleanupCallbacks: Array<() => void> = [];
260
254
  private themeCleanup: ReaderThemeCleanup | null = null;
261
255
 
262
256
  constructor(options?: DocumentSDKRuntimeOptions) {
263
257
  this.bridge.configureTimeouts({
264
- readyTimeoutMs: options?.adapterReadyTimeoutMs,
265
- requestTimeoutMs: options?.adapterRequestTimeoutMs,
258
+ readyTimeoutMs: options?.readyTimeoutMs,
259
+ requestTimeoutMs: options?.requestTimeoutMs,
266
260
  });
267
261
  }
268
262
 
@@ -270,12 +264,29 @@ export class DocumentSDK implements IDocumentSDK {
270
264
  this.debugEnabled = debug;
271
265
  };
272
266
 
273
- readonly changeLanguage: IDocumentSDK['changeLanguage'] = (): void => {
274
- // Phase 1: reserved for future reader language bridging.
267
+ readonly changeLanguage: IDocumentSDK['changeLanguage'] = (lang): void => {
268
+ if (!this.readerElement) {
269
+ return;
270
+ }
271
+
272
+ this.readerElement.setAttribute('language', lang);
275
273
  };
276
274
 
277
- readonly setLicense: IDocumentSDK['setLicense'] = (license, feature): void => {
278
- this.license = { license, feature };
275
+ readonly setThemeMode: IDocumentSDK['setThemeMode'] = (theme): void => {
276
+ this.themeCleanup?.();
277
+ this.themeCleanup = null;
278
+ this.normalizedConfiguration = this.normalizedConfiguration
279
+ ? {
280
+ ...this.normalizedConfiguration,
281
+ theme,
282
+ }
283
+ : null;
284
+
285
+ if (!this.readerElement) {
286
+ return;
287
+ }
288
+
289
+ this.themeCleanup = bindReaderElementTheme(this.readerElement, theme);
279
290
  };
280
291
 
281
292
  readonly setSessionUser: IDocumentSDK['setSessionUser'] = (userNameOrInfo): void => {
@@ -380,6 +391,10 @@ export class DocumentSDK implements IDocumentSDK {
380
391
  return this.pageTool;
381
392
  };
382
393
 
394
+ readonly getPageArrangeTool: IDocumentSDK['getPageArrangeTool'] = (): PageArrangeTool => {
395
+ return this.pageArrangeTool;
396
+ };
397
+
383
398
  readonly getFindTool: IDocumentSDK['getFindTool'] = (): FindTool => {
384
399
  return this.findTool;
385
400
  };
@@ -416,6 +431,10 @@ export class DocumentSDK implements IDocumentSDK {
416
431
  return this.cryptoTool;
417
432
  };
418
433
 
434
+ readonly getSecurityTool: IDocumentSDK['getSecurityTool'] = (): SecurityTool => {
435
+ return this.securityTool;
436
+ };
437
+
419
438
  readonly createDigitalSignOptions: IDocumentSDK['createDigitalSignOptions'] = () => {
420
439
  return new DigitalSignOptions();
421
440
  };
@@ -440,8 +459,12 @@ export class DocumentSDK implements IDocumentSDK {
440
459
  readerElement.setAttribute(RHC_OFFICE_READER_ID_ATTRIBUTE, readerId);
441
460
  this.readerId = readerId;
442
461
  this.bridge.setReaderId(readerId);
443
- applyReaderElementLayout(readerElement, configuration);
444
- this.themeCleanup = bindReaderElementTheme(readerElement, configuration);
462
+ applyReaderElementLayout(readerElement);
463
+ const shouldUseCompactMode =
464
+ configuration.compactViewer === true && configuration.keepPCMenu !== true;
465
+ readerElement.toggleAttribute('data-sdk-compact-mode', shouldUseCompactMode);
466
+ readerElement.setAttribute('language', configuration.language ?? 'zh_CN');
467
+ this.themeCleanup = bindReaderElementTheme(readerElement, configuration.theme);
445
468
  this.bindNativeReaderEvents(readerElement);
446
469
 
447
470
  hostContainer.replaceChildren(readerElement);
@@ -451,8 +474,13 @@ export class DocumentSDK implements IDocumentSDK {
451
474
  return;
452
475
  }
453
476
 
454
- if (configuration.scrollIntoView && typeof hostContainer.scrollIntoView === 'function') {
455
- hostContainer.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
477
+ const adapterReady = await this.bridge.waitForReady();
478
+ if (this.mountToken !== mountToken) {
479
+ return;
480
+ }
481
+
482
+ if (!adapterReady) {
483
+ throw new Error('Editor adapter is not available.');
456
484
  }
457
485
 
458
486
  this.isReady = true;
@@ -141,6 +141,15 @@ export class ReaderBridgeClient {
141
141
  return getAdapterGlobal()?.getCapabilities(this.readerId) ?? null;
142
142
  }
143
143
 
144
+ async waitForReady(options?: { timeoutMs?: number }): Promise<boolean> {
145
+ if (!this.readerId) {
146
+ return false;
147
+ }
148
+
149
+ const adapter = await this.waitForAdapter(this.readerId, options?.timeoutMs);
150
+ return Boolean(adapter);
151
+ }
152
+
144
153
  private async waitForAdapter(
145
154
  readerId: string,
146
155
  timeoutMs = this.readyTimeoutMs,
@@ -4,7 +4,6 @@ export type SupportedReaderTheme = 'light' | 'dark' | 'high-contrast' | 'auto';
4
4
 
5
5
  export interface NormalizedReaderEmbedOptions extends IReaderEmbedOptions {
6
6
  appUrl: string;
7
- scrollIntoView: boolean;
8
7
  theme?: SupportedReaderTheme;
9
8
  }
10
9
 
@@ -53,7 +52,6 @@ export const normalizeReaderEmbedOptions = (
53
52
  return {
54
53
  ...configuration,
55
54
  appUrl: normalizedAppUrl,
56
- scrollIntoView: configuration.scrollIntoView ?? true,
57
55
  theme: normalizeTheme(configuration.theme),
58
56
  };
59
57
  };
@@ -3,6 +3,8 @@ import type { AdapterStatePatch } from './AdapterProtocol';
3
3
  export interface ReaderStateSnapshot {
4
4
  annotationEnabled: boolean;
5
5
  annotationMode?: string;
6
+ annotations?: unknown[];
7
+ digitalSignatures?: unknown[];
6
8
  documentModified: boolean;
7
9
  documentOpened: boolean;
8
10
  documentType?: string;
@@ -37,6 +39,10 @@ export class ReaderStateStore {
37
39
  this.state = {
38
40
  ...this.state,
39
41
  ...patch,
42
+ annotations: patch.annotations ? [...patch.annotations] : this.state.annotations,
43
+ digitalSignatures: patch.digitalSignatures
44
+ ? [...patch.digitalSignatures]
45
+ : this.state.digitalSignatures,
40
46
  };
41
47
  }
42
48
 
@@ -48,6 +54,12 @@ export class ReaderStateStore {
48
54
  }
49
55
 
50
56
  snapshot(): ReaderStateSnapshot {
51
- return { ...this.state };
57
+ return {
58
+ ...this.state,
59
+ annotations: this.state.annotations ? [...this.state.annotations] : undefined,
60
+ digitalSignatures: this.state.digitalSignatures
61
+ ? [...this.state.digitalSignatures]
62
+ : undefined,
63
+ };
52
64
  }
53
65
  }
@@ -1,7 +1,13 @@
1
1
  import type {
2
2
  AnnotationEventCallback,
3
+ AnnotationEventPayload,
3
4
  DigitalSignatureRetrieveCallback,
4
5
  DocumentClosedCallback,
6
+ DocumentCloseResult,
7
+ DocumentOpenedCallback,
8
+ DocumentOpenResult,
9
+ DocumentReaderStatus,
10
+ DocumentSaveResult,
5
11
  DocumentSavedCallback,
6
12
  PageChangeCallback,
7
13
  PageModeChangeCallback,
@@ -9,6 +15,62 @@ import type {
9
15
  import type { IDigitalAnnotationInfo } from '../api/annotation-tool';
10
16
  import type { ISignServerAuthorization, SignServerAuthCallback } from '../api/sign-server';
11
17
 
18
+ const normalizeAnnotationEventPayload = (payload: unknown): AnnotationEventPayload | undefined => {
19
+ return typeof payload === 'object' && payload !== null && !Array.isArray(payload)
20
+ ? (payload as AnnotationEventPayload)
21
+ : undefined;
22
+ };
23
+
24
+ const isRecord = (value: unknown): value is Record<string, unknown> => {
25
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
26
+ };
27
+
28
+ const normalizeDocumentReaderStatus = (value: unknown): DocumentReaderStatus | undefined => {
29
+ if (!isRecord(value)) {
30
+ return undefined;
31
+ }
32
+
33
+ const state: DocumentReaderStatus = {};
34
+ if (typeof value.currentPage === 'number') {
35
+ state.currentPage = value.currentPage;
36
+ }
37
+ if (typeof value.documentType === 'string') {
38
+ state.documentType = value.documentType;
39
+ }
40
+ if (typeof value.totalPages === 'number') {
41
+ state.totalPages = value.totalPages;
42
+ } else if (typeof value.pageCount === 'number') {
43
+ state.totalPages = value.pageCount;
44
+ }
45
+ if (typeof value.zoomLevel === 'number') {
46
+ state.zoomLevel = value.zoomLevel;
47
+ }
48
+
49
+ return Object.keys(state).length > 0 ? state : undefined;
50
+ };
51
+
52
+ const normalizeDocumentOpenResult = (payload: unknown): DocumentOpenResult => {
53
+ if (!isRecord(payload)) {
54
+ return {
55
+ success: true,
56
+ status: 'ok',
57
+ };
58
+ }
59
+
60
+ const nestedState = normalizeDocumentReaderStatus(payload.state);
61
+ const payloadState = normalizeDocumentReaderStatus(payload);
62
+ const error = typeof payload.error === 'string' ? payload.error : undefined;
63
+ const success = typeof payload.success === 'boolean' ? payload.success : !error;
64
+ const status = typeof payload.status === 'string' ? payload.status : success ? 'ok' : 'error';
65
+
66
+ return {
67
+ success,
68
+ status,
69
+ error,
70
+ state: nestedState ?? payloadState,
71
+ };
72
+ };
73
+
12
74
  export class SdkCallbackRegistry {
13
75
  readonly annotationEvents: AnnotationEventCallback[] = [];
14
76
  readonly annotationPersist: Array<(event: unknown) => void> = [];
@@ -18,7 +80,7 @@ export class SdkCallbackRegistry {
18
80
  readonly digitalSignatureParse: DigitalSignatureRetrieveCallback[] = [];
19
81
  readonly digitalSignatureRetrieve: DigitalSignatureRetrieveCallback[] = [];
20
82
  readonly documentClosed: DocumentClosedCallback[] = [];
21
- readonly documentOpened: Array<(status: string, error: string) => void> = [];
83
+ readonly documentOpened: DocumentOpenedCallback[] = [];
22
84
  readonly documentSaved: DocumentSavedCallback[] = [];
23
85
  readonly pageChange: PageChangeCallback[] = [];
24
86
  readonly pageModeChange: PageModeChangeCallback[] = [];
@@ -27,14 +89,18 @@ export class SdkCallbackRegistry {
27
89
  emit(event: string, payload: unknown): void {
28
90
  switch (event) {
29
91
  case 'documentOpened':
30
- case 'documentLoaded':
31
- this.documentOpened.forEach((callback) => callback('ok', ''));
92
+ case 'documentLoaded': {
93
+ const result = normalizeDocumentOpenResult(payload);
94
+ this.documentOpened.forEach((callback) =>
95
+ callback(result.status ?? 'ok', result.error ?? '', result),
96
+ );
32
97
  return;
98
+ }
33
99
  case 'documentSaved':
34
- this.documentSaved.forEach((callback) => callback(payload));
100
+ this.documentSaved.forEach((callback) => callback(payload as DocumentSaveResult));
35
101
  return;
36
102
  case 'documentClosed':
37
- this.documentClosed.forEach((callback) => callback(payload));
103
+ this.documentClosed.forEach((callback) => callback(payload as DocumentCloseResult));
38
104
  return;
39
105
  case 'pageChange': {
40
106
  const pagePayload = payload as { pageIndex?: number; pageCount?: number };
@@ -51,7 +117,10 @@ export class SdkCallbackRegistry {
51
117
  case 'annotationEvent': {
52
118
  const annotationPayload = payload as { event?: string; payload?: unknown };
53
119
  this.annotationEvents.forEach((callback) =>
54
- callback(annotationPayload.event ?? 'annotationEvent', annotationPayload.payload),
120
+ callback(
121
+ annotationPayload.event ?? 'annotationEvent',
122
+ normalizeAnnotationEventPayload(annotationPayload.payload),
123
+ ),
55
124
  );
56
125
  return;
57
126
  }