@embedpdf/viewer-chrome 3.0.0-next.15 → 3.0.0-next.16

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 (200) hide show
  1. package/dist/{annotation-fonts-BqoLZ4Mp.js → annotation-fonts-DWjVOTP0.js} +2 -2
  2. package/dist/{annotation-fonts-BqoLZ4Mp.js.map → annotation-fonts-DWjVOTP0.js.map} +1 -1
  3. package/dist/{annotation-fonts-Dt0IQXhz.cjs → annotation-fonts-dpfVkhnq.cjs} +2 -2
  4. package/dist/{annotation-fonts-Dt0IQXhz.cjs.map → annotation-fonts-dpfVkhnq.cjs.map} +1 -1
  5. package/dist/{annotation-style-Bzvvp8-N.cjs → annotation-style-B3XKAyZ-.cjs} +3 -3
  6. package/dist/{annotation-style-Bzvvp8-N.cjs.map → annotation-style-B3XKAyZ-.cjs.map} +1 -1
  7. package/dist/{annotation-style--rPIZsuP.js → annotation-style-CXF3X47Z.js} +3 -3
  8. package/dist/{annotation-style--rPIZsuP.js.map → annotation-style-CXF3X47Z.js.map} +1 -1
  9. package/dist/{ar-DnEj5vbP.cjs → ar-B132r9bo.cjs} +93 -1
  10. package/dist/ar-B132r9bo.cjs.map +1 -0
  11. package/dist/{ar-D9XKAmDx.js → ar-BLWFJoA_.js} +93 -1
  12. package/dist/ar-BLWFJoA_.js.map +1 -0
  13. package/dist/attachments-panel-Cxln8xos.cjs +217 -0
  14. package/dist/attachments-panel-Cxln8xos.cjs.map +1 -0
  15. package/dist/attachments-panel-H1ucRbwo.js +217 -0
  16. package/dist/attachments-panel-H1ucRbwo.js.map +1 -0
  17. package/dist/chrome.cjs +21 -0
  18. package/dist/chrome.cjs.map +1 -1
  19. package/dist/chrome.js +21 -0
  20. package/dist/chrome.js.map +1 -1
  21. package/dist/{commands-BmgxhJ8B.js → commands-BkgLP3Om.js} +418 -23
  22. package/dist/commands-BkgLP3Om.js.map +1 -0
  23. package/dist/{commands-CYt4SFUX.cjs → commands-DL1gjZt7.cjs} +433 -20
  24. package/dist/commands-DL1gjZt7.cjs.map +1 -0
  25. package/dist/commands.cjs +2 -1
  26. package/dist/commands.d.cts +3 -1
  27. package/dist/commands.d.ts +3 -1
  28. package/dist/commands.js +2 -2
  29. package/dist/{comments-panel-pEcQg4Vs.cjs → comments-panel-BsnWedTh.cjs} +2 -2
  30. package/dist/{comments-panel-pEcQg4Vs.cjs.map → comments-panel-BsnWedTh.cjs.map} +1 -1
  31. package/dist/{comments-panel-MUVgLCBI.js → comments-panel-D7Eadws9.js} +2 -2
  32. package/dist/{comments-panel-MUVgLCBI.js.map → comments-panel-D7Eadws9.js.map} +1 -1
  33. package/dist/{de-Dv6zvbnd.cjs → de-7_MvFWzN.cjs} +93 -1
  34. package/dist/de-7_MvFWzN.cjs.map +1 -0
  35. package/dist/{de-Bdr4aWzm.js → de-BUhwc9-x.js} +93 -1
  36. package/dist/de-BUhwc9-x.js.map +1 -0
  37. package/dist/{dialog-B5GBisKv.js → dialog-BIb373cg.js} +3 -3
  38. package/dist/dialog-BIb373cg.js.map +1 -0
  39. package/dist/{dialog-t8F13BL_.cjs → dialog-CngKTnAM.cjs} +3 -3
  40. package/dist/dialog-CngKTnAM.cjs.map +1 -0
  41. package/dist/{es-BP09DR9w.cjs → es-DgYj-1L3.cjs} +93 -1
  42. package/dist/es-DgYj-1L3.cjs.map +1 -0
  43. package/dist/{es-BSXz5tBv.js → es-DoXTqFoO.js} +93 -1
  44. package/dist/es-DoXTqFoO.js.map +1 -0
  45. package/dist/{form-design-panel-vWWU9uB-.js → form-design-panel-CgV_5YWC.js} +3 -3
  46. package/dist/{form-design-panel-vWWU9uB-.js.map → form-design-panel-CgV_5YWC.js.map} +1 -1
  47. package/dist/{form-design-panel-B5MXTZ96.cjs → form-design-panel-D0FdmWXW.cjs} +3 -3
  48. package/dist/{form-design-panel-B5MXTZ96.cjs.map → form-design-panel-D0FdmWXW.cjs.map} +1 -1
  49. package/dist/{fr-Ckn3K9v1.js → fr-B-8NDhBA.js} +93 -1
  50. package/dist/fr-B-8NDhBA.js.map +1 -0
  51. package/dist/{fr-BBQQn7tJ.cjs → fr-C856dmQJ.cjs} +93 -1
  52. package/dist/fr-C856dmQJ.cjs.map +1 -0
  53. package/dist/{he-DRsG7bH7.cjs → he-BFTeNc4t.cjs} +93 -1
  54. package/dist/he-BFTeNc4t.cjs.map +1 -0
  55. package/dist/{he-wdGU5PkU.js → he-Dlh0fNXM.js} +93 -1
  56. package/dist/he-Dlh0fNXM.js.map +1 -0
  57. package/dist/{icons-x0Tc05bs.cjs → icons-1UfLUZ_y.cjs} +20 -1
  58. package/dist/icons-1UfLUZ_y.cjs.map +1 -0
  59. package/dist/{icons-BrK5iVL8.js → icons-7dB0Y1ct.js} +20 -1
  60. package/dist/icons-7dB0Y1ct.js.map +1 -0
  61. package/dist/index.cjs +740 -171
  62. package/dist/index.cjs.map +1 -1
  63. package/dist/index.d.cts +16 -2
  64. package/dist/index.d.ts +16 -2
  65. package/dist/index.js +727 -170
  66. package/dist/index.js.map +1 -1
  67. package/dist/{it-BuP4o0xQ.cjs → it-Bef-2Yxq.cjs} +93 -1
  68. package/dist/it-Bef-2Yxq.cjs.map +1 -0
  69. package/dist/{it-Us-VmvIu.js → it-BkirG7ol.js} +93 -1
  70. package/dist/it-BkirG7ol.js.map +1 -0
  71. package/dist/{ja-Cizj0-5O.js → ja-CGEjCE-s.js} +93 -1
  72. package/dist/ja-CGEjCE-s.js.map +1 -0
  73. package/dist/{ja-DovEd6ts.cjs → ja-DNw2zqSD.cjs} +93 -1
  74. package/dist/ja-DNw2zqSD.cjs.map +1 -0
  75. package/dist/{ko-DlrXliE1.js → ko-CTkl5vMh.js} +93 -1
  76. package/dist/ko-CTkl5vMh.js.map +1 -0
  77. package/dist/{ko-B-qJEol2.cjs → ko-YHzeBqP6.cjs} +93 -1
  78. package/dist/ko-YHzeBqP6.cjs.map +1 -0
  79. package/dist/{link-editor-CSjqPnj1.cjs → link-editor-CAS7MZM2.cjs} +2 -2
  80. package/dist/{link-editor-CSjqPnj1.cjs.map → link-editor-CAS7MZM2.cjs.map} +1 -1
  81. package/dist/{link-editor-SxM1nnJU.js → link-editor-CkwtqRvb.js} +2 -2
  82. package/dist/{link-editor-SxM1nnJU.js.map → link-editor-CkwtqRvb.js.map} +1 -1
  83. package/dist/{measurement-Bs61XWbJ.js → measurement-CQdbnIrn.js} +2 -2
  84. package/dist/{measurement-Bs61XWbJ.js.map → measurement-CQdbnIrn.js.map} +1 -1
  85. package/dist/{measurement-CcCsHPOX.cjs → measurement-Cxv1Ahxx.cjs} +2 -2
  86. package/dist/{measurement-CcCsHPOX.cjs.map → measurement-Cxv1Ahxx.cjs.map} +1 -1
  87. package/dist/{nl-D3KZDDiJ.cjs → nl-BjkbaLq3.cjs} +93 -1
  88. package/dist/nl-BjkbaLq3.cjs.map +1 -0
  89. package/dist/{nl-0aF7M_0h.js → nl-Dya4sR8_.js} +93 -1
  90. package/dist/nl-Dya4sR8_.js.map +1 -0
  91. package/dist/outline-panel-BpGtBdj0.cjs +707 -0
  92. package/dist/outline-panel-BpGtBdj0.cjs.map +1 -0
  93. package/dist/outline-panel-DO5_REYw.js +707 -0
  94. package/dist/outline-panel-DO5_REYw.js.map +1 -0
  95. package/dist/outline-properties-BCa2cc0t.js +330 -0
  96. package/dist/outline-properties-BCa2cc0t.js.map +1 -0
  97. package/dist/outline-properties-DT3FIxCw.cjs +330 -0
  98. package/dist/outline-properties-DT3FIxCw.cjs.map +1 -0
  99. package/dist/{pl-DSFhAUqx.cjs → pl-CKKdVnpZ.cjs} +93 -1
  100. package/dist/pl-CKKdVnpZ.cjs.map +1 -0
  101. package/dist/{pl-BW--AaCI.js → pl-DA9b5NVg.js} +93 -1
  102. package/dist/pl-DA9b5NVg.js.map +1 -0
  103. package/dist/print-dialog-BqIrHCBh.cjs +276 -0
  104. package/dist/print-dialog-BqIrHCBh.cjs.map +1 -0
  105. package/dist/print-dialog-DvcI2m2_.js +276 -0
  106. package/dist/print-dialog-DvcI2m2_.js.map +1 -0
  107. package/dist/{pt-C5S-8MC5.cjs → pt-DLcszlzi.cjs} +93 -1
  108. package/dist/pt-DLcszlzi.cjs.map +1 -0
  109. package/dist/{pt-DIhpU5pT.js → pt-Nm8yyjbX.js} +93 -1
  110. package/dist/pt-Nm8yyjbX.js.map +1 -0
  111. package/dist/{redact-confirm-CX_SY2ZN.cjs → redact-confirm-C6EiK8yN.cjs} +2 -2
  112. package/dist/{redact-confirm-CX_SY2ZN.cjs.map → redact-confirm-C6EiK8yN.cjs.map} +1 -1
  113. package/dist/{redact-confirm-B6j36TPw.js → redact-confirm-CKuv9iN_.js} +2 -2
  114. package/dist/{redact-confirm-B6j36TPw.js.map → redact-confirm-CKuv9iN_.js.map} +1 -1
  115. package/dist/{redaction-panel-IJDshSJI.js → redaction-panel-CgNZ-pQk.js} +2 -2
  116. package/dist/{redaction-panel-IJDshSJI.js.map → redaction-panel-CgNZ-pQk.js.map} +1 -1
  117. package/dist/{redaction-panel-BmoIl-Ll.cjs → redaction-panel-ZhX0dlMi.cjs} +2 -2
  118. package/dist/{redaction-panel-BmoIl-Ll.cjs.map → redaction-panel-ZhX0dlMi.cjs.map} +1 -1
  119. package/dist/{search-panel-HfIhJm1M.js → search-panel-BE4xzWlm.js} +4 -4
  120. package/dist/{search-panel-HfIhJm1M.js.map → search-panel-BE4xzWlm.js.map} +1 -1
  121. package/dist/{search-panel-s9IoiOtv.cjs → search-panel-wcbTNG1z.cjs} +4 -4
  122. package/dist/{search-panel-s9IoiOtv.cjs.map → search-panel-wcbTNG1z.cjs.map} +1 -1
  123. package/dist/{sheet-BDsa_Sup.cjs → sheet-DTBFiwde.cjs} +30 -11
  124. package/dist/sheet-DTBFiwde.cjs.map +1 -0
  125. package/dist/{sheet-R6XDgyEf.js → sheet-DyjKfAq0.js} +25 -12
  126. package/dist/sheet-DyjKfAq0.js.map +1 -0
  127. package/dist/{sign-dialog-CgnR7akj.cjs → sign-dialog-D5WGx-Yn.cjs} +2 -2
  128. package/dist/{sign-dialog-CgnR7akj.cjs.map → sign-dialog-D5WGx-Yn.cjs.map} +1 -1
  129. package/dist/{sign-dialog-GDqCoQhA.js → sign-dialog-DerNe8qT.js} +2 -2
  130. package/dist/{sign-dialog-GDqCoQhA.js.map → sign-dialog-DerNe8qT.js.map} +1 -1
  131. package/dist/{signature-inspector-DyO313Qf.cjs → signature-inspector-Bz6TAfZM.cjs} +4 -10
  132. package/dist/signature-inspector-Bz6TAfZM.cjs.map +1 -0
  133. package/dist/{signature-inspector-okFz8do6.js → signature-inspector-CsGr9EBk.js} +4 -10
  134. package/dist/signature-inspector-CsGr9EBk.js.map +1 -0
  135. package/dist/{signature-maker-BoYa8vgA.cjs → signature-maker-D_YfBXLn.cjs} +3 -3
  136. package/dist/{signature-maker-BoYa8vgA.cjs.map → signature-maker-D_YfBXLn.cjs.map} +1 -1
  137. package/dist/{signature-maker-BhCmYyHD.js → signature-maker-Dnth4rV4.js} +3 -3
  138. package/dist/{signature-maker-BhCmYyHD.js.map → signature-maker-Dnth4rV4.js.map} +1 -1
  139. package/dist/{signatures-panel-B56PC6d9.cjs → signatures-panel-Ci_LaI1C.cjs} +4 -10
  140. package/dist/signatures-panel-Ci_LaI1C.cjs.map +1 -0
  141. package/dist/{signatures-panel-CgnFfhFm.js → signatures-panel-DZ9ywrjz.js} +4 -10
  142. package/dist/signatures-panel-DZ9ywrjz.js.map +1 -0
  143. package/dist/{stamps-panel-CDO0FPyK.js → stamps-panel-BrczStaz.js} +4 -10
  144. package/dist/stamps-panel-BrczStaz.js.map +1 -0
  145. package/dist/{stamps-panel-B9NYGayn.cjs → stamps-panel-Cv9nJBwx.cjs} +4 -10
  146. package/dist/stamps-panel-Cv9nJBwx.cjs.map +1 -0
  147. package/dist/theme-Be0OZokZ.js +97 -0
  148. package/dist/theme-Be0OZokZ.js.map +1 -0
  149. package/dist/theme-FR26JI3r.cjs +126 -0
  150. package/dist/theme-FR26JI3r.cjs.map +1 -0
  151. package/dist/{toolbar-z9od3tKl.js → toolbar-DF361xWY.js} +7 -6
  152. package/dist/toolbar-DF361xWY.js.map +1 -0
  153. package/dist/{toolbar-CJu2wKTU.cjs → toolbar-ddvpsvTb.cjs} +7 -6
  154. package/dist/toolbar-ddvpsvTb.cjs.map +1 -0
  155. package/dist/{zh-cn-CxkUUBct.js → zh-cn-BMPPkLpL.js} +93 -1
  156. package/dist/zh-cn-BMPPkLpL.js.map +1 -0
  157. package/dist/{zh-cn-3tmMeHqv.cjs → zh-cn-CZOO3p4H.cjs} +93 -1
  158. package/dist/zh-cn-CZOO3p4H.cjs.map +1 -0
  159. package/package.json +4 -4
  160. package/src/styles.css +8 -0
  161. package/dist/ar-D9XKAmDx.js.map +0 -1
  162. package/dist/ar-DnEj5vbP.cjs.map +0 -1
  163. package/dist/commands-BmgxhJ8B.js.map +0 -1
  164. package/dist/commands-CYt4SFUX.cjs.map +0 -1
  165. package/dist/de-Bdr4aWzm.js.map +0 -1
  166. package/dist/de-Dv6zvbnd.cjs.map +0 -1
  167. package/dist/dialog-B5GBisKv.js.map +0 -1
  168. package/dist/dialog-t8F13BL_.cjs.map +0 -1
  169. package/dist/es-BP09DR9w.cjs.map +0 -1
  170. package/dist/es-BSXz5tBv.js.map +0 -1
  171. package/dist/fr-BBQQn7tJ.cjs.map +0 -1
  172. package/dist/fr-Ckn3K9v1.js.map +0 -1
  173. package/dist/he-DRsG7bH7.cjs.map +0 -1
  174. package/dist/he-wdGU5PkU.js.map +0 -1
  175. package/dist/icons-BrK5iVL8.js.map +0 -1
  176. package/dist/icons-x0Tc05bs.cjs.map +0 -1
  177. package/dist/it-BuP4o0xQ.cjs.map +0 -1
  178. package/dist/it-Us-VmvIu.js.map +0 -1
  179. package/dist/ja-Cizj0-5O.js.map +0 -1
  180. package/dist/ja-DovEd6ts.cjs.map +0 -1
  181. package/dist/ko-B-qJEol2.cjs.map +0 -1
  182. package/dist/ko-DlrXliE1.js.map +0 -1
  183. package/dist/nl-0aF7M_0h.js.map +0 -1
  184. package/dist/nl-D3KZDDiJ.cjs.map +0 -1
  185. package/dist/pl-BW--AaCI.js.map +0 -1
  186. package/dist/pl-DSFhAUqx.cjs.map +0 -1
  187. package/dist/pt-C5S-8MC5.cjs.map +0 -1
  188. package/dist/pt-DIhpU5pT.js.map +0 -1
  189. package/dist/sheet-BDsa_Sup.cjs.map +0 -1
  190. package/dist/sheet-R6XDgyEf.js.map +0 -1
  191. package/dist/signature-inspector-DyO313Qf.cjs.map +0 -1
  192. package/dist/signature-inspector-okFz8do6.js.map +0 -1
  193. package/dist/signatures-panel-B56PC6d9.cjs.map +0 -1
  194. package/dist/signatures-panel-CgnFfhFm.js.map +0 -1
  195. package/dist/stamps-panel-B9NYGayn.cjs.map +0 -1
  196. package/dist/stamps-panel-CDO0FPyK.js.map +0 -1
  197. package/dist/toolbar-CJu2wKTU.cjs.map +0 -1
  198. package/dist/toolbar-z9od3tKl.js.map +0 -1
  199. package/dist/zh-cn-3tmMeHqv.cjs.map +0 -1
  200. package/dist/zh-cn-CxkUUBct.js.map +0 -1
package/dist/index.cjs CHANGED
@@ -1,18 +1,21 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_icons = require("./icons-x0Tc05bs.cjs");
3
- const require_commands = require("./commands-CYt4SFUX.cjs");
2
+ const require_icons = require("./icons-1UfLUZ_y.cjs");
3
+ const require_commands = require("./commands-DL1gjZt7.cjs");
4
4
  const require_chrome = require("./chrome.cjs");
5
- const require_toolbar = require("./toolbar-CJu2wKTU.cjs");
6
- const require_sheet = require("./sheet-BDsa_Sup.cjs");
5
+ const require_toolbar = require("./toolbar-ddvpsvTb.cjs");
6
+ const require_theme = require("./theme-FR26JI3r.cjs");
7
+ const require_sheet = require("./sheet-DTBFiwde.cjs");
7
8
  const require_stamp_store = require("./stamp-store-BHvRs-Do.cjs");
8
- const require_annotation_fonts = require("./annotation-fonts-Dt0IQXhz.cjs");
9
- const require_dialog = require("./dialog-t8F13BL_.cjs");
9
+ const require_annotation_fonts = require("./annotation-fonts-dpfVkhnq.cjs");
10
+ const require_dialog = require("./dialog-CngKTnAM.cjs");
10
11
  let react = require("react");
11
12
  let _embedpdf_react_runtime = require("@embedpdf/react/runtime");
12
13
  let _embedpdf_react_stage = require("@embedpdf/react/stage");
13
14
  let _embedpdf_react_render = require("@embedpdf/react/render");
14
15
  let _embedpdf_react_page_edit = require("@embedpdf/react/page-edit");
15
16
  let _embedpdf_react_metadata = require("@embedpdf/react/metadata");
17
+ let _embedpdf_react_outline = require("@embedpdf/react/outline");
18
+ let _embedpdf_react_attachment = require("@embedpdf/react/attachment");
16
19
  let _embedpdf_react_interaction = require("@embedpdf/react/interaction");
17
20
  let _embedpdf_react_selection = require("@embedpdf/react/selection");
18
21
  let _embedpdf_react_annotation = require("@embedpdf/react/annotation");
@@ -150,6 +153,7 @@ const en = {
150
153
  note: "Comment",
151
154
  link: "Link",
152
155
  gotoLink: "Go to link",
156
+ saveFile: "Save file",
153
157
  removeLink: "Remove link",
154
158
  delete: "Delete",
155
159
  group: "Group",
@@ -206,12 +210,44 @@ const en = {
206
210
  "annotations-create": "Adding annotations isn't allowed",
207
211
  "doc-annotate-modify": "Changing annotations isn't allowed",
208
212
  "doc-annotate-read": "Viewing annotations isn't allowed",
213
+ "doc-attachments-modify": "Adding files isn’t allowed",
209
214
  "doc-download": "Downloading isn't allowed",
210
215
  "doc-forms-modify": "Editing form fields isn't allowed",
216
+ "doc-outline-modify": "Changing the outline isn’t allowed",
217
+ "doc-pages-assemble": "Changing pages isn’t allowed",
211
218
  "doc-print": "Printing isn't allowed",
212
219
  "doc-text-copy": "Copying isn't allowed",
213
220
  "doc-text-search": "Searching isn't allowed"
214
221
  },
222
+ attachment: {
223
+ add: "Add file",
224
+ save: "Save",
225
+ goTo: "Go to page",
226
+ delete: "Delete",
227
+ more: "More options"
228
+ },
229
+ outline: {
230
+ add: "Add item",
231
+ addChild: "Add child item",
232
+ rename: "Rename",
233
+ setDestination: "Set destination to current view",
234
+ properties: "Properties…",
235
+ delete: "Delete",
236
+ expandAll: "Expand all",
237
+ collapseAll: "Collapse all",
238
+ more: "More options"
239
+ },
240
+ pages: {
241
+ rotateClockwise: "Rotate Page Clockwise",
242
+ rotateCounterclockwise: "Rotate Page Counter-Clockwise",
243
+ delete: "Delete Pages",
244
+ duplicate: "Duplicate Pages",
245
+ insertBlank: "Insert Blank Page",
246
+ insertFile: "Insert from File…",
247
+ extract: "Extract Pages",
248
+ selectAll: "Select All Pages",
249
+ more: "Page Options"
250
+ },
215
251
  turnedOff: "{label} isn't available"
216
252
  },
217
253
  passwordPrompt: {
@@ -264,6 +300,25 @@ const en = {
264
300
  other: "Other"
265
301
  },
266
302
  goToPage: { go: "Go" },
303
+ print: {
304
+ title: "Print",
305
+ pages: "Pages",
306
+ allPages: "All pages",
307
+ currentPage: "Current page",
308
+ range: "Custom",
309
+ rangeLabel: "Pages to print",
310
+ rangePlaceholder: "e.g. 1-3, 5",
311
+ rangeInvalid: "Use page numbers from 1 to {total}, such as 1-3, 5",
312
+ annotations: "Print annotations",
313
+ preparing: "Preparing…",
314
+ preparingPage: "Preparing page {page} of {total}…",
315
+ ready: "Ready to print.",
316
+ images: "Pages print as images at {dpi} DPI.",
317
+ lowResolution: "This document allows only low-resolution printing ({dpi} DPI).",
318
+ failed: "The printout couldn’t be prepared.",
319
+ cancel: "Cancel",
320
+ print: "Print"
321
+ },
267
322
  panels: {
268
323
  thumbnails: "Thumbnails",
269
324
  outline: "Outline",
@@ -459,6 +514,46 @@ const en = {
459
514
  noRotate: "Stays upright when the page rotates",
460
515
  invisible: "Legacy: hide unknown subtypes"
461
516
  },
517
+ attachments: {
518
+ loading: "Loading attachments…",
519
+ failed: "The attachments couldn’t be read.",
520
+ empty: "This document has no attached files",
521
+ drop: "Drop files to attach them",
522
+ dropHint: "Or drop files here",
523
+ adding: "Adding…",
524
+ onPage: "Page {page}",
525
+ count: "{count} file",
526
+ countPlural: "{count} files"
527
+ },
528
+ outline: {
529
+ filter: "Filter outline",
530
+ loading: "Loading outline…",
531
+ failed: "The outline couldn’t be read.",
532
+ empty: "This document has no outline",
533
+ noMatches: "No items match",
534
+ incomplete: "Part of the outline couldn’t be read.",
535
+ untitled: "Untitled",
536
+ properties: {
537
+ title: "Item properties",
538
+ name: "Title",
539
+ color: "Color",
540
+ noColor: "None",
541
+ customColor: "Custom color",
542
+ bold: "Bold",
543
+ italic: "Italic",
544
+ open: "Expanded when the document opens",
545
+ target: "Destination",
546
+ targetNone: "None",
547
+ targetView: "Current view",
548
+ targetNamed: "Page action",
549
+ targetKept: "Kept as it is",
550
+ keptNote: "This item runs a script or opens another file. It can’t be changed here.",
551
+ fit: "Fit",
552
+ fitKept: "As it is",
553
+ save: "Save",
554
+ cancel: "Cancel"
555
+ }
556
+ },
462
557
  linkEditor: {
463
558
  toUrl: "Link to a URL",
464
559
  url: "URL",
@@ -621,18 +716,18 @@ const en = {
621
716
  */
622
717
  /** The viewer's languages besides English, by code. */
623
718
  const LOCALE_LOADERS = {
624
- de: () => Promise.resolve().then(() => require("./de-Dv6zvbnd.cjs")).then((module) => module.de),
625
- fr: () => Promise.resolve().then(() => require("./fr-BBQQn7tJ.cjs")).then((module) => module.fr),
626
- es: () => Promise.resolve().then(() => require("./es-BP09DR9w.cjs")).then((module) => module.es),
627
- it: () => Promise.resolve().then(() => require("./it-BuP4o0xQ.cjs")).then((module) => module.it),
628
- nl: () => Promise.resolve().then(() => require("./nl-D3KZDDiJ.cjs")).then((module) => module.nl),
629
- pt: () => Promise.resolve().then(() => require("./pt-C5S-8MC5.cjs")).then((module) => module.pt),
630
- pl: () => Promise.resolve().then(() => require("./pl-DSFhAUqx.cjs")).then((module) => module.pl),
631
- ja: () => Promise.resolve().then(() => require("./ja-DovEd6ts.cjs")).then((module) => module.ja),
632
- "zh-CN": () => Promise.resolve().then(() => require("./zh-cn-3tmMeHqv.cjs")).then((module) => module.zhCN),
633
- ko: () => Promise.resolve().then(() => require("./ko-B-qJEol2.cjs")).then((module) => module.ko),
634
- ar: () => Promise.resolve().then(() => require("./ar-DnEj5vbP.cjs")).then((module) => module.ar),
635
- he: () => Promise.resolve().then(() => require("./he-DRsG7bH7.cjs")).then((module) => module.he)
719
+ de: () => Promise.resolve().then(() => require("./de-7_MvFWzN.cjs")).then((module) => module.de),
720
+ fr: () => Promise.resolve().then(() => require("./fr-C856dmQJ.cjs")).then((module) => module.fr),
721
+ es: () => Promise.resolve().then(() => require("./es-DgYj-1L3.cjs")).then((module) => module.es),
722
+ it: () => Promise.resolve().then(() => require("./it-Bef-2Yxq.cjs")).then((module) => module.it),
723
+ nl: () => Promise.resolve().then(() => require("./nl-BjkbaLq3.cjs")).then((module) => module.nl),
724
+ pt: () => Promise.resolve().then(() => require("./pt-DLcszlzi.cjs")).then((module) => module.pt),
725
+ pl: () => Promise.resolve().then(() => require("./pl-CKKdVnpZ.cjs")).then((module) => module.pl),
726
+ ja: () => Promise.resolve().then(() => require("./ja-DNw2zqSD.cjs")).then((module) => module.ja),
727
+ "zh-CN": () => Promise.resolve().then(() => require("./zh-cn-CZOO3p4H.cjs")).then((module) => module.zhCN),
728
+ ko: () => Promise.resolve().then(() => require("./ko-YHzeBqP6.cjs")).then((module) => module.ko),
729
+ ar: () => Promise.resolve().then(() => require("./ar-B132r9bo.cjs")).then((module) => module.ar),
730
+ he: () => Promise.resolve().then(() => require("./he-BFTeNc4t.cjs")).then((module) => module.he)
636
731
  };
637
732
  /**
638
733
  * The language a `locale` value shows, among `codes`: the browser's languages for `'auto'`,
@@ -770,6 +865,8 @@ const VIEWER_PLUGINS = {
770
865
  signature: _embedpdf_react_signature.SignatureToken,
771
866
  pageEdit: _embedpdf_react_page_edit.PageEditToken,
772
867
  metadata: _embedpdf_react_metadata.MetadataToken,
868
+ outline: _embedpdf_react_outline.OutlineToken,
869
+ attachment: _embedpdf_react_attachment.AttachmentToken,
773
870
  actions: _embedpdf_react_actions.ActionsToken,
774
871
  documents: _embedpdf_react_runtime.DocumentsToken,
775
872
  interaction: _embedpdf_react_interaction.InteractionToken,
@@ -959,6 +1056,8 @@ const WITHOUT_SETTINGS = /* @__PURE__ */ new Set([
959
1056
  "link",
960
1057
  "pageEdit",
961
1058
  "metadata",
1059
+ "outline",
1060
+ "attachment",
962
1061
  "documents",
963
1062
  "shell"
964
1063
  ]);
@@ -1015,92 +1114,6 @@ function settingsOver(viewerSettings, settings) {
1015
1114
  return (0, _embedpdf_react_runtime.mergeSettings)(viewerSettings, settings);
1016
1115
  }
1017
1116
  //#endregion
1018
- //#region src/ui/theme.tsx
1019
- /**
1020
- * Light/dark theme — one class, and the CSS variables in styles.css do the
1021
- * rest (both toolbars, sidebars, popovers, and the canvas re-theme from it).
1022
- * The mode follows the embedder's `theme` preference while the viewer runs;
1023
- * `'system'` follows the OS setting, and switches when the user changes it.
1024
- * The class lands on <html> by default; a delivery that must not touch the
1025
- * page (the <embedpdf-viewer> shadow root) passes `target` and the class stays
1026
- * inside its own subtree. The theme's tokens are CSS variables too: a delivery
1027
- * applies {@link themeTokenCss} on the viewer's root.
1028
- */
1029
- /**
1030
- * The viewer's look, by name: each is the CSS variable `--epdf-<name>`, which the chrome's
1031
- * stylesheet declares with a default for each mode and mixes every other shade from.
1032
- */
1033
- const THEME_TOKENS = [
1034
- "accent",
1035
- "background",
1036
- "surface",
1037
- "surface-raised",
1038
- "text",
1039
- "text-muted",
1040
- "border",
1041
- "hover",
1042
- "canvas",
1043
- "radius",
1044
- "font"
1045
- ];
1046
- /** Normalize the shorthand — deliveries use this to read one shape. */
1047
- const themeConfigOf = (theme) => typeof theme === "string" ? { preference: theme } : theme ?? {};
1048
- const isThemeToken = (name) => THEME_TOKENS.includes(name);
1049
- /** The declarations of `tokens` that are tokens with a CSS value; each other entry warns. */
1050
- function tokenDeclarations(tokens) {
1051
- return Object.entries(tokens).filter(([name, value]) => {
1052
- if (value === void 0) return false;
1053
- if (!isThemeToken(name)) {
1054
- console.warn(`[embedpdf] theme: "${name}" isn't a token, ignored`);
1055
- return false;
1056
- }
1057
- if (typeof value !== "string" || /[{};]/.test(value)) {
1058
- console.warn(`[embedpdf] theme: ignoring the invalid value of "${name}"`);
1059
- return false;
1060
- }
1061
- return true;
1062
- }).map(([name, value]) => `--epdf-${name}:var(--embedpdf-host-${name},${value});`).join("");
1063
- }
1064
- /**
1065
- * The CSS that applies a theme's tokens on the viewer's root (`root`, a selector), for a sheet
1066
- * after the chrome's: its tokens win over the defaults in both modes by coming later, and its
1067
- * dark ones win in dark by naming the class too. A value is a default only: the page's own
1068
- * `--epdf-*` variable still wins, read on the host as the chrome's stylesheet does. Empty when
1069
- * the theme sets no token.
1070
- */
1071
- function themeTokenCss(theme, root) {
1072
- const { accent, tokens, dark } = themeConfigOf(theme);
1073
- const both = tokenDeclarations({
1074
- ...accent === void 0 ? null : { accent },
1075
- ...tokens
1076
- });
1077
- const darkOnly = dark ? tokenDeclarations(dark) : "";
1078
- return (both ? `${root}{${both}}` : "") + (darkOnly ? `${root}.dark{${darkOnly}}` : "");
1079
- }
1080
- const ThemeCtx = (0, react.createContext)(null);
1081
- const DARK_QUERY = "(prefers-color-scheme: dark)";
1082
- const systemMode = () => typeof window !== "undefined" && window.matchMedia?.(DARK_QUERY).matches ? "dark" : "light";
1083
- function ThemeProvider({ children, preference = "system", target }) {
1084
- const [system, setSystem] = (0, react.useState)(systemMode);
1085
- (0, react.useEffect)(() => {
1086
- if (preference !== "system" || typeof window === "undefined" || !window.matchMedia) return;
1087
- const query = window.matchMedia(DARK_QUERY);
1088
- const follow = () => setSystem(query.matches ? "dark" : "light");
1089
- follow();
1090
- query.addEventListener("change", follow);
1091
- return () => query.removeEventListener("change", follow);
1092
- }, [preference]);
1093
- const mode = preference === "system" ? system : preference;
1094
- (0, react.useLayoutEffect)(() => {
1095
- (target ?? document.documentElement).classList.toggle("dark", mode === "dark");
1096
- }, [mode, target]);
1097
- const value = (0, react.useMemo)(() => ({ mode }), [mode]);
1098
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ThemeCtx.Provider, {
1099
- value,
1100
- children
1101
- });
1102
- }
1103
- //#endregion
1104
1117
  //#region src/config/panels.ts
1105
1118
  /**
1106
1119
  * The panels a layout brings, as commands. Every panel gets `panel:<id>`, which
@@ -1120,6 +1133,12 @@ const panelSideOf = (panel) => panel.side === "start" ? "start" : "end";
1120
1133
  function panelsOnSide(data, side) {
1121
1134
  return Object.entries(data.panels ?? {}).filter(([, panel]) => isPanel(panel) && panelSideOf(panel) === side).map(([id]) => id);
1122
1135
  }
1136
+ /**
1137
+ * Whether a list panel has a job: its list holds entries, or the session may add some (the
1138
+ * right, and `adding`, the feature that turns adding off, on). A document without an outline
1139
+ * shows no outline button to a session that can't add items; the same for attachments.
1140
+ */
1141
+ const hasJob = (commandContext, entries, mayAdd, adding) => entries > 0 || mayAdd && !(commandContext.tryGet(_embedpdf_react_commands.CommandsToken)?.isCategoryDisabled(adding) ?? false);
1123
1142
  /** The search panel's id in the layout. */
1124
1143
  const SEARCH_PANEL = "search";
1125
1144
  /** Searching, which the search panel and Find need: without it every query is refused. */
@@ -1146,11 +1165,17 @@ const BUILT_IN_PANELS = /* @__PURE__ */ new Map([
1146
1165
  ["thumbnails", { categories: ["thumbnails"] }],
1147
1166
  ["outline", {
1148
1167
  categories: ["outline"],
1149
- visible: () => false
1168
+ visible: (commandContext) => {
1169
+ const outline = commandContext.tryGet(_embedpdf_react_outline.OutlineToken);
1170
+ return outline != null && hasJob(commandContext, outline.list().length, outline.canEdit(), "outline.editing");
1171
+ }
1150
1172
  }],
1151
1173
  ["attachments", {
1152
1174
  categories: ["attachments"],
1153
- visible: () => false
1175
+ visible: (commandContext) => {
1176
+ const attachment = commandContext.tryGet(_embedpdf_react_attachment.AttachmentToken);
1177
+ return attachment != null && hasJob(commandContext, attachment.list().length, attachment.canAdd(), "attachments.adding");
1178
+ }
1154
1179
  }],
1155
1180
  [SEARCH_PANEL, {
1156
1181
  ...SEARCHES,
@@ -1817,7 +1842,7 @@ function StripBar({ view, label }) {
1817
1842
  * groups vanish, null when nothing applies. Mounted in the Stage `overlay`
1818
1843
  * slot. The pixels are the shared <StripBar>.
1819
1844
  */
1820
- const LinkEditorCard = lazyComponent(() => Promise.resolve().then(() => require("./link-editor-CSjqPnj1.cjs")).then((ui) => ui.LinkEditorCard));
1845
+ const LinkEditorCard = lazyComponent(() => Promise.resolve().then(() => require("./link-editor-CAS7MZM2.cjs")).then((ui) => ui.LinkEditorCard));
1821
1846
  function AnnotationStrip() {
1822
1847
  const t = (0, _embedpdf_react_i18n.useT)();
1823
1848
  const view = (0, _embedpdf_react_toolbar.useStripView)(require_icons.useStripSchema("annotation"));
@@ -2517,6 +2542,551 @@ function PanelRow({ panel, current, onPicked }) {
2517
2542
  });
2518
2543
  }
2519
2544
  //#endregion
2545
+ //#region src/ui/thumbnail-drop.ts
2546
+ /** How thick the drop line is drawn, in px. */
2547
+ const LINE = 2;
2548
+ /** How many thumbnails share the first row on screen: 1 for a single column. */
2549
+ function columnsOf(boxes) {
2550
+ const first = boxes[0];
2551
+ if (!first) return 1;
2552
+ return Math.max(1, boxes.filter((box) => Math.abs(box.y - first.y) < 1).length);
2553
+ }
2554
+ /** How far a point is from a box: 0 inside it. */
2555
+ function distance(box, x, y) {
2556
+ const dx = Math.max(box.x - x, 0, x - (box.x + box.width));
2557
+ const dy = Math.max(box.y - y, 0, y - (box.y + box.height));
2558
+ return Math.hypot(dx, dy);
2559
+ }
2560
+ /**
2561
+ * The order of the document's pages once `moving` go to `position`, together in the order they
2562
+ * have now: what a reorder answers.
2563
+ */
2564
+ function orderAfter(order, moving, position) {
2565
+ const staying = order.filter((page) => !moving.has(page));
2566
+ const anchor = "before" in position ? position.before : position.after;
2567
+ const at = staying.indexOf(anchor) + ("after" in position ? 1 : 0);
2568
+ const moved = order.filter((page) => moving.has(page));
2569
+ return [
2570
+ ...staying.slice(0, at),
2571
+ ...moved,
2572
+ ...staying.slice(at)
2573
+ ];
2574
+ }
2575
+ /**
2576
+ * Where pages dropped at `point` land, or `null` when nothing would change: over a page that
2577
+ * moves, or in the place the pages already are. `order` is every page of the document in display
2578
+ * order; `moving` the pages dragged, empty for files dropped from outside.
2579
+ */
2580
+ function thumbDropAt(boxes, point, spacing, order, moving) {
2581
+ let nearest = null;
2582
+ for (const box of boxes) if (!nearest || distance(box, point.x, point.y) < distance(nearest, point.x, point.y)) nearest = box;
2583
+ if (!nearest || moving.has(nearest.page)) return null;
2584
+ const across = columnsOf(boxes) > 1;
2585
+ const before = across ? point.x < nearest.x + nearest.width / 2 : point.y < nearest.y + nearest.height / 2;
2586
+ const position = before ? { before: nearest.page } : { after: nearest.page };
2587
+ if (moving.size > 0) {
2588
+ if (orderAfter(order, moving, position).every((page, i) => page === order[i])) return null;
2589
+ }
2590
+ const half = spacing.gap / 2;
2591
+ return {
2592
+ position,
2593
+ line: across ? {
2594
+ x: (before ? nearest.x - half : nearest.x + nearest.width + half) - LINE / 2,
2595
+ y: nearest.y,
2596
+ width: LINE,
2597
+ height: nearest.height
2598
+ } : {
2599
+ x: nearest.x,
2600
+ y: (before ? nearest.y - half : nearest.y + nearest.height + spacing.band + half) - LINE / 2,
2601
+ width: nearest.width,
2602
+ height: LINE
2603
+ }
2604
+ };
2605
+ }
2606
+ /**
2607
+ * The page a move of one slot puts the selection next to, keys up or down: past the nearest page
2608
+ * that isn't selected, on that side. `null` at the start or the end.
2609
+ */
2610
+ function slotMove(order, selected, direction) {
2611
+ const indexes = order.flatMap((page, i) => selected.has(page) ? [i] : []);
2612
+ if (indexes.length === 0) return null;
2613
+ if (direction < 0) {
2614
+ for (let i = indexes[0] - 1; i >= 0; i -= 1) if (!selected.has(order[i])) return { before: order[i] };
2615
+ return null;
2616
+ }
2617
+ for (let i = indexes[indexes.length - 1] + 1; i < order.length; i += 1) if (!selected.has(order[i])) return { after: order[i] };
2618
+ return null;
2619
+ }
2620
+ //#endregion
2621
+ //#region src/ui/thumbnail-list.tsx
2622
+ /**
2623
+ * The thumbnails panel: the same document through the thumbnail Stage lens (a fixed-zoom grid
2624
+ * that wraps into as many columns as the panel's width fits; see the viewer's `thumbnails`
2625
+ * plugin). A click goes to the page, and the panel follows the main view.
2626
+ *
2627
+ * A session that may change the pages (`page:insert-blank` shows and is enabled, the outline
2628
+ * panel's rule) organizes them here too:
2629
+ * - a click selects the page, Ctrl/Cmd+click adds or removes one, Shift+click selects a range;
2630
+ * - each page has a menu: its button, a right-click, or a long press;
2631
+ * - dragging moves the selection if the page is in it, else that page, with a line where they
2632
+ * land; a pen or a finger holds the page first, so a swipe still scrolls;
2633
+ * - PDFs dropped between pages are inserted there, not opened as a tab;
2634
+ * - the header has insert, rotate, delete, the selection's menu, and undo and redo;
2635
+ * - the list is one tab stop: arrows go through the pages, Shift extends, Space adds or removes,
2636
+ * Alt+arrows move the selection one place, Delete deletes and Ctrl/Cmd+A selects every page.
2637
+ */
2638
+ /** How far the pointer moves before a press on a page becomes a drag, in px (the outline's). */
2639
+ const DRAG_SLOP_PX = 4;
2640
+ /** How long a pen or a finger holds a page before it drags it, or opens its menu, in ms. */
2641
+ const HOLD_MS = 450;
2642
+ /** Within this many px of the list's top or bottom, a drag scrolls the list. */
2643
+ const EDGE_PX = 28;
2644
+ /** The lens's spacing when its settings don't say it in px. */
2645
+ const DEFAULT_GAP_PX = 16;
2646
+ /** The header's commands: insert and rotate, delete, the menu of the rest, then the history. */
2647
+ const HEADER_EDITS = [
2648
+ "page:insert-blank",
2649
+ "page:rotate-counterclockwise",
2650
+ "page:rotate-clockwise",
2651
+ "page:delete",
2652
+ "menu:page"
2653
+ ];
2654
+ const HEADER_HISTORY = ["history:undo", "history:redo"];
2655
+ /** The thumbnails on screen, as boxes in the lens's viewport. */
2656
+ function boxesOf(thumbs) {
2657
+ return thumbs.listVisiblePages().map((page) => ({
2658
+ page: page.ref.objectNumber,
2659
+ x: page.screenX,
2660
+ y: page.screenY,
2661
+ width: page.transform.viewWidth,
2662
+ height: page.transform.viewHeight
2663
+ }));
2664
+ }
2665
+ const positionOf = (position) => "before" in position ? { before: (0, _embedpdf_react_runtime.toPageRef)(position.before) } : { after: (0, _embedpdf_react_runtime.toPageRef)(position.after) };
2666
+ function ThumbnailList() {
2667
+ const t = (0, _embedpdf_react_i18n.useT)();
2668
+ const idPrefix = (0, react.useId)();
2669
+ const main = (0, _embedpdf_react_stage.useStage)();
2670
+ const thumbs = (0, _embedpdf_react_stage.useStage)(ThumbsStageToken);
2671
+ const currentPage = (0, _embedpdf_react_stage.useStageState)((state) => state.currentPageIndex);
2672
+ const pages = (0, _embedpdf_react_runtime.usePageList)();
2673
+ const pageEdit = (0, _embedpdf_react_page_edit.usePageEdit)();
2674
+ const selected = (0, _embedpdf_react_page_edit.usePageEditState)((state) => state.selected);
2675
+ const commands = (0, _embedpdf_react_commands.useCommands)();
2676
+ const insertFile = (0, _embedpdf_react_commands.useCommand)("page:insert-file");
2677
+ const insertBlank = (0, _embedpdf_react_commands.useCommand)("page:insert-blank");
2678
+ const editable = insertBlank.visible && insertBlank.enabled;
2679
+ const closeOnPick = require_sheet.useCloseOnPick();
2680
+ const host = (0, react.useRef)(null);
2681
+ const [focusedPage, setFocusedPage] = (0, react.useState)(null);
2682
+ const [anchorPage, setAnchorPage] = (0, react.useState)(null);
2683
+ const [listFocused, setListFocused] = (0, react.useState)(false);
2684
+ const [drag, setDrag] = (0, react.useState)(null);
2685
+ const dragRef = (0, react.useRef)(null);
2686
+ dragRef.current = drag;
2687
+ const [fileDrop, setFileDrop] = (0, react.useState)(null);
2688
+ const holdTimer = (0, react.useRef)(null);
2689
+ const suppressClick = (0, react.useRef)(false);
2690
+ const order = pages.map((page) => page.ref.objectNumber);
2691
+ const indexOf = (page) => page === null ? -1 : order.indexOf(page);
2692
+ const selectedPages = new Set(selected.map((ref) => ref.objectNumber));
2693
+ const focusedIndex = indexOf(focusedPage) >= 0 ? indexOf(focusedPage) : currentPage;
2694
+ (0, react.useEffect)(() => thumbs.reveal(currentPage), [currentPage, thumbs]);
2695
+ const laidOut = (0, _embedpdf_react_stage.useStageState)((state) => state.pageCount, ThumbsStageToken);
2696
+ const lastSelected = selected[selected.length - 1]?.objectNumber ?? null;
2697
+ const lastSelectedIndex = lastSelected === null ? -1 : order.indexOf(lastSelected);
2698
+ (0, react.useEffect)(() => {
2699
+ if (lastSelectedIndex >= 0 && lastSelectedIndex < laidOut) thumbs.reveal(lastSelectedIndex);
2700
+ }, [
2701
+ lastSelectedIndex,
2702
+ laidOut,
2703
+ thumbs
2704
+ ]);
2705
+ const spacing = () => {
2706
+ const { gap, pageFrame } = thumbs.getSettings();
2707
+ return {
2708
+ gap: typeof gap === "object" && gap !== null && "px" in gap ? gap.px : DEFAULT_GAP_PX,
2709
+ band: pageFrame.bottom
2710
+ };
2711
+ };
2712
+ /** A pointer's place in the lens's viewport. */
2713
+ const pointOf = (clientX, clientY) => {
2714
+ const box = host.current?.getBoundingClientRect();
2715
+ return box ? {
2716
+ x: clientX - box.left,
2717
+ y: clientY - box.top
2718
+ } : null;
2719
+ };
2720
+ const dropAt = (clientX, clientY, moving) => {
2721
+ const point = pointOf(clientX, clientY);
2722
+ return point ? thumbDropAt(boxesOf(thumbs), point, spacing(), order, moving) : null;
2723
+ };
2724
+ const go = (index) => {
2725
+ main.goToPage(index);
2726
+ closeOnPick();
2727
+ };
2728
+ const select = (refs) => pageEdit.select(refs);
2729
+ const onPageClick = (ref, index, event) => {
2730
+ if (suppressClick.current) {
2731
+ suppressClick.current = false;
2732
+ return;
2733
+ }
2734
+ const page = ref.objectNumber;
2735
+ setFocusedPage(page);
2736
+ if (editable && (event.metaKey || event.ctrlKey)) {
2737
+ select(selectedPages.has(page) ? selected.filter((each) => each.objectNumber !== page) : [...selected, ref]);
2738
+ setAnchorPage(page);
2739
+ return;
2740
+ }
2741
+ if (editable && event.shiftKey && indexOf(anchorPage) >= 0) {
2742
+ const from = indexOf(anchorPage);
2743
+ const [low, high] = from < index ? [from, index] : [index, from];
2744
+ select(pages.slice(low, high + 1).map((each) => each.ref));
2745
+ return;
2746
+ }
2747
+ setAnchorPage(page);
2748
+ if (editable) select([ref]);
2749
+ go(index);
2750
+ };
2751
+ /** A page's menu is about to open: an unselected page becomes the selection. */
2752
+ const onMenu = (ref) => {
2753
+ setFocusedPage(ref.objectNumber);
2754
+ if (!selectedPages.has(ref.objectNumber)) select([ref]);
2755
+ };
2756
+ const openMenuOf = (page) => host.current?.querySelector(`[data-epdf-page-menu="${page}"] button`)?.click();
2757
+ const stopHold = () => {
2758
+ if (holdTimer.current !== null) clearTimeout(holdTimer.current);
2759
+ holdTimer.current = null;
2760
+ };
2761
+ const onPagePointerDown = (ref, event) => {
2762
+ if (!editable || event.button !== 0) return;
2763
+ if (event.target.closest("[data-epdf-page-menu]")) return;
2764
+ const page = ref.objectNumber;
2765
+ const moving = selectedPages.has(page) ? selectedPages : /* @__PURE__ */ new Set([page]);
2766
+ setDrag({
2767
+ pointerId: event.pointerId,
2768
+ startX: event.clientX,
2769
+ startY: event.clientY,
2770
+ page,
2771
+ moving,
2772
+ held: false,
2773
+ active: false,
2774
+ drop: null
2775
+ });
2776
+ if (event.pointerType !== "mouse") holdTimer.current = setTimeout(() => {
2777
+ const current = dragRef.current;
2778
+ if (current && !current.active) setDrag({
2779
+ ...current,
2780
+ held: true
2781
+ });
2782
+ }, HOLD_MS);
2783
+ };
2784
+ const dragging = drag?.active === true;
2785
+ const pressed = drag !== null;
2786
+ (0, react.useEffect)(() => {
2787
+ if (!pressed) return void 0;
2788
+ const move = (event) => {
2789
+ const current = dragRef.current;
2790
+ if (!current || event.pointerId !== current.pointerId) return;
2791
+ if (!current.active) {
2792
+ if (Math.hypot(event.clientX - current.startX, event.clientY - current.startY) <= DRAG_SLOP_PX) return;
2793
+ if (event.pointerType !== "mouse" && !current.held) {
2794
+ stopHold();
2795
+ setDrag(null);
2796
+ return;
2797
+ }
2798
+ }
2799
+ const box = host.current?.getBoundingClientRect();
2800
+ if (box && event.clientY < box.top + EDGE_PX) thumbs.scrollBy({ top: -8 });
2801
+ else if (box && event.clientY > box.bottom - EDGE_PX) thumbs.scrollBy({ top: 8 });
2802
+ setDrag({
2803
+ ...current,
2804
+ active: true,
2805
+ drop: dropAt(event.clientX, event.clientY, current.moving)
2806
+ });
2807
+ };
2808
+ const end = (event, commit) => {
2809
+ stopHold();
2810
+ const current = dragRef.current;
2811
+ if (!current || event.pointerId !== current.pointerId) return;
2812
+ setDrag(null);
2813
+ if (!current.active) {
2814
+ if (current.held && commit) {
2815
+ suppressClick.current = true;
2816
+ onMenu((0, _embedpdf_react_runtime.toPageRef)(current.page));
2817
+ openMenuOf(current.page);
2818
+ }
2819
+ return;
2820
+ }
2821
+ suppressClick.current = true;
2822
+ setTimeout(() => {
2823
+ suppressClick.current = false;
2824
+ }, 0);
2825
+ if (!commit || !current.drop) return;
2826
+ const moving = pages.filter((page) => current.moving.has(page.ref.objectNumber));
2827
+ pageEdit.reorder(moving.map((page) => page.ref), positionOf(current.drop.position)).catch(() => {});
2828
+ };
2829
+ const up = (event) => end(event, true);
2830
+ const cancel = (event) => end(event, false);
2831
+ window.addEventListener("pointermove", move);
2832
+ window.addEventListener("pointerup", up);
2833
+ window.addEventListener("pointercancel", cancel);
2834
+ return () => {
2835
+ window.removeEventListener("pointermove", move);
2836
+ window.removeEventListener("pointerup", up);
2837
+ window.removeEventListener("pointercancel", cancel);
2838
+ };
2839
+ });
2840
+ (0, react.useEffect)(() => {
2841
+ if (!dragging) return void 0;
2842
+ const prevent = (event) => event.preventDefault();
2843
+ document.addEventListener("touchmove", prevent, { passive: false });
2844
+ return () => document.removeEventListener("touchmove", prevent);
2845
+ }, [dragging]);
2846
+ (0, react.useEffect)(() => stopHold, []);
2847
+ const takesFiles = (event) => editable && insertFile.visible && insertFile.enabled && require_commands.mayCarryPdf(event.dataTransfer);
2848
+ const onDragOver = (event) => {
2849
+ if (!takesFiles(event)) return;
2850
+ event.preventDefault();
2851
+ event.stopPropagation();
2852
+ event.dataTransfer.dropEffect = "copy";
2853
+ setFileDrop(dropAt(event.clientX, event.clientY, /* @__PURE__ */ new Set()));
2854
+ };
2855
+ const onDragLeave = (event) => {
2856
+ if (!takesFiles(event)) return;
2857
+ event.stopPropagation();
2858
+ const next = event.relatedTarget;
2859
+ if (!next || !host.current?.contains(next)) setFileDrop(null);
2860
+ };
2861
+ const onDrop = (event) => {
2862
+ if (!takesFiles(event)) return;
2863
+ event.preventDefault();
2864
+ event.stopPropagation();
2865
+ const drop = dropAt(event.clientX, event.clientY, /* @__PURE__ */ new Set());
2866
+ setFileDrop(null);
2867
+ const files = Array.from(event.dataTransfer.files).filter(require_commands.isPdfFile);
2868
+ if (files.length === 0) return;
2869
+ const args = {
2870
+ files,
2871
+ ...drop ? { position: positionOf(drop.position) } : {}
2872
+ };
2873
+ commands.execute("page:insert-file", { args }).catch(() => {});
2874
+ };
2875
+ const focusIndex = (index, extend) => {
2876
+ const page = pages[index];
2877
+ if (!page) return;
2878
+ setFocusedPage(page.ref.objectNumber);
2879
+ thumbs.reveal(index);
2880
+ if (!editable) {
2881
+ main.goToPage(index);
2882
+ return;
2883
+ }
2884
+ if (extend && indexOf(anchorPage) >= 0) {
2885
+ const from = indexOf(anchorPage);
2886
+ const [low, high] = from < index ? [from, index] : [index, from];
2887
+ select(pages.slice(low, high + 1).map((each) => each.ref));
2888
+ return;
2889
+ }
2890
+ setAnchorPage(page.ref.objectNumber);
2891
+ select([page.ref]);
2892
+ main.goToPage(index);
2893
+ };
2894
+ const onKeyDown = (event) => {
2895
+ if (event.target !== event.currentTarget || pages.length === 0) return;
2896
+ setListFocused(true);
2897
+ const columns = columnsOf(boxesOf(thumbs));
2898
+ const step = {
2899
+ ArrowLeft: -1,
2900
+ ArrowRight: 1,
2901
+ ArrowUp: -columns,
2902
+ ArrowDown: columns
2903
+ }[event.key];
2904
+ const mod = event.metaKey || event.ctrlKey;
2905
+ if (step !== void 0 && event.altKey && editable) {
2906
+ event.preventDefault();
2907
+ const position = slotMove(order, selectedPages, step < 0 ? -1 : 1);
2908
+ const moving = pages.filter((page) => selectedPages.has(page.ref.objectNumber));
2909
+ if (position && moving.length > 0) pageEdit.reorder(moving.map((page) => page.ref), positionOf(position)).catch(() => {});
2910
+ return;
2911
+ }
2912
+ if (step !== void 0) {
2913
+ event.preventDefault();
2914
+ focusIndex(Math.max(0, Math.min(pages.length - 1, focusedIndex + step)), event.shiftKey);
2915
+ return;
2916
+ }
2917
+ switch (event.key) {
2918
+ case "Home":
2919
+ case "End":
2920
+ event.preventDefault();
2921
+ focusIndex(event.key === "Home" ? 0 : pages.length - 1, event.shiftKey);
2922
+ return;
2923
+ case "Enter":
2924
+ event.preventDefault();
2925
+ go(focusedIndex);
2926
+ return;
2927
+ case " ": {
2928
+ if (!editable) return;
2929
+ event.preventDefault();
2930
+ const page = pages[focusedIndex];
2931
+ if (!page) return;
2932
+ const number = page.ref.objectNumber;
2933
+ setAnchorPage(number);
2934
+ select(selectedPages.has(number) ? selected.filter((each) => each.objectNumber !== number) : [...selected, page.ref]);
2935
+ return;
2936
+ }
2937
+ case "Delete":
2938
+ case "Backspace":
2939
+ if (!editable) return;
2940
+ event.preventDefault();
2941
+ commands.execute("page:delete").catch(() => {});
2942
+ return;
2943
+ case "a":
2944
+ case "A":
2945
+ if (!mod || !editable) return;
2946
+ event.preventDefault();
2947
+ commands.execute("page:select-all").catch(() => {});
2948
+ return;
2949
+ }
2950
+ };
2951
+ const focusedRef = pages[focusedIndex]?.ref ?? null;
2952
+ const shownDrop = dragging ? drag.drop : fileDrop;
2953
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2954
+ className: "flex min-h-0 flex-1 flex-col",
2955
+ children: [editable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PageHeader, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2956
+ ref: host,
2957
+ role: "listbox",
2958
+ "aria-label": t("panels.thumbnails"),
2959
+ "aria-multiselectable": editable || void 0,
2960
+ tabIndex: 0,
2961
+ "aria-activedescendant": listFocused && focusedRef ? `${idPrefix}-${focusedRef.objectNumber}` : void 0,
2962
+ onKeyDown,
2963
+ onFocus: (event) => event.target === event.currentTarget && setListFocused(event.currentTarget.matches(":focus-visible")),
2964
+ onBlur: (event) => event.target === event.currentTarget && setListFocused(false),
2965
+ onDragEnter: onDragOver,
2966
+ onDragOver,
2967
+ onDragLeave,
2968
+ onDrop,
2969
+ className: "focus-visible:ring-accent relative flex min-h-0 flex-1 flex-col outline-none focus-visible:ring-2 focus-visible:ring-inset",
2970
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_embedpdf_react_stage.Stage, {
2971
+ token: ThumbsStageToken,
2972
+ className: "flex-1",
2973
+ style: { position: "relative" },
2974
+ overlay: shownDrop ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2975
+ "aria-hidden": true,
2976
+ className: "bg-accent pointer-events-none absolute rounded-full",
2977
+ style: {
2978
+ left: shownDrop.line.x,
2979
+ top: shownDrop.line.y,
2980
+ width: shownDrop.line.width,
2981
+ height: shownDrop.line.height
2982
+ }
2983
+ }) : null,
2984
+ pageChrome: (page) => {
2985
+ const number = page.ref.objectNumber;
2986
+ const isSelected = editable && selectedPages.has(number);
2987
+ const isCurrent = page.pageIndex === currentPage;
2988
+ const isFocused = listFocused && focusedRef?.objectNumber === number;
2989
+ const isMoving = dragging && drag.moving.has(number);
2990
+ const label = t("thumbnails.page", { params: { page: page.pageIndex + 1 } });
2991
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2992
+ className: "group",
2993
+ style: {
2994
+ position: "absolute",
2995
+ inset: 0
2996
+ },
2997
+ children: [
2998
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2999
+ type: "button",
3000
+ id: `${idPrefix}-${number}`,
3001
+ role: "option",
3002
+ "aria-selected": editable ? isSelected : isCurrent,
3003
+ "aria-current": isCurrent ? "page" : void 0,
3004
+ "aria-label": label,
3005
+ tabIndex: -1,
3006
+ title: label,
3007
+ onClick: (event) => onPageClick(page.ref, page.pageIndex, event),
3008
+ onPointerDown: (event) => onPagePointerDown(page.ref, event),
3009
+ onContextMenu: (event) => {
3010
+ if (!editable) return;
3011
+ event.preventDefault();
3012
+ onMenu(page.ref);
3013
+ openMenuOf(number);
3014
+ },
3015
+ className: `box-border cursor-pointer touch-manipulation rounded ${isSelected || isCurrent ? "border-accent border-2" : "border-border-subtle border"} ${isCurrent ? "ring-accent-light ring-2" : ""} ${isSelected ? "bg-accent/10" : ""} ${isFocused ? "outline-accent outline outline-2 outline-offset-2" : ""} ${isMoving ? "bg-surface/60" : ""}`,
3016
+ style: {
3017
+ position: "absolute",
3018
+ top: page.frame.top,
3019
+ left: page.frame.left,
3020
+ right: page.frame.right,
3021
+ bottom: page.frame.bottom
3022
+ }
3023
+ }),
3024
+ editable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3025
+ "data-epdf-page-menu": number,
3026
+ onClick: (event) => event.stopPropagation(),
3027
+ onPointerDownCapture: () => onMenu(page.ref),
3028
+ className: `bg-elevated absolute rounded shadow-sm ${isSelected || isFocused ? "" : "opacity-0 focus-within:opacity-100 group-hover:opacity-100"}`,
3029
+ style: {
3030
+ top: page.frame.top + 4,
3031
+ right: page.frame.right + 4
3032
+ },
3033
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PageMenuButton, {})
3034
+ }),
3035
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3036
+ style: {
3037
+ position: "absolute",
3038
+ bottom: 0,
3039
+ left: 0,
3040
+ right: 0,
3041
+ height: page.frame.bottom,
3042
+ display: "flex",
3043
+ alignItems: "center",
3044
+ justifyContent: "center",
3045
+ fontSize: 11,
3046
+ color: "var(--epdf-text-muted)",
3047
+ pointerEvents: "none"
3048
+ },
3049
+ children: page.pageIndex + 1
3050
+ })
3051
+ ]
3052
+ });
3053
+ },
3054
+ children: () => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_embedpdf_react_render.RenderLayer, {})
3055
+ })
3056
+ })]
3057
+ });
3058
+ }
3059
+ /** A page's menu button: the page commands for the selected pages. */
3060
+ function PageMenuButton() {
3061
+ const more = (0, _embedpdf_react_commands.useCommand)("menu:page");
3062
+ if (!more.visible) return null;
3063
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_toolbar.CommandButton, {
3064
+ cmd: more,
3065
+ variant: "icon",
3066
+ run: () => void more.run()
3067
+ });
3068
+ }
3069
+ /** The header over the thumbnails while the pages can be changed: the edits, then the history. */
3070
+ function PageHeader() {
3071
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3072
+ className: "border-border-subtle flex items-center gap-1 border-b p-2",
3073
+ children: [
3074
+ HEADER_EDITS.map((id) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HeaderButton, { id }, id)),
3075
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "flex-1" }),
3076
+ HEADER_HISTORY.map((id) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HeaderButton, { id }, id))
3077
+ ]
3078
+ });
3079
+ }
3080
+ function HeaderButton({ id }) {
3081
+ const command = (0, _embedpdf_react_commands.useCommand)(id);
3082
+ if (!command.visible) return null;
3083
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_toolbar.CommandButton, {
3084
+ cmd: command,
3085
+ variant: "icon",
3086
+ run: () => void command.run()
3087
+ });
3088
+ }
3089
+ //#endregion
2520
3090
  //#region src/ui/panels.tsx
2521
3091
  /**
2522
3092
  * The layout's panels, drawn: on each side of the pages, the panel open on
@@ -2532,19 +3102,29 @@ function PanelRow({ panel, current, onPicked }) {
2532
3102
  * A panel whose button no longer shows (its feature turned off, or not
2533
3103
  * allowed) closes.
2534
3104
  */
2535
- const SearchPanel = lazyComponent(() => Promise.resolve().then(() => require("./search-panel-s9IoiOtv.cjs")).then((ui) => ui.SearchPanel));
2536
- const CommentsPanel = lazyComponent(() => Promise.resolve().then(() => require("./comments-panel-pEcQg4Vs.cjs")).then((ui) => ui.CommentsPanel));
2537
- const MeasurementSection = lazyComponent(() => Promise.resolve().then(() => require("./measurement-CcCsHPOX.cjs")).then((ui) => ui.MeasurementSection));
2538
- const AnnotationStylePanel = lazyComponent(() => Promise.resolve().then(() => require("./annotation-style-Bzvvp8-N.cjs")).then((ui) => ui.AnnotationStylePanel));
2539
- const StampsPanel = lazyComponent(() => Promise.resolve().then(() => require("./stamps-panel-B9NYGayn.cjs")).then((ui) => ui.StampsPanel));
2540
- const SignaturesPanel = lazyComponent(() => Promise.resolve().then(() => require("./signatures-panel-B56PC6d9.cjs")).then((ui) => ui.SignaturesPanel));
2541
- const RedactionPanel = lazyComponent(() => Promise.resolve().then(() => require("./redaction-panel-BmoIl-Ll.cjs")).then((ui) => ui.RedactionPanel));
2542
- const FormDesignPanel = lazyComponent(() => Promise.resolve().then(() => require("./form-design-panel-B5MXTZ96.cjs")).then((ui) => ui.FormDesignPanel));
3105
+ const SearchPanel = lazyComponent(() => Promise.resolve().then(() => require("./search-panel-wcbTNG1z.cjs")).then((ui) => ui.SearchPanel));
3106
+ const CommentsPanel = lazyComponent(() => Promise.resolve().then(() => require("./comments-panel-BsnWedTh.cjs")).then((ui) => ui.CommentsPanel));
3107
+ const MeasurementSection = lazyComponent(() => Promise.resolve().then(() => require("./measurement-Cxv1Ahxx.cjs")).then((ui) => ui.MeasurementSection));
3108
+ const AnnotationStylePanel = lazyComponent(() => Promise.resolve().then(() => require("./annotation-style-B3XKAyZ-.cjs")).then((ui) => ui.AnnotationStylePanel));
3109
+ const StampsPanel = lazyComponent(() => Promise.resolve().then(() => require("./stamps-panel-Cv9nJBwx.cjs")).then((ui) => ui.StampsPanel));
3110
+ const SignaturesPanel = lazyComponent(() => Promise.resolve().then(() => require("./signatures-panel-Ci_LaI1C.cjs")).then((ui) => ui.SignaturesPanel));
3111
+ const RedactionPanel = lazyComponent(() => Promise.resolve().then(() => require("./redaction-panel-ZhX0dlMi.cjs")).then((ui) => ui.RedactionPanel));
3112
+ const OutlinePanel = lazyComponent(() => Promise.resolve().then(() => require("./outline-panel-BpGtBdj0.cjs")).then((ui) => ui.OutlinePanel));
3113
+ const AttachmentsPanel = lazyComponent(() => Promise.resolve().then(() => require("./attachments-panel-Cxln8xos.cjs")).then((ui) => ui.AttachmentsPanel));
3114
+ const FormDesignPanel = lazyComponent(() => Promise.resolve().then(() => require("./form-design-panel-D0FdmWXW.cjs")).then((ui) => ui.FormDesignPanel));
2543
3115
  const BUILT_IN_CONTENT = /* @__PURE__ */ new Map([
2544
3116
  ["thumbnails", {
2545
3117
  draw: () => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ThumbnailList, {}),
2546
3118
  list: true
2547
3119
  }],
3120
+ ["outline", {
3121
+ draw: (documentId) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OutlinePanel, {}, documentId ?? "none"),
3122
+ list: true
3123
+ }],
3124
+ ["attachments", {
3125
+ draw: (documentId) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AttachmentsPanel, {}, documentId ?? "none"),
3126
+ list: true
3127
+ }],
2548
3128
  ["search", {
2549
3129
  draw: (documentId) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SearchPanel, {}, documentId ?? "none"),
2550
3130
  list: true
@@ -2625,51 +3205,6 @@ function OpenPanel({ id, side, siblings }) {
2625
3205
  })
2626
3206
  });
2627
3207
  }
2628
- function ThumbnailList() {
2629
- const t = (0, _embedpdf_react_i18n.useT)();
2630
- const main = (0, _embedpdf_react_stage.useStage)();
2631
- const thumbs = (0, _embedpdf_react_stage.useStage)(ThumbsStageToken);
2632
- const currentPage = (0, _embedpdf_react_stage.useStageState)((state) => state.currentPageIndex);
2633
- const closeOnPick = require_sheet.useCloseOnPick();
2634
- (0, react.useEffect)(() => thumbs.reveal(currentPage), [currentPage, thumbs]);
2635
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_embedpdf_react_stage.Stage, {
2636
- token: ThumbsStageToken,
2637
- className: "flex-1",
2638
- style: { position: "relative" },
2639
- pageChrome: (page) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2640
- type: "button",
2641
- onClick: () => {
2642
- main.goToPage(page.pageIndex);
2643
- closeOnPick();
2644
- },
2645
- title: t("thumbnails.page", { params: { page: page.pageIndex + 1 } }),
2646
- className: `box-border cursor-pointer rounded ${page.pageIndex === currentPage ? "border-accent ring-accent-light border-2 ring-2" : "border-border-subtle border"}`,
2647
- style: {
2648
- position: "absolute",
2649
- top: page.frame.top,
2650
- left: page.frame.left,
2651
- right: page.frame.right,
2652
- bottom: page.frame.bottom
2653
- }
2654
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2655
- style: {
2656
- position: "absolute",
2657
- bottom: 0,
2658
- left: 0,
2659
- right: 0,
2660
- height: page.frame.bottom,
2661
- display: "flex",
2662
- alignItems: "center",
2663
- justifyContent: "center",
2664
- fontSize: 11,
2665
- color: "var(--epdf-text-muted)",
2666
- pointerEvents: "none"
2667
- },
2668
- children: page.pageIndex + 1
2669
- })] }),
2670
- children: () => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_embedpdf_react_render.RenderLayer, {})
2671
- });
2672
- }
2673
3208
  //#endregion
2674
3209
  //#region src/ui/placed-components.tsx
2675
3210
  /**
@@ -2992,7 +3527,8 @@ const GROUPS = [
2992
3527
  "selection",
2993
3528
  "annotation",
2994
3529
  "redaction",
2995
- "measurement"
3530
+ "measurement",
3531
+ "outline"
2996
3532
  ]
2997
3533
  }
2998
3534
  ];
@@ -3082,6 +3618,18 @@ function ShortcutsList({ onClose }) {
3082
3618
  });
3083
3619
  }
3084
3620
  //#endregion
3621
+ //#region src/ui/sidebar-reads.tsx
3622
+ /**
3623
+ * Once a document shows: read its outline and its attachments, so their panels' buttons know
3624
+ * whether the panels have a job (`config/panels.ts`). Reading a plugin's state is what reads it;
3625
+ * a viewer without the plugin reads nothing. Mounted once per document view; renders nothing.
3626
+ */
3627
+ function SidebarReads() {
3628
+ (0, _embedpdf_react_outline.useOutlineState)((state) => state.status);
3629
+ (0, _embedpdf_react_attachment.useAttachmentState)((state) => state.status);
3630
+ return null;
3631
+ }
3632
+ //#endregion
3085
3633
  //#region src/ui/signature-bridge.tsx
3086
3634
  /**
3087
3635
  * The signature plugin's UI intents → shell surfaces. The plugin owns the
@@ -3409,11 +3957,15 @@ const useCalibrating = () => (0, _embedpdf_react_measurement.useMeasurementState
3409
3957
  const useSignDialogOpen = () => (0, _embedpdf_react_shell.useSurface)("signature-sign").isOpen;
3410
3958
  const useSignatureMakerOpen = () => (0, _embedpdf_react_shell.useSurface)("signature-maker").isOpen;
3411
3959
  const useSignatureInspectorOpen = () => (0, _embedpdf_react_shell.useSurface)("signature-inspector").isOpen;
3412
- const RedactConfirmModal = lazyComponent(() => Promise.resolve().then(() => require("./redact-confirm-CX_SY2ZN.cjs")).then((ui) => ui.RedactConfirmModal), { shownWhile: useRedactConfirmOpen });
3413
- const CalibrationDialog = lazyComponent(() => Promise.resolve().then(() => require("./measurement-CcCsHPOX.cjs")).then((ui) => ui.CalibrationDialog), { shownWhile: useCalibrating });
3414
- const SignDialog = lazyComponent(() => Promise.resolve().then(() => require("./sign-dialog-CgnR7akj.cjs")).then((ui) => ui.SignDialog), { shownWhile: useSignDialogOpen });
3415
- const SignatureMakerModal = lazyComponent(() => Promise.resolve().then(() => require("./signature-maker-BoYa8vgA.cjs")).then((ui) => ui.SignatureMakerModal), { shownWhile: useSignatureMakerOpen });
3416
- const SignatureInspector = lazyComponent(() => Promise.resolve().then(() => require("./signature-inspector-DyO313Qf.cjs")).then((ui) => ui.SignatureInspector), { shownWhile: useSignatureInspectorOpen });
3960
+ const usePrintDialogOpen = () => (0, _embedpdf_react_shell.useSurface)("print").isOpen;
3961
+ const RedactConfirmModal = lazyComponent(() => Promise.resolve().then(() => require("./redact-confirm-C6EiK8yN.cjs")).then((ui) => ui.RedactConfirmModal), { shownWhile: useRedactConfirmOpen });
3962
+ const CalibrationDialog = lazyComponent(() => Promise.resolve().then(() => require("./measurement-Cxv1Ahxx.cjs")).then((ui) => ui.CalibrationDialog), { shownWhile: useCalibrating });
3963
+ const SignDialog = lazyComponent(() => Promise.resolve().then(() => require("./sign-dialog-D5WGx-Yn.cjs")).then((ui) => ui.SignDialog), { shownWhile: useSignDialogOpen });
3964
+ const SignatureMakerModal = lazyComponent(() => Promise.resolve().then(() => require("./signature-maker-D_YfBXLn.cjs")).then((ui) => ui.SignatureMakerModal), { shownWhile: useSignatureMakerOpen });
3965
+ const SignatureInspector = lazyComponent(() => Promise.resolve().then(() => require("./signature-inspector-Bz6TAfZM.cjs")).then((ui) => ui.SignatureInspector), { shownWhile: useSignatureInspectorOpen });
3966
+ const PrintDialog = lazyComponent(() => Promise.resolve().then(() => require("./print-dialog-BqIrHCBh.cjs")).then((ui) => ui.PrintDialog), { shownWhile: usePrintDialogOpen });
3967
+ const useOutlinePropertiesOpen = () => (0, _embedpdf_react_shell.useSurface)(require_commands.OUTLINE_PROPERTIES_DIALOG).isOpen;
3968
+ const OutlinePropertiesDialog = lazyComponent(() => Promise.resolve().then(() => require("./outline-properties-DT3FIxCw.cjs")).then((ui) => ui.OutlinePropertiesDialog), { shownWhile: useOutlinePropertiesOpen });
3417
3969
  /** The document tabs, as the layout says: always, while more than one document is open, or never. */
3418
3970
  function DocumentTabs() {
3419
3971
  const visibility = (0, _embedpdf_core_ui.tabsOf)(require_icons.useResolvedLayout().data);
@@ -3538,8 +4090,11 @@ function Shell({ components }) {
3538
4090
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RedactConfirmModal, {}),
3539
4091
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CalibrationDialog, {}),
3540
4092
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(GoToPageDialog, {}),
4093
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PrintDialog, {}),
4094
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OutlinePropertiesDialog, {}),
3541
4095
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ShortcutsSheet, {}),
3542
4096
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SignatureBridge, {}),
4097
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SidebarReads, {}),
3543
4098
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FeaturePrefetch, {}),
3544
4099
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SignDialog, {}),
3545
4100
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SignatureMakerModal, {})
@@ -3717,6 +4272,8 @@ function FullViewer({ engine, initialDocuments, fallback, commands, icons, strin
3717
4272
  (0, _embedpdf_react_render.renderPlugin)(settings.render),
3718
4273
  (0, _embedpdf_react_page_edit.pageEditPlugin)(),
3719
4274
  (0, _embedpdf_react_metadata.metadataPlugin)(),
4275
+ (0, _embedpdf_react_outline.outlinePlugin)(),
4276
+ (0, _embedpdf_react_attachment.attachmentPlugin)(),
3720
4277
  (0, _embedpdf_react_interaction.interactionPlugin)(settings.interaction),
3721
4278
  (0, _embedpdf_react_interaction.feedbackPlugin)({ provider: _embedpdf_react_interaction.vibrationFeedback }),
3722
4279
  (0, _embedpdf_react_selection.selectionPlugin)(settings.selection),
@@ -3787,8 +4344,8 @@ function FullViewer({ engine, initialDocuments, fallback, commands, icons, strin
3787
4344
  ...resolved.plugins.own.map(({ plugin }) => plugin)
3788
4345
  ]);
3789
4346
  const config = resolved;
3790
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ThemeProvider, {
3791
- preference: themeConfigOf(theme).preference,
4347
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_theme.ThemeProvider, {
4348
+ preference: require_theme.themeConfigOf(theme).preference,
3792
4349
  target: themeTarget,
3793
4350
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_embedpdf_react_runtime.Viewer, {
3794
4351
  engine,
@@ -3839,6 +4396,12 @@ Object.defineProperty(exports, "AnnotationToken", {
3839
4396
  return _embedpdf_react_annotation.AnnotationToken;
3840
4397
  }
3841
4398
  });
4399
+ Object.defineProperty(exports, "AttachmentToken", {
4400
+ enumerable: true,
4401
+ get: function() {
4402
+ return _embedpdf_react_attachment.AttachmentToken;
4403
+ }
4404
+ });
3842
4405
  Object.defineProperty(exports, "CommandsToken", {
3843
4406
  enumerable: true,
3844
4407
  get: function() {
@@ -3888,6 +4451,12 @@ Object.defineProperty(exports, "MetadataToken", {
3888
4451
  return _embedpdf_react_metadata.MetadataToken;
3889
4452
  }
3890
4453
  });
4454
+ Object.defineProperty(exports, "OutlineToken", {
4455
+ enumerable: true,
4456
+ get: function() {
4457
+ return _embedpdf_react_outline.OutlineToken;
4458
+ }
4459
+ });
3891
4460
  Object.defineProperty(exports, "PageEditToken", {
3892
4461
  enumerable: true,
3893
4462
  get: function() {
@@ -3942,7 +4511,7 @@ Object.defineProperty(exports, "StampToken", {
3942
4511
  return _embedpdf_react_stamp.StampToken;
3943
4512
  }
3944
4513
  });
3945
- exports.THEME_TOKENS = THEME_TOKENS;
4514
+ exports.THEME_TOKENS = require_theme.THEME_TOKENS;
3946
4515
  exports.TOOLBAR_ITEM_CONTEXT_ATTRIBUTES = require_toolbar.TOOLBAR_ITEM_CONTEXT_ATTRIBUTES;
3947
4516
  exports.VIEWER_PLUGINS = VIEWER_PLUGINS;
3948
4517
  Object.defineProperty(exports, "createLayout", {
@@ -3986,8 +4555,8 @@ Object.defineProperty(exports, "remoteSigner", {
3986
4555
  return _embedpdf_react_signature.remoteSigner;
3987
4556
  }
3988
4557
  });
3989
- exports.themeConfigOf = themeConfigOf;
3990
- exports.themeTokenCss = themeTokenCss;
4558
+ exports.themeConfigOf = require_theme.themeConfigOf;
4559
+ exports.themeTokenCss = require_theme.themeTokenCss;
3991
4560
  Object.defineProperty(exports, "webCryptoSigner", {
3992
4561
  enumerable: true,
3993
4562
  get: function() {