@ohif/app 3.10.0-beta.8 → 3.10.0-beta.80

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 (242) hide show
  1. package/dist/{1520.bundle.8138f1baf81233ac0ce1.js → 1395.bundle.8176cda4db90bc91a0b5.js} +1236 -609
  2. package/dist/{717.bundle.1c2404038dcfde78da8a.js → 1919.bundle.42923d5d2f27680765de.js} +289 -28
  3. package/dist/{1801.css → 1919.css} +0 -1
  4. package/dist/{1927.bundle.c08eed6a2faeed833931.js → 1927.bundle.81b7ac9fa6e3ae8aba5a.js} +3 -3
  5. package/dist/{213.bundle.52a9aa1cf72345a59a87.js → 213.bundle.9ebbaab968df3804c41d.js} +2 -2
  6. package/dist/{2424.bundle.f0f304a4b1966515f188.js → 2424.bundle.6fced125a11549e7a7b0.js} +2 -2
  7. package/dist/{2701.bundle.46f7148916e85e1cf4f4.js → 2701.bundle.835eb3e0006bcfb85469.js} +76 -89
  8. package/dist/{8523.bundle.648334132159465cdc41.js → 2712.bundle.c699447e74e43c93de8c.js} +15416 -14136
  9. package/dist/{2825.bundle.dbae71a20f0a97feb283.js → 2825.bundle.11a5f9c94fce2eaa6011.js} +190 -169
  10. package/dist/{4571.bundle.a838b008320a4c3b6d40.js → 3353.bundle.7b884aa0f7a26146cbed.js} +624 -566
  11. package/dist/{3677.bundle.b3ac66bea976765cde72.js → 3677.bundle.d3c30c37d00fc58b4442.js} +846 -0
  12. package/dist/{4202.bundle.1311396ecdb6c0b09eb0.js → 4202.bundle.0bd2c1e4f2a3c55f4404.js} +6 -3
  13. package/dist/{8295.bundle.14cddaccdcd3a7093398.js → 4526.bundle.7d643ae29b3ac24f4972.js} +37 -18
  14. package/dist/4526.css +1 -0
  15. package/dist/4759.bundle.f4683c6bbb72fd79db48.js +269 -0
  16. package/dist/{4834.bundle.3e828d6d761bd65a5b82.js → 4834.bundle.9ac6bfd81e47b81a7b74.js} +4 -2
  17. package/dist/{967.bundle.fee0d6c1e9e244ad5bb3.js → 4991.bundle.3e1460e703ed405e44d1.js} +274 -1
  18. package/dist/{3900.bundle.0df808a5e65ca15f8794.js → 5038.bundle.ba16b298b06579c34e6f.js} +2644 -1644
  19. package/dist/{5247.bundle.6849abfbe09a7540f358.js → 5247.bundle.91eadb4cf817594d55b1.js} +10 -8
  20. package/dist/5674.bundle.c12a7e754ef95a8123ab.js +269 -0
  21. package/dist/{3200.css → 5674.css} +0 -1
  22. package/dist/{5823.bundle.c4aac836954d54e38b4e.js → 573.bundle.d08dcb8e65e3b7729b58.js} +25 -856
  23. package/dist/{5687.bundle.ed091049bbae4b733e8d.js → 5770.bundle.803fdc3f05ffbcb07763.js} +1203 -1153
  24. package/dist/{1374.bundle.39504ff7280f7a98e907.js → 6027.bundle.6a8206ef297b237bc5fd.js} +9 -7
  25. package/dist/{5139.bundle.472e964beb4f1a768bfd.js → 6201.bundle.09453cb0bc5bc9071380.js} +7 -7
  26. package/dist/{1266.css → 6201.css} +0 -1
  27. package/dist/{1266.bundle.ed26e46d64c406e6bb90.js → 6734.bundle.24f57935b90568978f81.js} +14 -38
  28. package/dist/{3198.css → 6734.css} +0 -1
  29. package/dist/{3970.bundle.5e5da5ca8ecc9e6e9da6.js → 6896.bundle.e0149d4d95293b20e3dc.js} +543 -21
  30. package/dist/{7197.bundle.2f4838b95e5384a2c348.js → 7197.bundle.96981a98a7d19cab8784.js} +10 -10
  31. package/dist/{1185.bundle.770f9fc106b2ca6eba5f.js → 7490.bundle.88a76c5a01ec0bf89296.js} +11320 -10570
  32. package/dist/{7955.bundle.1d17b3b51bcd3d22dbf2.js → 7955.bundle.4c6f05831be2f3294de6.js} +16 -26
  33. package/dist/{8008.bundle.aa3fb269780462d5ec44.js → 8008.bundle.ae19d8c87355be5c0698.js} +4 -2
  34. package/dist/{3198.bundle.97bb448150dbe71177c1.js → 810.bundle.4d39b796975922bf3bc4.js} +26 -18
  35. package/dist/810.css +3 -0
  36. package/dist/{8228.bundle.0c1f0d650adb9be44119.js → 8228.bundle.069dfcd6b11f7f774340.js} +10 -28
  37. package/dist/{8259.bundle.43f290345d498e11596f.js → 8259.bundle.f9b64a0bfd3a0dc7a01e.js} +14 -9
  38. package/dist/8402.css +3 -0
  39. package/dist/{8558.bundle.ed85dc17fcc2b22d82bf.js → 8558.bundle.70ab1862605fdd0ab44a.js} +14 -5
  40. package/dist/{3200.bundle.9bec1fd1e061e052869c.js → 870.bundle.394dd6238e46baac8d75.js} +107 -125
  41. package/dist/870.css +3 -0
  42. package/dist/{9611.bundle.adf2bcfdeed6861d736f.js → 9026.bundle.b8a3e1be70effe7ebe86.js} +491 -894
  43. package/dist/{9611.css → 9026.css} +1 -0
  44. package/dist/{5252.bundle.5149fccf46e44c2d3360.js → 9113.bundle.ea06cd5c0417be2096fd.js} +891 -311
  45. package/dist/{8104.bundle.203cbb0887b16ff49142.js → 9196.bundle.23880ce013c5d3794c88.js} +19904 -912
  46. package/dist/{9551.bundle.1c000aebaff640a6da03.js → 9551.bundle.0227d4d2f618b0bd8ddf.js} +13 -24
  47. package/dist/{5717.bundle.eacd161b081fcca2162c.js → 9677.bundle.d09a4e387931be7c1804.js} +3549 -959
  48. package/dist/{9862.bundle.335b4016d36d81d959b5.js → 9862.bundle.ab8b2aeb9a77e016d61d.js} +25 -35
  49. package/dist/{3121.bundle.67ff7e799683191bb324.js → 9890.bundle.fa30fef9d54652d5980a.js} +41 -21
  50. package/dist/9890.css +3 -0
  51. package/dist/app-config.js +98 -2
  52. package/dist/app.bundle.css +5 -4
  53. package/dist/{app.bundle.f3350dde8c0fcb7047e5.js → app.bundle.dfc4886c9d805b72c3f6.js} +87792 -100025
  54. package/dist/{histogram-worker.bundle.85d57affe3baefc07925.js → histogram-worker.bundle.f978654858500a3080cc.js} +3 -3
  55. package/dist/index.html +4 -2
  56. package/dist/{polySeg.bundle.c369de6e297794c8b39f.js → polySeg.bundle.4c7da20a2061038ede40.js} +3 -3
  57. package/dist/serve.json +1 -10
  58. package/dist/{suv-peak-worker.bundle.30144a40940ad001040b.js → suv-peak-worker.bundle.6b3b00ebe4bba9f01673.js} +4 -4
  59. package/dist/sw.js +1 -1
  60. package/package.json +20 -19
  61. package/dist/4182.css +0 -4
  62. package/dist/5139.css +0 -4
  63. package/dist/717.css +0 -4
  64. package/dist/assets/images/action-new-dialog.svg +0 -14
  65. package/dist/assets/images/arrow-down.svg +0 -5
  66. package/dist/assets/images/arrow-left-small.svg +0 -6
  67. package/dist/assets/images/arrow-left.svg +0 -6
  68. package/dist/assets/images/arrow-right-small.svg +0 -6
  69. package/dist/assets/images/arrow-right.svg +0 -6
  70. package/dist/assets/images/calendar.svg +0 -5
  71. package/dist/assets/images/cancel.svg +0 -8
  72. package/dist/assets/images/checkbox-active.svg +0 -9
  73. package/dist/assets/images/checkbox-checked.svg +0 -9
  74. package/dist/assets/images/checkbox-default.svg +0 -3
  75. package/dist/assets/images/checkbox-unchecked.svg +0 -3
  76. package/dist/assets/images/chevron-down.svg +0 -3
  77. package/dist/assets/images/chevron-left.svg +0 -3
  78. package/dist/assets/images/chevron-menu.svg +0 -12
  79. package/dist/assets/images/chevron-next.svg +0 -6
  80. package/dist/assets/images/chevron-prev.svg +0 -6
  81. package/dist/assets/images/chevron-right.svg +0 -3
  82. package/dist/assets/images/circled-checkmark.svg +0 -6
  83. package/dist/assets/images/clipboard.svg +0 -1
  84. package/dist/assets/images/closeIcon.svg +0 -3
  85. package/dist/assets/images/content-next.svg +0 -9
  86. package/dist/assets/images/content-prev.svg +0 -9
  87. package/dist/assets/images/database.svg +0 -8
  88. package/dist/assets/images/dotted-circle.svg +0 -3
  89. package/dist/assets/images/edit-patient.svg +0 -15
  90. package/dist/assets/images/exclamation.svg +0 -9
  91. package/dist/assets/images/external-link.svg +0 -5
  92. package/dist/assets/images/eye-hidden.svg +0 -8
  93. package/dist/assets/images/eye-visible.svg +0 -6
  94. package/dist/assets/images/focus-frame-target.svg +0 -13
  95. package/dist/assets/images/group-layers.svg +0 -6
  96. package/dist/assets/images/icon-add.svg +0 -15
  97. package/dist/assets/images/icon-alert-small.svg +0 -8
  98. package/dist/assets/images/icon-chevron-patient.svg +0 -12
  99. package/dist/assets/images/icon-clear-field.svg +0 -8
  100. package/dist/assets/images/icon-close.svg +0 -8
  101. package/dist/assets/images/icon-color-lut.svg +0 -23
  102. package/dist/assets/images/icon-delete.svg +0 -17
  103. package/dist/assets/images/icon-disclosure-close.svg +0 -12
  104. package/dist/assets/images/icon-disclosure-open.svg +0 -12
  105. package/dist/assets/images/icon-display-settings.svg +0 -21
  106. package/dist/assets/images/icon-more-menu.svg +0 -17
  107. package/dist/assets/images/icon-mpr-alt.svg +0 -9
  108. package/dist/assets/images/icon-multiple-patients.svg +0 -21
  109. package/dist/assets/images/icon-next-inactive.svg +0 -6
  110. package/dist/assets/images/icon-next.svg +0 -6
  111. package/dist/assets/images/icon-patient.svg +0 -13
  112. package/dist/assets/images/icon-pause.svg +0 -6
  113. package/dist/assets/images/icon-play.svg +0 -6
  114. package/dist/assets/images/icon-prev-inactive.svg +0 -6
  115. package/dist/assets/images/icon-prev.svg +0 -6
  116. package/dist/assets/images/icon-rename.svg +0 -15
  117. package/dist/assets/images/icon-search.svg +0 -9
  118. package/dist/assets/images/icon-settings.svg +0 -13
  119. package/dist/assets/images/icon-status-alert.svg +0 -8
  120. package/dist/assets/images/icon-tool-scissor.svg +0 -17
  121. package/dist/assets/images/icon-toolbar-back.svg +0 -12
  122. package/dist/assets/images/icon-transferring.svg +0 -6
  123. package/dist/assets/images/icon-upload.svg +0 -6
  124. package/dist/assets/images/icons-alert-outline.svg +0 -8
  125. package/dist/assets/images/illustration-investigational-use.svg +0 -20
  126. package/dist/assets/images/info-action.svg +0 -10
  127. package/dist/assets/images/info-link.svg +0 -7
  128. package/dist/assets/images/info.svg +0 -3
  129. package/dist/assets/images/launch-arrow.svg +0 -7
  130. package/dist/assets/images/launch-info.svg +0 -8
  131. package/dist/assets/images/layout-advanced-3d-four-up.svg +0 -13
  132. package/dist/assets/images/layout-advanced-3d-main.svg +0 -12
  133. package/dist/assets/images/layout-advanced-3d-only.svg +0 -9
  134. package/dist/assets/images/layout-advanced-3d-primary.svg +0 -12
  135. package/dist/assets/images/layout-advanced-axial-primary.svg +0 -11
  136. package/dist/assets/images/layout-advanced-mpr.svg +0 -11
  137. package/dist/assets/images/layout-common-1x1.svg +0 -9
  138. package/dist/assets/images/layout-common-1x2.svg +0 -10
  139. package/dist/assets/images/layout-common-2x2.svg +0 -11
  140. package/dist/assets/images/layout-common-2x3.svg +0 -12
  141. package/dist/assets/images/list-bullets.svg +0 -10
  142. package/dist/assets/images/loading-ohif-mark.svg +0 -5
  143. package/dist/assets/images/lock.svg +0 -1
  144. package/dist/assets/images/logo-ohif-small.svg +0 -5
  145. package/dist/assets/images/magnifier.svg +0 -7
  146. package/dist/assets/images/navigation-panel-right-hide.svg +0 -5
  147. package/dist/assets/images/navigation-panel-right-reveal.svg +0 -5
  148. package/dist/assets/images/next-arrow.svg +0 -12
  149. package/dist/assets/images/notifications-error.svg +0 -8
  150. package/dist/assets/images/notifications-info.svg +0 -8
  151. package/dist/assets/images/notifications-success.svg +0 -6
  152. package/dist/assets/images/notifications-warning.svg +0 -8
  153. package/dist/assets/images/notificationwarning-diamond.svg +0 -10
  154. package/dist/assets/images/ohif-logo-color-darkbg.svg +0 -20
  155. package/dist/assets/images/ohif-logo.svg +0 -18
  156. package/dist/assets/images/old-play.svg +0 -9
  157. package/dist/assets/images/old-stop.svg +0 -9
  158. package/dist/assets/images/old-trash.svg +0 -9
  159. package/dist/assets/images/panel-group-more.svg +0 -6
  160. package/dist/assets/images/panel-group-open-close.svg +0 -6
  161. package/dist/assets/images/pencil.svg +0 -4
  162. package/dist/assets/images/power-off.svg +0 -11
  163. package/dist/assets/images/prev-arrow.svg +0 -12
  164. package/dist/assets/images/profile.svg +0 -1
  165. package/dist/assets/images/push-left.svg +0 -5
  166. package/dist/assets/images/push-right.svg +0 -5
  167. package/dist/assets/images/row-add.svg +0 -8
  168. package/dist/assets/images/row-edit.svg +0 -9
  169. package/dist/assets/images/row-hidden.svg +0 -11
  170. package/dist/assets/images/row-lock.svg +0 -7
  171. package/dist/assets/images/row-shown.svg +0 -9
  172. package/dist/assets/images/row-unlock.svg +0 -7
  173. package/dist/assets/images/settings.svg +0 -6
  174. package/dist/assets/images/side-panel-close-left.svg +0 -14
  175. package/dist/assets/images/side-panel-close-right.svg +0 -14
  176. package/dist/assets/images/sorting-active-down.svg +0 -6
  177. package/dist/assets/images/sorting-active-up.svg +0 -6
  178. package/dist/assets/images/sorting.svg +0 -6
  179. package/dist/assets/images/status-alert-warning.svg +0 -9
  180. package/dist/assets/images/status-alert.svg +0 -7
  181. package/dist/assets/images/status-locked.svg +0 -7
  182. package/dist/assets/images/status-tracked.svg +0 -7
  183. package/dist/assets/images/status-untracked.svg +0 -6
  184. package/dist/assets/images/tab-4d.svg +0 -13
  185. package/dist/assets/images/tab-linear.svg +0 -8
  186. package/dist/assets/images/tab-patient-info.svg +0 -7
  187. package/dist/assets/images/tab-roi-threshold.svg +0 -10
  188. package/dist/assets/images/tab-segmentation.svg +0 -11
  189. package/dist/assets/images/tab-studies.svg +0 -13
  190. package/dist/assets/images/tool-3d-rotate.svg +0 -20
  191. package/dist/assets/images/tool-angle.svg +0 -12
  192. package/dist/assets/images/tool-annotate.svg +0 -11
  193. package/dist/assets/images/tool-bidirectional.svg +0 -21
  194. package/dist/assets/images/tool-calibrate.svg +0 -19
  195. package/dist/assets/images/tool-capture.svg +0 -10
  196. package/dist/assets/images/tool-cine.svg +0 -9
  197. package/dist/assets/images/tool-circle.svg +0 -8
  198. package/dist/assets/images/tool-cobb-angle.svg +0 -14
  199. package/dist/assets/images/tool-create-threshold.svg +0 -9
  200. package/dist/assets/images/tool-crosshair.svg +0 -14
  201. package/dist/assets/images/tool-dicom-tag-browser.svg +0 -15
  202. package/dist/assets/images/tool-flip-horizontal.svg +0 -10
  203. package/dist/assets/images/tool-freehand-polygon.svg +0 -37
  204. package/dist/assets/images/tool-freehand-roi.svg +0 -12
  205. package/dist/assets/images/tool-freehand.svg +0 -34
  206. package/dist/assets/images/tool-fusion-color.svg +0 -13
  207. package/dist/assets/images/tool-invert.svg +0 -10
  208. package/dist/assets/images/tool-layout-default.svg +0 -22
  209. package/dist/assets/images/tool-length.svg +0 -16
  210. package/dist/assets/images/tool-magnetic-roi.svg +0 -17
  211. package/dist/assets/images/tool-magnify.svg +0 -7
  212. package/dist/assets/images/tool-measure-elipse.svg +0 -12
  213. package/dist/assets/images/tool-more-menu.svg +0 -6
  214. package/dist/assets/images/tool-move.svg +0 -13
  215. package/dist/assets/images/tool-polygon.svg +0 -3
  216. package/dist/assets/images/tool-quick-magnify.svg +0 -11
  217. package/dist/assets/images/tool-rectangle.svg +0 -12
  218. package/dist/assets/images/tool-reference-lines.svg +0 -13
  219. package/dist/assets/images/tool-reset.svg +0 -9
  220. package/dist/assets/images/tool-rotate-right.svg +0 -12
  221. package/dist/assets/images/tool-seg-brush.svg +0 -9
  222. package/dist/assets/images/tool-seg-eraser.svg +0 -10
  223. package/dist/assets/images/tool-seg-shape.svg +0 -9
  224. package/dist/assets/images/tool-seg-threshold.svg +0 -17
  225. package/dist/assets/images/tool-spline-roi.svg +0 -14
  226. package/dist/assets/images/tool-stack-image-sync.svg +0 -10
  227. package/dist/assets/images/tool-stack-scroll.svg +0 -10
  228. package/dist/assets/images/tool-toggle-dicom-overlay.svg +0 -9
  229. package/dist/assets/images/tool-ultrasound-bidirectional.svg +0 -15
  230. package/dist/assets/images/tool-window-level.svg +0 -9
  231. package/dist/assets/images/tool-window-region.svg +0 -12
  232. package/dist/assets/images/tool-zoom.svg +0 -9
  233. package/dist/assets/images/tracked.svg +0 -6
  234. package/dist/assets/images/ui-arrow-down.svg +0 -3
  235. package/dist/assets/images/ui-arrow-left.svg +0 -3
  236. package/dist/assets/images/ui-arrow-right.svg +0 -3
  237. package/dist/assets/images/ui-arrow-up.svg +0 -3
  238. package/dist/assets/images/unlink.svg +0 -9
  239. package/dist/assets/images/viewport-status-tracked.svg +0 -13
  240. package/dist/assets/images/viewport-window-level.svg +0 -17
  241. /package/dist/{3334.bundle.0e6ba24024018199ab66.js → 3334.bundle.e36011d0fd5fcb7e8b84.js} +0 -0
  242. /package/dist/{2591.css → 4759.css} +0 -0
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
- (self["webpackChunk"] = self["webpackChunk"] || []).push([[1520],{
2
+ (self["webpackChunk"] = self["webpackChunk"] || []).push([[1395],{
3
3
 
4
- /***/ 71520:
4
+ /***/ 91395:
5
5
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
6
6
 
7
7
  // ESM COMPAT FLAG
@@ -11,6 +11,7 @@ __webpack_require__.r(__webpack_exports__);
11
11
  __webpack_require__.d(__webpack_exports__, {
12
12
  ContextMenuController: () => (/* reexport */ ContextMenuController),
13
13
  CustomizableContextMenuTypes: () => (/* reexport */ types_namespaceObject),
14
+ MoreDropdownMenu: () => (/* reexport */ MoreDropdownMenu),
14
15
  PanelStudyBrowserHeader: () => (/* reexport */ PanelStudyBrowserHeader),
15
16
  StaticWadoClient: () => (/* reexport */ StaticWadoClient),
16
17
  callInputDialog: () => (/* reexport */ callInputDialog),
@@ -24,12 +25,13 @@ __webpack_require__.d(__webpack_exports__, {
24
25
  getStudiesForPatientByMRN: () => (/* reexport */ Panels_getStudiesForPatientByMRN),
25
26
  promptLabelAnnotation: () => (/* reexport */ utils_promptLabelAnnotation),
26
27
  promptSaveReport: () => (/* reexport */ utils_promptSaveReport),
28
+ requestDisplaySetCreationForStudy: () => (/* reexport */ Panels_requestDisplaySetCreationForStudy),
27
29
  showLabelAnnotationPopup: () => (/* reexport */ showLabelAnnotationPopup),
28
30
  useDisplaySetSelectorStore: () => (/* reexport */ useDisplaySetSelectorStore),
29
31
  useHangingProtocolStageIndexStore: () => (/* reexport */ useHangingProtocolStageIndexStore),
30
32
  usePatientInfo: () => (/* reexport */ hooks_usePatientInfo),
31
33
  useToggleHangingProtocolStore: () => (/* reexport */ useToggleHangingProtocolStore),
32
- useToggleOneUpViewportGridStore: () => (/* reexport */ useToggleOneUpViewportGridStore/* useToggleOneUpViewportGridStore */.Y),
34
+ useToggleOneUpViewportGridStore: () => (/* reexport */ useToggleOneUpViewportGridStore),
33
35
  useUIStateStore: () => (/* reexport */ useUIStateStore),
34
36
  useViewportGridStore: () => (/* reexport */ useViewportGridStore),
35
37
  useViewportsByPositionStore: () => (/* reexport */ useViewportsByPositionStore),
@@ -59,8 +61,8 @@ __webpack_require__.d(src_utils_namespaceObject, {
59
61
 
60
62
  // EXTERNAL MODULE: ../../../node_modules/dicomweb-client/build/dicomweb-client.es.js
61
63
  var dicomweb_client_es = __webpack_require__(83562);
62
- // EXTERNAL MODULE: ../../core/src/index.ts + 71 modules
63
- var src = __webpack_require__(29463);
64
+ // EXTERNAL MODULE: ../../core/src/index.ts + 73 modules
65
+ var src = __webpack_require__(10532);
64
66
  // EXTERNAL MODULE: ../../core/src/utils/sortStudy.ts
65
67
  var sortStudy = __webpack_require__(45476);
66
68
  ;// CONCATENATED MODULE: ../../../extensions/default/src/DicomWebDataSource/qido.js
@@ -270,7 +272,7 @@ function mapParams(params, options = {}) {
270
272
  }
271
273
 
272
274
  ;// CONCATENATED MODULE: ../../../extensions/default/src/DicomWebDataSource/dcm4cheeReject.js
273
- /* harmony default export */ function dcm4cheeReject(wadoRoot) {
275
+ /* harmony default export */ function dcm4cheeReject(wadoRoot, getAuthrorizationHeader) {
274
276
  return {
275
277
  series: (StudyInstanceUID, SeriesInstanceUID) => {
276
278
  return new Promise((resolve, reject) => {
@@ -279,6 +281,10 @@ function mapParams(params, options = {}) {
279
281
  const url = `${wadoRoot}/studies/${StudyInstanceUID}/series/${SeriesInstanceUID}/reject/${CodeValueAndCodeSchemeDesignator}`;
280
282
  const xhr = new XMLHttpRequest();
281
283
  xhr.open('POST', url, true);
284
+ const headers = getAuthrorizationHeader();
285
+ for (const key in headers) {
286
+ xhr.setRequestHeader(key, headers[key]);
287
+ }
282
288
 
283
289
  //Send the proper header information along with the request
284
290
  // TODO -> Auth when we re-add authorization.
@@ -469,7 +475,6 @@ class RetrieveMetadataLoader {
469
475
  // import DICOMWeb from '../../../DICOMWeb/';
470
476
 
471
477
 
472
-
473
478
  /**
474
479
  * Class for sync load of study metadata.
475
480
  * It inherits from RetrieveMetadataLoader
@@ -1069,18 +1074,33 @@ class StaticWadoClient extends dicomweb_client_es/* api */.FH.DICOMwebClient {
1069
1074
  *
1070
1075
  * @param {*} desired
1071
1076
  * @param {*} actual
1077
+ * @param {*} options - fuzzyMatching: if true, then do a sub-string match
1072
1078
  * @returns true if the values match
1073
1079
  */
1074
- compareValues(desired, actual) {
1080
+ compareValues(desired, actual, options) {
1081
+ const {
1082
+ fuzzyMatching
1083
+ } = options;
1075
1084
  if (Array.isArray(desired)) {
1076
- return desired.find(item => this.compareValues(item, actual));
1085
+ return desired.find(item => this.compareValues(item, actual, options));
1077
1086
  }
1078
1087
  if (Array.isArray(actual)) {
1079
- return actual.find(actualItem => this.compareValues(desired, actualItem));
1088
+ return actual.find(actualItem => this.compareValues(desired, actualItem, options));
1080
1089
  }
1081
1090
  if (actual?.Alphabetic) {
1082
1091
  actual = actual.Alphabetic;
1083
1092
  }
1093
+ if (fuzzyMatching && typeof actual === 'string' && typeof desired === 'string') {
1094
+ const normalizeValue = str => {
1095
+ return str.toLowerCase();
1096
+ };
1097
+ const normalizedDesired = normalizeValue(desired);
1098
+ const normalizedActual = normalizeValue(actual);
1099
+ const tokenizeAndNormalize = str => str.split(/[\s^]+/).filter(Boolean);
1100
+ const desiredTokens = tokenizeAndNormalize(normalizedDesired);
1101
+ const actualTokens = tokenizeAndNormalize(normalizedActual);
1102
+ return desiredTokens.every(desiredToken => actualTokens.some(actualToken => actualToken.startsWith(desiredToken)));
1103
+ }
1084
1104
  if (typeof actual == 'string') {
1085
1105
  if (actual.length === 0) {
1086
1106
  return true;
@@ -1107,7 +1127,7 @@ class StaticWadoClient extends dicomweb_client_es/* api */.FH.DICOMwebClient {
1107
1127
  }
1108
1128
  const dash = range.indexOf('-');
1109
1129
  if (dash === -1) {
1110
- return this.compareValues(range, value);
1130
+ return this.compareValues(range, value, {});
1111
1131
  }
1112
1132
  const start = range.substring(0, dash);
1113
1133
  const end = range.substring(dash + 1);
@@ -1124,6 +1144,13 @@ class StaticWadoClient extends dicomweb_client_es/* api */.FH.DICOMwebClient {
1124
1144
  * @returns
1125
1145
  */
1126
1146
  filterItem(key, queryParams, study, sourceFilterMap) {
1147
+ const isName = key => key.indexOf('name') !== -1;
1148
+ const {
1149
+ supportsFuzzyMatching = false
1150
+ } = this.config;
1151
+ const options = {
1152
+ fuzzyMatching: isName(key) && supportsFuzzyMatching
1153
+ };
1127
1154
  const altKey = sourceFilterMap[key] || key;
1128
1155
  if (!queryParams) {
1129
1156
  return true;
@@ -1140,7 +1167,7 @@ class StaticWadoClient extends dicomweb_client_es/* api */.FH.DICOMwebClient {
1140
1167
  return this.compareDateRange(testValue, valueElem.Value[0]);
1141
1168
  }
1142
1169
  const value = valueElem.Value;
1143
- return this.compareValues(testValue, value);
1170
+ return this.compareValues(testValue, value, options);
1144
1171
  }
1145
1172
 
1146
1173
  /** Converts the query parameters to lower case query parameters */
@@ -1383,7 +1410,7 @@ function fixBulkDataURI(value, instance, dicomWebConfig) {
1383
1410
  }
1384
1411
  }
1385
1412
 
1386
- ;// CONCATENATED MODULE: ../../../extensions/default/src/DicomWebDataSource/index.js
1413
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/DicomWebDataSource/index.ts
1387
1414
 
1388
1415
 
1389
1416
 
@@ -1406,44 +1433,22 @@ const ImplementationClassUID = '2.25.270695996825855179949881587723571202391.2.0
1406
1433
  const ImplementationVersionName = 'OHIF-VIEWER-2.0.0';
1407
1434
  const EXPLICIT_VR_LITTLE_ENDIAN = '1.2.840.10008.1.2.1';
1408
1435
  const metadataProvider = src/* classes */.Ly.MetadataProvider;
1409
-
1410
1436
  /**
1411
1437
  * Creates a DICOM Web API based on the provided configuration.
1412
1438
  *
1413
- * @param {object} dicomWebConfig - Configuration for the DICOM Web API
1414
- * @param {string} dicomWebConfig.name - Data source name
1415
- * @param {string} dicomWebConfig.wadoUriRoot - Legacy? (potentially unused/replaced)
1416
- * @param {string} dicomWebConfig.qidoRoot - Base URL to use for QIDO requests
1417
- * @param {string} dicomWebConfig.wadoRoot - Base URL to use for WADO requests
1418
- * @param {string} dicomWebConfig.wadoUri - Base URL to use for WADO URI requests
1419
- * @param {boolean} dicomWebConfig.qidoSupportsIncludeField - Whether QIDO supports the "Include" option to request additional fields in response
1420
- * @param {string} dicomWebConfig.imageRendering - wadors | ? (unsure of where/how this is used)
1421
- * @param {string} dicomWebConfig.thumbnailRendering - wadors | ? (unsure of where/how this is used)
1422
- * @param {boolean} dicomWebConfig.supportsReject - Whether the server supports reject calls (i.e. DCM4CHEE)
1423
- * @param {boolean} dicomWebConfig.lazyLoadStudy - "enableStudyLazyLoad"; Request series meta async instead of blocking
1424
- * @param {string|boolean} dicomWebConfig.singlepart - indicates if the retrieves can fetch singlepart. Options are bulkdata, video, image, or boolean true
1425
- * @param {string} dicomWebConfig.requestTransferSyntaxUID - Transfer syntax to request from the server
1426
- * @param {object} dicomWebConfig.acceptHeader - Accept header to use for requests
1427
- * @param {boolean} dicomWebConfig.omitQuotationForMultipartRequest - Whether to omit quotation marks for multipart requests
1428
- * @param {boolean} dicomWebConfig.supportsFuzzyMatching - Whether the server supports fuzzy matching
1429
- * @param {boolean} dicomWebConfig.supportsWildcard - Whether the server supports wildcard matching
1430
- * @param {boolean} dicomWebConfig.supportsNativeDICOMModel - Whether the server supports the native DICOM model
1431
- * @param {boolean} dicomWebConfig.enableStudyLazyLoad - Whether to enable study lazy loading
1432
- * @param {boolean} dicomWebConfig.enableRequestTag - Whether to enable request tag
1433
- * @param {boolean} dicomWebConfig.enableStudyLazyLoad - Whether to enable study lazy loading
1434
- * @param {boolean} dicomWebConfig.bulkDataURI - Whether to enable bulkDataURI
1435
- * @param {function} dicomWebConfig.onConfiguration - Function that is called after the configuration is initialized
1436
- * @param {boolean} dicomWebConfig.staticWado - Whether to use the static WADO client
1437
- * @param {object} userAuthenticationService - User authentication service
1438
- * @param {object} userAuthenticationService.getAuthorizationHeader - Function that returns the authorization header
1439
- * @returns {object} - DICOM Web API object
1439
+ * @param dicomWebConfig - Configuration for the DICOM Web API
1440
+ * @returns DICOM Web API object
1440
1441
  */
1441
1442
  function createDicomWebApi(dicomWebConfig, servicesManager) {
1442
1443
  const {
1443
- userAuthenticationService,
1444
- customizationService
1444
+ userAuthenticationService
1445
1445
  } = servicesManager.services;
1446
- let dicomWebConfigCopy, qidoConfig, wadoConfig, qidoDicomWebClient, wadoDicomWebClient, getAuthrorizationHeader, generateWadoHeader;
1446
+ let dicomWebConfigCopy, qidoConfig, wadoConfig, qidoDicomWebClient, wadoDicomWebClient, getAuthorizationHeader, generateWadoHeader;
1447
+ // Default to enabling bulk data retrieves, with no other customization as
1448
+ // this is part of hte base standard.
1449
+ dicomWebConfig.bulkDataURI ||= {
1450
+ enabled: true
1451
+ };
1447
1452
  const implementation = {
1448
1453
  initialize: ({
1449
1454
  params,
@@ -1456,7 +1461,7 @@ function createDicomWebApi(dicomWebConfig, servicesManager) {
1456
1461
  });
1457
1462
  }
1458
1463
  dicomWebConfigCopy = JSON.parse(JSON.stringify(dicomWebConfig));
1459
- getAuthrorizationHeader = () => {
1464
+ getAuthorizationHeader = () => {
1460
1465
  const xhrRequestHeaders = {};
1461
1466
  const authHeaders = userAuthenticationService.getAuthorizationHeader();
1462
1467
  if (authHeaders && authHeaders.Authorization) {
@@ -1465,7 +1470,7 @@ function createDicomWebApi(dicomWebConfig, servicesManager) {
1465
1470
  return xhrRequestHeaders;
1466
1471
  };
1467
1472
  generateWadoHeader = () => {
1468
- const authorizationHeader = getAuthrorizationHeader();
1473
+ const authorizationHeader = getAuthorizationHeader();
1469
1474
  //Generate accept header depending on config params
1470
1475
  const formattedAcceptHeader = src/* utils */.Wp.generateAcceptHeader(dicomWebConfig.acceptHeader, dicomWebConfig.requestTransferSyntaxUID, dicomWebConfig.omitQuotationForMultipartRequest);
1471
1476
  return {
@@ -1478,14 +1483,16 @@ function createDicomWebApi(dicomWebConfig, servicesManager) {
1478
1483
  staticWado: dicomWebConfig.staticWado,
1479
1484
  singlepart: dicomWebConfig.singlepart,
1480
1485
  headers: userAuthenticationService.getAuthorizationHeader(),
1481
- errorInterceptor: src/* errorHandler */.r_.getHTTPErrorHandler()
1486
+ errorInterceptor: src/* errorHandler */.r_.getHTTPErrorHandler(),
1487
+ supportsFuzzyMatching: dicomWebConfig.supportsFuzzyMatching
1482
1488
  };
1483
1489
  wadoConfig = {
1484
1490
  url: dicomWebConfig.wadoRoot,
1485
1491
  staticWado: dicomWebConfig.staticWado,
1486
1492
  singlepart: dicomWebConfig.singlepart,
1487
1493
  headers: userAuthenticationService.getAuthorizationHeader(),
1488
- errorInterceptor: src/* errorHandler */.r_.getHTTPErrorHandler()
1494
+ errorInterceptor: src/* errorHandler */.r_.getHTTPErrorHandler(),
1495
+ supportsFuzzyMatching: dicomWebConfig.supportsFuzzyMatching
1489
1496
  };
1490
1497
 
1491
1498
  // TODO -> Two clients sucks, but its better than 1000.
@@ -1497,7 +1504,7 @@ function createDicomWebApi(dicomWebConfig, servicesManager) {
1497
1504
  studies: {
1498
1505
  mapParams: mapParams.bind(),
1499
1506
  search: async function (origParams) {
1500
- qidoDicomWebClient.headers = getAuthrorizationHeader();
1507
+ qidoDicomWebClient.headers = getAuthorizationHeader();
1501
1508
  const {
1502
1509
  studyInstanceUid,
1503
1510
  seriesInstanceUid,
@@ -1514,7 +1521,7 @@ function createDicomWebApi(dicomWebConfig, servicesManager) {
1514
1521
  series: {
1515
1522
  // mapParams: mapParams.bind(),
1516
1523
  search: async function (studyInstanceUid) {
1517
- qidoDicomWebClient.headers = getAuthrorizationHeader();
1524
+ qidoDicomWebClient.headers = getAuthorizationHeader();
1518
1525
  const results = await seriesInStudy(qidoDicomWebClient, studyInstanceUid);
1519
1526
  return processSeriesResults(results);
1520
1527
  }
@@ -1522,7 +1529,7 @@ function createDicomWebApi(dicomWebConfig, servicesManager) {
1522
1529
  },
1523
1530
  instances: {
1524
1531
  search: (studyInstanceUid, queryParameters) => {
1525
- qidoDicomWebClient.headers = getAuthrorizationHeader();
1532
+ qidoDicomWebClient.headers = getAuthorizationHeader();
1526
1533
  return search.call(undefined, qidoDicomWebClient, studyInstanceUid, null, queryParameters);
1527
1534
  }
1528
1535
  }
@@ -1557,7 +1564,7 @@ function createDicomWebApi(dicomWebConfig, servicesManager) {
1557
1564
  StudyInstanceUID,
1558
1565
  BulkDataURI
1559
1566
  }) => {
1560
- qidoDicomWebClient.headers = getAuthrorizationHeader();
1567
+ qidoDicomWebClient.headers = getAuthorizationHeader();
1561
1568
  const options = {
1562
1569
  multipart: false,
1563
1570
  BulkDataURI,
@@ -1589,7 +1596,7 @@ function createDicomWebApi(dicomWebConfig, servicesManager) {
1589
1596
  },
1590
1597
  store: {
1591
1598
  dicom: async (dataset, request, dicomDict) => {
1592
- wadoDicomWebClient.headers = getAuthrorizationHeader();
1599
+ wadoDicomWebClient.headers = getAuthorizationHeader();
1593
1600
  if (dataset instanceof ArrayBuffer) {
1594
1601
  const options = {
1595
1602
  datasets: [dataset],
@@ -1686,7 +1693,8 @@ function createDicomWebApi(dicomWebConfig, servicesManager) {
1686
1693
  const value = naturalized[key];
1687
1694
  if (Array.isArray(value) && typeof value[0] === 'object') {
1688
1695
  // Fix recursive values
1689
- value.forEach(child => addRetrieveBulkDataNaturalized(child, instance));
1696
+ const validValues = value.filter(Boolean);
1697
+ validValues.forEach(child => addRetrieveBulkDataNaturalized(child, instance));
1690
1698
  continue;
1691
1699
  }
1692
1700
 
@@ -1726,23 +1734,35 @@ function createDicomWebApi(dicomWebConfig, servicesManager) {
1726
1734
  naturalizedInstances.forEach(instance => {
1727
1735
  instance.wadoRoot = dicomWebConfig.wadoRoot;
1728
1736
  instance.wadoUri = dicomWebConfig.wadoUri;
1729
- const imageId = implementation.getImageIdsForInstance({
1730
- instance
1731
- });
1737
+ const {
1738
+ StudyInstanceUID,
1739
+ SeriesInstanceUID,
1740
+ SOPInstanceUID
1741
+ } = instance;
1742
+ const numberOfFrames = instance.NumberOfFrames || 1;
1743
+ // Process all frames consistently, whether single or multiframe
1744
+ for (let i = 0; i < numberOfFrames; i++) {
1745
+ const frameNumber = i + 1;
1746
+ const frameImageId = implementation.getImageIdsForInstance({
1747
+ instance,
1748
+ frame: frameNumber
1749
+ });
1750
+ // Add imageId specific mapping to this data as the URL isn't necessarily WADO-URI.
1751
+ metadataProvider.addImageIdToUIDs(frameImageId, {
1752
+ StudyInstanceUID,
1753
+ SeriesInstanceUID,
1754
+ SOPInstanceUID,
1755
+ frameNumber: numberOfFrames > 1 ? frameNumber : undefined
1756
+ });
1757
+ }
1732
1758
 
1733
1759
  // Adding imageId to each instance
1734
1760
  // Todo: This is not the best way I can think of to let external
1735
1761
  // metadata handlers know about the imageId that is stored in the store
1736
- instance.imageId = imageId;
1737
-
1738
- // Adding UIDs to metadataProvider
1739
- // Note: storing imageURI in metadataProvider since stack viewports
1740
- // will use the same imageURI
1741
- metadataProvider.addImageIdToUIDs(imageId, {
1742
- StudyInstanceUID,
1743
- SeriesInstanceUID: instance.SeriesInstanceUID,
1744
- SOPInstanceUID: instance.SOPInstanceUID
1762
+ const imageId = implementation.getImageIdsForInstance({
1763
+ instance
1745
1764
  });
1765
+ instance.imageId = imageId;
1746
1766
  });
1747
1767
  src/* DicomMetadataStore */.H8.addInstances(naturalizedInstances, madeInClient);
1748
1768
  }
@@ -1821,17 +1841,15 @@ function createDicomWebApi(dicomWebConfig, servicesManager) {
1821
1841
  params,
1822
1842
  query
1823
1843
  }) {
1824
- const {
1825
- StudyInstanceUIDs: paramsStudyInstanceUIDs
1826
- } = params;
1827
- const queryStudyInstanceUIDs = src/* utils */.Wp.splitComma(query.getAll('StudyInstanceUIDs'));
1844
+ const paramsStudyInstanceUIDs = params.StudyInstanceUIDs || params.studyInstanceUIDs;
1845
+ const queryStudyInstanceUIDs = src/* utils */.Wp.splitComma(query.getAll('StudyInstanceUIDs').concat(query.getAll('studyInstanceUIDs')));
1828
1846
  const StudyInstanceUIDs = queryStudyInstanceUIDs.length && queryStudyInstanceUIDs || paramsStudyInstanceUIDs;
1829
1847
  const StudyInstanceUIDsAsArray = StudyInstanceUIDs && Array.isArray(StudyInstanceUIDs) ? StudyInstanceUIDs : [StudyInstanceUIDs];
1830
1848
  return StudyInstanceUIDsAsArray;
1831
1849
  }
1832
1850
  };
1833
1851
  if (dicomWebConfig.supportsReject) {
1834
- implementation.reject = dcm4cheeReject(dicomWebConfig.wadoRoot);
1852
+ implementation.reject = dcm4cheeReject(dicomWebConfig.wadoRoot, getAuthorizationHeader);
1835
1853
  }
1836
1854
  return src/* IWebApiDataSource */.pt.create(implementation);
1837
1855
  }
@@ -1964,7 +1982,7 @@ function createDicomJSONApi(dicomJsonConfig) {
1964
1982
  query
1965
1983
  } = query_string.parseUrl(instance.url);
1966
1984
 
1967
- // Add imageId specific mapping to this data as the URL isn't necessarliy WADO-URI.
1985
+ // Add imageId specific mapping to this data as the URL isn't necessarily WADO-URI.
1968
1986
  DicomJSONDataSource_metadataProvider.addImageIdToUIDs(imageId, {
1969
1987
  StudyInstanceUID,
1970
1988
  SeriesInstanceUID,
@@ -2388,14 +2406,17 @@ function createDicomLocalApi(dicomLocalConfig) {
2388
2406
  instance,
2389
2407
  frame
2390
2408
  }) {
2391
- if (instance.imageId) {
2392
- return instance.imageId;
2393
- }
2409
+ // Important: Never use instance.imageId because it might be multiframe,
2410
+ // which would make it an invalid imageId.
2411
+ // if (instance.imageId) {
2412
+ // return instance.imageId;
2413
+ // }
2414
+
2394
2415
  const {
2395
2416
  StudyInstanceUID,
2396
- SeriesInstanceUID,
2397
- SOPInstanceUID
2417
+ SeriesInstanceUID
2398
2418
  } = instance;
2419
+ const SOPInstanceUID = instance.SOPInstanceUID || instance.SopInstanceUID;
2399
2420
  const storedInstance = src/* DicomMetadataStore */.H8.getInstance(StudyInstanceUID, SeriesInstanceUID, SOPInstanceUID);
2400
2421
  let imageId = storedInstance.url;
2401
2422
  if (frame !== undefined) {
@@ -2825,18 +2846,16 @@ var react = __webpack_require__(86326);
2825
2846
  // EXTERNAL MODULE: ../../../node_modules/prop-types/index.js
2826
2847
  var prop_types = __webpack_require__(97598);
2827
2848
  var prop_types_default = /*#__PURE__*/__webpack_require__.n(prop_types);
2828
- // EXTERNAL MODULE: ../../ui/src/index.js + 690 modules
2829
- var ui_src = __webpack_require__(35647);
2849
+ // EXTERNAL MODULE: ../../ui/src/index.js + 691 modules
2850
+ var ui_src = __webpack_require__(32907);
2830
2851
  // EXTERNAL MODULE: ./state/index.js + 1 modules
2831
2852
  var state = __webpack_require__(45981);
2832
2853
  // EXTERNAL MODULE: ../../../node_modules/react-router-dom/dist/index.js
2833
2854
  var dist = __webpack_require__(4194);
2834
2855
  // EXTERNAL MODULE: ../../../node_modules/react-i18next/dist/es/index.js + 15 modules
2835
2856
  var es = __webpack_require__(99993);
2836
- // EXTERNAL MODULE: ../../../node_modules/react-router/dist/index.js
2837
- var react_router_dist = __webpack_require__(42277);
2838
- // EXTERNAL MODULE: ../../ui-next/src/index.ts + 2483 modules
2839
- var ui_next_src = __webpack_require__(35570);
2857
+ // EXTERNAL MODULE: ../../ui-next/src/index.ts + 2624 modules
2858
+ var ui_next_src = __webpack_require__(18817);
2840
2859
  // EXTERNAL MODULE: ../../i18n/src/index.js + 150 modules
2841
2860
  var i18n_src = __webpack_require__(16076);
2842
2861
  ;// CONCATENATED MODULE: ../../../extensions/default/src/Toolbar/Toolbar.tsx
@@ -2918,7 +2937,7 @@ function usePatientInfo(servicesManager) {
2918
2937
  }
2919
2938
  setPatientInfo({
2920
2939
  PatientID: instance.PatientID || null,
2921
- PatientName: instance.PatientName ? formatPN(instance.PatientName.Alphabetic) : null,
2940
+ PatientName: instance.PatientName ? formatPN(instance.PatientName) : null,
2922
2941
  PatientSex: instance.PatientSex || null,
2923
2942
  PatientDOB: formatDate(instance.PatientBirthDate) || null
2924
2943
  });
@@ -2991,7 +3010,7 @@ function HeaderPatientInfo({
2991
3010
  className: "text-aqua-pale flex gap-2 text-[11px]"
2992
3011
  }, /*#__PURE__*/react.createElement("div", null, formattedPatientID), /*#__PURE__*/react.createElement("div", null, patientInfo.PatientSex), /*#__PURE__*/react.createElement("div", null, patientInfo.PatientDOB))) : /*#__PURE__*/react.createElement("div", {
2993
3012
  className: "text-primary-active self-center text-[13px]"
2994
- }, isMixedPatients ? 'Multiple Patients' : 'Patient')), /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI.ChevronPatient, {
3013
+ }, isMixedPatients ? 'Multiple Patients' : 'Patient')), /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI.ArrowLeft, {
2995
3014
  className: `text-primary-active ${expanded ? 'rotate-180' : ''}`
2996
3015
  }));
2997
3016
  }
@@ -2999,6 +3018,8 @@ function HeaderPatientInfo({
2999
3018
  ;// CONCATENATED MODULE: ../../../extensions/default/src/ViewerLayout/HeaderPatientInfo/index.js
3000
3019
 
3001
3020
  /* harmony default export */ const ViewerLayout_HeaderPatientInfo = (HeaderPatientInfo_HeaderPatientInfo);
3021
+ // EXTERNAL MODULE: ./index.js + 43 modules
3022
+ var index = __webpack_require__(50484);
3002
3023
  ;// CONCATENATED MODULE: ../../../extensions/default/src/ViewerLayout/ViewerHeader.tsx
3003
3024
 
3004
3025
 
@@ -3023,25 +3044,21 @@ function ViewerHeader({
3023
3044
  appConfig
3024
3045
  }) {
3025
3046
  const navigate = (0,dist/* useNavigate */.Zp)();
3026
- const location = (0,react_router_dist/* useLocation */.zy)();
3047
+ const location = (0,dist/* useLocation */.zy)();
3027
3048
  const onClickReturnButton = () => {
3028
3049
  const {
3029
3050
  pathname
3030
3051
  } = location;
3031
3052
  const dataSourceIdx = pathname.indexOf('/', 1);
3032
- const query = new URLSearchParams(window.location.search);
3033
- const configUrl = query.get('configUrl');
3034
3053
  const dataSourceName = pathname.substring(dataSourceIdx + 1);
3035
3054
  const existingDataSource = extensionManager.getDataSources(dataSourceName);
3036
3055
  const searchQuery = new URLSearchParams();
3037
3056
  if (dataSourceIdx !== -1 && existingDataSource) {
3038
3057
  searchQuery.append('datasources', pathname.substring(dataSourceIdx + 1));
3039
3058
  }
3040
- if (configUrl) {
3041
- searchQuery.append('configUrl', configUrl);
3042
- }
3059
+ (0,index/* preserveQueryParameters */.Nn)(searchQuery);
3043
3060
  navigate({
3044
- pathname: '/',
3061
+ pathname: index/* publicUrl */.x6,
3045
3062
  search: decodeURIComponent(searchQuery.toString())
3046
3063
  });
3047
3064
  };
@@ -3056,8 +3073,8 @@ function ViewerHeader({
3056
3073
  hotkeyDefinitions,
3057
3074
  hotkeyDefaults
3058
3075
  } = hotkeysManager;
3059
- const versionNumber = "3.10.0-beta.8";
3060
- const commitHash = "44648eef92265f0a80c0c72ca1729d6eca6c4178";
3076
+ const versionNumber = "3.10.0-beta.80";
3077
+ const commitHash = "054b262e9cbeb0f44de65d05641efe1e8944a4f5";
3061
3078
  const menuOptions = [{
3062
3079
  title: t('Header:About'),
3063
3080
  icon: 'info',
@@ -3140,38 +3157,41 @@ const SidePanelWithServices = ({
3140
3157
  servicesManager,
3141
3158
  side,
3142
3159
  activeTabIndex: activeTabIndexProp,
3160
+ isExpanded,
3143
3161
  tabs: tabsProp,
3144
- expandedWidth,
3162
+ onOpen,
3163
+ onClose,
3145
3164
  ...props
3146
3165
  }) => {
3147
3166
  const panelService = servicesManager?.services?.panelService;
3148
3167
 
3149
3168
  // Tracks whether this SidePanel has been opened at least once since this SidePanel was inserted into the DOM.
3150
3169
  // Thus going to the Study List page and back to the viewer resets this flag for a SidePanel.
3151
- const [sidePanelOpen, setSidePanelOpen] = (0,react.useState)(activeTabIndexProp !== null);
3152
- const [activeTabIndex, setActiveTabIndex] = (0,react.useState)(activeTabIndexProp);
3170
+ const [sidePanelExpanded, setSidePanelExpanded] = (0,react.useState)(isExpanded);
3171
+ const [activeTabIndex, setActiveTabIndex] = (0,react.useState)(activeTabIndexProp ?? 0);
3172
+ const [closedManually, setClosedManually] = (0,react.useState)(false);
3153
3173
  const [tabs, setTabs] = (0,react.useState)(tabsProp ?? panelService.getPanels(side));
3154
3174
  const handleActiveTabIndexChange = (0,react.useCallback)(({
3155
3175
  activeTabIndex
3156
3176
  }) => {
3157
3177
  setActiveTabIndex(activeTabIndex);
3158
- setSidePanelOpen(activeTabIndex !== null);
3159
3178
  }, []);
3160
3179
  const handleOpen = (0,react.useCallback)(() => {
3161
- setSidePanelOpen(true);
3162
- // If panel is being opened but no tab is active, set first tab as active
3163
- if (activeTabIndex === null && tabs.length > 0) {
3164
- setActiveTabIndex(0);
3165
- }
3166
- }, [activeTabIndex, tabs]);
3180
+ setSidePanelExpanded(true);
3181
+ onOpen?.();
3182
+ }, [onOpen]);
3167
3183
  const handleClose = (0,react.useCallback)(() => {
3168
- setSidePanelOpen(false);
3169
- setActiveTabIndex(null);
3170
- }, []);
3184
+ setSidePanelExpanded(false);
3185
+ setClosedManually(true);
3186
+ onClose?.();
3187
+ }, [onClose]);
3188
+ (0,react.useEffect)(() => {
3189
+ setSidePanelExpanded(isExpanded);
3190
+ }, [isExpanded]);
3171
3191
 
3172
3192
  /** update the active tab index from outside */
3173
3193
  (0,react.useEffect)(() => {
3174
- setActiveTabIndex(activeTabIndexProp);
3194
+ setActiveTabIndex(activeTabIndexProp ?? 0);
3175
3195
  }, [activeTabIndexProp]);
3176
3196
  (0,react.useEffect)(() => {
3177
3197
  const {
@@ -3188,9 +3208,12 @@ const SidePanelWithServices = ({
3188
3208
  }, [panelService, side]);
3189
3209
  (0,react.useEffect)(() => {
3190
3210
  const activatePanelSubscription = panelService.subscribe(panelService.EVENTS.ACTIVATE_PANEL, activatePanelEvent => {
3191
- if (sidePanelOpen || activatePanelEvent.forceActive) {
3211
+ if (sidePanelExpanded || activatePanelEvent.forceActive) {
3192
3212
  const tabIndex = tabs.findIndex(tab => tab.id === activatePanelEvent.panelId);
3193
3213
  if (tabIndex !== -1) {
3214
+ if (!closedManually) {
3215
+ setSidePanelExpanded(true);
3216
+ }
3194
3217
  setActiveTabIndex(tabIndex);
3195
3218
  }
3196
3219
  }
@@ -3198,19 +3221,310 @@ const SidePanelWithServices = ({
3198
3221
  return () => {
3199
3222
  activatePanelSubscription.unsubscribe();
3200
3223
  };
3201
- }, [tabs, sidePanelOpen, panelService]);
3224
+ }, [tabs, sidePanelExpanded, panelService, closedManually]);
3202
3225
  return /*#__PURE__*/react.createElement(ui_next_src/* SidePanel */.d_, SidePanelWithServices_extends({}, props, {
3203
3226
  side: side,
3204
3227
  tabs: tabs,
3205
3228
  activeTabIndex: activeTabIndex,
3229
+ isExpanded: sidePanelExpanded,
3206
3230
  onOpen: handleOpen,
3207
3231
  onClose: handleClose,
3208
- onActiveTabIndexChange: handleActiveTabIndexChange,
3209
- expandedWidth: expandedWidth
3232
+ onActiveTabIndexChange: handleActiveTabIndexChange
3210
3233
  }));
3211
3234
  };
3212
3235
  /* harmony default export */ const Components_SidePanelWithServices = (SidePanelWithServices);
3236
+ // EXTERNAL MODULE: ../../../node_modules/react-resizable-panels/dist/react-resizable-panels.browser.esm.js
3237
+ var react_resizable_panels_browser_esm = __webpack_require__(17825);
3238
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/ViewerLayout/constants/panels.ts
3239
+ const expandedInsideBorderSize = 0;
3240
+ const collapsedInsideBorderSize = 4;
3241
+ const collapsedOutsideBorderSize = 4;
3242
+ const collapsedWidth = 25;
3243
+ const rightPanelInitialExpandedWidth = 280;
3244
+ const leftPanelInitialExpandedWidth = 282;
3245
+ const panelGroupDefinition = {
3246
+ groupId: 'viewerLayoutResizablePanelGroup',
3247
+ shared: {
3248
+ expandedInsideBorderSize,
3249
+ collapsedInsideBorderSize,
3250
+ collapsedOutsideBorderSize,
3251
+ collapsedWidth
3252
+ },
3253
+ left: {
3254
+ // id
3255
+ panelId: 'viewerLayoutResizableLeftPanel',
3256
+ // expanded width
3257
+ initialExpandedWidth: leftPanelInitialExpandedWidth,
3258
+ // expanded width + expanded inside border
3259
+ minimumExpandedOffsetWidth: 145 + expandedInsideBorderSize,
3260
+ // initial expanded width
3261
+ initialExpandedOffsetWidth: leftPanelInitialExpandedWidth + expandedInsideBorderSize,
3262
+ // collapsed width + collapsed inside border + collapsed outside border
3263
+ collapsedOffsetWidth: collapsedWidth + collapsedInsideBorderSize + collapsedOutsideBorderSize
3264
+ },
3265
+ right: {
3266
+ panelId: 'viewerLayoutResizableRightPanel',
3267
+ initialExpandedWidth: rightPanelInitialExpandedWidth,
3268
+ minimumExpandedOffsetWidth: rightPanelInitialExpandedWidth + expandedInsideBorderSize,
3269
+ initialExpandedOffsetWidth: rightPanelInitialExpandedWidth + expandedInsideBorderSize,
3270
+ collapsedOffsetWidth: collapsedWidth + collapsedInsideBorderSize + collapsedOutsideBorderSize
3271
+ }
3272
+ };
3273
+
3274
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/ViewerLayout/ResizablePanelsHook.tsx
3275
+
3276
+
3277
+
3278
+
3279
+ /**
3280
+ * Set the minimum and maximum css style width attributes for the given element.
3281
+ * The two style attributes are cleared whenever the width
3282
+ * argument is undefined.
3283
+ * <p>
3284
+ * This utility is used as part of a HACK throughout the ViewerLayout component as
3285
+ * the means of restricting the side panel widths during the resizing of the
3286
+ * browser window. In general, the widths are always set unless the resize
3287
+ * handle for either side panel is being dragged (i.e. a side panel is being resized).
3288
+ *
3289
+ * @param elem the element
3290
+ * @param width the max and min width to set on the element
3291
+ */
3292
+ const setMinMaxWidth = (elem, width) => {
3293
+ elem.style.minWidth = width === undefined ? '' : `${width}px`;
3294
+ elem.style.maxWidth = elem.style.minWidth;
3295
+ };
3296
+ const useResizablePanels = (leftPanelClosed, setLeftPanelClosed, rightPanelClosed, setRightPanelClosed) => {
3297
+ const [leftPanelExpandedWidth, setLeftPanelExpandedWidth] = (0,react.useState)(panelGroupDefinition.left.initialExpandedWidth);
3298
+ const [rightPanelExpandedWidth, setRightPanelExpandedWidth] = (0,react.useState)(panelGroupDefinition.right.initialExpandedWidth);
3299
+ const [leftResizablePanelMinimumSize, setLeftResizablePanelMinimumSize] = (0,react.useState)(0);
3300
+ const [rightResizablePanelMinimumSize, setRightResizablePanelMinimumSize] = (0,react.useState)(0);
3301
+ const [leftResizablePanelCollapsedSize, setLeftResizePanelCollapsedSize] = (0,react.useState)(0);
3302
+ const [rightResizePanelCollapsedSize, setRightResizePanelCollapsedSize] = (0,react.useState)(0);
3303
+ const resizablePanelGroupElemRef = (0,react.useRef)(null);
3304
+ const resizableLeftPanelElemRef = (0,react.useRef)(null);
3305
+ const resizableRightPanelElemRef = (0,react.useRef)(null);
3306
+ const resizableLeftPanelAPIRef = (0,react.useRef)(null);
3307
+ const resizableRightPanelAPIRef = (0,react.useRef)(null);
3308
+ const isResizableHandleDraggingRef = (0,react.useRef)(false);
3309
+
3310
+ // The total width of both handles.
3311
+ const resizableHandlesWidth = (0,react.useRef)(null);
3312
+
3313
+ // This useLayoutEffect is used to...
3314
+ // - Grab a reference to the various resizable panel elements needed for
3315
+ // converting between percentages and pixels in various callbacks.
3316
+ // - Expand those panels that are initially expanded.
3317
+ (0,react.useLayoutEffect)(() => {
3318
+ const panelGroupElem = (0,react_resizable_panels_browser_esm/* getPanelGroupElement */.Gx)(panelGroupDefinition.groupId);
3319
+ resizablePanelGroupElemRef.current = panelGroupElem;
3320
+ const leftPanelElem = (0,react_resizable_panels_browser_esm/* getPanelElement */.PV)(panelGroupDefinition.left.panelId);
3321
+ resizableLeftPanelElemRef.current = leftPanelElem;
3322
+ const rightPanelElem = (0,react_resizable_panels_browser_esm/* getPanelElement */.PV)(panelGroupDefinition.right.panelId);
3323
+ resizableRightPanelElemRef.current = rightPanelElem;
3324
+
3325
+ // Calculate and set the width of both handles combined.
3326
+ const resizeHandles = document.querySelectorAll('[data-panel-resize-handle-id]');
3327
+ resizableHandlesWidth.current = 0;
3328
+ resizeHandles.forEach(resizeHandle => {
3329
+ resizableHandlesWidth.current += resizeHandle.offsetWidth;
3330
+ });
3331
+
3332
+ // Since both resizable panels are collapsed by default (i.e. their default size is zero),
3333
+ // on the very first render check if either/both side panels should be expanded.
3334
+ // we use the initialExpandedOffsetWidth on the first render incase the panel has min width but we want the initial state to be larger than that
3335
+
3336
+ if (!leftPanelClosed) {
3337
+ const leftResizablePanelExpandedSize = getPercentageSize(panelGroupDefinition.left.initialExpandedOffsetWidth);
3338
+ resizableLeftPanelAPIRef?.current?.expand(leftResizablePanelExpandedSize);
3339
+ setMinMaxWidth(leftPanelElem, panelGroupDefinition.left.initialExpandedOffsetWidth);
3340
+ }
3341
+ if (!rightPanelClosed) {
3342
+ const rightResizablePanelExpandedSize = getPercentageSize(panelGroupDefinition.right.initialExpandedOffsetWidth);
3343
+ resizableRightPanelAPIRef?.current?.expand(rightResizablePanelExpandedSize);
3344
+ setMinMaxWidth(rightPanelElem, panelGroupDefinition.right.initialExpandedOffsetWidth);
3345
+ }
3346
+ }, []); // no dependencies because this useLayoutEffect is only needed on the very first render
3347
+
3348
+ // This useLayoutEffect follows the pattern prescribed by the react-resizable-panels
3349
+ // readme for converting between pixel values and percentages. An example of
3350
+ // the pattern can be found here:
3351
+ // https://github.com/bvaughn/react-resizable-panels/issues/46#issuecomment-1368108416
3352
+ // This useLayoutEffect is used to...
3353
+ // - Ensure that the percentage size is up-to-date with the pixel sizes
3354
+ // - Add a resize observer to the resizable panel group to reset various state
3355
+ // values whenever the resizable panel group is resized (e.g. whenever the
3356
+ // browser window is resized).
3357
+ (0,react.useLayoutEffect)(() => {
3358
+ // Ensure the side panels' percentage size is in synch with the pixel width of the
3359
+ // expanded side panels. In general the two get out-of-sync during a browser
3360
+ // window resize. Note that this code is here and NOT in the ResizeObserver
3361
+ // because it has to be done AFTER the minimum percentage size for a panel is
3362
+ // updated which occurs only AFTER the render following a browser window resize.
3363
+ // And by virtue of the dependency on the minimum size state variables, this code
3364
+ // is executed on the render following an update of the minimum percentage sizes
3365
+ // for a panel.
3366
+ if (!resizableLeftPanelAPIRef.current.isCollapsed()) {
3367
+ const leftSize = getPercentageSize(leftPanelExpandedWidth + panelGroupDefinition.shared.expandedInsideBorderSize);
3368
+ resizableLeftPanelAPIRef.current.resize(leftSize);
3369
+ }
3370
+ if (!resizableRightPanelAPIRef.current.isCollapsed()) {
3371
+ const rightSize = getPercentageSize(rightPanelExpandedWidth + panelGroupDefinition.shared.expandedInsideBorderSize);
3372
+ resizableRightPanelAPIRef.current.resize(rightSize);
3373
+ }
3374
+
3375
+ // This observer kicks in when the ViewportLayout resizable panel group
3376
+ // component is resized. This typically occurs when the browser window resizes.
3377
+ const observer = new ResizeObserver(() => {
3378
+ const minimumLeftSize = getPercentageSize(panelGroupDefinition.left.minimumExpandedOffsetWidth);
3379
+ const minimumRightSize = getPercentageSize(panelGroupDefinition.right.minimumExpandedOffsetWidth);
3380
+
3381
+ // Set the new minimum and collapsed resizable panel sizes.
3382
+ setLeftResizablePanelMinimumSize(minimumLeftSize);
3383
+ setRightResizablePanelMinimumSize(minimumRightSize);
3384
+ setLeftResizePanelCollapsedSize(getPercentageSize(panelGroupDefinition.left.collapsedOffsetWidth));
3385
+ setRightResizePanelCollapsedSize(getPercentageSize(panelGroupDefinition.right.collapsedOffsetWidth));
3386
+ });
3387
+ observer.observe(resizablePanelGroupElemRef.current);
3388
+ return () => {
3389
+ observer.disconnect();
3390
+ };
3391
+ }, [leftPanelExpandedWidth, rightPanelExpandedWidth, leftResizablePanelMinimumSize, rightResizablePanelMinimumSize]);
3392
+
3393
+ /**
3394
+ * Handles dragging of either side panel resize handle.
3395
+ */
3396
+ const onHandleDragging = (0,react.useCallback)(isStartDrag => {
3397
+ if (isStartDrag) {
3398
+ isResizableHandleDraggingRef.current = true;
3399
+ setMinMaxWidth(resizableLeftPanelElemRef.current);
3400
+ setMinMaxWidth(resizableRightPanelElemRef.current);
3401
+ } else {
3402
+ isResizableHandleDraggingRef.current = false;
3403
+ if (resizableLeftPanelAPIRef?.current?.isExpanded()) {
3404
+ setMinMaxWidth(resizableLeftPanelElemRef.current, leftPanelExpandedWidth + panelGroupDefinition.shared.expandedInsideBorderSize);
3405
+ }
3406
+ if (resizableRightPanelAPIRef?.current?.isExpanded()) {
3407
+ setMinMaxWidth(resizableRightPanelElemRef.current, rightPanelExpandedWidth + panelGroupDefinition.shared.expandedInsideBorderSize);
3408
+ }
3409
+ }
3410
+ }, [leftPanelExpandedWidth, rightPanelExpandedWidth]);
3411
+ const onLeftPanelClose = (0,react.useCallback)(() => {
3412
+ setLeftPanelClosed(true);
3413
+ setMinMaxWidth(resizableLeftPanelElemRef.current);
3414
+ resizableLeftPanelAPIRef?.current?.collapse();
3415
+ }, [setLeftPanelClosed]);
3416
+ const onLeftPanelOpen = (0,react.useCallback)(() => {
3417
+ resizableLeftPanelAPIRef?.current?.expand(getPercentageSize(panelGroupDefinition.left.initialExpandedOffsetWidth));
3418
+ setLeftPanelClosed(false);
3419
+ }, [setLeftPanelClosed]);
3420
+ const onLeftPanelResize = (0,react.useCallback)(size => {
3421
+ if (!resizablePanelGroupElemRef?.current || resizableLeftPanelAPIRef.current.isCollapsed()) {
3422
+ return;
3423
+ }
3424
+ const newExpandedWidth = getExpandedPixelWidth(size);
3425
+ setLeftPanelExpandedWidth(newExpandedWidth);
3426
+ if (!isResizableHandleDraggingRef.current) {
3427
+ // This typically gets executed when the left panel is expanded via one of the UI
3428
+ // buttons. It is done here instead of in the onLeftPanelOpen method
3429
+ // because here we know the size of the expanded panel.
3430
+ setMinMaxWidth(resizableLeftPanelElemRef.current, newExpandedWidth);
3431
+ }
3432
+ }, []);
3433
+ const onRightPanelClose = (0,react.useCallback)(() => {
3434
+ setRightPanelClosed(true);
3435
+ setMinMaxWidth(resizableRightPanelElemRef.current);
3436
+ resizableRightPanelAPIRef?.current?.collapse();
3437
+ }, [setRightPanelClosed]);
3438
+ const onRightPanelOpen = (0,react.useCallback)(() => {
3439
+ resizableRightPanelAPIRef?.current?.expand(getPercentageSize(panelGroupDefinition.right.initialExpandedOffsetWidth));
3440
+ setRightPanelClosed(false);
3441
+ }, [setRightPanelClosed]);
3442
+ const onRightPanelResize = (0,react.useCallback)(size => {
3443
+ if (!resizablePanelGroupElemRef?.current || resizableRightPanelAPIRef.current.isCollapsed()) {
3444
+ return;
3445
+ }
3446
+ const newExpandedWidth = getExpandedPixelWidth(size);
3447
+ setRightPanelExpandedWidth(newExpandedWidth);
3448
+ if (!isResizableHandleDraggingRef.current) {
3449
+ // This typically gets executed when the right panel is expanded via one of the UI
3450
+ // buttons. It is done here instead of in the onRightPanelOpen method
3451
+ // because here we know the size of the expanded panel.
3452
+ setMinMaxWidth(resizableRightPanelElemRef.current, newExpandedWidth);
3453
+ }
3454
+ }, []);
3455
+
3456
+ /**
3457
+ * Gets the percentage size corresponding to the given pixel size.
3458
+ * Note that the width attributed to the handles must be taken into account.
3459
+ */
3460
+ const getPercentageSize = pixelSize => {
3461
+ const {
3462
+ width: panelGroupWidth
3463
+ } = resizablePanelGroupElemRef.current.getBoundingClientRect();
3464
+ return pixelSize / (panelGroupWidth - resizableHandlesWidth.current) * 100;
3465
+ };
3466
+
3467
+ /**
3468
+ * Gets the width in pixels for an expanded panel given its percentage size/width.
3469
+ * Note that the width attributed to the handles must be taken into account.
3470
+ */
3471
+ const getExpandedPixelWidth = percentageSize => {
3472
+ const {
3473
+ width: panelGroupWidth
3474
+ } = resizablePanelGroupElemRef.current.getBoundingClientRect();
3475
+ const expandedWidth = percentageSize / 100 * (panelGroupWidth - resizableHandlesWidth.current) - panelGroupDefinition.shared.expandedInsideBorderSize;
3476
+ return expandedWidth;
3477
+ };
3478
+ return [{
3479
+ expandedWidth: leftPanelExpandedWidth,
3480
+ collapsedWidth: panelGroupDefinition.shared.collapsedWidth,
3481
+ collapsedInsideBorderSize: panelGroupDefinition.shared.collapsedInsideBorderSize,
3482
+ collapsedOutsideBorderSize: panelGroupDefinition.shared.collapsedOutsideBorderSize,
3483
+ expandedInsideBorderSize: panelGroupDefinition.shared.expandedInsideBorderSize,
3484
+ onClose: onLeftPanelClose,
3485
+ onOpen: onLeftPanelOpen
3486
+ }, {
3487
+ expandedWidth: rightPanelExpandedWidth,
3488
+ collapsedWidth: panelGroupDefinition.shared.collapsedWidth,
3489
+ collapsedInsideBorderSize: panelGroupDefinition.shared.collapsedInsideBorderSize,
3490
+ collapsedOutsideBorderSize: panelGroupDefinition.shared.collapsedOutsideBorderSize,
3491
+ expandedInsideBorderSize: panelGroupDefinition.shared.expandedInsideBorderSize,
3492
+ onClose: onRightPanelClose,
3493
+ onOpen: onRightPanelOpen
3494
+ }, {
3495
+ direction: 'horizontal',
3496
+ id: panelGroupDefinition.groupId
3497
+ }, {
3498
+ defaultSize: leftResizablePanelMinimumSize,
3499
+ minSize: leftResizablePanelMinimumSize,
3500
+ onResize: onLeftPanelResize,
3501
+ collapsible: true,
3502
+ collapsedSize: leftResizablePanelCollapsedSize,
3503
+ onCollapse: () => setLeftPanelClosed(true),
3504
+ onExpand: () => setLeftPanelClosed(false),
3505
+ ref: resizableLeftPanelAPIRef,
3506
+ order: 0,
3507
+ id: panelGroupDefinition.left.panelId
3508
+ }, {
3509
+ order: 1,
3510
+ id: 'viewerLayoutResizableViewportGridPanel'
3511
+ }, {
3512
+ defaultSize: rightResizablePanelMinimumSize,
3513
+ minSize: rightResizablePanelMinimumSize,
3514
+ onResize: onRightPanelResize,
3515
+ collapsible: true,
3516
+ collapsedSize: rightResizePanelCollapsedSize,
3517
+ onCollapse: () => setRightPanelClosed(true),
3518
+ onExpand: () => setRightPanelClosed(false),
3519
+ ref: resizableRightPanelAPIRef,
3520
+ order: 2,
3521
+ id: panelGroupDefinition.right.panelId
3522
+ }, onHandleDragging];
3523
+ };
3524
+ /* harmony default export */ const ResizablePanelsHook = (useResizablePanels);
3213
3525
  ;// CONCATENATED MODULE: ../../../extensions/default/src/ViewerLayout/index.tsx
3526
+ function ViewerLayout_extends() { return ViewerLayout_extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, ViewerLayout_extends.apply(null, arguments); }
3527
+
3214
3528
 
3215
3529
 
3216
3530
 
@@ -3219,6 +3533,7 @@ const SidePanelWithServices = ({
3219
3533
 
3220
3534
 
3221
3535
 
3536
+ const resizableHandleClassName = 'mt-[1px] bg-black';
3222
3537
  function ViewerLayout({
3223
3538
  // From Extension Module Params
3224
3539
  extensionManager,
@@ -3229,7 +3544,9 @@ function ViewerLayout({
3229
3544
  viewports,
3230
3545
  ViewportGridComp,
3231
3546
  leftPanelClosed = false,
3232
- rightPanelClosed = false
3547
+ rightPanelClosed = false,
3548
+ leftPanelResizable = false,
3549
+ rightPanelResizable = false
3233
3550
  }) {
3234
3551
  const [appConfig] = (0,state/* useAppConfig */.r)();
3235
3552
  const {
@@ -3242,6 +3559,7 @@ function ViewerLayout({
3242
3559
  const [hasLeftPanels, setHasLeftPanels] = (0,react.useState)(hasPanels('left'));
3243
3560
  const [leftPanelClosedState, setLeftPanelClosed] = (0,react.useState)(leftPanelClosed);
3244
3561
  const [rightPanelClosedState, setRightPanelClosed] = (0,react.useState)(rightPanelClosed);
3562
+ const [leftPanelProps, rightPanelProps, resizablePanelGroupProps, resizableLeftPanelProps, resizableViewportGridPanelProps, resizableRightPanelProps, onHandleDragging] = ResizablePanelsHook(leftPanelClosed, setLeftPanelClosed, rightPanelClosed, setRightPanelClosed);
3245
3563
 
3246
3564
  /**
3247
3565
  * Set body classes (tailwindcss) that don't allow vertical
@@ -3321,11 +3639,15 @@ function ViewerLayout({
3321
3639
  }
3322
3640
  }, /*#__PURE__*/react.createElement(react.Fragment, null, showLoadingIndicator && /*#__PURE__*/react.createElement(ui_src/* LoadingIndicatorProgress */.Jx, {
3323
3641
  className: "h-full w-full bg-black"
3324
- }), hasLeftPanels ? /*#__PURE__*/react.createElement(Components_SidePanelWithServices, {
3642
+ }), /*#__PURE__*/react.createElement(ui_next_src/* ResizablePanelGroup */.HK, resizablePanelGroupProps, hasLeftPanels ? /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement(ui_next_src/* ResizablePanel */.wV, resizableLeftPanelProps, /*#__PURE__*/react.createElement(Components_SidePanelWithServices, ViewerLayout_extends({
3325
3643
  side: "left",
3326
- activeTabIndex: leftPanelClosedState ? null : 0,
3644
+ isExpanded: !leftPanelClosedState,
3327
3645
  servicesManager: servicesManager
3328
- }) : null, /*#__PURE__*/react.createElement("div", {
3646
+ }, leftPanelProps))), /*#__PURE__*/react.createElement(ui_next_src/* ResizableHandle */.WM, {
3647
+ onDragging: onHandleDragging,
3648
+ disabled: !leftPanelResizable,
3649
+ className: resizableHandleClassName
3650
+ })) : null, /*#__PURE__*/react.createElement(ui_next_src/* ResizablePanel */.wV, resizableViewportGridPanelProps, /*#__PURE__*/react.createElement("div", {
3329
3651
  className: "flex h-full flex-1 flex-col"
3330
3652
  }, /*#__PURE__*/react.createElement("div", {
3331
3653
  className: "relative flex h-full flex-1 items-center justify-center overflow-hidden bg-black"
@@ -3333,11 +3655,15 @@ function ViewerLayout({
3333
3655
  servicesManager: servicesManager,
3334
3656
  viewportComponents: viewportComponents,
3335
3657
  commandsManager: commandsManager
3336
- }))), hasRightPanels ? /*#__PURE__*/react.createElement(Components_SidePanelWithServices, {
3658
+ })))), hasRightPanels ? /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement(ui_next_src/* ResizableHandle */.WM, {
3659
+ onDragging: onHandleDragging,
3660
+ disabled: !rightPanelResizable,
3661
+ className: resizableHandleClassName
3662
+ }), /*#__PURE__*/react.createElement(ui_next_src/* ResizablePanel */.wV, resizableRightPanelProps, /*#__PURE__*/react.createElement(Components_SidePanelWithServices, ViewerLayout_extends({
3337
3663
  side: "right",
3338
- activeTabIndex: rightPanelClosedState ? null : 0,
3664
+ isExpanded: !rightPanelClosedState,
3339
3665
  servicesManager: servicesManager
3340
- }) : null)), /*#__PURE__*/react.createElement(ui_next_src/* Onboarding */.M7, null), /*#__PURE__*/react.createElement(ui_src/* InvestigationalUseDialog */.j, {
3666
+ }, rightPanelProps)))) : null))), /*#__PURE__*/react.createElement(ui_next_src/* Onboarding */.M7, null), /*#__PURE__*/react.createElement(ui_src/* InvestigationalUseDialog */.j, {
3341
3667
  dialogConfiguration: appConfig?.investigationalUseDialog
3342
3668
  }));
3343
3669
  }
@@ -3453,6 +3779,84 @@ const defaultViewPresets = [{
3453
3779
 
3454
3780
 
3455
3781
 
3782
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/Components/MoreDropdownMenu.tsx
3783
+
3784
+
3785
+
3786
+ /**
3787
+ * The default sub-menu appearance and setup is defined here, but this can be
3788
+ * replaced by
3789
+ */
3790
+ const getMenuItemsDefault = ({
3791
+ commandsManager,
3792
+ items,
3793
+ servicesManager,
3794
+ ...props
3795
+ }) => {
3796
+ const {
3797
+ customizationService
3798
+ } = servicesManager.services;
3799
+
3800
+ // This allows replacing the default child item for menus, whereas the entire
3801
+ // getMenuItems can also be replaced by providing it to the MoreDropdownMenu
3802
+ const menuContent = customizationService.getCustomization('ohif.menuContent');
3803
+ return /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuContent */.SQ, {
3804
+ hideWhenDetached: true,
3805
+ align: "start",
3806
+ onClick: e => {
3807
+ e.stopPropagation();
3808
+ e.preventDefault();
3809
+ }
3810
+ }, items?.map((item, index) => /*#__PURE__*/react.createElement(menuContent.content, {
3811
+ key: item.id || `menu-item-${index}`,
3812
+ item,
3813
+ commandsManager,
3814
+ servicesManager,
3815
+ ...props
3816
+ })));
3817
+ };
3818
+
3819
+ /**
3820
+ * The component provides a ... sub-menu for various components which appears
3821
+ * on hover over the main component.
3822
+ *
3823
+ * @param bindProps - properties to define the sub-menu
3824
+ * @returns Component bound to the bindProps
3825
+ */
3826
+ function MoreDropdownMenu(bindProps) {
3827
+ const {
3828
+ menuItemsKey,
3829
+ getMenuItems = getMenuItemsDefault,
3830
+ commandsManager,
3831
+ servicesManager
3832
+ } = bindProps;
3833
+ const {
3834
+ customizationService
3835
+ } = servicesManager.services;
3836
+ const items = customizationService.getCustomization(menuItemsKey);
3837
+ if (!items?.length) {
3838
+ return null;
3839
+ }
3840
+ function BoundMoreDropdownMenu(props) {
3841
+ return /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenu */.rI, null, /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuTrigger */.ty, {
3842
+ asChild: true
3843
+ }, /*#__PURE__*/react.createElement(ui_next_src/* Button */.$n, {
3844
+ variant: "ghost",
3845
+ size: "icon",
3846
+ className: "hidden group-hover:inline-flex data-[state=open]:inline-flex",
3847
+ onClick: e => {
3848
+ e.preventDefault();
3849
+ e.stopPropagation();
3850
+ }
3851
+ }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI.More, null))), getMenuItems({
3852
+ ...props,
3853
+ commandsManager: commandsManager,
3854
+ servicesManager: servicesManager,
3855
+ items
3856
+ }));
3857
+ }
3858
+ return BoundMoreDropdownMenu;
3859
+ }
3456
3860
  ;// CONCATENATED MODULE: ../../../extensions/default/src/Panels/StudyBrowser/PanelStudyBrowser.tsx
3457
3861
 
3458
3862
 
@@ -3462,6 +3866,8 @@ const defaultViewPresets = [{
3462
3866
 
3463
3867
 
3464
3868
 
3869
+
3870
+
3465
3871
  const {
3466
3872
  sortStudyInstances,
3467
3873
  formatDate: PanelStudyBrowser_formatDate,
@@ -3498,14 +3904,14 @@ function PanelStudyBrowser({
3498
3904
  activeViewportId,
3499
3905
  viewports,
3500
3906
  isHangingProtocolLayout
3501
- }, viewportGridService] = (0,ui_src/* useViewportGrid */.ih)();
3907
+ }, viewportGridService] = (0,ui_next_src/* useViewportGrid */.ih)();
3502
3908
  const [activeTabName, setActiveTabName] = (0,react.useState)('all');
3503
3909
  const [expandedStudyInstanceUIDs, setExpandedStudyInstanceUIDs] = (0,react.useState)([...StudyInstanceUIDs]);
3504
3910
  const [hasLoadedViewports, setHasLoadedViewports] = (0,react.useState)(false);
3505
3911
  const [studyDisplayList, setStudyDisplayList] = (0,react.useState)([]);
3506
3912
  const [displaySets, setDisplaySets] = (0,react.useState)([]);
3507
3913
  const [thumbnailImageSrcMap, setThumbnailImageSrcMap] = (0,react.useState)({});
3508
- const [viewPresets, setViewPresets] = (0,react.useState)(customizationService.getCustomization('studyBrowser.viewPresets')?.value || defaultViewPresets);
3914
+ const [viewPresets, setViewPresets] = (0,react.useState)(customizationService.getCustomization('studyBrowser.viewPresets'));
3509
3915
  const [actionIcons, setActionIcons] = (0,react.useState)(defaultActionIcons);
3510
3916
 
3511
3917
  // multiple can be true or false
@@ -3699,9 +4105,6 @@ function PanelStudyBrowser({
3699
4105
  }
3700
4106
  }
3701
4107
  const activeDisplaySetInstanceUIDs = viewports.get(activeViewportId)?.displaySetInstanceUIDs;
3702
- const onThumbnailContextMenu = (commandName, options) => {
3703
- commandsManager.runCommand(commandName, options);
3704
- };
3705
4108
  return /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement(PanelStudyBrowserHeader, {
3706
4109
  viewPresets: viewPresets,
3707
4110
  updateViewPresetValue: updateViewPresetValue,
@@ -3715,16 +4118,26 @@ function PanelStudyBrowser({
3715
4118
  tabs: tabs,
3716
4119
  servicesManager: servicesManager,
3717
4120
  activeTabName: activeTabName,
3718
- onDoubleClickThumbnail: onDoubleClickThumbnailHandler,
3719
- activeDisplaySetInstanceUIDs: activeDisplaySetInstanceUIDs,
3720
4121
  expandedStudyInstanceUIDs: expandedStudyInstanceUIDs,
3721
4122
  onClickStudy: _handleStudyClick,
3722
4123
  onClickTab: clickedTabName => {
3723
4124
  setActiveTabName(clickedTabName);
3724
4125
  },
4126
+ onClickThumbnail: () => {},
4127
+ onDoubleClickThumbnail: onDoubleClickThumbnailHandler,
4128
+ activeDisplaySetInstanceUIDs: activeDisplaySetInstanceUIDs,
3725
4129
  showSettings: actionIcons.find(icon => icon.id === 'settings').value,
3726
4130
  viewPresets: viewPresets,
3727
- onThumbnailContextMenu: onThumbnailContextMenu
4131
+ ThumbnailMenuItems: MoreDropdownMenu({
4132
+ commandsManager,
4133
+ servicesManager,
4134
+ menuItemsKey: 'studyBrowser.thumbnailMenuItems'
4135
+ }),
4136
+ StudyMenuItems: MoreDropdownMenu({
4137
+ commandsManager,
4138
+ servicesManager,
4139
+ menuItemsKey: 'studyBrowser.studyMenuItems'
4140
+ })
3728
4141
  }));
3729
4142
  }
3730
4143
  /* harmony default export */ const StudyBrowser_PanelStudyBrowser = (PanelStudyBrowser);
@@ -3824,7 +4237,7 @@ function requestDisplaySetCreationForStudy(dataSource, displaySetService, StudyI
3824
4237
  if (displaySetService.activeDisplaySets.some(displaySet => displaySet.StudyInstanceUID === StudyInstanceUID)) {
3825
4238
  return;
3826
4239
  }
3827
- dataSource.retrieve.series.metadata({
4240
+ return dataSource.retrieve.series.metadata({
3828
4241
  StudyInstanceUID,
3829
4242
  madeInClient
3830
4243
  });
@@ -3847,18 +4260,19 @@ function requestDisplaySetCreationForStudy(dataSource, displaySetService, StudyI
3847
4260
  * @param {object} extensionManager
3848
4261
  */
3849
4262
  function WrappedPanelStudyBrowser({
3850
- commandsManager,
3851
4263
  extensionManager,
3852
- servicesManager
4264
+ servicesManager,
4265
+ commandsManager
3853
4266
  }) {
3854
4267
  // TODO: This should be made available a different way; route should have
3855
4268
  // already determined our datasource
3856
- const dataSource = extensionManager.getDataSources()[0];
4269
+ const [dataSource] = extensionManager.getActiveDataSource();
3857
4270
  const _getStudiesForPatientByMRN = Panels_getStudiesForPatientByMRN.bind(null, dataSource);
3858
4271
  const _getImageSrcFromImageId = (0,react.useCallback)(_createGetImageSrcFromImageIdFn(extensionManager), []);
3859
4272
  const _requestDisplaySetCreationForStudy = Panels_requestDisplaySetCreationForStudy.bind(null, dataSource);
3860
4273
  return /*#__PURE__*/react.createElement(StudyBrowser_PanelStudyBrowser, {
3861
4274
  servicesManager: servicesManager,
4275
+ commandsManager: commandsManager,
3862
4276
  dataSource: dataSource,
3863
4277
  getImageSrc: _getImageSrcFromImageId,
3864
4278
  getStudiesForPatientByMRN: _getStudiesForPatientByMRN,
@@ -4133,7 +4547,7 @@ function areAllImageDimensionsEqual(instances) {
4133
4547
  Rows,
4134
4548
  Columns
4135
4549
  } = instance;
4136
- if (Rows !== firstImageRows || Columns !== firstImageColumns) {
4550
+ if ((0,toNumber/* default */.A)(Rows) !== firstImageRows || (0,toNumber/* default */.A)(Columns) !== firstImageColumns) {
4137
4551
  return false;
4138
4552
  }
4139
4553
  }
@@ -4240,6 +4654,9 @@ function areAllImagePositionsEqual(instances) {
4240
4654
  const scanAxisNormal = calculateScanAxisNormal(firstImageOrientationPatient);
4241
4655
  const firstImagePositionPatient = (0,toNumber/* default */.A)(instances[0].ImagePositionPatient);
4242
4656
  const lastIpp = (0,toNumber/* default */.A)(instances[instances.length - 1].ImagePositionPatient);
4657
+ if (!firstImagePositionPatient || !lastIpp) {
4658
+ return false;
4659
+ }
4243
4660
  const averageSpacingBetweenFrames = (0,isDisplaySetReconstructable/* _getPerpendicularDistance */.jj)(firstImagePositionPatient, lastIpp) / (instances.length - 1);
4244
4661
  let previousImagePositionPatient = firstImagePositionPatient;
4245
4662
  for (let i = 1; i < instances.length; i++) {
@@ -4714,70 +5131,6 @@ function ToolbarLayoutSelector_extends() { return ToolbarLayoutSelector_extends
4714
5131
 
4715
5132
 
4716
5133
 
4717
- const defaultCommonPresets = [{
4718
- icon: 'layout-common-1x1',
4719
- commandOptions: {
4720
- numRows: 1,
4721
- numCols: 1
4722
- }
4723
- }, {
4724
- icon: 'layout-common-1x2',
4725
- commandOptions: {
4726
- numRows: 1,
4727
- numCols: 2
4728
- }
4729
- }, {
4730
- icon: 'layout-common-2x2',
4731
- commandOptions: {
4732
- numRows: 2,
4733
- numCols: 2
4734
- }
4735
- }, {
4736
- icon: 'layout-common-2x3',
4737
- commandOptions: {
4738
- numRows: 2,
4739
- numCols: 3
4740
- }
4741
- }];
4742
- const _areSelectorsValid = (hp, displaySets, hangingProtocolService) => {
4743
- if (!hp.displaySetSelectors || Object.values(hp.displaySetSelectors).length === 0) {
4744
- return true;
4745
- }
4746
- return hangingProtocolService.areRequiredSelectorsValid(Object.values(hp.displaySetSelectors), displaySets[0]);
4747
- };
4748
- const generateAdvancedPresets = ({
4749
- servicesManager
4750
- }) => {
4751
- const {
4752
- hangingProtocolService,
4753
- viewportGridService,
4754
- displaySetService
4755
- } = servicesManager.services;
4756
- const hangingProtocols = Array.from(hangingProtocolService.protocols.values());
4757
- const viewportId = viewportGridService.getActiveViewportId();
4758
- if (!viewportId) {
4759
- return [];
4760
- }
4761
- const displaySetInsaneUIDs = viewportGridService.getDisplaySetsUIDsForViewport(viewportId);
4762
- if (!displaySetInsaneUIDs) {
4763
- return [];
4764
- }
4765
- const displaySets = displaySetInsaneUIDs.map(uid => displaySetService.getDisplaySetByUID(uid));
4766
- return hangingProtocols.map(hp => {
4767
- if (!hp.isPreset) {
4768
- return null;
4769
- }
4770
- const areValid = _areSelectorsValid(hp, displaySets, hangingProtocolService);
4771
- return {
4772
- icon: hp.icon,
4773
- title: hp.name,
4774
- commandOptions: {
4775
- protocolId: hp.id
4776
- },
4777
- disabled: !areValid
4778
- };
4779
- }).filter(preset => preset !== null);
4780
- };
4781
5134
  function ToolbarLayoutSelectorWithServices({
4782
5135
  commandsManager,
4783
5136
  servicesManager,
@@ -4830,8 +5183,9 @@ function LayoutSelector({
4830
5183
  const {
4831
5184
  customizationService
4832
5185
  } = servicesManager.services;
4833
- const commonPresets = customizationService.get('commonPresets') || defaultCommonPresets;
4834
- const advancedPresets = customizationService.get('advancedPresets') || generateAdvancedPresets({
5186
+ const commonPresets = customizationService.getCustomization('layoutSelector.commonPresets');
5187
+ const advancedPresetsGenerator = customizationService.getCustomization('layoutSelector.advancedPresetGenerator');
5188
+ const advancedPresets = advancedPresetsGenerator({
4835
5189
  servicesManager
4836
5190
  });
4837
5191
  const closeOnOutsideClick = event => {
@@ -4893,7 +5247,7 @@ function LayoutSelector({
4893
5247
  commandOptions: preset.commandOptions,
4894
5248
  onSelection: onSelectionPreset
4895
5249
  })))), /*#__PURE__*/react.createElement("div", {
4896
- className: "bg-primary-dark flex flex-col gap-2.5 border-l-2 border-solid border-black p-2"
5250
+ className: "bg-primary-dark flex flex-col gap-2.5 border-l-2 border-solid border-black p-2"
4897
5251
  }, /*#__PURE__*/react.createElement("div", {
4898
5252
  className: "text-aqua-pale text-xs"
4899
5253
  }, "Custom"), /*#__PURE__*/react.createElement(DropdownContent, {
@@ -5319,7 +5673,7 @@ function adaptItem(item, subProps) {
5319
5673
  value: subProps.selectorProps?.value
5320
5674
  };
5321
5675
  if (item.actionType === 'ShowSubMenu' && !newItem.iconRight) {
5322
- newItem.iconRight = 'chevron-menu';
5676
+ newItem.iconRight = 'chevron-down';
5323
5677
  }
5324
5678
  if (!item.action) {
5325
5679
  newItem.action = (itemRef, componentProps) => {
@@ -5343,8 +5697,8 @@ function adaptItem(item, subProps) {
5343
5697
  }
5344
5698
  // EXTERNAL MODULE: ../../ui/src/components/ContextMenu/ContextMenu.tsx
5345
5699
  var ContextMenu = __webpack_require__(59852);
5346
- // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/index.js + 82 modules
5347
- var dist_esm = __webpack_require__(55139);
5700
+ // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/index.js + 94 modules
5701
+ var dist_esm = __webpack_require__(75851);
5348
5702
  ;// CONCATENATED MODULE: ../../../extensions/default/src/CustomizableContextMenu/ContextMenuController.tsx
5349
5703
  var _ContextMenuController;
5350
5704
 
@@ -5394,15 +5748,22 @@ class ContextMenuController {
5394
5748
  menus,
5395
5749
  selectorProps
5396
5750
  } = contextMenuProps;
5397
- const annotationManager = dist_esm.annotation.state.getAnnotationManager();
5751
+ if (!menus) {
5752
+ console.warn('No menus found for', menuId);
5753
+ return;
5754
+ }
5398
5755
  const {
5399
- locking
5756
+ locking,
5757
+ visibility
5400
5758
  } = dist_esm.annotation;
5401
5759
  const targetAnnotationId = selectorProps?.nearbyToolData?.annotationUID;
5402
- const isLocked = locking.isAnnotationLocked(annotationManager.getAnnotation(targetAnnotationId));
5403
- if (isLocked) {
5404
- console.warn('Annotation is locked.');
5405
- return;
5760
+ if (targetAnnotationId) {
5761
+ const isLocked = locking.isAnnotationLocked(targetAnnotationId);
5762
+ const isVisible = visibility.isAnnotationVisible(targetAnnotationId);
5763
+ if (isLocked || !isVisible) {
5764
+ console.warn(`Annotation is ${isLocked ? 'locked' : 'not visible'}.`);
5765
+ return;
5766
+ }
5406
5767
  }
5407
5768
  const items = getMenuItems(selectorProps || contextMenuProps, event, menus, menuId);
5408
5769
  this.services.uiDialogService.dismiss({
@@ -5413,7 +5774,7 @@ class ContextMenuController {
5413
5774
  isDraggable: false,
5414
5775
  preservePosition: false,
5415
5776
  preventCutOf: true,
5416
- defaultPosition: ContextMenuController._getDefaultPosition(defaultPointsPosition, event?.detail, viewportElement),
5777
+ defaultPosition: ContextMenuController._getDefaultPosition(defaultPointsPosition, event?.detail || event, viewportElement),
5417
5778
  event,
5418
5779
  content: ContextMenu/* default */.A,
5419
5780
  // This naming is part of the uiDialogService convention
@@ -5427,7 +5788,7 @@ class ContextMenuController {
5427
5788
  menus,
5428
5789
  event,
5429
5790
  subMenu,
5430
- eventData: event?.detail,
5791
+ eventData: event?.detail || event,
5431
5792
  onClose: () => {
5432
5793
  this.services.uiDialogService.dismiss({
5433
5794
  id: 'context-menu'
@@ -5469,8 +5830,8 @@ ContextMenuController.getDefaultPosition = () => {
5469
5830
  };
5470
5831
  };
5471
5832
  ContextMenuController._getEventDefaultPosition = eventDetail => ({
5472
- x: eventDetail && eventDetail.currentPoints.client[0],
5473
- y: eventDetail && eventDetail.currentPoints.client[1]
5833
+ x: eventDetail?.currentPoints?.client[0] ?? eventDetail?.pageX,
5834
+ y: eventDetail?.currentPoints?.client[1] ?? eventDetail?.pageY
5474
5835
  });
5475
5836
  ContextMenuController._getElementDefaultPosition = element => {
5476
5837
  if (element) {
@@ -5525,34 +5886,6 @@ ContextMenuController._getDefaultPosition = (canvasPoints, eventDetail, viewerEl
5525
5886
  }
5526
5887
  return position;
5527
5888
  };
5528
- ;// CONCATENATED MODULE: ../../../extensions/default/src/CustomizableContextMenu/defaultContextMenu.ts
5529
- const defaultContextMenu = {
5530
- id: 'measurementsContextMenu',
5531
- customizationType: 'ohif.contextMenu',
5532
- menus: [
5533
- // Get the items from the UI Customization for the menu name (and have a custom name)
5534
- {
5535
- id: 'forExistingMeasurement',
5536
- selector: ({
5537
- nearbyToolData
5538
- }) => !!nearbyToolData,
5539
- items: [{
5540
- label: 'Delete measurement',
5541
- commands: [{
5542
- commandName: 'deleteMeasurement',
5543
- // we only have support for cornerstoneTools context menu since
5544
- // they are svg based
5545
- context: 'CORNERSTONE'
5546
- }]
5547
- }, {
5548
- label: 'Add Label',
5549
- commands: [{
5550
- commandName: 'setMeasurementLabel'
5551
- }]
5552
- }]
5553
- }]
5554
- };
5555
- /* harmony default export */ const CustomizableContextMenu_defaultContextMenu = (defaultContextMenu);
5556
5889
  ;// CONCATENATED MODULE: ../../../extensions/default/src/CustomizableContextMenu/types.ts
5557
5890
 
5558
5891
 
@@ -5561,7 +5894,6 @@ const defaultContextMenu = {
5561
5894
 
5562
5895
 
5563
5896
 
5564
-
5565
5897
  // EXTERNAL MODULE: ../../../node_modules/moment/moment.js
5566
5898
  var moment = __webpack_require__(14867);
5567
5899
  var moment_default = /*#__PURE__*/__webpack_require__.n(moment);
@@ -6301,7 +6633,7 @@ const reuseCachedLayout = (state, hangingProtocolService) => {
6301
6633
 
6302
6634
 
6303
6635
  const useViewportsByPositionStore_PRESENTATION_TYPE_ID = 'viewportsByPositionId';
6304
- const useViewportsByPositionStore_DEBUG_STORE = true;
6636
+ const useViewportsByPositionStore_DEBUG_STORE = false;
6305
6637
 
6306
6638
  /**
6307
6639
  * Represents the state and actions for managing viewports by position.
@@ -6450,8 +6782,6 @@ const findViewportsByPosition = (state, {
6450
6782
  initialInDisplay.forEach(displaySetInstanceUID => addInitialInDisplay(displaySetInstanceUID));
6451
6783
  };
6452
6784
  /* harmony default export */ const src_findViewportsByPosition = (findViewportsByPosition);
6453
- // EXTERNAL MODULE: ./index.js + 41 modules
6454
- var index = __webpack_require__(16265);
6455
6785
  ;// CONCATENATED MODULE: ../../../extensions/default/src/stores/useToggleHangingProtocolStore.ts
6456
6786
 
6457
6787
 
@@ -6495,8 +6825,21 @@ const createToggleHangingProtocolStore = set => ({
6495
6825
  const useToggleHangingProtocolStore = (0,zustand_esm/* create */.vt)()(useToggleHangingProtocolStore_DEBUG_STORE ? (0,middleware/* devtools */.lt)(createToggleHangingProtocolStore, {
6496
6826
  name: 'ToggleHangingProtocolStore'
6497
6827
  }) : createToggleHangingProtocolStore);
6498
- // EXTERNAL MODULE: ../../../extensions/default/src/stores/useToggleOneUpViewportGridStore.ts
6499
- var useToggleOneUpViewportGridStore = __webpack_require__(73325);
6828
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/stores/useToggleOneUpViewportGridStore.ts
6829
+
6830
+ const useToggleOneUpViewportGridStore_PRESENTATION_TYPE_ID = 'toggleOneUpViewportGridId';
6831
+ // Stores the entire ViewportGridService getState when toggling to one up
6832
+ // (e.g. via a double click) so that it can be restored when toggling back.
6833
+ const useToggleOneUpViewportGridStore = (0,zustand_esm/* create */.vt)(set => ({
6834
+ toggleOneUpViewportGridStore: null,
6835
+ type: useToggleOneUpViewportGridStore_PRESENTATION_TYPE_ID,
6836
+ setToggleOneUpViewportGridStore: state => set({
6837
+ toggleOneUpViewportGridStore: state
6838
+ }),
6839
+ clearToggleOneUpViewportGridStore: () => set({
6840
+ toggleOneUpViewportGridStore: null
6841
+ })
6842
+ }));
6500
6843
  ;// CONCATENATED MODULE: ../../../extensions/default/src/commandsModule.ts
6501
6844
 
6502
6845
 
@@ -6509,9 +6852,12 @@ var useToggleOneUpViewportGridStore = __webpack_require__(73325);
6509
6852
 
6510
6853
 
6511
6854
 
6855
+
6856
+
6512
6857
  const commandsModule = ({
6513
6858
  servicesManager,
6514
- commandsManager
6859
+ commandsManager,
6860
+ extensionManager
6515
6861
  }) => {
6516
6862
  const {
6517
6863
  customizationService,
@@ -6519,12 +6865,55 @@ const commandsModule = ({
6519
6865
  hangingProtocolService,
6520
6866
  uiNotificationService,
6521
6867
  viewportGridService,
6522
- displaySetService
6868
+ displaySetService,
6869
+ multiMonitorService
6523
6870
  } = servicesManager.services;
6524
6871
 
6525
6872
  // Define a context menu controller for use with any context menus
6526
6873
  const contextMenuController = new ContextMenuController(servicesManager, commandsManager);
6527
6874
  const actions = {
6875
+ /**
6876
+ * Runs a command in multi-monitor mode. No-op if not multi-monitor.
6877
+ */
6878
+ multimonitor: async options => {
6879
+ const {
6880
+ screenDelta,
6881
+ StudyInstanceUID,
6882
+ commands,
6883
+ hashParams
6884
+ } = options;
6885
+ if (multiMonitorService.numberOfScreens < 2) {
6886
+ return options.fallback?.(options);
6887
+ }
6888
+ const newWindow = await multiMonitorService.launchWindow(StudyInstanceUID, screenDelta, hashParams);
6889
+
6890
+ // Only run commands if we successfully got a window with a commands manager
6891
+ if (newWindow && commands) {
6892
+ // Todo: fix this properly, but it takes time for the new window to load
6893
+ // and then the commandsManager is available for it
6894
+ setTimeout(() => {
6895
+ multiMonitorService.run(screenDelta, commands, options);
6896
+ }, 1000);
6897
+ }
6898
+ },
6899
+ /**
6900
+ * Ensures that the specified study is available for display
6901
+ * Then, if commands is specified, runs the given commands list/instance
6902
+ */
6903
+ loadStudy: async options => {
6904
+ const {
6905
+ StudyInstanceUID
6906
+ } = options;
6907
+ const displaySets = displaySetService.getActiveDisplaySets();
6908
+ const isActive = displaySets.find(ds => ds.StudyInstanceUID === StudyInstanceUID);
6909
+ if (isActive) {
6910
+ return;
6911
+ }
6912
+ const [dataSource] = extensionManager.getActiveDataSource();
6913
+ await Panels_requestDisplaySetCreationForStudy(dataSource, displaySetService, StudyInstanceUID);
6914
+ const study = src/* DicomMetadataStore */.H8.getStudy(StudyInstanceUID);
6915
+ hangingProtocolService.addStudy(study);
6916
+ },
6528
6917
  /**
6529
6918
  * Show the context menu.
6530
6919
  * @param options.menuId defines the menu name to lookup, from customizationService
@@ -6545,7 +6934,7 @@ const commandsModule = ({
6545
6934
  ...options
6546
6935
  };
6547
6936
  if (menuCustomizationId) {
6548
- Object.assign(optionsToUse, customizationService.get(menuCustomizationId, CustomizableContextMenu_defaultContextMenu));
6937
+ Object.assign(optionsToUse, customizationService.getCustomization(menuCustomizationId));
6549
6938
  }
6550
6939
 
6551
6940
  // TODO - make the selectorProps richer by including the study metadata and display set.
@@ -6577,7 +6966,7 @@ const commandsModule = ({
6577
6966
  });
6578
6967
  },
6579
6968
  clearMeasurements: () => {
6580
- measurementService.clear();
6969
+ measurementService.clearMeasurements();
6581
6970
  },
6582
6971
  /**
6583
6972
  * Sets the specified protocol
@@ -6602,14 +6991,24 @@ const commandsModule = ({
6602
6991
  * @param options.stageId - the stageId to apply
6603
6992
  * @param options.stageIndex - the index of the stage to go to.
6604
6993
  * @param options.reset - flag to indicate if the HP should be reset to its original and not restored to a previous state
6994
+ *
6995
+ * commandsManager.run('setHangingProtocol', {
6996
+ * activeStudyUID: '1.2.3',
6997
+ * protocolId: 'myProtocol',
6998
+ * stageId: 'myStage',
6999
+ * stageIndex: 0,
7000
+ * reset: false,
7001
+ * });
6605
7002
  */
6606
7003
  setHangingProtocol: ({
6607
7004
  activeStudyUID = '',
7005
+ StudyInstanceUID = '',
6608
7006
  protocolId,
6609
7007
  stageId,
6610
7008
  stageIndex,
6611
7009
  reset = false
6612
7010
  }) => {
7011
+ const toUseStudyInstanceUID = activeStudyUID || StudyInstanceUID;
6613
7012
  try {
6614
7013
  // Stores in the state the display set selector id to displaySetUID mapping
6615
7014
  // Pass in viewportId for the active viewport. This item will get set as
@@ -6631,22 +7030,30 @@ const commandsModule = ({
6631
7030
  }
6632
7031
  } else if (stageIndex === undefined && stageId === undefined) {
6633
7032
  // Re-set the same stage as was previously used
6634
- const hangingId = `${activeStudyUID || hpInfo.activeStudyUID}:${protocolId}`;
7033
+ const hangingId = `${toUseStudyInstanceUID || hpInfo.activeStudyUID}:${protocolId}`;
6635
7034
  stageIndex = hangingProtocolStageIndexMap[hangingId]?.stageIndex;
6636
7035
  }
6637
7036
  const useStageIdx = stageIndex ?? hangingProtocolService.getStageIndex(protocolId, {
6638
7037
  stageId,
6639
7038
  stageIndex
6640
7039
  });
6641
- if (activeStudyUID) {
6642
- hangingProtocolService.setActiveStudyUID(activeStudyUID);
6643
- }
6644
- const storedHanging = `${hangingProtocolService.getState().activeStudyUID}:${protocolId}:${useStageIdx || 0}`;
7040
+ const activeStudyChanged = hangingProtocolService.setActiveStudyUID(toUseStudyInstanceUID);
7041
+ const storedHanging = `${toUseStudyInstanceUID || hangingProtocolService.getState().activeStudyUID}:${protocolId}:${useStageIdx || 0}`;
6645
7042
  const {
6646
7043
  viewportGridState
6647
7044
  } = useViewportGridStore.getState();
6648
7045
  const restoreProtocol = !reset && viewportGridState[storedHanging];
6649
- if (protocolId === hpInfo.protocolId && useStageIdx === hpInfo.stageIndex && !activeStudyUID) {
7046
+ if (reset || activeStudyChanged && !viewportGridState[storedHanging] && stageIndex === undefined && stageId === undefined) {
7047
+ // Run the hanging protocol fresh, re-using the existing study data
7048
+ // This is done on reset or when the study changes and we haven't yet
7049
+ // applied it, and don't specify exact stage to use.
7050
+ const displaySets = displaySetService.getActiveDisplaySets();
7051
+ const activeStudy = {
7052
+ StudyInstanceUID: toUseStudyInstanceUID,
7053
+ displaySets
7054
+ };
7055
+ hangingProtocolService.run(activeStudy, protocolId);
7056
+ } else if (protocolId === hpInfo.protocolId && useStageIdx === hpInfo.stageIndex && !toUseStudyInstanceUID) {
6650
7057
  // Clear the HP setting to reset them
6651
7058
  hangingProtocolService.setProtocol(protocolId, {
6652
7059
  stageId,
@@ -6667,7 +7074,7 @@ const commandsModule = ({
6667
7074
  const {
6668
7075
  setDisplaySetSelector
6669
7076
  } = useDisplaySetSelectorStore.getState();
6670
- setDisplaySetSelector(`${activeStudyUID || hpInfo.activeStudyUID}:activeDisplaySet:0`, null);
7077
+ setDisplaySetSelector(`${toUseStudyInstanceUID || hpInfo.activeStudyUID}:activeDisplaySet:0`, null);
6671
7078
  return true;
6672
7079
  } catch (e) {
6673
7080
  console.error(e);
@@ -6798,7 +7205,7 @@ const commandsModule = ({
6798
7205
  // The viewer is in one-up. Check if there is a state to restore/toggle back to.
6799
7206
  const {
6800
7207
  toggleOneUpViewportGridStore
6801
- } = useToggleOneUpViewportGridStore/* useToggleOneUpViewportGridStore */.Y.getState();
7208
+ } = useToggleOneUpViewportGridStore.getState();
6802
7209
  if (!toggleOneUpViewportGridStore) {
6803
7210
  return;
6804
7211
  }
@@ -6854,7 +7261,7 @@ const commandsModule = ({
6854
7261
  // Store the current viewport grid state so we can toggle it back later.
6855
7262
  const {
6856
7263
  setToggleOneUpViewportGridStore
6857
- } = useToggleOneUpViewportGridStore/* useToggleOneUpViewportGridStore */.Y.getState();
7264
+ } = useToggleOneUpViewportGridStore.getState();
6858
7265
  setToggleOneUpViewportGridStore(viewportGridState);
6859
7266
 
6860
7267
  // one being toggled to one up.
@@ -6894,7 +7301,7 @@ const commandsModule = ({
6894
7301
  * for `replace` is false
6895
7302
  */
6896
7303
  navigateHistory(historyArgs) {
6897
- index/* history */.b.navigate(historyArgs.to, historyArgs.options);
7304
+ index/* history */.b6.navigate(historyArgs.to, historyArgs.options);
6898
7305
  },
6899
7306
  openDICOMTagViewer({
6900
7307
  displaySetInstanceUID
@@ -7004,27 +7411,15 @@ const commandsModule = ({
7004
7411
  }
7005
7412
  };
7006
7413
  const definitions = {
7007
- showContextMenu: {
7008
- commandFn: actions.showContextMenu
7009
- },
7010
- closeContextMenu: {
7011
- commandFn: actions.closeContextMenu
7012
- },
7013
- clearMeasurements: {
7014
- commandFn: actions.clearMeasurements
7015
- },
7016
- displayNotification: {
7017
- commandFn: actions.displayNotification
7018
- },
7019
- setHangingProtocol: {
7020
- commandFn: actions.setHangingProtocol
7021
- },
7022
- toggleHangingProtocol: {
7023
- commandFn: actions.toggleHangingProtocol
7024
- },
7025
- navigateHistory: {
7026
- commandFn: actions.navigateHistory
7027
- },
7414
+ multimonitor: actions.multimonitor,
7415
+ loadStudy: actions.loadStudy,
7416
+ showContextMenu: actions.showContextMenu,
7417
+ closeContextMenu: actions.closeContextMenu,
7418
+ clearMeasurements: actions.clearMeasurements,
7419
+ displayNotification: actions.displayNotification,
7420
+ setHangingProtocol: actions.setHangingProtocol,
7421
+ toggleHangingProtocol: actions.toggleHangingProtocol,
7422
+ navigateHistory: actions.navigateHistory,
7028
7423
  nextStage: {
7029
7424
  commandFn: actions.deltaStage,
7030
7425
  options: {
@@ -7037,18 +7432,10 @@ const commandsModule = ({
7037
7432
  direction: -1
7038
7433
  }
7039
7434
  },
7040
- setViewportGridLayout: {
7041
- commandFn: actions.setViewportGridLayout
7042
- },
7043
- toggleOneUp: {
7044
- commandFn: actions.toggleOneUp
7045
- },
7046
- openDICOMTagViewer: {
7047
- commandFn: actions.openDICOMTagViewer
7048
- },
7049
- updateViewportDisplaySet: {
7050
- commandFn: actions.updateViewportDisplaySet
7051
- }
7435
+ setViewportGridLayout: actions.setViewportGridLayout,
7436
+ toggleOneUp: actions.toggleOneUp,
7437
+ openDICOMTagViewer: actions.openDICOMTagViewer,
7438
+ updateViewportDisplaySet: actions.updateViewportDisplaySet
7052
7439
  };
7053
7440
  return {
7054
7441
  actions,
@@ -7057,22 +7444,71 @@ const commandsModule = ({
7057
7444
  };
7058
7445
  };
7059
7446
  /* harmony default export */ const src_commandsModule = (commandsModule);
7060
- ;// CONCATENATED MODULE: ../../../extensions/default/src/hangingprotocols/hpMNGrid.ts
7061
- /**
7062
- * Sync group configuration for hydrating segmentations across viewports
7063
- * that share the same frame of reference
7064
- * @type {Types.HangingProtocol.SyncGroup}
7065
- */
7066
- const HYDRATE_SEG_SYNC_GROUP = {
7067
- type: 'hydrateseg',
7068
- id: 'sameFORId',
7069
- source: true,
7070
- target: true,
7071
- options: {
7072
- matchingRules: ['sameFOR']
7447
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/hangingprotocols/utils/studySelectors.ts
7448
+ const studyWithImages = [{
7449
+ id: 'OneOrMoreSeries',
7450
+ weight: 25,
7451
+ attribute: 'numberOfDisplaySetsWithImages',
7452
+ constraint: {
7453
+ greaterThan: 0
7073
7454
  }
7074
- };
7075
-
7455
+ }];
7456
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/hangingprotocols/utils/seriesSelectors.ts
7457
+ const seriesWithImages = [{
7458
+ attribute: 'numImageFrames',
7459
+ constraint: {
7460
+ greaterThan: {
7461
+ value: 0
7462
+ }
7463
+ },
7464
+ weight: 1,
7465
+ required: true
7466
+ },
7467
+ // This display set will select the specified items by preference
7468
+ // It has no affect if nothing is specified in the URL.
7469
+ {
7470
+ attribute: 'isDisplaySetFromUrl',
7471
+ weight: 20,
7472
+ constraint: {
7473
+ equals: true
7474
+ }
7475
+ }];
7476
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/hangingprotocols/utils/viewportOptions.ts
7477
+ /** A default viewport options */
7478
+ const viewportOptions = {
7479
+ toolGroupId: 'default',
7480
+ allowUnmatchedView: true,
7481
+ syncGroups: [{
7482
+ type: 'hydrateseg',
7483
+ id: 'sameFORId',
7484
+ source: true,
7485
+ target: true,
7486
+ options: {
7487
+ matchingRules: ['sameFOR']
7488
+ }
7489
+ }]
7490
+ };
7491
+ const hydrateSegDefault = (/* unused pure expression or super */ null && (viewportOptions));
7492
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/hangingprotocols/hpMNGrid.ts
7493
+
7494
+
7495
+
7496
+
7497
+ /**
7498
+ * Sync group configuration for hydrating segmentations across viewports
7499
+ * that share the same frame of reference
7500
+ * @type {Types.HangingProtocol.SyncGroup}
7501
+ */
7502
+ const HYDRATE_SEG_SYNC_GROUP = {
7503
+ type: 'hydrateseg',
7504
+ id: 'sameFORId',
7505
+ source: true,
7506
+ target: true,
7507
+ options: {
7508
+ matchingRules: ['sameFOR']
7509
+ }
7510
+ };
7511
+
7076
7512
  /**
7077
7513
  * This hanging protocol can be activated on the primary mode by directly
7078
7514
  * referencing it in a URL or by directly including it within a mode, e.g.:
@@ -7083,42 +7519,18 @@ const hpMN = {
7083
7519
  id: '@ohif/mnGrid',
7084
7520
  description: 'Has various hanging protocol grid layouts',
7085
7521
  name: '2x2',
7086
- protocolMatchingRules: [{
7087
- id: 'OneOrMoreSeries',
7088
- weight: 25,
7089
- attribute: 'numberOfDisplaySetsWithImages',
7090
- constraint: {
7091
- greaterThan: 0
7092
- }
7093
- }],
7522
+ protocolMatchingRules: studyWithImages,
7094
7523
  toolGroupIds: ['default'],
7095
7524
  displaySetSelectors: {
7096
7525
  defaultDisplaySetId: {
7097
- seriesMatchingRules: [{
7098
- attribute: 'numImageFrames',
7099
- constraint: {
7100
- greaterThan: {
7101
- value: 0
7102
- }
7103
- },
7104
- required: true
7105
- },
7106
- // This display set will select the specified items by preference
7107
- // It has no affect if nothing is specified in the URL.
7108
- {
7109
- attribute: 'isDisplaySetFromUrl',
7110
- weight: 10,
7111
- constraint: {
7112
- equals: true
7113
- }
7114
- }]
7526
+ allowUnmatchedView: true,
7527
+ seriesMatchingRules: seriesWithImages
7115
7528
  }
7116
7529
  },
7117
7530
  defaultViewport: {
7118
7531
  viewportOptions: {
7119
7532
  viewportType: 'stack',
7120
7533
  toolGroupId: 'default',
7121
- allowUnmatchedView: true,
7122
7534
  syncGroups: [HYDRATE_SEG_SYNC_GROUP]
7123
7535
  },
7124
7536
  displaySets: [{
@@ -7142,63 +7554,24 @@ const hpMN = {
7142
7554
  }
7143
7555
  },
7144
7556
  viewports: [{
7145
- viewportOptions: {
7146
- toolGroupId: 'default',
7147
- allowUnmatchedView: true,
7148
- syncGroups: [{
7149
- type: 'hydrateseg',
7150
- id: 'sameFORId',
7151
- source: true,
7152
- target: true,
7153
- options: {
7154
- matchingRules: ['sameFOR']
7155
- }
7156
- }]
7157
- },
7557
+ viewportOptions: viewportOptions,
7158
7558
  displaySets: [{
7159
7559
  id: 'defaultDisplaySetId'
7160
7560
  }]
7161
7561
  }, {
7162
- viewportOptions: {
7163
- toolGroupId: 'default',
7164
- allowUnmatchedView: true
7165
- },
7562
+ viewportOptions: viewportOptions,
7166
7563
  displaySets: [{
7167
7564
  matchedDisplaySetsIndex: 1,
7168
7565
  id: 'defaultDisplaySetId'
7169
7566
  }]
7170
7567
  }, {
7171
- viewportOptions: {
7172
- toolGroupId: 'default',
7173
- allowUnmatchedView: true,
7174
- syncGroups: [{
7175
- type: 'hydrateseg',
7176
- id: 'sameFORId',
7177
- source: true,
7178
- target: true
7179
- // options: {
7180
- // matchingRules: ['sameFOR'],
7181
- // },
7182
- }]
7183
- },
7568
+ viewportOptions: viewportOptions,
7184
7569
  displaySets: [{
7185
7570
  matchedDisplaySetsIndex: 2,
7186
7571
  id: 'defaultDisplaySetId'
7187
7572
  }]
7188
7573
  }, {
7189
- viewportOptions: {
7190
- toolGroupId: 'default',
7191
- allowUnmatchedView: true,
7192
- syncGroups: [{
7193
- type: 'hydrateseg',
7194
- id: 'sameFORId',
7195
- source: true,
7196
- target: true
7197
- // options: {
7198
- // matchingRules: ['sameFOR'],
7199
- // },
7200
- }]
7201
- },
7574
+ viewportOptions: viewportOptions,
7202
7575
  displaySets: [{
7203
7576
  matchedDisplaySetsIndex: 3,
7204
7577
  id: 'defaultDisplaySetId'
@@ -7207,11 +7580,7 @@ const hpMN = {
7207
7580
  },
7208
7581
  // 3x1 stage
7209
7582
  {
7210
- id: '3x1',
7211
- // Obsolete settings:
7212
- requiredViewports: 1,
7213
- preferredViewports: 3,
7214
- // New equivalent:
7583
+ name: '3x1',
7215
7584
  stageActivation: {
7216
7585
  enabled: {
7217
7586
  minViewportsMatched: 3
@@ -7225,27 +7594,18 @@ const hpMN = {
7225
7594
  }
7226
7595
  },
7227
7596
  viewports: [{
7228
- viewportOptions: {
7229
- toolGroupId: 'default',
7230
- allowUnmatchedView: true
7231
- },
7597
+ viewportOptions: viewportOptions,
7232
7598
  displaySets: [{
7233
7599
  id: 'defaultDisplaySetId'
7234
7600
  }]
7235
7601
  }, {
7236
- viewportOptions: {
7237
- toolGroupId: 'default',
7238
- allowUnmatchedView: true
7239
- },
7602
+ viewportOptions: viewportOptions,
7240
7603
  displaySets: [{
7241
7604
  id: 'defaultDisplaySetId',
7242
7605
  matchedDisplaySetsIndex: 1
7243
7606
  }]
7244
7607
  }, {
7245
- viewportOptions: {
7246
- toolGroupId: 'default',
7247
- allowUnmatchedView: true
7248
- },
7608
+ viewportOptions: viewportOptions,
7249
7609
  displaySets: [{
7250
7610
  id: 'defaultDisplaySetId',
7251
7611
  matchedDisplaySetsIndex: 2
@@ -7254,9 +7614,7 @@ const hpMN = {
7254
7614
  },
7255
7615
  // A 2x1 stage
7256
7616
  {
7257
- id: '2x1',
7258
- requiredViewports: 1,
7259
- preferredViewports: 2,
7617
+ name: '2x1',
7260
7618
  stageActivation: {
7261
7619
  enabled: {
7262
7620
  minViewportsMatched: 2
@@ -7270,18 +7628,12 @@ const hpMN = {
7270
7628
  }
7271
7629
  },
7272
7630
  viewports: [{
7273
- viewportOptions: {
7274
- toolGroupId: 'default',
7275
- allowUnmatchedView: true
7276
- },
7631
+ viewportOptions: viewportOptions,
7277
7632
  displaySets: [{
7278
7633
  id: 'defaultDisplaySetId'
7279
7634
  }]
7280
7635
  }, {
7281
- viewportOptions: {
7282
- toolGroupId: 'default',
7283
- allowUnmatchedView: true
7284
- },
7636
+ viewportOptions: viewportOptions,
7285
7637
  displaySets: [{
7286
7638
  matchedDisplaySetsIndex: 1,
7287
7639
  id: 'defaultDisplaySetId'
@@ -7290,9 +7642,7 @@ const hpMN = {
7290
7642
  },
7291
7643
  // A 1x1 stage - should be automatically activated if there is only 1 viewable instance
7292
7644
  {
7293
- id: '1x1',
7294
- requiredViewports: 1,
7295
- preferredViewports: 1,
7645
+ name: '1x1',
7296
7646
  stageActivation: {
7297
7647
  enabled: {
7298
7648
  minViewportsMatched: 1
@@ -7306,10 +7656,7 @@ const hpMN = {
7306
7656
  }
7307
7657
  },
7308
7658
  viewports: [{
7309
- viewportOptions: {
7310
- toolGroupId: 'default',
7311
- allowUnmatchedView: true
7312
- },
7659
+ viewportOptions: viewportOptions,
7313
7660
  displaySets: [{
7314
7661
  id: 'defaultDisplaySetId'
7315
7662
  }]
@@ -7317,7 +7664,135 @@ const hpMN = {
7317
7664
  }],
7318
7665
  numberOfPriorsReferenced: -1
7319
7666
  };
7320
- /* harmony default export */ const hpMNGrid = (hpMN);
7667
+
7668
+ /**
7669
+ * This hanging protocol can be activated on the primary mode by directly
7670
+ * referencing it in a URL or by directly including it within a mode, e.g.:
7671
+ * `&hangingProtocolId=@ohif/mnGrid8` added to the viewer URL
7672
+ * It is not included in the viewer mode by default.
7673
+ */
7674
+ const hpMN8 = {
7675
+ ...hpMN,
7676
+ id: '@ohif/mnGrid8',
7677
+ description: 'Has various hanging protocol grid layouts up to 4x2',
7678
+ name: '4x2',
7679
+ stages: [{
7680
+ id: '4x2',
7681
+ name: '4x2',
7682
+ stageActivation: {
7683
+ enabled: {
7684
+ minViewportsMatched: 7
7685
+ }
7686
+ },
7687
+ viewportStructure: {
7688
+ layoutType: 'grid',
7689
+ properties: {
7690
+ rows: 2,
7691
+ columns: 4
7692
+ }
7693
+ },
7694
+ viewports: [{
7695
+ viewportOptions: viewportOptions,
7696
+ displaySets: [{
7697
+ id: 'defaultDisplaySetId'
7698
+ }]
7699
+ }, {
7700
+ viewportOptions: viewportOptions,
7701
+ displaySets: [{
7702
+ matchedDisplaySetsIndex: 1,
7703
+ id: 'defaultDisplaySetId'
7704
+ }]
7705
+ }, {
7706
+ viewportOptions: viewportOptions,
7707
+ displaySets: [{
7708
+ matchedDisplaySetsIndex: 2,
7709
+ id: 'defaultDisplaySetId'
7710
+ }]
7711
+ }, {
7712
+ viewportOptions: viewportOptions,
7713
+ displaySets: [{
7714
+ matchedDisplaySetsIndex: 3,
7715
+ id: 'defaultDisplaySetId'
7716
+ }]
7717
+ }, {
7718
+ viewportOptions: viewportOptions,
7719
+ displaySets: [{
7720
+ matchedDisplaySetsIndex: 4,
7721
+ id: 'defaultDisplaySetId'
7722
+ }]
7723
+ }, {
7724
+ viewportOptions: viewportOptions,
7725
+ displaySets: [{
7726
+ matchedDisplaySetsIndex: 5,
7727
+ id: 'defaultDisplaySetId'
7728
+ }]
7729
+ }, {
7730
+ viewportOptions: viewportOptions,
7731
+ displaySets: [{
7732
+ matchedDisplaySetsIndex: 6,
7733
+ id: 'defaultDisplaySetId'
7734
+ }]
7735
+ }, {
7736
+ viewportOptions: viewportOptions,
7737
+ displaySets: [{
7738
+ matchedDisplaySetsIndex: 7,
7739
+ id: 'defaultDisplaySetId'
7740
+ }]
7741
+ }]
7742
+ }, {
7743
+ id: '3x2',
7744
+ name: '3x2',
7745
+ stageActivation: {
7746
+ enabled: {
7747
+ minViewportsMatched: 5
7748
+ }
7749
+ },
7750
+ viewportStructure: {
7751
+ layoutType: 'grid',
7752
+ properties: {
7753
+ rows: 2,
7754
+ columns: 3
7755
+ }
7756
+ },
7757
+ viewports: [{
7758
+ viewportOptions: viewportOptions,
7759
+ displaySets: [{
7760
+ id: 'defaultDisplaySetId'
7761
+ }]
7762
+ }, {
7763
+ viewportOptions: viewportOptions,
7764
+ displaySets: [{
7765
+ matchedDisplaySetsIndex: 1,
7766
+ id: 'defaultDisplaySetId'
7767
+ }]
7768
+ }, {
7769
+ viewportOptions: viewportOptions,
7770
+ displaySets: [{
7771
+ matchedDisplaySetsIndex: 2,
7772
+ id: 'defaultDisplaySetId'
7773
+ }]
7774
+ }, {
7775
+ viewportOptions: viewportOptions,
7776
+ displaySets: [{
7777
+ matchedDisplaySetsIndex: 3,
7778
+ id: 'defaultDisplaySetId'
7779
+ }]
7780
+ }, {
7781
+ viewportOptions: viewportOptions,
7782
+ displaySets: [{
7783
+ matchedDisplaySetsIndex: 4,
7784
+ id: 'defaultDisplaySetId'
7785
+ }]
7786
+ }, {
7787
+ viewportOptions: viewportOptions,
7788
+ displaySets: [{
7789
+ matchedDisplaySetsIndex: 5,
7790
+ id: 'defaultDisplaySetId'
7791
+ }]
7792
+ }]
7793
+ }, ...hpMN.stages]
7794
+ };
7795
+ /* harmony default export */ const hpMNGrid = ((/* unused pure expression or super */ null && (hpMN)));
7321
7796
  ;// CONCATENATED MODULE: ../../../extensions/default/src/hangingprotocols/hpCompare.ts
7322
7797
  const defaultDisplaySetSelector = {
7323
7798
  studyMatchingRules: [{
@@ -7344,7 +7819,7 @@ const defaultDisplaySetSelector = {
7344
7819
  // It has no affect if nothing is specified in the URL.
7345
7820
  {
7346
7821
  attribute: 'isDisplaySetFromUrl',
7347
- weight: 10,
7822
+ weight: 20,
7348
7823
  constraint: {
7349
7824
  equals: true
7350
7825
  }
@@ -7375,7 +7850,7 @@ const priorDisplaySetSelector = {
7375
7850
  // It has no affect if nothing is specified in the URL.
7376
7851
  {
7377
7852
  attribute: 'isDisplaySetFromUrl',
7378
- weight: 10,
7853
+ weight: 20,
7379
7854
  constraint: {
7380
7855
  equals: true
7381
7856
  }
@@ -7485,7 +7960,7 @@ const hpMNCompare = {
7485
7960
  }]
7486
7961
  };
7487
7962
  /* harmony default export */ const hpCompare = (hpMNCompare);
7488
- ;// CONCATENATED MODULE: ../../../extensions/default/src/hangingprotocols/mammoDisplaySetSelector.ts
7963
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/hangingprotocols/utils/mammoDisplaySetSelector.ts
7489
7964
  const priorStudyMatchingRules = [{
7490
7965
  // The priorInstance is a study counter that indicates what position this study is in
7491
7966
  // and the value comes from the options parameter.
@@ -7865,7 +8340,7 @@ const hpScale = {
7865
8340
  // It has no affect if nothing is specified in the URL.
7866
8341
  {
7867
8342
  attribute: 'isDisplaySetFromUrl',
7868
- weight: 10,
8343
+ weight: 20,
7869
8344
  constraint: {
7870
8345
  equals: true
7871
8346
  }
@@ -8001,7 +8476,7 @@ const defaultProtocol = {
8001
8476
  // It has no affect if nothing is specified in the URL.
8002
8477
  {
8003
8478
  attribute: 'isDisplaySetFromUrl',
8004
- weight: 10,
8479
+ weight: 20,
8005
8480
  constraint: {
8006
8481
  equals: true
8007
8482
  }
@@ -8067,11 +8542,51 @@ function getHangingProtocolModule() {
8067
8542
  },
8068
8543
  // Create a MxN hanging protocol available by default
8069
8544
  {
8070
- name: hpMNGrid.id,
8071
- protocol: hpMNGrid
8545
+ name: hpMN.id,
8546
+ protocol: hpMN
8547
+ }, {
8548
+ name: hpMN8.id,
8549
+ protocol: hpMN8
8072
8550
  }];
8073
8551
  }
8074
8552
  /* harmony default export */ const src_getHangingProtocolModule = (getHangingProtocolModule);
8553
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/customizations/defaultContextMenuCustomization.ts
8554
+ /* harmony default export */ const defaultContextMenuCustomization = ({
8555
+ measurementsContextMenu: {
8556
+ inheritsFrom: 'ohif.contextMenu',
8557
+ menus: [
8558
+ // Get the items from the UI Customization for the menu name (and have a custom name)
8559
+ {
8560
+ id: 'forExistingMeasurement',
8561
+ selector: ({
8562
+ nearbyToolData
8563
+ }) => !!nearbyToolData,
8564
+ items: [{
8565
+ label: 'Delete measurement',
8566
+ commands: 'deleteMeasurement'
8567
+ }, {
8568
+ label: 'Add Label',
8569
+ commands: 'setMeasurementLabel'
8570
+ }]
8571
+ }]
8572
+ }
8573
+ });
8574
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/customizations/helloPageCustomization.tsx
8575
+
8576
+ /* harmony default export */ const helloPageCustomization = ({
8577
+ 'routes.customRoutes': {
8578
+ routes: {
8579
+ $push: [{
8580
+ path: '/custom',
8581
+ children: () => /*#__PURE__*/react.createElement("h1", {
8582
+ style: {
8583
+ color: 'white'
8584
+ }
8585
+ }, "Hello Custom Route")
8586
+ }]
8587
+ }
8588
+ }
8589
+ });
8075
8590
  ;// CONCATENATED MODULE: ../../../extensions/default/src/Panels/DataSourceSelector.tsx
8076
8591
 
8077
8592
 
@@ -8091,7 +8606,7 @@ function DataSourceSelector() {
8091
8606
  height: '100%'
8092
8607
  }
8093
8608
  }, /*#__PURE__*/react.createElement("div", {
8094
- className: "flex h-screen w-screen items-center justify-center "
8609
+ className: "flex h-screen w-screen items-center justify-center"
8095
8610
  }, /*#__PURE__*/react.createElement("div", {
8096
8611
  className: "bg-secondary-dark mx-auto space-y-2 rounded-lg py-8 px-8 drop-shadow-md"
8097
8612
  }, /*#__PURE__*/react.createElement("img", {
@@ -8116,11 +8631,230 @@ function DataSourceSelector() {
8116
8631
  }, ds.sourceName), /*#__PURE__*/react.createElement("br", null)))))));
8117
8632
  }
8118
8633
  /* harmony default export */ const Panels_DataSourceSelector = (DataSourceSelector);
8634
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/customizations/datasourcesCustomization.tsx
8635
+
8636
+ /* harmony default export */ const datasourcesCustomization = ({
8637
+ 'routes.customRoutes': {
8638
+ routes: {
8639
+ $push: [{
8640
+ path: '/datasources',
8641
+ children: Panels_DataSourceSelector
8642
+ }]
8643
+ }
8644
+ }
8645
+ });
8646
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/customizations/multimonitorCustomization.ts
8647
+ /* harmony default export */ const multimonitorCustomization = ({
8648
+ 'studyBrowser.studyMenuItems': {
8649
+ $push: [{
8650
+ id: 'applyHangingProtocol',
8651
+ label: 'Apply Hanging Protocol',
8652
+ iconName: 'ViewportViews',
8653
+ items: [{
8654
+ id: 'applyDefaultProtocol',
8655
+ label: 'Default',
8656
+ commands: ['loadStudy', {
8657
+ commandName: 'setHangingProtocol',
8658
+ commandOptions: {
8659
+ protocolId: 'default'
8660
+ }
8661
+ }]
8662
+ }, {
8663
+ id: 'applyMPRProtocol',
8664
+ label: '2x2 Grid',
8665
+ commands: ['loadStudy', {
8666
+ commandName: 'setHangingProtocol',
8667
+ commandOptions: {
8668
+ protocolId: '@ohif/mnGrid'
8669
+ }
8670
+ }]
8671
+ }]
8672
+ }, {
8673
+ id: 'showInOtherMonitor',
8674
+ label: 'Launch On Second Monitor',
8675
+ iconName: 'DicomTagBrowser',
8676
+ selector: ({
8677
+ servicesManager
8678
+ }) => {
8679
+ const {
8680
+ multiMonitorService
8681
+ } = servicesManager.services;
8682
+ return multiMonitorService.isMultimonitor;
8683
+ },
8684
+ commands: {
8685
+ commandName: 'multimonitor',
8686
+ commandOptions: {
8687
+ hashParams: '&hangingProtocolId=@ohif/mnGrid8',
8688
+ commands: ['loadStudy', {
8689
+ commandName: 'setHangingProtocol',
8690
+ commandOptions: {
8691
+ protocolId: '@ohif/mnGrid8'
8692
+ }
8693
+ }]
8694
+ }
8695
+ }
8696
+ }]
8697
+ }
8698
+ });
8699
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/customizations/customRoutesCustomization.ts
8700
+ /* harmony default export */ const customRoutesCustomization = ({
8701
+ 'routes.customRoutes': {
8702
+ routes: [],
8703
+ notFoundRoute: null
8704
+ }
8705
+ });
8706
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/customizations/studyBrowserCustomization.ts
8707
+
8708
+ const {
8709
+ formatDate: studyBrowserCustomization_formatDate
8710
+ } = src/* utils */.Wp;
8711
+ /* harmony default export */ const studyBrowserCustomization = ({
8712
+ 'studyBrowser.studyMenuItems': [],
8713
+ 'studyBrowser.thumbnailMenuItems': [{
8714
+ id: 'tagBrowser',
8715
+ label: 'Tag Browser',
8716
+ iconName: 'DicomTagBrowser',
8717
+ commands: 'openDICOMTagViewer'
8718
+ }],
8719
+ 'studyBrowser.sortFunctions': [{
8720
+ label: 'Series Number',
8721
+ sortFunction: (a, b) => {
8722
+ return a?.SeriesNumber - b?.SeriesNumber;
8723
+ }
8724
+ }, {
8725
+ label: 'Series Date',
8726
+ sortFunction: (a, b) => {
8727
+ const dateA = new Date(studyBrowserCustomization_formatDate(a?.SeriesDate));
8728
+ const dateB = new Date(studyBrowserCustomization_formatDate(b?.SeriesDate));
8729
+ return dateB.getTime() - dateA.getTime();
8730
+ }
8731
+ }],
8732
+ 'studyBrowser.viewPresets': [{
8733
+ id: 'list',
8734
+ iconName: 'ListView',
8735
+ selected: false
8736
+ }, {
8737
+ id: 'thumbnails',
8738
+ iconName: 'ThumbnailView',
8739
+ selected: true
8740
+ }],
8741
+ 'studyBrowser.studyMode': 'all'
8742
+ });
8743
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/customizations/overlayItemCustomization.tsx
8744
+
8745
+ /* harmony default export */ const overlayItemCustomization = ({
8746
+ 'ohif.overlayItem': function (props) {
8747
+ if (this.condition && !this.condition(props)) {
8748
+ return null;
8749
+ }
8750
+ const {
8751
+ instance
8752
+ } = props;
8753
+ const value = instance && this.attribute ? instance[this.attribute] : this.contentF && typeof this.contentF === 'function' ? this.contentF(props) : null;
8754
+ if (!value) {
8755
+ return null;
8756
+ }
8757
+ return /*#__PURE__*/react.createElement("span", {
8758
+ className: "overlay-item flex flex-row",
8759
+ style: {
8760
+ color: this.color || undefined
8761
+ },
8762
+ title: this.title || ''
8763
+ }, this.label && /*#__PURE__*/react.createElement("span", {
8764
+ className: "mr-1 shrink-0"
8765
+ }, this.label), /*#__PURE__*/react.createElement("span", {
8766
+ className: "font-light"
8767
+ }, value));
8768
+ }
8769
+ });
8770
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/customizations/contextMenuCustomization.ts
8771
+ /* harmony default export */ const contextMenuCustomization = ({
8772
+ 'ohif.contextMenu': {
8773
+ $transform: function (customizationService) {
8774
+ /**
8775
+ * Applies the inheritsFrom to all the menu items.
8776
+ * This function clones the object and child objects to prevent
8777
+ * changes to the original customization object.
8778
+ */
8779
+ // Don't modify the children, as those are copied by reference
8780
+ const clonedObject = {
8781
+ ...this
8782
+ };
8783
+ clonedObject.menus = this.menus.map(menu => ({
8784
+ ...menu
8785
+ }));
8786
+ for (const menu of clonedObject.menus) {
8787
+ const {
8788
+ items: originalItems
8789
+ } = menu;
8790
+ menu.items = [];
8791
+ for (const item of originalItems) {
8792
+ menu.items.push(customizationService.transform(item));
8793
+ }
8794
+ }
8795
+ return clonedObject;
8796
+ }
8797
+ }
8798
+ });
8799
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/customizations/menuContentCustomization.tsx
8800
+
8801
+
8802
+ /* harmony default export */ const menuContentCustomization = ({
8803
+ 'ohif.menuContent': function (props) {
8804
+ const {
8805
+ item: topLevelItem,
8806
+ commandsManager,
8807
+ servicesManager,
8808
+ ...rest
8809
+ } = props;
8810
+ const content = function (subProps) {
8811
+ const {
8812
+ item: subItem
8813
+ } = subProps;
8814
+
8815
+ // Regular menu item
8816
+ const isDisabled = subItem.selector && !subItem.selector({
8817
+ servicesManager
8818
+ });
8819
+ return /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._2, {
8820
+ disabled: isDisabled,
8821
+ onSelect: () => {
8822
+ commandsManager.runAsync(subItem.commands, {
8823
+ ...subItem.commandOptions,
8824
+ ...rest
8825
+ });
8826
+ },
8827
+ className: "gap-[6px]"
8828
+ }, subItem.iconName && /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI.ByName, {
8829
+ name: subItem.iconName,
8830
+ className: "-ml-1"
8831
+ }), subItem.label);
8832
+ };
8833
+
8834
+ // If item has sub-items, render a submenu
8835
+ if (topLevelItem.items) {
8836
+ return /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuSub */.lv, null, /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuSubTrigger */.nV, {
8837
+ className: "gap-[6px]"
8838
+ }, topLevelItem.iconName && /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI.ByName, {
8839
+ name: topLevelItem.iconName,
8840
+ className: "-ml-1"
8841
+ }), topLevelItem.label), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuPortal */.dc, null, /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuSubContent */.M5, null, topLevelItem.items.map(subItem => content({
8842
+ ...props,
8843
+ item: subItem
8844
+ })))));
8845
+ }
8846
+ return content({
8847
+ ...props,
8848
+ item: topLevelItem
8849
+ });
8850
+ }
8851
+ });
8119
8852
  ;// CONCATENATED MODULE: ../../../extensions/default/src/Components/ItemListComponent.tsx
8120
8853
 
8121
8854
 
8122
8855
 
8123
8856
 
8857
+
8124
8858
  function ItemListComponent({
8125
8859
  itemLabel,
8126
8860
  itemList,
@@ -8150,8 +8884,7 @@ function ItemListComponent({
8150
8884
  className: 'h-full w-full'
8151
8885
  }) : itemList.length === 0 ? /*#__PURE__*/react.createElement("div", {
8152
8886
  className: "text-primary-light flex h-full flex-col items-center justify-center px-6 py-4"
8153
- }, /*#__PURE__*/react.createElement(ui_src/* Icon */.In, {
8154
- name: "magnifier",
8887
+ }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI.ToolMagnify, {
8155
8888
  className: "mb-4"
8156
8889
  }), /*#__PURE__*/react.createElement("span", null, t(`No ${itemLabel} available`))) : /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement("div", {
8157
8890
  className: "bg-secondary-dark px-3 py-1.5 text-white"
@@ -8165,7 +8898,7 @@ function ItemListComponent({
8165
8898
  }, /*#__PURE__*/react.createElement("div", null, item.name), /*#__PURE__*/react.createElement(ui_src/* Button */.$n, {
8166
8899
  onClick: () => onItemClicked(item),
8167
8900
  className: "invisible group-hover:visible",
8168
- endIcon: /*#__PURE__*/react.createElement(ui_src/* Icon */.In, {
8901
+ endIcon: /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI.ByName, {
8169
8902
  name: "arrow-left"
8170
8903
  })
8171
8904
  }, t('Select')));
@@ -8260,9 +8993,9 @@ function DataSourceConfigurationModalComponent({
8260
8993
  } : undefined
8261
8994
  }, /*#__PURE__*/react.createElement("div", {
8262
8995
  className: "text- flex items-center gap-2"
8263
- }, itemLabelIndex < selectedItems.length ? /*#__PURE__*/react.createElement(ui_src/* Icon */.In, {
8996
+ }, itemLabelIndex < selectedItems.length ? /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI.ByName, {
8264
8997
  name: "status-tracked"
8265
- }) : /*#__PURE__*/react.createElement(ui_src/* Icon */.In, {
8998
+ }) : /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI.ByName, {
8266
8999
  name: "status-untracked"
8267
9000
  }), /*#__PURE__*/react.createElement("div", {
8268
9001
  className: classnames_default()(NO_WRAP_ELLIPSIS_CLASS_NAMES)
@@ -8290,6 +9023,7 @@ function DataSourceConfigurationModalComponent({
8290
9023
 
8291
9024
 
8292
9025
 
9026
+
8293
9027
  function DataSourceConfigurationComponent({
8294
9028
  servicesManager,
8295
9029
  extensionManager
@@ -8315,7 +9049,9 @@ function DataSourceConfigurationComponent({
8315
9049
  }
8316
9050
  const {
8317
9051
  factory: configurationAPIFactory
8318
- } = customizationService.get(activeDataSourceDef.configuration.configurationAPI) ?? {};
9052
+ } = customizationService.getCustomization(activeDataSourceDef.configuration.configurationAPI) ?? {
9053
+ factory: () => null
9054
+ };
8319
9055
  if (!configurationAPIFactory) {
8320
9056
  return;
8321
9057
  }
@@ -8359,8 +9095,7 @@ function DataSourceConfigurationComponent({
8359
9095
  }, [configurationAPI, configuredItems, showConfigurationModal]);
8360
9096
  return configuredItems ? /*#__PURE__*/react.createElement("div", {
8361
9097
  className: "text-aqua-pale flex items-center overflow-hidden"
8362
- }, /*#__PURE__*/react.createElement(ui_src/* Icon */.In, {
8363
- name: "settings",
9098
+ }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI.Settings, {
8364
9099
  className: "mr-2.5 h-3.5 w-3.5 shrink-0 cursor-pointer",
8365
9100
  onClick: showConfigurationModal
8366
9101
  }), configuredItems.map((item, itemIndex) => {
@@ -8541,6 +9276,44 @@ class GoogleCloudDataSourceConfigurationAPI {
8541
9276
  }
8542
9277
  }
8543
9278
 
9279
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/customizations/dataSourceConfigurationCustomization.ts
9280
+
9281
+
9282
+ function getDataSourceConfigurationCustomization({
9283
+ servicesManager,
9284
+ extensionManager
9285
+ }) {
9286
+ return {
9287
+ // the generic GUI component to configure a data source using an instance of a BaseDataSourceConfigurationAPI
9288
+ 'ohif.dataSourceConfigurationComponent': Components_DataSourceConfigurationComponent.bind(null, {
9289
+ servicesManager,
9290
+ extensionManager
9291
+ }),
9292
+ // The factory for creating an instance of a BaseDataSourceConfigurationAPI for Google Cloud Healthcare
9293
+ 'ohif.dataSourceConfigurationAPI.google': dataSourceName => new GoogleCloudDataSourceConfigurationAPI(dataSourceName, servicesManager, extensionManager)
9294
+ };
9295
+ }
9296
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/customizations/progressDropdownCustomization.ts
9297
+
9298
+ /* harmony default export */ const progressDropdownCustomization = ({
9299
+ progressDropdownWithServiceComponent: ProgressDropdownWithService
9300
+ });
9301
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/customizations/sortingCriteriaCustomization.ts
9302
+
9303
+ const {
9304
+ sortingCriteria
9305
+ } = src/* utils */.Wp;
9306
+ /* harmony default export */ const sortingCriteriaCustomization = ({
9307
+ sortingCriteria: sortingCriteria.seriesSortCriteria.seriesInfoSortingCriteria
9308
+ });
9309
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/customizations/onDropHandlerCustomization.ts
9310
+ /* harmony default export */ const onDropHandlerCustomization = ({
9311
+ customOnDropHandler: () => {
9312
+ return Promise.resolve({
9313
+ handled: false
9314
+ });
9315
+ }
9316
+ });
8544
9317
  ;// CONCATENATED MODULE: ../../../extensions/default/src/getCustomizationModule.tsx
8545
9318
 
8546
9319
 
@@ -8548,7 +9321,13 @@ class GoogleCloudDataSourceConfigurationAPI {
8548
9321
 
8549
9322
 
8550
9323
 
8551
- const getCustomizationModule_formatDate = src/* utils */.Wp.formatDate;
9324
+
9325
+
9326
+
9327
+
9328
+
9329
+
9330
+
8552
9331
 
8553
9332
  /**
8554
9333
  *
@@ -8565,161 +9344,30 @@ function getCustomizationModule({
8565
9344
  }) {
8566
9345
  return [{
8567
9346
  name: 'helloPage',
8568
- merge: 'Append',
8569
- value: {
8570
- id: 'customRoutes',
8571
- routes: [{
8572
- path: '/custom',
8573
- children: () => /*#__PURE__*/react.createElement("h1", {
8574
- style: {
8575
- color: 'white'
8576
- }
8577
- }, "Hello Custom Route")
8578
- }]
8579
- }
8580
- },
8581
- // Example customization to list a set of datasources
8582
- {
9347
+ value: helloPageCustomization
9348
+ }, {
8583
9349
  name: 'datasources',
8584
- merge: 'Append',
8585
- value: {
8586
- id: 'customRoutes',
8587
- routes: [{
8588
- path: '/datasources',
8589
- children: Panels_DataSourceSelector
8590
- }]
8591
- }
9350
+ value: datasourcesCustomization
9351
+ }, {
9352
+ name: 'multimonitor',
9353
+ value: multimonitorCustomization
8592
9354
  }, {
8593
9355
  name: 'default',
8594
- value: [
8595
- /**
8596
- * Customization Component Type definition for overlay items.
8597
- * Overlay items are texts (or other components) that will be displayed
8598
- * on a Viewport Overlay, which contains the information panels on the
8599
- * four corners of a viewport.
8600
- *
8601
- * @definition of a overlay item using this type
8602
- * The value to be displayed is defined by
8603
- * - setting DICOM image instance's property to this field,
8604
- * - or defining contentF()
8605
- *
8606
- * {
8607
- * id: string - unique id for the overlay item
8608
- * customizationType: string - indicates customization type definition to this
8609
- * label: string - Label, to be displayed for the item
8610
- * title: string - Tooltip, for the item
8611
- * color: string - Color of the text
8612
- * condition: ({ instance }) => boolean - decides whether to display the overlay item or not
8613
- * attribute: string - property name of the DICOM image instance
8614
- * contentF: ({ instance, formatters }) => string | component,
8615
- * }
8616
- *
8617
- * @example
8618
- * {
8619
- * id: 'PatientNameOverlay',
8620
- * customizationType: 'ohif.overlayItem',
8621
- * label: 'PN:',
8622
- * title: 'Patient Name',
8623
- * color: 'yellow',
8624
- * condition: ({ instance }) => instance && instance.PatientName && instance.PatientName.Alphabetic,
8625
- * attribute: 'PatientName',
8626
- * contentF: ({ instance, formatters: { formatPN } }) => `${formatPN(instance.PatientName.Alphabetic)} ${(instance.PatientSex ? '(' + instance.PatientSex + ')' : '')}`,
8627
- * },
8628
- *
8629
- * @see CustomizableViewportOverlay
8630
- */
8631
- {
8632
- id: 'ohif.overlayItem',
8633
- content: function (props) {
8634
- if (this.condition && !this.condition(props)) {
8635
- return null;
8636
- }
8637
- const {
8638
- instance
8639
- } = props;
8640
- const value = instance && this.attribute ? instance[this.attribute] : this.contentF && typeof this.contentF === 'function' ? this.contentF(props) : null;
8641
- if (!value) {
8642
- return null;
8643
- }
8644
- return /*#__PURE__*/react.createElement("span", {
8645
- className: "overlay-item flex flex-row",
8646
- style: {
8647
- color: this.color || undefined
8648
- },
8649
- title: this.title || ''
8650
- }, this.label && /*#__PURE__*/react.createElement("span", {
8651
- className: "mr-1 shrink-0"
8652
- }, this.label), /*#__PURE__*/react.createElement("span", {
8653
- className: "font-light"
8654
- }, value));
8655
- }
8656
- }, {
8657
- id: 'ohif.contextMenu',
8658
- /** Applies the customizationType to all the menu items.
8659
- * This function clones the object and child objects to prevent
8660
- * changes to the original customization object.
8661
- */
8662
- transform: function (customizationService) {
8663
- // Don't modify the children, as those are copied by reference
8664
- const clonedObject = {
8665
- ...this
8666
- };
8667
- clonedObject.menus = this.menus.map(menu => ({
8668
- ...menu
8669
- }));
8670
- for (const menu of clonedObject.menus) {
8671
- const {
8672
- items: originalItems
8673
- } = menu;
8674
- menu.items = [];
8675
- for (const item of originalItems) {
8676
- menu.items.push(customizationService.transform(item));
8677
- }
8678
- }
8679
- return clonedObject;
8680
- }
8681
- }, {
8682
- // the generic GUI component to configure a data source using an instance of a BaseDataSourceConfigurationAPI
8683
- id: 'ohif.dataSourceConfigurationComponent',
8684
- component: Components_DataSourceConfigurationComponent.bind(null, {
9356
+ value: {
9357
+ ...customRoutesCustomization,
9358
+ ...studyBrowserCustomization,
9359
+ ...overlayItemCustomization,
9360
+ ...contextMenuCustomization,
9361
+ ...menuContentCustomization,
9362
+ ...getDataSourceConfigurationCustomization({
8685
9363
  servicesManager,
8686
9364
  extensionManager
8687
- })
8688
- }, {
8689
- // The factory for creating an instance of a BaseDataSourceConfigurationAPI for Google Cloud Healthcare
8690
- id: 'ohif.dataSourceConfigurationAPI.google',
8691
- factory: dataSourceName => new GoogleCloudDataSourceConfigurationAPI(dataSourceName, servicesManager, extensionManager)
8692
- }, {
8693
- id: 'progressDropdownWithServiceComponent',
8694
- component: ProgressDropdownWithService
8695
- }, {
8696
- id: 'studyBrowser.sortFunctions',
8697
- values: [{
8698
- label: 'Series Number',
8699
- sortFunction: (a, b) => {
8700
- return a?.SeriesNumber - b?.SeriesNumber;
8701
- }
8702
- }, {
8703
- label: 'Series Date',
8704
- sortFunction: (a, b) => {
8705
- const dateA = new Date(getCustomizationModule_formatDate(a?.SeriesDate));
8706
- const dateB = new Date(getCustomizationModule_formatDate(b?.SeriesDate));
8707
- return dateB.getTime() - dateA.getTime();
8708
- }
8709
- }]
8710
- }, {
8711
- id: 'studyBrowser.viewPresets',
8712
- // change your default selected preset here
8713
- value: [{
8714
- id: 'list',
8715
- iconName: 'ListView',
8716
- selected: false
8717
- }, {
8718
- id: 'thumbnails',
8719
- iconName: 'ThumbnailView',
8720
- selected: true
8721
- }]
8722
- }]
9365
+ }),
9366
+ ...progressDropdownCustomization,
9367
+ ...sortingCriteriaCustomization,
9368
+ ...defaultContextMenuCustomization,
9369
+ ...onDropHandlerCustomization
9370
+ }
8723
9371
  }];
8724
9372
  }
8725
9373
  ;// CONCATENATED MODULE: ../../../extensions/default/src/Components/LineChartViewport/LineChartViewport.tsx
@@ -8839,7 +9487,7 @@ function convertInterfaceDateToString(date) {
8839
9487
  return dateString;
8840
9488
  }
8841
9489
 
8842
- ;// CONCATENATED MODULE: ../../../extensions/default/src/hangingprotocols/viewCode.ts
9490
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/hangingprotocols/utils/viewCode.ts
8843
9491
  /* harmony default export */ const viewCode = (displaySet => {
8844
9492
  const ViewCodeSequence = displaySet?.images[0]?.ViewCodeSequence[0];
8845
9493
  if (!ViewCodeSequence) {
@@ -8854,7 +9502,7 @@ function convertInterfaceDateToString(date) {
8854
9502
  }
8855
9503
  return `${CodingSchemeDesignator}:${CodeValue}`;
8856
9504
  });
8857
- ;// CONCATENATED MODULE: ../../../extensions/default/src/hangingprotocols/laterality.ts
9505
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/hangingprotocols/utils/laterality.ts
8858
9506
  /* harmony default export */ const laterality = (displaySet => {
8859
9507
  const frameAnatomy = displaySet?.images?.[0]?.SharedFunctionalGroupsSequence?.[0]?.FrameAnatomySequence?.[0];
8860
9508
  if (!frameAnatomy) {
@@ -8863,7 +9511,7 @@ function convertInterfaceDateToString(date) {
8863
9511
  const laterality = frameAnatomy?.FrameLaterality;
8864
9512
  return laterality;
8865
9513
  });
8866
- ;// CONCATENATED MODULE: ../../../extensions/default/src/hangingprotocols/registerHangingProtocolAttributes.ts
9514
+ ;// CONCATENATED MODULE: ../../../extensions/default/src/hangingprotocols/utils/registerHangingProtocolAttributes.ts
8867
9515
 
8868
9516
 
8869
9517
  function registerHangingProtocolAttributes({
@@ -8883,6 +9531,7 @@ function registerHangingProtocolAttributes({
8883
9531
 
8884
9532
 
8885
9533
 
9534
+
8886
9535
  ;// CONCATENATED MODULE: ../../../extensions/default/src/init.ts
8887
9536
 
8888
9537
 
@@ -9525,7 +10174,7 @@ function promptLabelAnnotation({
9525
10174
  measurementId
9526
10175
  } = evt;
9527
10176
  return new Promise(async function (resolve) {
9528
- const labelConfig = customizationService.get('measurementLabels');
10177
+ const labelConfig = customizationService.getCustomization('measurementLabels');
9529
10178
  const measurement = measurementService.getMeasurement(measurementId);
9530
10179
  const value = await showLabelAnnotationPopup(measurement, servicesManager.services.uiDialogService, labelConfig);
9531
10180
  measurementService.update(measurementId, {
@@ -9580,6 +10229,8 @@ function addIcon(name, icon) {
9580
10229
 
9581
10230
 
9582
10231
 
10232
+
10233
+
9583
10234
 
9584
10235
 
9585
10236
 
@@ -9620,30 +10271,6 @@ const defaultExtension = {
9620
10271
  /* harmony default export */ const default_src = (defaultExtension);
9621
10272
 
9622
10273
 
9623
- /***/ }),
9624
-
9625
- /***/ 73325:
9626
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
9627
-
9628
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
9629
- /* harmony export */ Y: () => (/* binding */ useToggleOneUpViewportGridStore)
9630
- /* harmony export */ });
9631
- /* harmony import */ var zustand__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(78713);
9632
-
9633
- const PRESENTATION_TYPE_ID = 'toggleOneUpViewportGridId';
9634
- // Stores the entire ViewportGridService getState when toggling to one up
9635
- // (e.g. via a double click) so that it can be restored when toggling back.
9636
- const useToggleOneUpViewportGridStore = (0,zustand__WEBPACK_IMPORTED_MODULE_0__/* .create */ .vt)(set => ({
9637
- toggleOneUpViewportGridStore: null,
9638
- type: PRESENTATION_TYPE_ID,
9639
- setToggleOneUpViewportGridStore: state => set({
9640
- toggleOneUpViewportGridStore: state
9641
- }),
9642
- clearToggleOneUpViewportGridStore: () => set({
9643
- toggleOneUpViewportGridStore: null
9644
- })
9645
- }));
9646
-
9647
10274
  /***/ })
9648
10275
 
9649
10276
  }]);