@rhc-office/sdk 6.6.268 → 6.6.363

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 +187 -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 +19 -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 +469 -359
  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 +8 -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 +10 -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 +257 -140
  54. package/src/api/callbacks.ts +48 -7
  55. package/src/api/document-sdk.ts +9 -5
  56. package/src/api/document-tool.ts +28 -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 +84 -163
  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 +120 -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,12 +49,30 @@ 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;
54
+ }
55
+
56
+ type ReaderHostRuntimeKind = 'server' | 'browser-static' | 'mobile-webview' | 'desktop-shell';
57
+
58
+ interface ReaderHostRuntimeConfig {
59
+ hostKind?: ReaderHostRuntimeKind | (string & {});
60
+ server?: {
61
+ baseUrl?: string;
62
+ paths?: Record<string, string | undefined>;
63
+ };
50
64
  }
51
65
 
52
66
  type NativeReaderEventName = 'documentLoaded' | 'documentStateChange' | 'documentError';
53
67
  type ReaderThemeCleanup = () => void;
68
+ const READER_RUNTIME_GLOBAL_KEY = '__RHC_OFFICE_READER_RUNTIME__' as const;
69
+ const READER_RUNTIME_PROPERTY_KEY = '__rhcOfficeReaderRuntimeConfig' as const;
70
+ type ReaderRuntimeBrowserGlobal = typeof globalThis & {
71
+ __RHC_OFFICE_READER_RUNTIME__?: ReaderHostRuntimeConfig;
72
+ };
73
+ type ReaderRuntimeElement = HTMLElement & {
74
+ [READER_RUNTIME_PROPERTY_KEY]?: ReaderHostRuntimeConfig;
75
+ };
54
76
  type CompatibleMediaQueryList = MediaQueryList & {
55
77
  addListener?: (listener: (event: MediaQueryListEvent) => void) => void;
56
78
  removeListener?: (listener: (event: MediaQueryListEvent) => void) => void;
@@ -151,36 +173,25 @@ const removeMediaQueryListener = (
151
173
  }
152
174
  };
153
175
 
154
- const applyReaderElementLayout = (
155
- readerElement: HTMLElement,
156
- configuration: NormalizedReaderEmbedOptions,
157
- ): void => {
158
- if (configuration.style) {
159
- readerElement.style.cssText = configuration.style;
160
- }
161
-
176
+ const applyReaderElementLayout = (readerElement: HTMLElement): void => {
162
177
  if (!readerElement.style.display) {
163
178
  readerElement.style.display = 'block';
164
179
  }
165
180
 
166
181
  if (!readerElement.style.width) {
167
- readerElement.style.width = configuration.width ?? '100%';
168
- } else if (configuration.width) {
169
- readerElement.style.width = configuration.width;
182
+ readerElement.style.width = '100%';
170
183
  }
171
184
 
172
185
  if (!readerElement.style.height) {
173
- readerElement.style.height = configuration.height ?? '100%';
174
- } else if (configuration.height) {
175
- readerElement.style.height = configuration.height;
186
+ readerElement.style.height = '100%';
176
187
  }
177
188
  };
178
189
 
179
190
  const bindReaderElementTheme = (
180
191
  readerElement: HTMLElement,
181
- configuration: NormalizedReaderEmbedOptions,
192
+ theme: ReaderThemeMode | undefined,
182
193
  ): ReaderThemeCleanup | null => {
183
- const configuredTheme = configuration.theme;
194
+ const configuredTheme = theme;
184
195
  if (!configuredTheme) {
185
196
  readerElement.removeAttribute('theme');
186
197
  return null;
@@ -230,6 +241,7 @@ export class DocumentSDK implements IDocumentSDK {
230
241
  private readonly documentTool = new DocumentToolImpl(this.bridgeToolContext);
231
242
  private readonly uiTool = new UIToolImpl(this.bridgeToolContext);
232
243
  private readonly pageTool = new PageToolImpl(this.bridgeToolContext);
244
+ private readonly pageArrangeTool = new PageArrangeToolImpl(this.bridgeToolContext);
233
245
  private readonly findTool = new FindToolImpl(this.bridgeToolContext);
234
246
  private readonly signServerTool = new SignServerToolImpl(this.bridgeToolContext);
235
247
  private readonly digitalSignTool = new DigitalSignToolImpl(this.bridgeToolContext);
@@ -239,6 +251,7 @@ export class DocumentSDK implements IDocumentSDK {
239
251
  private readonly pdfFormFiller = new PdfFormFillerImpl(this.bridgeToolContext);
240
252
  private readonly networkingTool = new NetworkingToolImpl(this.bridgeToolContext);
241
253
  private readonly cryptoTool = new CryptoToolImpl(this.bridgeToolContext);
254
+ private readonly securityTool = new SecurityToolImpl(this.bridgeToolContext);
242
255
 
243
256
  private readonly readyCallbacks: ReaderReadyCallback[] = [];
244
257
  private readonly unloadCallbacks: ReaderUnloadCallback[] = [];
@@ -253,16 +266,19 @@ export class DocumentSDK implements IDocumentSDK {
253
266
  private readerElement: HTMLElement | null = null;
254
267
  private readerId: string | null = null;
255
268
  private normalizedConfiguration: NormalizedReaderEmbedOptions | null = null;
269
+ private runtimeRestoreState: {
270
+ hadPreviousRuntime: boolean;
271
+ previousRuntime?: ReaderHostRuntimeConfig;
272
+ } | null = null;
256
273
  private sessionUser?: Parameters<IDocumentSDK['setSessionUser']>[0];
257
274
  private sessionData?: string;
258
- private license?: { license: string; feature: string };
259
275
  private readonly nativeEventCleanupCallbacks: Array<() => void> = [];
260
276
  private themeCleanup: ReaderThemeCleanup | null = null;
261
277
 
262
278
  constructor(options?: DocumentSDKRuntimeOptions) {
263
279
  this.bridge.configureTimeouts({
264
- readyTimeoutMs: options?.adapterReadyTimeoutMs,
265
- requestTimeoutMs: options?.adapterRequestTimeoutMs,
280
+ readyTimeoutMs: options?.readyTimeoutMs,
281
+ requestTimeoutMs: options?.requestTimeoutMs,
266
282
  });
267
283
  }
268
284
 
@@ -270,12 +286,29 @@ export class DocumentSDK implements IDocumentSDK {
270
286
  this.debugEnabled = debug;
271
287
  };
272
288
 
273
- readonly changeLanguage: IDocumentSDK['changeLanguage'] = (): void => {
274
- // Phase 1: reserved for future reader language bridging.
289
+ readonly changeLanguage: IDocumentSDK['changeLanguage'] = (lang): void => {
290
+ if (!this.readerElement) {
291
+ return;
292
+ }
293
+
294
+ this.readerElement.setAttribute('language', lang);
275
295
  };
276
296
 
277
- readonly setLicense: IDocumentSDK['setLicense'] = (license, feature): void => {
278
- this.license = { license, feature };
297
+ readonly setThemeMode: IDocumentSDK['setThemeMode'] = (theme): void => {
298
+ this.themeCleanup?.();
299
+ this.themeCleanup = null;
300
+ this.normalizedConfiguration = this.normalizedConfiguration
301
+ ? {
302
+ ...this.normalizedConfiguration,
303
+ theme,
304
+ }
305
+ : null;
306
+
307
+ if (!this.readerElement) {
308
+ return;
309
+ }
310
+
311
+ this.themeCleanup = bindReaderElementTheme(this.readerElement, theme);
279
312
  };
280
313
 
281
314
  readonly setSessionUser: IDocumentSDK['setSessionUser'] = (userNameOrInfo): void => {
@@ -345,6 +378,7 @@ export class DocumentSDK implements IDocumentSDK {
345
378
  this.mountToken += 1;
346
379
  this.cleanupNativeEventForwarders();
347
380
  this.cleanupThemeBinding();
381
+ this.restoreReaderRuntimeConfig();
348
382
 
349
383
  if (this.readerElement?.parentNode) {
350
384
  this.readerElement.parentNode.removeChild(this.readerElement);
@@ -380,6 +414,10 @@ export class DocumentSDK implements IDocumentSDK {
380
414
  return this.pageTool;
381
415
  };
382
416
 
417
+ readonly getPageArrangeTool: IDocumentSDK['getPageArrangeTool'] = (): PageArrangeTool => {
418
+ return this.pageArrangeTool;
419
+ };
420
+
383
421
  readonly getFindTool: IDocumentSDK['getFindTool'] = (): FindTool => {
384
422
  return this.findTool;
385
423
  };
@@ -416,6 +454,10 @@ export class DocumentSDK implements IDocumentSDK {
416
454
  return this.cryptoTool;
417
455
  };
418
456
 
457
+ readonly getSecurityTool: IDocumentSDK['getSecurityTool'] = (): SecurityTool => {
458
+ return this.securityTool;
459
+ };
460
+
419
461
  readonly createDigitalSignOptions: IDocumentSDK['createDigitalSignOptions'] = () => {
420
462
  return new DigitalSignOptions();
421
463
  };
@@ -440,8 +482,13 @@ export class DocumentSDK implements IDocumentSDK {
440
482
  readerElement.setAttribute(RHC_OFFICE_READER_ID_ATTRIBUTE, readerId);
441
483
  this.readerId = readerId;
442
484
  this.bridge.setReaderId(readerId);
443
- applyReaderElementLayout(readerElement, configuration);
444
- this.themeCleanup = bindReaderElementTheme(readerElement, configuration);
485
+ applyReaderElementLayout(readerElement);
486
+ this.applyReaderRuntimeConfig(readerElement, configuration);
487
+ const shouldUseCompactMode =
488
+ configuration.compactViewer === true && configuration.keepPCMenu !== true;
489
+ readerElement.toggleAttribute('data-sdk-compact-mode', shouldUseCompactMode);
490
+ readerElement.setAttribute('language', configuration.language ?? 'zh_CN');
491
+ this.themeCleanup = bindReaderElementTheme(readerElement, configuration.theme);
445
492
  this.bindNativeReaderEvents(readerElement);
446
493
 
447
494
  hostContainer.replaceChildren(readerElement);
@@ -451,8 +498,13 @@ export class DocumentSDK implements IDocumentSDK {
451
498
  return;
452
499
  }
453
500
 
454
- if (configuration.scrollIntoView && typeof hostContainer.scrollIntoView === 'function') {
455
- hostContainer.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
501
+ const adapterReady = await this.bridge.waitForReady();
502
+ if (this.mountToken !== mountToken) {
503
+ return;
504
+ }
505
+
506
+ if (!adapterReady) {
507
+ throw new Error('Editor adapter is not available.');
456
508
  }
457
509
 
458
510
  this.isReady = true;
@@ -468,6 +520,44 @@ export class DocumentSDK implements IDocumentSDK {
468
520
  }
469
521
  };
470
522
 
523
+ private applyReaderRuntimeConfig(
524
+ readerElement: HTMLElement,
525
+ configuration: NormalizedReaderEmbedOptions,
526
+ ): void {
527
+ this.restoreReaderRuntimeConfig();
528
+ const readerHost: ReaderHostRuntimeConfig = {
529
+ hostKind: 'server',
530
+ server: {
531
+ baseUrl: configuration.appUrl,
532
+ },
533
+ };
534
+
535
+ const runtimeElement = readerElement as ReaderRuntimeElement;
536
+ runtimeElement[READER_RUNTIME_PROPERTY_KEY] = readerHost;
537
+
538
+ const browserGlobal = globalThis as ReaderRuntimeBrowserGlobal;
539
+ const previousRuntime = browserGlobal[READER_RUNTIME_GLOBAL_KEY];
540
+ this.runtimeRestoreState = {
541
+ hadPreviousRuntime: previousRuntime !== undefined,
542
+ ...(previousRuntime !== undefined ? { previousRuntime } : {}),
543
+ };
544
+ browserGlobal[READER_RUNTIME_GLOBAL_KEY] = readerHost;
545
+ }
546
+
547
+ private restoreReaderRuntimeConfig(): void {
548
+ if (!this.runtimeRestoreState) {
549
+ return;
550
+ }
551
+
552
+ const browserGlobal = globalThis as ReaderRuntimeBrowserGlobal;
553
+ if (this.runtimeRestoreState.hadPreviousRuntime) {
554
+ browserGlobal[READER_RUNTIME_GLOBAL_KEY] = this.runtimeRestoreState.previousRuntime;
555
+ } else {
556
+ Reflect.deleteProperty(browserGlobal, READER_RUNTIME_GLOBAL_KEY);
557
+ }
558
+ this.runtimeRestoreState = null;
559
+ }
560
+
471
561
  private readonly bindNativeReaderEvents = (readerElement: HTMLElement): void => {
472
562
  this.cleanupNativeEventForwarders();
473
563
 
@@ -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
  }