@ohif/app 3.13.0-beta.8 → 3.13.0-beta.81

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 (72) hide show
  1. package/dist/{1459.bundle.9fbac3c8e089c433777e.js → 1459.bundle.8dac0d666a38bfa74d75.js} +5 -6
  2. package/dist/{1608.bundle.0687c661f1c9edfb3b8a.js → 1608.bundle.26306ea38618db59eff7.js} +12 -12
  3. package/dist/{1927.bundle.3050588e95f43cf57cdd.js → 1927.bundle.be67b3aafe238ca9f191.js} +27 -38
  4. package/dist/{1933.bundle.7ae9ef1a7b5ed55d9550.js → 1933.bundle.98bb859a3903ca9f7073.js} +32 -27
  5. package/dist/{2018.bundle.b8f9fe454ee996818531.js → 2018.bundle.9a31f91584577a24862e.js} +18 -19
  6. package/dist/{6409.bundle.b36048896cb11c8571fb.js → 2075.bundle.ba9ac60662f1fa739378.js} +337 -261
  7. package/dist/{2108.bundle.e84aa8d858d8c4f2413e.js → 2108.bundle.aea8d3b39486dd5ab39e.js} +569 -558
  8. package/dist/{213.bundle.9cff7f3868971abefe05.js → 213.bundle.54412c1510ab6ac3e129.js} +3 -5
  9. package/dist/{2424.bundle.9c081095926163e359e0.js → 2424.bundle.a7c50eea1404f7706d03.js} +3 -5
  10. package/dist/{2516.bundle.1ea0988d309a757bb6da.js → 2516.bundle.f62228e9a800de8d4b31.js} +6 -6
  11. package/dist/{2701.bundle.12bd01a80a9f8ea4cd94.js → 2701.bundle.6873805ddfdccc7a8b1e.js} +10 -10
  12. package/dist/{9195.bundle.a749686750f08e4adf93.js → 2851.bundle.bbb7743b8a06e85a2d8b.js} +484 -177
  13. package/dist/{1730.bundle.4f947de94428632e2499.js → 3138.bundle.f0c27e0fa51e8e522a03.js} +16 -310
  14. package/dist/{3461.bundle.8ce95fd079101d3e01b6.js → 3461.bundle.b8e87344d06051ccab12.js} +131 -107
  15. package/dist/{147.bundle.37d627289453cb6c3937.js → 3754.bundle.d2435bb372912595708c.js} +486 -49
  16. package/dist/{4202.bundle.5a0f8e4004c5d8a68548.js → 4202.bundle.4fcd0de412907efd5b53.js} +6 -6
  17. package/dist/{4019.bundle.83a604779f7da0101ced.js → 4287.bundle.4f28e48c1e39a46dfc87.js} +352 -238
  18. package/dist/{5462.bundle.21beddaca145b7465c72.js → 4406.bundle.573d234b4641d23cf8db.js} +1083 -1308
  19. package/dist/{1403.bundle.f7392178d9262e1d99c2.js → 4507.bundle.48936299167b13472d81.js} +10 -305
  20. package/dist/{6347.bundle.784c48912700f281de1d.js → 4579.bundle.1c315389368cc476aed3.js} +1439 -1879
  21. package/dist/{4819.bundle.c0b6dd8690d5755fde43.js → 4819.bundle.1793d3fea8733ed305f7.js} +88 -53
  22. package/dist/{4775.bundle.5671e155db52c026a803.js → 5015.bundle.efefa774795b62cde37f.js} +29 -333
  23. package/dist/{5028.bundle.bc79f49125393ecc4f5f.js → 5028.bundle.41653a25d1fe816326d2.js} +11 -13
  24. package/dist/{5261.bundle.6e1a017f8f1027557f5b.js → 5261.bundle.2655560097e9250eac44.js} +412 -345
  25. package/dist/{5457.bundle.7720e5daa4e2bdff83ee.js → 5457.bundle.c34363f925f44fb40bbf.js} +16 -23
  26. package/dist/{5485.bundle.2c2a09db8c7a29258e9f.js → 5485.bundle.d829c2a13b08d0c13e94.js} +30 -36
  27. package/dist/{5491.bundle.2e01dd7ad29e4cc01bc1.js → 5491.bundle.4866d2ecb20dd089e071.js} +54 -51
  28. package/dist/{5802.bundle.3bf5e6b3ab330a594a47.js → 5802.bundle.cd36386cbe1613913ed4.js} +79 -20
  29. package/dist/5802.css +1 -1
  30. package/dist/{5830.bundle.b073c265c4fcea1afff3.js → 5830.bundle.791019deddd536980a11.js} +3 -3
  31. package/dist/{5858.bundle.ff6b340cf7457db76a1a.js → 5858.bundle.466e58128de344ab53f3.js} +90 -86
  32. package/dist/{6027.bundle.49a5c78a49ed6cd15f72.js → 6027.bundle.68fec283e9239785829d.js} +3 -5
  33. package/dist/{6354.bundle.c387737dc09c9cab4ff2.js → 6354.bundle.929febcf6d326e582e00.js} +151 -140
  34. package/dist/{6376.bundle.9cb74d7bc08476e2f1a7.js → 6376.bundle.527820a5cb1eece2a8d2.js} +6 -6
  35. package/dist/{2842.bundle.860b9f10fcdd9656947a.js → 6386.bundle.dc7e3b159d6b4733647f.js} +913 -2290
  36. package/dist/6939.bundle.41fbdef87597b5172ec6.js +3 -3
  37. package/dist/{7159.bundle.a5991a5d4f0dd8f1c95f.js → 7159.bundle.fb9df255868960f69765.js} +7 -5
  38. package/dist/{3081.bundle.30cd450e2dd213b1b978.js → 7166.bundle.d78a2e98bfcd9467f4c5.js} +1257 -467
  39. package/dist/{7190.bundle.e8f0193e0e06472f795c.js → 7190.bundle.479332d662ffe08d1f92.js} +1228 -855
  40. package/dist/{732.bundle.6978ac30a1e36abf06db.js → 732.bundle.ea6f9d8504e37e01a208.js} +5 -13
  41. package/dist/{7431.bundle.b01791d10e6cf9f503b0.js → 7431.bundle.a9b4dbf97a8c196efe51.js} +28 -28
  42. package/dist/{4410.bundle.c5224cd7d6238a7d4660.js → 7537.bundle.88314e5a6269f96a0bae.js} +5226 -2250
  43. package/dist/{7639.bundle.78e54c6f8dee95f4a6b7.js → 7639.bundle.0894138f5a71ebb77573.js} +3 -5
  44. package/dist/7758.bundle.c8d106364298e7d288f0.js +3 -3
  45. package/dist/{8094.bundle.5c44190a325ac23e3e5c.js → 8094.bundle.148a66619607e37cbf19.js} +3 -4
  46. package/dist/{8305.bundle.d7423a538dca30c376ce.js → 8305.bundle.889f34636979b7d84c2f.js} +71 -66
  47. package/dist/{6163.bundle.ab7295912f610ef8b0eb.js → 8499.bundle.a5bcbdc972c96cc2a9b8.js} +7 -302
  48. package/dist/8499.css +2 -0
  49. package/dist/{85.bundle.0efe2e23b40b836a1fc1.js → 85.bundle.12227ce146b7ba52a74b.js} +3 -5
  50. package/dist/{8558.bundle.53e0018bbb77300516b5.js → 8558.bundle.71a05b3a3031e9638f52.js} +15 -309
  51. package/dist/{8583.bundle.4658de27c0d59037cc9b.js → 8583.bundle.ba19b136c21afeebaed0.js} +24 -27
  52. package/dist/{997.bundle.822b33e561263084e18c.js → 9039.bundle.f5db80328c99cd11293b.js} +4086 -3015
  53. package/dist/{7412.bundle.fab1742191b7fe937330.js → 9205.bundle.f2121894550d46d17398.js} +6180 -3330
  54. package/dist/{3584.bundle.8cc0750425513433e9cc.js → 9567.bundle.ff782480a4c66e306027.js} +3751 -2856
  55. package/dist/{9845.bundle.255e7c7f7a88193b4e47.js → 9845.bundle.8c450e8d65a78a5afcd3.js} +10 -10
  56. package/dist/{9862.bundle.3a8958a82c572015d25d.js → 9862.bundle.6d793a997f85d73002e9.js} +8 -6
  57. package/dist/{9927.bundle.34fec2c87a385cd104be.js → 9927.bundle.f9f850442da32cf50f8a.js} +8 -6
  58. package/dist/app-config.js +12 -0
  59. package/dist/{app.bundle.43da7d5a1360d749cf34.js → app.bundle.bee5d88f966ce61e1d93.js} +65888 -62863
  60. package/dist/app.bundle.css +3 -3
  61. package/dist/{polySeg.bundle.a5aa9130b4191253c410.js → compute.bundle.5e9691bc58308d865058.js} +8 -20
  62. package/dist/{histogram-worker.bundle.d4e40a8018d2698b072e.js → histogram-worker.bundle.a2a50c4674d99c619ca7.js} +11 -23
  63. package/dist/index.html +1 -1
  64. package/dist/{interpolation.bundle.c70cb95d164dc494e6dc.js → interpolation.bundle.829844ff3f72f5645f29.js} +14 -26
  65. package/dist/{compute.bundle.64280c7af19ff567465f.js → polySeg.bundle.c394421c24d8c27d54ca.js} +10 -22
  66. package/dist/sw.js +1 -1
  67. package/package.json +23 -22
  68. package/dist/3343.bundle.d7578ce8f75d158c0bab.js +0 -297
  69. /package/dist/{1730.css → 3138.css} +0 -0
  70. /package/dist/{147.css → 3754.css} +0 -0
  71. /package/dist/{3343.css → 4972.css} +0 -0
  72. /package/dist/{6163.css → 7829.css} +0 -0
@@ -1,14 +1,14 @@
1
1
  "use strict";
2
- (globalThis["webpackChunk"] = globalThis["webpackChunk"] || []).push([[9195],{
2
+ (globalThis["webpackChunk"] = globalThis["webpackChunk"] || []).push([[2851],{
3
3
 
4
- /***/ 52675:
5
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
4
+ /***/ 52675
5
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
6
6
 
7
7
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
8
8
  /* harmony export */ A: () => (/* binding */ MoreDropdownMenu)
9
9
  /* harmony export */ });
10
10
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(86326);
11
- /* harmony import */ var _ohif_ui_next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12517);
11
+ /* harmony import */ var _ohif_ui_next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(564);
12
12
  /* harmony import */ var _ohif_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(42356);
13
13
  function _extends() { return _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; }, _extends.apply(null, arguments); }
14
14
 
@@ -110,10 +110,10 @@ function MoreDropdownMenu(bindProps) {
110
110
  return BoundMoreDropdownMenu;
111
111
  }
112
112
 
113
- /***/ }),
113
+ /***/ },
114
114
 
115
- /***/ 40565:
116
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
115
+ /***/ 40565
116
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
117
117
 
118
118
 
119
119
  // EXPORTS
@@ -123,8 +123,8 @@ __webpack_require__.d(__webpack_exports__, {
123
123
 
124
124
  // EXTERNAL MODULE: ../../../node_modules/react/index.js
125
125
  var react = __webpack_require__(86326);
126
- // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3075 modules
127
- var src = __webpack_require__(12517);
126
+ // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3085 modules
127
+ var src = __webpack_require__(564);
128
128
  // EXTERNAL MODULE: ../../core/src/index.ts + 69 modules
129
129
  var core_src = __webpack_require__(42356);
130
130
  // EXTERNAL MODULE: ../../../node_modules/react-router-dom/dist/index.js
@@ -239,7 +239,7 @@ function PanelStudyBrowser({
239
239
  commandsManager,
240
240
  servicesManager,
241
241
  isHangingProtocolLayout,
242
- appConfig: extensionManager._appConfig
242
+ appConfig: extensionManager.appConfig
243
243
  };
244
244
  const handlers = customHandler?.callbacks.map(callback => callback(setupArgs));
245
245
  for (const handler of handlers) {
@@ -491,7 +491,7 @@ function PanelStudyBrowser({
491
491
  updateActionIconValue: updateActionIconValue
492
492
  }), /*#__PURE__*/react.createElement(src/* Separator */.wvv, {
493
493
  orientation: "horizontal",
494
- className: "bg-black",
494
+ className: "bg-background",
495
495
  thickness: "2px"
496
496
  })), /*#__PURE__*/react.createElement(src/* StudyBrowser */.M4o, {
497
497
  tabs: tabs,
@@ -609,16 +609,16 @@ function _findTabAndStudyOfDisplaySet(displaySetInstanceUID, tabs, currentTabNam
609
609
  }
610
610
  }
611
611
 
612
- /***/ }),
612
+ /***/ },
613
613
 
614
- /***/ 3329:
615
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
614
+ /***/ 3329
615
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
616
616
 
617
617
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
618
618
  /* harmony export */ T: () => (/* binding */ PanelStudyBrowserHeader)
619
619
  /* harmony export */ });
620
620
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(86326);
621
- /* harmony import */ var _ohif_ui_next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12517);
621
+ /* harmony import */ var _ohif_ui_next__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(564);
622
622
 
623
623
 
624
624
 
@@ -656,15 +656,15 @@ function PanelStudyBrowserHeader({
656
656
  key: index,
657
657
  "aria-label": viewPreset.id,
658
658
  value: viewPreset.id,
659
- className: "text-actions-primary"
659
+ className: "text-primary"
660
660
  }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement(_ohif_ui_next__WEBPACK_IMPORTED_MODULE_1__/* .Icons */ .FI1[viewPreset.iconName] || _ohif_ui_next__WEBPACK_IMPORTED_MODULE_1__/* .Icons */ .FI1.MissingIcon)))))))));
661
661
  }
662
662
 
663
663
 
664
- /***/ }),
664
+ /***/ },
665
665
 
666
- /***/ 20528:
667
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
666
+ /***/ 20528
667
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
668
668
 
669
669
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
670
670
  /* harmony export */ M: () => (/* binding */ Toolbar)
@@ -743,66 +743,41 @@ function Toolbar({
743
743
  }));
744
744
  }
745
745
 
746
- /***/ }),
746
+ /***/ },
747
747
 
748
- /***/ 39195:
749
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
748
+ /***/ 62851
749
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
750
750
 
751
- // ESM COMPAT FLAG
752
- __webpack_require__.r(__webpack_exports__);
753
751
 
754
752
  // EXPORTS
755
753
  __webpack_require__.d(__webpack_exports__, {
756
- ContextMenuController: () => (/* reexport */ ContextMenuController),
757
- CustomizableContextMenuTypes: () => (/* reexport */ types_namespaceObject),
758
- MoreDropdownMenu: () => (/* reexport */ MoreDropdownMenu/* default */.A),
759
- PanelStudyBrowserHeader: () => (/* reexport */ PanelStudyBrowserHeader/* PanelStudyBrowserHeader */.T),
760
- StaticWadoClient: () => (/* reexport */ StaticWadoClient),
761
- Toolbar: () => (/* reexport */ Toolbar/* Toolbar */.M),
762
- Toolbox: () => (/* reexport */ Toolbox),
763
- callInputDialog: () => (/* reexport */ callInputDialog),
764
- callInputDialogAutoComplete: () => (/* reexport */ callInputDialogAutoComplete),
765
- cleanDenaturalizedDataset: () => (/* reexport */ cleanDenaturalizedDataset),
766
- colorPickerDialog: () => (/* reexport */ colorPickerDialog),
767
- createReportAsync: () => (/* reexport */ Actions_createReportAsync),
768
- createReportDialogPrompt: () => (/* reexport */ CreateReportDialogPrompt),
754
+ tm: () => (/* reexport */ StaticWadoClient),
755
+ M7: () => (/* reexport */ Toolbar/* Toolbar */.M),
756
+ OO: () => (/* reexport */ Toolbox),
757
+ l5: () => (/* reexport */ callInputDialog),
758
+ fq: () => (/* reexport */ callInputDialogAutoComplete),
759
+ wZ: () => (/* reexport */ cleanDenaturalizedDataset),
760
+ wS: () => (/* reexport */ colorPickerDialog),
761
+ Vy: () => (/* reexport */ Actions_createReportAsync),
762
+ tc: () => (/* reexport */ CreateReportDialogPrompt),
769
763
  "default": () => (/* binding */ default_src),
770
- dicomWebUtils: () => (/* reexport */ utils_namespaceObject),
771
- getStudiesForPatientByMRN: () => (/* reexport */ Panels_getStudiesForPatientByMRN),
772
- promptLabelAnnotation: () => (/* reexport */ utils_promptLabelAnnotation),
773
- promptSaveReport: () => (/* reexport */ utils_promptSaveReport),
774
- requestDisplaySetCreationForStudy: () => (/* reexport */ Panels_requestDisplaySetCreationForStudy),
775
- useDisplaySetSelectorStore: () => (/* reexport */ useDisplaySetSelectorStore),
776
- useHangingProtocolStageIndexStore: () => (/* reexport */ useHangingProtocolStageIndexStore),
777
- usePatientInfo: () => (/* reexport */ hooks_usePatientInfo),
778
- useToggleHangingProtocolStore: () => (/* reexport */ useToggleHangingProtocolStore),
779
- useToggleOneUpViewportGridStore: () => (/* reexport */ useToggleOneUpViewportGridStore),
780
- useUIStateStore: () => (/* reexport */ useUIStateStore),
781
- useViewportGridStore: () => (/* reexport */ useViewportGridStore),
782
- useViewportsByPositionStore: () => (/* reexport */ useViewportsByPositionStore),
783
- utils: () => (/* reexport */ src_utils_namespaceObject)
764
+ CA: () => (/* reexport */ utils_namespaceObject),
765
+ uR: () => (/* reexport */ utils_promptLabelAnnotation),
766
+ MP: () => (/* reexport */ utils_promptSaveReport),
767
+ Z: () => (/* reexport */ Panels_requestDisplaySetCreationForStudy),
768
+ Yd: () => (/* reexport */ useToggleOneUpViewportGridStore),
769
+ FS: () => (/* reexport */ useUIStateStore)
784
770
  });
785
771
 
786
- // NAMESPACE OBJECT: ../../../extensions/default/src/CustomizableContextMenu/types.ts
787
- var types_namespaceObject = {};
788
- __webpack_require__.r(types_namespaceObject);
772
+ // UNUSED EXPORTS: ContextMenuController, CustomizableContextMenuTypes, MoreDropdownMenu, PanelStudyBrowserHeader, getStudiesForPatientByMRN, useDisplaySetSelectorStore, useHangingProtocolStageIndexStore, usePatientInfo, useToggleHangingProtocolStore, useViewportGridStore, useViewportsByPositionStore, utils
789
773
 
790
774
  // NAMESPACE OBJECT: ../../../extensions/default/src/DicomWebDataSource/utils/index.ts
791
775
  var utils_namespaceObject = {};
792
776
  __webpack_require__.r(utils_namespaceObject);
793
777
  __webpack_require__.d(utils_namespaceObject, {
794
- cleanDenaturalizedDataset: () => (cleanDenaturalizedDataset),
795
- fixBulkDataURI: () => (fixBulkDataURI),
796
- fixMultiValueKeys: () => (fixMultiValueKeys),
797
- transferDenaturalizedDataset: () => (transferDenaturalizedDataset)
798
- });
799
-
800
- // NAMESPACE OBJECT: ../../../extensions/default/src/utils/index.ts
801
- var src_utils_namespaceObject = {};
802
- __webpack_require__.r(src_utils_namespaceObject);
803
- __webpack_require__.d(src_utils_namespaceObject, {
804
- Toolbox: () => (Toolbox),
805
- addIcon: () => (addIcon)
778
+ wZ: () => (cleanDenaturalizedDataset),
779
+ Uk: () => (fixMultiValueKeys),
780
+ If: () => (transferDenaturalizedDataset)
806
781
  });
807
782
 
808
783
  // EXTERNAL MODULE: ../../../node_modules/dicomweb-client/build/dicomweb-client.es.js
@@ -2735,12 +2710,97 @@ function retrieveBulkData(value, options = {}) {
2735
2710
 
2736
2711
  // EXTERNAL MODULE: ../../../node_modules/query-string/index.js
2737
2712
  var query_string = __webpack_require__(98985);
2713
+ ;// ../../../extensions/default/src/utils/secureConfigFetch.js
2714
+ // @ts-nocheck
2715
+
2716
+ function normalizeAllowedOrigins(allowedOrigins = []) {
2717
+ if (!Array.isArray(allowedOrigins)) {
2718
+ return [];
2719
+ }
2720
+ const configuredOrigins = allowedOrigins.filter(origin => typeof origin === 'string').map(origin => origin.trim()).filter(Boolean);
2721
+ return configuredOrigins.map(origin => {
2722
+ try {
2723
+ const parsedOrigin = new URL(origin);
2724
+ if (!['http:', 'https:'].includes(parsedOrigin.protocol)) {
2725
+ console.error(`[secureConfigFetch] Ignoring misconfigured allowed origin "${origin}". ` + 'Entries must use http:// or https://.');
2726
+ return null;
2727
+ }
2728
+ if (parsedOrigin.username || parsedOrigin.password || parsedOrigin.pathname !== '/' || parsedOrigin.search || parsedOrigin.hash) {
2729
+ console.error(`[secureConfigFetch] Ignoring misconfigured allowed origin "${origin}". ` + 'Entries must be bare origins only (scheme + host + optional port), with no username/password, path, query, or hash.');
2730
+ return null;
2731
+ }
2732
+ return parsedOrigin.origin;
2733
+ } catch {
2734
+ console.error(`[secureConfigFetch] Ignoring misconfigured allowed origin "${origin}". Entry is not a valid URL.`);
2735
+ return null;
2736
+ }
2737
+ }).filter(Boolean);
2738
+ }
2739
+ function resolveConfigUrl(rawUrl) {
2740
+ if (!rawUrl || typeof rawUrl !== 'string') {
2741
+ throw new Error('Missing required "url" query parameter');
2742
+ }
2743
+ try {
2744
+ return new URL(rawUrl, window.location.href);
2745
+ } catch {
2746
+ throw new Error('Invalid URL in "url" query parameter');
2747
+ }
2748
+ }
2749
+ function resolveConfigFetchPolicy(rawUrl, policy = {}) {
2750
+ const {
2751
+ allowedOrigins = [],
2752
+ userAuthenticationService
2753
+ } = policy;
2754
+ const parsedUrl = resolveConfigUrl(rawUrl);
2755
+ const protocol = parsedUrl.protocol.toLowerCase();
2756
+ const isSameOrigin = parsedUrl.origin === window.location.origin;
2757
+ if (!['http:', 'https:'].includes(protocol)) {
2758
+ throw new Error('Only HTTP(S) URLs are allowed for dynamic datasource configuration');
2759
+ }
2760
+ if (parsedUrl.hash) {
2761
+ throw new Error('URL fragments are not allowed for dynamic datasource configuration');
2762
+ }
2763
+ if (parsedUrl.username || parsedUrl.password) {
2764
+ throw new Error('URL userinfo is not allowed for dynamic datasource configuration');
2765
+ }
2766
+ const isAuthenticated = Boolean(userAuthenticationService?.getAuthorizationHeader?.()?.Authorization);
2767
+ if (isAuthenticated && !isSameOrigin) {
2768
+ const normalizedAllowedOrigins = normalizeAllowedOrigins(allowedOrigins);
2769
+ if (!normalizedAllowedOrigins.length || !normalizedAllowedOrigins.includes(parsedUrl.origin)) {
2770
+ throw new Error(`Blocked remote configuration origin "${parsedUrl.origin}" in authenticated environment`);
2771
+ }
2772
+ }
2773
+ return {
2774
+ parsedUrl,
2775
+ normalizedUrl: parsedUrl.toString(),
2776
+ isAuthenticated,
2777
+ isSameOrigin
2778
+ };
2779
+ }
2780
+ async function fetchConfigJson(normalizedPolicy) {
2781
+ const {
2782
+ normalizedUrl
2783
+ } = normalizedPolicy;
2784
+ const response = await fetch(normalizedUrl, {
2785
+ method: 'GET',
2786
+ mode: 'cors',
2787
+ credentials: 'same-origin',
2788
+ redirect: 'error',
2789
+ referrerPolicy: 'no-referrer'
2790
+ });
2791
+ if (!response.ok) {
2792
+ throw new Error(`Failed to fetch dynamic datasource configuration (${response.status})`);
2793
+ }
2794
+ return response.json();
2795
+ }
2796
+
2738
2797
  ;// ../../../extensions/default/src/DicomJSONDataSource/index.js
2739
2798
 
2740
2799
 
2741
2800
 
2742
2801
 
2743
2802
 
2803
+
2744
2804
  const DicomJSONDataSource_metadataProvider = src/* default.classes */.Ay.classes.MetadataProvider;
2745
2805
  const mappings = {
2746
2806
  studyInstanceUid: 'StudyInstanceUID',
@@ -2787,7 +2847,10 @@ const findStudies = (key, value) => {
2787
2847
  });
2788
2848
  return studies;
2789
2849
  };
2790
- function createDicomJSONApi(dicomJsonConfig) {
2850
+ function createDicomJSONApi(dicomJsonConfig, servicesManager) {
2851
+ const {
2852
+ userAuthenticationService
2853
+ } = servicesManager.services;
2791
2854
  const implementation = {
2792
2855
  initialize: async ({
2793
2856
  query,
@@ -2796,7 +2859,11 @@ function createDicomJSONApi(dicomJsonConfig) {
2796
2859
  if (!url) {
2797
2860
  url = query.get('url');
2798
2861
  }
2799
- let metaData = getMetaDataByURL(url);
2862
+ const evaluatedUrl = resolveConfigFetchPolicy(url, {
2863
+ allowedOrigins: dicomJsonConfig.dangerouslyAllowedOriginsForAuthenticatedEnvironments,
2864
+ userAuthenticationService
2865
+ });
2866
+ let metaData = getMetaDataByURL(evaluatedUrl.normalizedUrl);
2800
2867
 
2801
2868
  // if we have already cached the data from this specific url
2802
2869
  // We are only handling one StudyInstanceUID to run; however,
@@ -2806,8 +2873,7 @@ function createDicomJSONApi(dicomJsonConfig) {
2806
2873
  return aStudy.StudyInstanceUID;
2807
2874
  });
2808
2875
  }
2809
- const response = await fetch(url);
2810
- const data = await response.json();
2876
+ const data = await fetchConfigJson(evaluatedUrl);
2811
2877
  let StudyInstanceUID;
2812
2878
  let SeriesInstanceUID;
2813
2879
  data.studies.forEach(study => {
@@ -2837,10 +2903,10 @@ function createDicomJSONApi(dicomJsonConfig) {
2837
2903
  });
2838
2904
  });
2839
2905
  _store.urls.push({
2840
- url,
2906
+ url: evaluatedUrl.normalizedUrl,
2841
2907
  studies: [...data.studies]
2842
2908
  });
2843
- _store.studyInstanceUIDMap.set(url, data.studies.map(study => study.StudyInstanceUID));
2909
+ _store.studyInstanceUIDMap.set(evaluatedUrl.normalizedUrl, data.studies.map(study => study.StudyInstanceUID));
2844
2910
  },
2845
2911
  query: {
2846
2912
  studies: {
@@ -2975,6 +3041,8 @@ function createDicomJSONApi(dicomJsonConfig) {
2975
3041
  console.warn(' DICOMJson store dicom not implemented');
2976
3042
  }
2977
3043
  },
3044
+ reject: {},
3045
+ deleteStudyMetadataPromise: () => {},
2978
3046
  getImageIdsForDisplaySet(displaySet) {
2979
3047
  const images = displaySet.images;
2980
3048
  const imageIds = [];
@@ -3033,8 +3101,20 @@ function createDicomJSONApi(dicomJsonConfig) {
3033
3101
  query
3034
3102
  }) => {
3035
3103
  const url = query.get('url');
3036
- return _store.studyInstanceUIDMap.get(url);
3037
- }
3104
+ if (!url) {
3105
+ return;
3106
+ }
3107
+ try {
3108
+ const evaluatedUrl = resolveConfigFetchPolicy(url, {
3109
+ allowedOrigins: dicomJsonConfig.dangerouslyAllowedOriginsForAuthenticatedEnvironments,
3110
+ userAuthenticationService
3111
+ });
3112
+ return _store.studyInstanceUIDMap.get(evaluatedUrl.normalizedUrl);
3113
+ } catch {
3114
+ return;
3115
+ }
3116
+ },
3117
+ getConfig: () => dicomJsonConfig
3038
3118
  };
3039
3119
  return src/* IWebApiDataSource */.pt.create(implementation);
3040
3120
  }
@@ -3303,6 +3383,7 @@ function createDicomLocalApi(dicomLocalConfig) {
3303
3383
 
3304
3384
 
3305
3385
 
3386
+
3306
3387
  /**
3307
3388
  * This datasource is initialized with a url that returns a JSON object with a
3308
3389
  * dicomWeb datasource configuration array present in a "servers" object.
@@ -3315,6 +3396,9 @@ function createDicomWebProxyApi(dicomWebProxyConfig, servicesManager) {
3315
3396
  const {
3316
3397
  name
3317
3398
  } = dicomWebProxyConfig;
3399
+ const {
3400
+ userAuthenticationService
3401
+ } = servicesManager.services;
3318
3402
  let dicomWebDelegate = undefined;
3319
3403
  const implementation = {
3320
3404
  initialize: async ({
@@ -3325,8 +3409,11 @@ function createDicomWebProxyApi(dicomWebProxyConfig, servicesManager) {
3325
3409
  if (!url) {
3326
3410
  throw new Error(`No url for '${name}'`);
3327
3411
  } else {
3328
- const response = await fetch(url);
3329
- const data = await response.json();
3412
+ const evaluatedUrl = resolveConfigFetchPolicy(url, {
3413
+ allowedOrigins: dicomWebProxyConfig.dangerouslyAllowedOriginsForAuthenticatedEnvironments,
3414
+ userAuthenticationService
3415
+ });
3416
+ const data = await fetchConfigJson(evaluatedUrl);
3330
3417
  if (!data.servers?.dicomWeb?.[0]) {
3331
3418
  throw new Error('Invalid configuration returned by url');
3332
3419
  }
@@ -3357,9 +3444,15 @@ function createDicomWebProxyApi(dicomWebProxyConfig, servicesManager) {
3357
3444
  store: {
3358
3445
  dicom: (...args) => dicomWebDelegate.store.dicom(...args)
3359
3446
  },
3360
- deleteStudyMetadataPromise: (...args) => dicomWebDelegate.deleteStudyMetadataPromise(...args),
3361
- getImageIdsForDisplaySet: (...args) => dicomWebDelegate.getImageIdsForDisplaySet(...args),
3362
- getImageIdsForInstance: (...args) => dicomWebDelegate.getImageIdsForInstance(...args),
3447
+ reject: {
3448
+ series: (...args) => dicomWebDelegate?.reject?.series?.(...args)
3449
+ },
3450
+ deleteStudyMetadataPromise: (...args) => dicomWebDelegate?.deleteStudyMetadataPromise?.(...args),
3451
+ getImageIdsForDisplaySet: (...args) => dicomWebDelegate?.getImageIdsForDisplaySet?.(...args),
3452
+ getImageIdsForInstance: (...args) => dicomWebDelegate?.getImageIdsForInstance?.(...args),
3453
+ getConfig: (...args) => dicomWebDelegate?.getConfig?.(...args) ?? {
3454
+ dicomUploadEnabled: false
3455
+ },
3363
3456
  getStudyInstanceUIDs({
3364
3457
  params,
3365
3458
  query
@@ -3697,8 +3790,8 @@ var react = __webpack_require__(86326);
3697
3790
  // EXTERNAL MODULE: ../../../node_modules/prop-types/index.js
3698
3791
  var prop_types = __webpack_require__(97598);
3699
3792
  var prop_types_default = /*#__PURE__*/__webpack_require__.n(prop_types);
3700
- // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3075 modules
3701
- var ui_next_src = __webpack_require__(12517);
3793
+ // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3085 modules
3794
+ var ui_next_src = __webpack_require__(564);
3702
3795
  // EXTERNAL MODULE: ./state/index.js + 1 modules
3703
3796
  var state = __webpack_require__(45981);
3704
3797
  // EXTERNAL MODULE: ../../../node_modules/react-router-dom/dist/index.js
@@ -3811,7 +3904,7 @@ function HeaderPatientInfo({
3811
3904
  const formattedPatientName = formatWithEllipsis(patientInfo.PatientName, 27);
3812
3905
  const formattedPatientID = formatWithEllipsis(patientInfo.PatientID, 15);
3813
3906
  return /*#__PURE__*/react.createElement("div", {
3814
- className: "hover:bg-primary-dark flex cursor-pointer items-center justify-center gap-1 rounded-lg",
3907
+ className: "hover:bg-muted flex cursor-pointer items-center justify-center gap-1 rounded-lg",
3815
3908
  onClick: handleOnClick
3816
3909
  }, isMixedPatients ? /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.MultiplePatients, {
3817
3910
  className: "text-primary"
@@ -3820,9 +3913,9 @@ function HeaderPatientInfo({
3820
3913
  }), /*#__PURE__*/react.createElement("div", {
3821
3914
  className: "flex flex-col justify-center"
3822
3915
  }, expanded ? /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement("div", {
3823
- className: "self-start text-[13px] font-bold text-white"
3916
+ className: "text-foreground self-start text-[13px] font-bold"
3824
3917
  }, formattedPatientName), /*#__PURE__*/react.createElement("div", {
3825
- className: "text-aqua-pale flex gap-2 text-[11px]"
3918
+ className: "text-muted-foreground flex gap-2 text-[11px]"
3826
3919
  }, /*#__PURE__*/react.createElement("div", null, formattedPatientID), /*#__PURE__*/react.createElement("div", null, patientInfo.PatientSex), /*#__PURE__*/react.createElement("div", null, patientInfo.PatientDOB))) : /*#__PURE__*/react.createElement("div", {
3827
3920
  className: "text-primary self-center text-[13px]"
3828
3921
  }, isMixedPatients ? 'Multiple Patients' : 'Patient')), /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.ArrowLeft, {
@@ -3925,7 +4018,8 @@ function ViewerHeader({
3925
4018
  className: "text-primary flex cursor-pointer items-center"
3926
4019
  }, /*#__PURE__*/react.createElement(ui_next_src/* Button */.$nd, {
3927
4020
  variant: "ghost",
3928
- className: "hover:bg-primary-dark",
4021
+ className: "hover:bg-muted",
4022
+ "data-cy": "undo-btn",
3929
4023
  onClick: () => {
3930
4024
  commandsManager.run('undo');
3931
4025
  }
@@ -3933,7 +4027,8 @@ function ViewerHeader({
3933
4027
  className: ""
3934
4028
  })), /*#__PURE__*/react.createElement(ui_next_src/* Button */.$nd, {
3935
4029
  variant: "ghost",
3936
- className: "hover:bg-primary-dark",
4030
+ className: "hover:bg-muted",
4031
+ "data-cy": "redo-btn",
3937
4032
  onClick: () => {
3938
4033
  commandsManager.run('redo');
3939
4034
  }
@@ -4355,7 +4450,7 @@ function ViewerLayout_extends() { return ViewerLayout_extends = Object.assign ?
4355
4450
 
4356
4451
 
4357
4452
 
4358
- const resizableHandleClassName = 'mt-[1px] bg-black';
4453
+ const resizableHandleClassName = 'mt-[1px] bg-background';
4359
4454
  function ViewerLayout({
4360
4455
  // From Extension Module Params
4361
4456
  extensionManager,
@@ -4398,10 +4493,10 @@ function ViewerLayout({
4398
4493
  * is sized to our viewport.
4399
4494
  */
4400
4495
  (0,react.useEffect)(() => {
4401
- document.body.classList.add('bg-black');
4496
+ document.body.classList.add('bg-background');
4402
4497
  document.body.classList.add('overflow-hidden');
4403
4498
  return () => {
4404
- document.body.classList.remove('bg-black');
4499
+ document.body.classList.remove('bg-background');
4405
4500
  document.body.classList.remove('overflow-hidden');
4406
4501
  };
4407
4502
  }, []);
@@ -4464,12 +4559,12 @@ function ViewerLayout({
4464
4559
  servicesManager: servicesManager,
4465
4560
  appConfig: appConfig
4466
4561
  }), /*#__PURE__*/react.createElement("div", {
4467
- className: "relative flex w-full flex-row flex-nowrap items-stretch overflow-hidden bg-black",
4562
+ className: "relative flex w-full flex-row flex-nowrap items-stretch overflow-hidden bg-background",
4468
4563
  style: {
4469
4564
  height: 'calc(100vh - 52px'
4470
4565
  }
4471
4566
  }, /*#__PURE__*/react.createElement(react.Fragment, null, showLoadingIndicator && /*#__PURE__*/react.createElement(LoadingIndicatorProgress, {
4472
- className: "h-full w-full bg-black"
4567
+ className: "h-full w-full bg-background"
4473
4568
  }), /*#__PURE__*/react.createElement(ui_next_src/* ResizablePanelGroup */.HKS, resizablePanelGroupProps, hasLeftPanels ? /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement(ui_next_src/* ResizablePanel */.wVo, resizableLeftPanelProps, /*#__PURE__*/react.createElement(Components_SidePanelWithServices, ViewerLayout_extends({
4474
4569
  side: "left",
4475
4570
  isExpanded: !leftPanelClosedState,
@@ -4481,7 +4576,7 @@ function ViewerLayout({
4481
4576
  })) : null, /*#__PURE__*/react.createElement(ui_next_src/* ResizablePanel */.wVo, resizableViewportGridPanelProps, /*#__PURE__*/react.createElement("div", {
4482
4577
  className: "flex h-full flex-1 flex-col"
4483
4578
  }, /*#__PURE__*/react.createElement("div", {
4484
- className: "relative flex h-full flex-1 items-center justify-center overflow-hidden bg-black",
4579
+ className: "relative flex h-full flex-1 items-center justify-center overflow-hidden bg-background",
4485
4580
  onMouseEnter: handleMouseEnter
4486
4581
  }, /*#__PURE__*/react.createElement(ViewportGridComp, {
4487
4582
  servicesManager: servicesManager,
@@ -4688,7 +4783,8 @@ function CreateReportDialogPrompt({
4688
4783
  minSeriesNumber = 0,
4689
4784
  predecessorImageId,
4690
4785
  extensionManager,
4691
- servicesManager
4786
+ servicesManager,
4787
+ enableDownload = false
4692
4788
  }) {
4693
4789
  const {
4694
4790
  uiDialogService,
@@ -4708,6 +4804,7 @@ function CreateReportDialogPrompt({
4708
4804
  predecessorImageId,
4709
4805
  minSeriesNumber,
4710
4806
  modality,
4807
+ enableDownload,
4711
4808
  onSave: async ({
4712
4809
  reportName,
4713
4810
  dataSource: selectedDataSource,
@@ -5180,7 +5277,6 @@ var dist_esm = __webpack_require__(15327);
5180
5277
  const {
5181
5278
  isImage,
5182
5279
  sortStudyInstances,
5183
- instancesSortCriteria,
5184
5280
  sopClassDictionary,
5185
5281
  isDisplaySetReconstructable: getSopClassHandlerModule_isDisplaySetReconstructable
5186
5282
  } = src/* utils */.Wp;
@@ -5225,12 +5321,17 @@ function getDisplaySetInfo(instances) {
5225
5321
  const instancesMap = new Map();
5226
5322
  let firstTimePointInstances;
5227
5323
  if (instances[0].NumberOfFrames > 1 && timePoints.length > 1) {
5228
- // handle multiframe dynamic volume
5229
- firstTimePointInstances = timePoints[0].map(imageId => dist_esm.metaData.get('instance', imageId));
5324
+ // Handle multiframe dynamic volumes. Local file frame imageIds do not
5325
+ // always resolve to a frame-level instance object, so keep resolved
5326
+ // entries and fall back to the source multiframe instance when needed.
5327
+ firstTimePointInstances = timePoints[0].map(imageId => dist_esm.metaData.get('instance', imageId)).filter(Boolean);
5328
+ if (!firstTimePointInstances.length) {
5329
+ firstTimePointInstances = [instances[0]];
5330
+ }
5230
5331
  } else {
5231
5332
  // O(n) to convert it into a map and O(1) to find each instance
5232
5333
  instances.forEach(instance => instancesMap.set(instance.imageId, instance));
5233
- firstTimePointInstances = timePoint.map(imageId => instancesMap.get(imageId));
5334
+ firstTimePointInstances = timePoint.map(imageId => instancesMap.get(imageId)).filter(Boolean);
5234
5335
  }
5235
5336
  displaySetInfo = getSopClassHandlerModule_isDisplaySetReconstructable(firstTimePointInstances, appConfig);
5236
5337
  } else {
@@ -5393,7 +5494,7 @@ function getDisplaySetsFromSeries(instances) {
5393
5494
  }
5394
5495
  return displaySets;
5395
5496
  }
5396
- const getSopClassHandlerModule_sopClassUids = [sopClassDictionary.ComputedRadiographyImageStorage, sopClassDictionary.DigitalXRayImageStorageForPresentation, sopClassDictionary.DigitalXRayImageStorageForProcessing, sopClassDictionary.DigitalMammographyXRayImageStorageForPresentation, sopClassDictionary.DigitalMammographyXRayImageStorageForProcessing, sopClassDictionary.DigitalIntraOralXRayImageStorageForPresentation, sopClassDictionary.DigitalIntraOralXRayImageStorageForProcessing, sopClassDictionary.CTImageStorage, sopClassDictionary.EnhancedCTImageStorage, sopClassDictionary.LegacyConvertedEnhancedCTImageStorage, sopClassDictionary.UltrasoundMultiframeImageStorage, sopClassDictionary.MRImageStorage, sopClassDictionary.EnhancedMRImageStorage, sopClassDictionary.EnhancedMRColorImageStorage, sopClassDictionary.LegacyConvertedEnhancedMRImageStorage, sopClassDictionary.UltrasoundImageStorage, sopClassDictionary.UltrasoundImageStorageRET, sopClassDictionary.SecondaryCaptureImageStorage, sopClassDictionary.MultiframeSingleBitSecondaryCaptureImageStorage, sopClassDictionary.MultiframeGrayscaleByteSecondaryCaptureImageStorage, sopClassDictionary.MultiframeGrayscaleWordSecondaryCaptureImageStorage, sopClassDictionary.MultiframeTrueColorSecondaryCaptureImageStorage, sopClassDictionary.XRayAngiographicImageStorage, sopClassDictionary.EnhancedXAImageStorage, sopClassDictionary.XRayRadiofluoroscopicImageStorage, sopClassDictionary.EnhancedXRFImageStorage, sopClassDictionary.XRay3DAngiographicImageStorage, sopClassDictionary.XRay3DCraniofacialImageStorage, sopClassDictionary.BreastTomosynthesisImageStorage, sopClassDictionary.BreastProjectionXRayImageStorageForPresentation, sopClassDictionary.BreastProjectionXRayImageStorageForProcessing, sopClassDictionary.IntravascularOpticalCoherenceTomographyImageStorageForPresentation, sopClassDictionary.IntravascularOpticalCoherenceTomographyImageStorageForProcessing, sopClassDictionary.NuclearMedicineImageStorage, sopClassDictionary.VLEndoscopicImageStorage, sopClassDictionary.VideoEndoscopicImageStorage, sopClassDictionary.VLMicroscopicImageStorage, sopClassDictionary.VideoMicroscopicImageStorage, sopClassDictionary.VLSlideCoordinatesMicroscopicImageStorage, sopClassDictionary.VLPhotographicImageStorage, sopClassDictionary.VideoPhotographicImageStorage, sopClassDictionary.OphthalmicPhotography8BitImageStorage, sopClassDictionary.OphthalmicPhotography16BitImageStorage, sopClassDictionary.OphthalmicTomographyImageStorage,
5497
+ const getSopClassHandlerModule_sopClassUids = [sopClassDictionary.ComputedRadiographyImageStorage, sopClassDictionary.DigitalXRayImageStorageForPresentation, sopClassDictionary.DigitalXRayImageStorageForProcessing, sopClassDictionary.DigitalMammographyXRayImageStorageForPresentation, sopClassDictionary.DigitalMammographyXRayImageStorageForProcessing, sopClassDictionary.DigitalIntraOralXRayImageStorageForPresentation, sopClassDictionary.DigitalIntraOralXRayImageStorageForProcessing, sopClassDictionary.CTImageStorage, sopClassDictionary.EnhancedCTImageStorage, sopClassDictionary.LegacyConvertedEnhancedCTImageStorage, sopClassDictionary.UltrasoundMultiframeImageStorage, sopClassDictionary.MRImageStorage, sopClassDictionary.EnhancedMRImageStorage, sopClassDictionary.EnhancedMRColorImageStorage, sopClassDictionary.LegacyConvertedEnhancedMRImageStorage, sopClassDictionary.UltrasoundImageStorage, sopClassDictionary.UltrasoundImageStorageRET, sopClassDictionary.SecondaryCaptureImageStorage, sopClassDictionary.MultiframeSingleBitSecondaryCaptureImageStorage, sopClassDictionary.MultiframeGrayscaleByteSecondaryCaptureImageStorage, sopClassDictionary.MultiframeGrayscaleWordSecondaryCaptureImageStorage, sopClassDictionary.MultiframeTrueColorSecondaryCaptureImageStorage, sopClassDictionary.XRayAngiographicImageStorage, sopClassDictionary.EnhancedXAImageStorage, sopClassDictionary.XRayRadiofluoroscopicImageStorage, sopClassDictionary.EnhancedXRFImageStorage, sopClassDictionary.XRay3DAngiographicImageStorage, sopClassDictionary.XRay3DCraniofacialImageStorage, sopClassDictionary.BreastTomosynthesisImageStorage, sopClassDictionary.CornealTopographyMapStorage, sopClassDictionary.BreastProjectionXRayImageStorageForPresentation, sopClassDictionary.BreastProjectionXRayImageStorageForProcessing, sopClassDictionary.IntravascularOpticalCoherenceTomographyImageStorageForPresentation, sopClassDictionary.IntravascularOpticalCoherenceTomographyImageStorageForProcessing, sopClassDictionary.NuclearMedicineImageStorage, sopClassDictionary.VLEndoscopicImageStorage, sopClassDictionary.VideoEndoscopicImageStorage, sopClassDictionary.VLMicroscopicImageStorage, sopClassDictionary.VideoMicroscopicImageStorage, sopClassDictionary.VLSlideCoordinatesMicroscopicImageStorage, sopClassDictionary.VLPhotographicImageStorage, sopClassDictionary.VideoPhotographicImageStorage, sopClassDictionary.OphthalmicPhotography8BitImageStorage, sopClassDictionary.OphthalmicPhotography16BitImageStorage, sopClassDictionary.OphthalmicTomographyImageStorage,
5397
5498
  // Handled by another sop class module
5398
5499
  // sopClassDictionary.VLWholeSlideMicroscopyImageStorage,
5399
5500
  sopClassDictionary.PositronEmissionTomographyImageStorage, sopClassDictionary.EnhancedPETImageStorage, sopClassDictionary.LegacyConvertedEnhancedPETImageStorage, sopClassDictionary.RTImageStorage, sopClassDictionary.EnhancedUSVolumeStorage, sopClassDictionary.RTDoseStorage];
@@ -5555,7 +5656,7 @@ function ToolbarLayoutSelectorWithServices({
5555
5656
  disabled: preset.disabled,
5556
5657
  isPreset: true
5557
5658
  })))), /*#__PURE__*/react.createElement("div", {
5558
- className: "bg-muted flex flex-col gap-2.5 border-l-2 border-solid border-black p-2"
5659
+ className: "bg-muted flex flex-col gap-2.5 border-l-2 border-solid border-background p-2"
5559
5660
  }, /*#__PURE__*/react.createElement("div", {
5560
5661
  className: "text-muted-foreground text-xs"
5561
5662
  }, t('Custom')), /*#__PURE__*/react.createElement(ui_next_src/* LayoutSelector */.sG4.GridSelector, {
@@ -5843,6 +5944,7 @@ function ToolButtonWrapper(props) {
5843
5944
  }
5844
5945
 
5845
5946
  ;// ../../../extensions/default/src/Toolbar/ToolbarDivider.tsx
5947
+ /* unused harmony import specifier */ var React;
5846
5948
 
5847
5949
  function ToolbarDivider() {
5848
5950
  return /*#__PURE__*/React.createElement("span", {
@@ -6315,7 +6417,7 @@ const RowComponent = ({
6315
6417
  ...style,
6316
6418
  ...rowStyle
6317
6419
  },
6318
- className: classnames_default()('hover:bg-secondary-main border-secondary-light text-foreground flex w-full flex-row items-center break-all bg-black text-base transition duration-300', lineHeightClassName),
6420
+ className: classnames_default()('hover:bg-primary/25 border-input text-foreground flex w-full flex-row items-center break-all bg-background text-base', lineHeightClassName),
6319
6421
  key: keyPrefix
6320
6422
  }, isChildOrParent && /*#__PURE__*/react.createElement("div", {
6321
6423
  style: {
@@ -6345,34 +6447,34 @@ function ColumnHeaders({
6345
6447
  valueRef
6346
6448
  }) {
6347
6449
  return /*#__PURE__*/react.createElement("div", {
6348
- className: classnames_default()('bg-secondary-dark ohif-scrollbar flex w-full flex-row overflow-y-scroll'),
6450
+ className: classnames_default()('bg-popover ohif-scrollbar flex w-full flex-row overflow-y-scroll'),
6349
6451
  style: rowVerticalPaddingStyle
6350
6452
  }, /*#__PURE__*/react.createElement("div", {
6351
6453
  className: "w-4/24 px-3"
6352
6454
  }, /*#__PURE__*/react.createElement("label", {
6353
6455
  ref: tagRef,
6354
- className: "flex flex-1 select-none flex-col pl-1 text-lg text-white"
6456
+ className: "text-foreground flex flex-1 select-none flex-col pl-1 text-lg"
6355
6457
  }, /*#__PURE__*/react.createElement("span", {
6356
6458
  className: "flex flex-row items-center focus:outline-none"
6357
6459
  }, "Tag"))), /*#__PURE__*/react.createElement("div", {
6358
6460
  className: "w-2/24 px-3"
6359
6461
  }, /*#__PURE__*/react.createElement("label", {
6360
6462
  ref: vrRef,
6361
- className: "flex flex-1 select-none flex-col pl-1 text-lg text-white"
6463
+ className: "text-foreground flex flex-1 select-none flex-col pl-1 text-lg"
6362
6464
  }, /*#__PURE__*/react.createElement("span", {
6363
6465
  className: "flex flex-row items-center focus:outline-none"
6364
6466
  }, "VR"))), /*#__PURE__*/react.createElement("div", {
6365
6467
  className: "w-6/24 px-3"
6366
6468
  }, /*#__PURE__*/react.createElement("label", {
6367
6469
  ref: keywordRef,
6368
- className: "flex flex-1 select-none flex-col pl-1 text-lg text-white"
6470
+ className: "text-foreground flex flex-1 select-none flex-col pl-1 text-lg"
6369
6471
  }, /*#__PURE__*/react.createElement("span", {
6370
6472
  className: "flex flex-row items-center focus:outline-none"
6371
6473
  }, "Keyword"))), /*#__PURE__*/react.createElement("div", {
6372
6474
  className: "w-5/24 grow px-3"
6373
6475
  }, /*#__PURE__*/react.createElement("label", {
6374
6476
  ref: valueRef,
6375
- className: "flex flex-1 select-none flex-col pl-1 text-lg text-white"
6477
+ className: "text-foreground flex flex-1 select-none flex-col pl-1 text-lg"
6376
6478
  }, /*#__PURE__*/react.createElement("span", {
6377
6479
  className: "flex flex-row items-center focus:outline-none"
6378
6480
  }, "Value"))));
@@ -6520,7 +6622,7 @@ function DicomTagTable({
6520
6622
  keywordRef: keywordRef,
6521
6623
  valueRef: valueRef
6522
6624
  }), /*#__PURE__*/react.createElement("div", {
6523
- className: "relative m-auto border-2 border-black bg-black",
6625
+ className: "relative m-auto border-2 border-background bg-background",
6524
6626
  style: {
6525
6627
  height: '32rem'
6526
6628
  }
@@ -6635,7 +6737,7 @@ const DicomTagBrowser = ({
6635
6737
  }, /*#__PURE__*/react.createElement("div", {
6636
6738
  className: "mb-6 flex flex-row items-start pl-1"
6637
6739
  }, /*#__PURE__*/react.createElement("div", {
6638
- className: "flex w-full flex-row items-start gap-4"
6740
+ className: "flex w-full flex-row items-start gap-6"
6639
6741
  }, /*#__PURE__*/react.createElement("div", {
6640
6742
  className: "flex w-1/3 flex-col"
6641
6743
  }, /*#__PURE__*/react.createElement("span", {
@@ -6645,7 +6747,11 @@ const DicomTagBrowser = ({
6645
6747
  onValueChange: value => onSelectChange({
6646
6748
  value
6647
6749
  })
6648
- }, /*#__PURE__*/react.createElement(ui_next_src/* SelectTrigger */.bqE, null, displaySetList.find(ds => ds.value === selectedDisplaySetInstanceUID)?.label || 'Select Series'), /*#__PURE__*/react.createElement(ui_next_src/* SelectContent */.gCo, null, displaySetList.map(item => {
6750
+ }, /*#__PURE__*/react.createElement(ui_next_src/* SelectTrigger */.bqE, {
6751
+ "data-cy": "dicom-tag-series-select-trigger"
6752
+ }, /*#__PURE__*/react.createElement(ui_next_src/* SelectValue */.yvm, {
6753
+ "data-cy": "dicom-tag-series-select-value"
6754
+ }, displaySetList.find(ds => ds.value === selectedDisplaySetInstanceUID)?.label || 'Select Series')), /*#__PURE__*/react.createElement(ui_next_src/* SelectContent */.gCo, null, displaySetList.map(item => {
6649
6755
  return /*#__PURE__*/react.createElement(ui_next_src/* SelectItem */.ebT, {
6650
6756
  key: item.value,
6651
6757
  value: item.value
@@ -6664,7 +6770,7 @@ const DicomTagBrowser = ({
6664
6770
  min: 1,
6665
6771
  max: activeDisplaySet?.images?.length,
6666
6772
  step: 1,
6667
- className: "pt-4"
6773
+ className: "pt-3"
6668
6774
  })), /*#__PURE__*/react.createElement("div", {
6669
6775
  className: "ml-auto mr-1 flex w-1/3 flex-col"
6670
6776
  }, /*#__PURE__*/react.createElement("span", {
@@ -7223,8 +7329,14 @@ function configureViewportForLayerAddition(params) {
7223
7329
 
7224
7330
  // If a viewport type was already set do not reset it.
7225
7331
  if (!viewport.viewportOptions.viewportType) {
7226
- // Special handling for overlay display sets
7227
- if (requestedLayerDisplaySet.isOverlayDisplaySet) {
7332
+ // If the live Cornerstone viewport is already orthographic (volume), keep it as
7333
+ // 'volume'. Prevents accidentally downgrading a volume viewport to 'stack' when
7334
+ // viewportOptions arrives without a viewportType (e.g. from the HP overlay path).
7335
+ const csViewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
7336
+ if (csViewport?.type === 'orthographic') {
7337
+ viewport.viewportOptions.viewportType = 'volume';
7338
+ // Special handling for overlay display sets
7339
+ } else if (requestedLayerDisplaySet.isOverlayDisplaySet) {
7228
7340
  // Do not force volume for SEG and RTSTRUCT if it and all the current display sets are for the same display set
7229
7341
  const isSameDisplaySet = currentDisplaySetUIDs.every(uid => {
7230
7342
  const currentDisplaySet = displaySetService.getDisplaySetByUID(uid);
@@ -7280,7 +7392,8 @@ function configureViewportForLayerRemoval(params) {
7280
7392
  if (!viewport.viewportOptions) {
7281
7393
  viewport.viewportOptions = {};
7282
7394
  }
7283
- viewport.viewportOptions.viewportType = 'volume';
7395
+ const csViewportOrthographic = cornerstoneViewportService.getCornerstoneViewport(viewportId)?.type === 'orthographic';
7396
+ viewport.viewportOptions.viewportType = csViewportOrthographic ? 'volume' : 'stack';
7284
7397
 
7285
7398
  // orientation
7286
7399
  if (!viewport.viewportOptions.orientation) {
@@ -7537,8 +7650,6 @@ const useToggleOneUpViewportGridStore = (0,zustand_esm/* create */.vt)(set => ({
7537
7650
  })
7538
7651
  }));
7539
7652
  ;// ../../../extensions/default/src/Actions/createReportAsync.tsx
7540
-
7541
-
7542
7653
  /**
7543
7654
  *
7544
7655
  * @param {*} servicesManager
@@ -7546,7 +7657,8 @@ const useToggleOneUpViewportGridStore = (0,zustand_esm/* create */.vt)(set => ({
7546
7657
  async function createReportAsync({
7547
7658
  servicesManager,
7548
7659
  getReport,
7549
- reportType = 'measurement'
7660
+ reportType = 'Measurements',
7661
+ successMessage
7550
7662
  }) {
7551
7663
  const {
7552
7664
  displaySetService,
@@ -7559,15 +7671,13 @@ async function createReportAsync({
7559
7671
  return;
7560
7672
  }
7561
7673
 
7562
- // The "Mode" route listens for DicomMetadataStore changes
7563
- // When a new instance is added, it listens and
7564
- // automatically calls makeDisplaySets
7565
- src/* DicomMetadataStore */.H8.addInstances([naturalizedReport], true);
7674
+ // addInstances is called by the store command (storeMeasurements/storeSegmentation),
7675
+ // so the display set should already exist at this point.
7566
7676
  const displaySet = displaySetService.getMostRecentDisplaySet();
7567
7677
  const displaySetInstanceUID = displaySet.displaySetInstanceUID;
7568
7678
  uiNotificationService.show({
7569
7679
  title: 'Create Report',
7570
- message: `${reportType} saved successfully`,
7680
+ message: successMessage ?? `${reportType} saved successfully`,
7571
7681
  type: 'success'
7572
7682
  });
7573
7683
  return [displaySetInstanceUID];
@@ -7623,34 +7733,32 @@ async function promptSaveReport({
7623
7733
  predecessorImageId,
7624
7734
  minSeriesNumber: 3000,
7625
7735
  extensionManager,
7626
- servicesManager
7736
+ servicesManager,
7737
+ enableDownload: true
7627
7738
  });
7628
7739
  if (promptResult.action === PROMPT_RESPONSES/* default */.A.CREATE_REPORT) {
7629
- const dataSources = extensionManager.getDataSources(promptResult.dataSourceName);
7630
- const dataSource = dataSources[0];
7631
7740
  const {
7632
7741
  series,
7633
7742
  priorSeriesNumber,
7634
- value: reportName
7743
+ value: reportName,
7744
+ dataSourceName
7635
7745
  } = promptResult;
7636
7746
  const SeriesDescription = reportName || defaultSaveTitle;
7637
- const getReport = async () => {
7638
- return commandsManager.runCommand('storeMeasurements', {
7639
- measurementData,
7640
- dataSource,
7641
- additionalFindingTypes: ['ArrowAnnotate'],
7642
- options: {
7643
- SeriesDescription,
7644
- SeriesNumber: 1 + priorSeriesNumber,
7645
- predecessorImageId: series
7646
- }
7647
- }, 'CORNERSTONE_STRUCTURED_REPORT');
7648
- };
7747
+ const getReport = async () => commandsManager.runCommand('storeMeasurements', {
7748
+ measurementData,
7749
+ dataSource: dataSourceName,
7750
+ additionalFindingTypes: ['ArrowAnnotate'],
7751
+ options: {
7752
+ SeriesDescription,
7753
+ SeriesNumber: 1 + priorSeriesNumber,
7754
+ predecessorImageId: series
7755
+ }
7756
+ }, 'CORNERSTONE_STRUCTURED_REPORT');
7649
7757
  displaySetInstanceUIDs = await Actions_createReportAsync({
7650
7758
  servicesManager,
7651
7759
  getReport
7652
7760
  });
7653
- } else if (promptResult.action === RESPONSE.CANCEL) {
7761
+ } else if (promptResult.action === PROMPT_RESPONSES/* default */.A.CANCEL) {
7654
7762
  // Do nothing
7655
7763
  }
7656
7764
  return {
@@ -7682,6 +7790,10 @@ function findPredecessorImageId(annotations) {
7682
7790
  ;// ../../../extensions/default/src/commandsModule.ts
7683
7791
 
7684
7792
 
7793
+ const {
7794
+ downloadBlob
7795
+ } = src/* utils */.Wp;
7796
+
7685
7797
 
7686
7798
 
7687
7799
 
@@ -7811,6 +7923,19 @@ const commandsModule = ({
7811
7923
  return;
7812
7924
  }
7813
7925
 
7926
+ // Check if it's a segmentation and handle accordingly.
7927
+ // Note that for the sake of hydrated segmentations, we remove the
7928
+ // segmentation before checking if the display set is indeed in the viewport.
7929
+ // This is because hydrated segmentations are not in the viewport per se
7930
+ // {i.e. they are not layered) but are simply referenced by the display
7931
+ // set in the viewport.
7932
+ const isSegmentation = DERIVED_OVERLAY_MODALITIES.includes(displaySet.Modality);
7933
+ if (isSegmentation) {
7934
+ segmentationService.removeRepresentationsFromViewport(viewportId, {
7935
+ segmentationId: displaySetInstanceUID
7936
+ });
7937
+ }
7938
+
7814
7939
  // Get current display sets for the viewport
7815
7940
  const currentDisplaySetUIDs = viewportGridService.getDisplaySetsUIDsForViewport(viewportId);
7816
7941
 
@@ -7818,14 +7943,6 @@ const commandsModule = ({
7818
7943
  if (!currentDisplaySetUIDs.includes(displaySetInstanceUID)) {
7819
7944
  return;
7820
7945
  }
7821
-
7822
- // Check if it's a segmentation and handle accordingly
7823
- const isSegmentation = DERIVED_OVERLAY_MODALITIES.includes(displaySet.Modality);
7824
- if (isSegmentation) {
7825
- segmentationService.removeSegmentationRepresentations(viewportId, {
7826
- segmentationId: displaySetInstanceUID
7827
- });
7828
- }
7829
7946
  const updatedViewports = hangingProtocolService.getViewportsRequireUpdate(viewportId, displaySetInstanceUID);
7830
7947
 
7831
7948
  // Configure each viewport for layer removal
@@ -8310,7 +8427,7 @@ const commandsModule = ({
8310
8427
  const {
8311
8428
  UIModalService
8312
8429
  } = servicesManager.services;
8313
- const defaultDisplaySetInstanceUID = displaySetInstanceUID || displaySetInstanceUIDs[0];
8430
+ const defaultDisplaySetInstanceUID = displaySetInstanceUID || displaySetInstanceUIDs[0] || displaySets[0]?.displaySetInstanceUID;
8314
8431
  UIModalService.show({
8315
8432
  content: DicomTagBrowser_DicomTagBrowser,
8316
8433
  contentProps: {
@@ -8371,7 +8488,11 @@ const commandsModule = ({
8371
8488
  const activeDisplaySetIndex = currentDisplaySets.findIndex(displaySet => displaySetInstanceUIDs.includes(displaySet.displaySetInstanceUID));
8372
8489
  let displaySetIndexToShow;
8373
8490
  for (displaySetIndexToShow = activeDisplaySetIndex + direction; displaySetIndexToShow > -1 && displaySetIndexToShow < currentDisplaySets.length; displaySetIndexToShow += direction) {
8374
- if (!excludeNonImageModalities || !nonImageModalities.includes(currentDisplaySets[displaySetIndexToShow].Modality)) {
8491
+ const nextDisplaySet = currentDisplaySets[displaySetIndexToShow];
8492
+ if (nextDisplaySet.madeInClient) {
8493
+ continue;
8494
+ }
8495
+ if (!excludeNonImageModalities || !nonImageModalities.includes(nextDisplaySet.Modality)) {
8375
8496
  break;
8376
8497
  }
8377
8498
  }
@@ -8397,6 +8518,74 @@ const commandsModule = ({
8397
8518
  viewportsToUpdate: updatedViewports
8398
8519
  });
8399
8520
  setTimeout(() => actions.scrollActiveThumbnailIntoView(), 0);
8521
+ },
8522
+ /**
8523
+ * Creates a store function based on the data source type.
8524
+ * @param dataSource - 'download', 'copyToClipboard', or a named data source
8525
+ * @param defaultFileName - Default filename for download/clipboard
8526
+ * @param defaultContentType - Default content type for clipboard
8527
+ * @returns A store function, or null if no valid store exists
8528
+ */
8529
+ createStoreFunction: ({
8530
+ dataSource,
8531
+ defaultFileName,
8532
+ defaultContentType
8533
+ }) => {
8534
+ if (dataSource === 'download') {
8535
+ return async dicom => {
8536
+ const instances = Array.isArray(dicom) ? dicom : [dicom];
8537
+ src/* DicomMetadataStore */.H8.addInstances(instances, true);
8538
+ if (instances.length !== 1) {
8539
+ throw new Error('Download only supports a single DICOM instance');
8540
+ }
8541
+ const reportBlob = dcmjs_es/* default.data */.Ay.data.datasetToBlob(instances[0]);
8542
+ downloadBlob(reportBlob, {
8543
+ filename: defaultFileName || 'dicom.dcm'
8544
+ });
8545
+ };
8546
+ }
8547
+ if (dataSource === 'copyToClipboard') {
8548
+ return async dicom => {
8549
+ const instances = Array.isArray(dicom) ? dicom : [dicom];
8550
+ src/* DicomMetadataStore */.H8.addInstances(instances, true);
8551
+ if (instances.length !== 1) {
8552
+ throw new Error('Copy to clipboard only supports a single DICOM instance');
8553
+ }
8554
+ const reportBlob = dcmjs_es/* default.data */.Ay.data.datasetToBlob(instances[0]);
8555
+ const type = defaultContentType || 'application/dicom';
8556
+ await navigator.clipboard.write([new ClipboardItem({
8557
+ [type]: new Blob([reportBlob], {
8558
+ type
8559
+ })
8560
+ })]);
8561
+ };
8562
+ }
8563
+
8564
+ // DICOM STOW path — resolve the named data source
8565
+ const dataSources = extensionManager.getDataSources(dataSource);
8566
+ const resolvedDataSource = dataSources?.[0];
8567
+ if (!resolvedDataSource?.store?.dicom) {
8568
+ return null;
8569
+ }
8570
+ return async (dicom, {
8571
+ dicomDict
8572
+ } = {}) => {
8573
+ const instances = Array.isArray(dicom) ? dicom : [dicom];
8574
+ const config = resolvedDataSource.getConfig?.();
8575
+ if (config?.wadoRoot) {
8576
+ instances.forEach(instance => {
8577
+ instance.wadoRoot = config.wadoRoot;
8578
+ });
8579
+ }
8580
+ src/* DicomMetadataStore */.H8.addInstances(instances, true);
8581
+ for (const instance of instances) {
8582
+ await resolvedDataSource.store.dicom(instance, null, dicomDict);
8583
+ }
8584
+ const studyUIDs = new Set(instances.map(i => i.StudyInstanceUID).filter(Boolean));
8585
+ for (const uid of studyUIDs) {
8586
+ resolvedDataSource.deleteStudyMetadataPromise(uid);
8587
+ }
8588
+ };
8400
8589
  }
8401
8590
  };
8402
8591
  const definitions = {
@@ -8428,7 +8617,8 @@ const commandsModule = ({
8428
8617
  updateViewportDisplaySet: actions.updateViewportDisplaySet,
8429
8618
  scrollActiveThumbnailIntoView: actions.scrollActiveThumbnailIntoView,
8430
8619
  addDisplaySetAsLayer: actions.addDisplaySetAsLayer,
8431
- removeDisplaySetLayer: actions.removeDisplaySetLayer
8620
+ removeDisplaySetLayer: actions.removeDisplaySetLayer,
8621
+ createStoreFunction: actions.createStoreFunction
8432
8622
  };
8433
8623
  return {
8434
8624
  actions,
@@ -9605,7 +9795,7 @@ function DataSourceSelector() {
9605
9795
  }, /*#__PURE__*/react.createElement("div", {
9606
9796
  className: "flex h-screen w-screen items-center justify-center"
9607
9797
  }, /*#__PURE__*/react.createElement("div", {
9608
- className: "bg-secondary-dark mx-auto space-y-2 rounded-lg py-8 px-8 drop-shadow-md"
9798
+ className: "bg-popover mx-auto space-y-2 rounded-lg py-8 px-8 drop-shadow-md"
9609
9799
  }, /*#__PURE__*/react.createElement("img", {
9610
9800
  className: "mx-auto block h-14",
9611
9801
  src: "./ohif-logo.svg",
@@ -9615,7 +9805,7 @@ function DataSourceSelector() {
9615
9805
  }, dsConfigs.filter(it => it.sourceName !== 'dicomjson' && it.sourceName !== 'dicomlocal').map(ds => /*#__PURE__*/react.createElement("div", {
9616
9806
  key: ds.sourceName
9617
9807
  }, /*#__PURE__*/react.createElement("h1", {
9618
- className: "text-white"
9808
+ className: "text-foreground"
9619
9809
  }, ds.configuration?.friendlyName || ds.friendlyName), /*#__PURE__*/react.createElement(ui_src/* Button */.$n, {
9620
9810
  type: ui_src/* ButtonEnums.type */.Ny.NW.primary,
9621
9811
  className: classnames_default()('ml-2'),
@@ -9923,7 +10113,7 @@ function ItemListComponent({
9923
10113
  }), /*#__PURE__*/react.createElement(ui_next_src/* InputFilter */.zbB.ClearButton, {
9924
10114
  className: "text-primary mr-0.5 p-0.5"
9925
10115
  }))), /*#__PURE__*/react.createElement("div", {
9926
- className: "relative flex min-h-[1px] grow flex-col bg-black text-[14px]"
10116
+ className: "relative flex min-h-[1px] grow flex-col bg-background text-[14px]"
9927
10117
  }, itemList == null ? /*#__PURE__*/react.createElement(LoadingIndicatorProgress, {
9928
10118
  className: 'h-full w-full'
9929
10119
  }) : itemList.length === 0 ? /*#__PURE__*/react.createElement("div", {
@@ -10015,16 +10205,16 @@ function DataSourceConfigurationModalComponent({
10015
10205
  };
10016
10206
  }, [selectedItems, configurationAPI, onHide, itemLabels, showFullConfig, currentSelectedItemIndex]);
10017
10207
  const getSelectedItemCursorClasses = itemIndex => itemIndex !== itemLabels.length - 1 && itemIndex < selectedItems.length ? 'cursor-pointer' : 'cursor-auto';
10018
- const getSelectedItemBackgroundClasses = itemIndex => itemIndex < selectedItems.length ? classnames_default()('bg-black/[.4]', itemIndex !== itemLabels.length - 1 ? 'hover:bg-transparent active:bg-secondary-dark' : '') : 'bg-transparent';
10019
- const getSelectedItemBorderClasses = itemIndex => itemIndex === currentSelectedItemIndex + 1 ? classnames_default()('border-2', 'border-solid', 'border-primary-light') : itemIndex < selectedItems.length ? 'border border-solid border-primary-active hover:border-primary-light active:border-white' : 'border border-dashed border-secondary-light';
10020
- const getSelectedItemTextClasses = itemIndex => itemIndex <= selectedItems.length ? 'text-primary-light' : 'text-primary';
10208
+ const getSelectedItemBackgroundClasses = itemIndex => itemIndex < selectedItems.length ? classnames_default()('bg-background/[.4]', itemIndex !== itemLabels.length - 1 ? 'hover:bg-transparent active:bg-popover' : '') : 'bg-transparent';
10209
+ const getSelectedItemBorderClasses = itemIndex => itemIndex === currentSelectedItemIndex + 1 ? classnames_default()('border-2', 'border-solid', 'border-highlight') : itemIndex < selectedItems.length ? 'border border-solid border-primary hover:border-highlight active:border-white' : 'border border-dashed border-input';
10210
+ const getSelectedItemTextClasses = itemIndex => itemIndex <= selectedItems.length ? 'text-highlight' : 'text-primary';
10021
10211
  const getErrorComponent = () => {
10022
10212
  return /*#__PURE__*/react.createElement("div", {
10023
10213
  className: "flex min-h-[1px] grow flex-col gap-4"
10024
10214
  }, /*#__PURE__*/react.createElement("div", {
10025
- className: "text-primary-light text-[20px]"
10215
+ className: "text-highlight text-[20px]"
10026
10216
  }, t(`Error fetching ${itemLabels[selectedItems.length]} list`)), /*#__PURE__*/react.createElement("div", {
10027
- className: "grow bg-black p-4 text-[14px]"
10217
+ className: "grow bg-background p-4 text-[14px]"
10028
10218
  }, errorMessage));
10029
10219
  };
10030
10220
  const getSelectedItemsComponent = () => {
@@ -10047,14 +10237,14 @@ function DataSourceConfigurationModalComponent({
10047
10237
  }), /*#__PURE__*/react.createElement("div", {
10048
10238
  className: classnames_default()(NO_WRAP_ELLIPSIS_CLASS_NAMES)
10049
10239
  }, t(itemLabel))), itemLabelIndex < selectedItems.length ? /*#__PURE__*/react.createElement("div", {
10050
- className: classnames_default()('text-[14px] text-white', NO_WRAP_ELLIPSIS_CLASS_NAMES)
10240
+ className: classnames_default()('text-foreground text-[14px]', NO_WRAP_ELLIPSIS_CLASS_NAMES)
10051
10241
  }, selectedItems[itemLabelIndex].name) : /*#__PURE__*/react.createElement("br", null));
10052
10242
  }));
10053
10243
  };
10054
10244
  return /*#__PURE__*/react.createElement("div", {
10055
10245
  className: "flex h-[calc(100vh-300px)] select-none flex-col gap-4 pt-0.5"
10056
10246
  }, getSelectedItemsComponent(), /*#__PURE__*/react.createElement("div", {
10057
- className: "h-0.5 w-full shrink-0 bg-black"
10247
+ className: "h-0.5 w-full shrink-0 bg-background"
10058
10248
  }), errorMessage ? getErrorComponent() : /*#__PURE__*/react.createElement(Components_ItemListComponent, {
10059
10249
  itemLabel: itemLabels[currentSelectedItemIndex + 1],
10060
10250
  itemList: itemList,
@@ -10137,7 +10327,7 @@ function DataSourceConfigurationComponent({
10137
10327
  }
10138
10328
  }, [configurationAPI, configuredItems, showConfigurationModal]);
10139
10329
  return configuredItems ? /*#__PURE__*/react.createElement("div", {
10140
- className: "text-aqua-pale flex items-center overflow-hidden"
10330
+ className: "text-muted-foreground flex items-center overflow-hidden"
10141
10331
  }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Settings, {
10142
10332
  className: "mr-2.5 h-3.5 w-3.5 shrink-0 cursor-pointer",
10143
10333
  onClick: showConfigurationModal
@@ -10346,8 +10536,14 @@ function getDataSourceConfigurationCustomization({
10346
10536
  const {
10347
10537
  sortingCriteria
10348
10538
  } = src/* utils */.Wp;
10539
+ const {
10540
+ seriesSortCriteria
10541
+ } = sortingCriteria;
10542
+
10543
+ /** Stable series order for e2e (Playwright sets TEST_ENV=true via cross-env). */
10544
+ const sortingCriteriaFn = false ? 0 : seriesSortCriteria.seriesInfoSortingCriteria;
10349
10545
  /* harmony default export */ const sortingCriteriaCustomization = ({
10350
- sortingCriteria: sortingCriteria.seriesSortCriteria.seriesInfoSortingCriteria
10546
+ sortingCriteria: sortingCriteriaFn
10351
10547
  });
10352
10548
  ;// ../../../extensions/default/src/customizations/onDropHandlerCustomization.ts
10353
10549
  /* harmony default export */ const onDropHandlerCustomization = ({
@@ -10418,8 +10614,8 @@ function AboutModalDefault() {
10418
10614
  name
10419
10615
  } = (0,browser_detect_es5/* default */.A)();
10420
10616
  const browser = `${name[0].toUpperCase()}${name.substr(1)} ${version}`;
10421
- const versionNumber = "3.13.0-beta.8";
10422
- const commitHash = "4e9b5c2e228dabeb663df04e1a31e05dfa309588";
10617
+ const versionNumber = "3.13.0-beta.81";
10618
+ const commitHash = "2258c7957a18ed0f1a75d2bd5d379006797b2882";
10423
10619
  const [main, beta] = versionNumber.split('-');
10424
10620
  return /*#__PURE__*/react.createElement(ui_next_src/* AboutModal */.VTU, {
10425
10621
  className: "w-[400px]"
@@ -10450,16 +10646,50 @@ const {
10450
10646
  defaultLanguage,
10451
10647
  currentLanguage: currentLanguageFn
10452
10648
  } = i18n_src/* default */.A;
10649
+ const MODIFIER_OPTIONS = [{
10650
+ value: '16',
10651
+ label: 'Shift'
10652
+ }, {
10653
+ value: '17',
10654
+ label: 'Ctrl'
10655
+ }, {
10656
+ value: '18',
10657
+ label: 'Alt'
10658
+ }, {
10659
+ value: '91',
10660
+ label: 'Meta'
10661
+ }];
10662
+ const DEFAULT_TOOL_BINDINGS_STORAGE_KEY = 'user-preferred-tool-bindings';
10663
+ function getToolModifier(toolGroupService, toolGroupId, toolName, mouseButton) {
10664
+ if (!toolGroupService) {
10665
+ return null;
10666
+ }
10667
+ const bindings = toolGroupService.getToolBindings(toolGroupId, toolName);
10668
+ if (!bindings?.length) {
10669
+ return null;
10670
+ }
10671
+ const modifierBinding = bindings.find(binding => binding.mouseButton === mouseButton && binding.modifierKey != null && binding.numTouchPoints == null);
10672
+ return modifierBinding?.modifierKey != null ? String(modifierBinding.modifierKey) : null;
10673
+ }
10674
+ function getModifierFromBindings(bindings, mouseButton) {
10675
+ if (!bindings?.length) {
10676
+ return null;
10677
+ }
10678
+ const modifierBinding = bindings.find(binding => binding.mouseButton === mouseButton && binding.modifierKey != null && binding.numTouchPoints == null);
10679
+ return modifierBinding?.modifierKey != null ? String(modifierBinding.modifierKey) : null;
10680
+ }
10453
10681
  function UserPreferencesModalDefault({
10454
10682
  hide
10455
10683
  }) {
10456
10684
  const {
10457
- hotkeysManager
10685
+ hotkeysManager,
10686
+ servicesManager
10458
10687
  } = (0,src/* useSystem */.Jg)();
10459
10688
  const {
10460
10689
  t,
10461
10690
  i18n: i18nextInstance
10462
10691
  } = (0,es/* useTranslation */.Bd)('UserPreferencesModal');
10692
+ const toolGroupService = servicesManager?.services?.toolGroupService;
10463
10693
  const {
10464
10694
  hotkeyDefinitions = {},
10465
10695
  hotkeyDefaults = {}
@@ -10476,9 +10706,12 @@ function UserPreferencesModalDefault({
10476
10706
  const resolvedHotkeyDefaults = Object.keys(hotkeyDefaults).length ? hotkeyDefaults : fallbackHotkeyDefinitions;
10477
10707
  const initialHotkeyDefinitions = Object.keys(hotkeyDefinitions).length ? hotkeyDefinitions : resolvedHotkeyDefaults;
10478
10708
  const currentLanguage = currentLanguageFn();
10709
+ const initialCrosshairModifier = (0,react.useMemo)(() => getToolModifier(toolGroupService, 'mpr', 'Crosshairs', 1), [toolGroupService]);
10710
+ const defaultCrosshairBindings = (0,react.useMemo)(() => toolGroupService?.getDefaultToolBindings?.('mpr', 'Crosshairs'), [toolGroupService]);
10479
10711
  const [state, setState] = (0,react.useState)({
10480
10712
  hotkeyDefinitions: initialHotkeyDefinitions,
10481
- languageValue: currentLanguage.value
10713
+ languageValue: currentLanguage.value,
10714
+ crosshairModifier: initialCrosshairModifier
10482
10715
  });
10483
10716
  const onLanguageChangeHandler = value => {
10484
10717
  setState(state => ({
@@ -10502,9 +10735,17 @@ function UserPreferencesModalDefault({
10502
10735
  setState(state => ({
10503
10736
  ...state,
10504
10737
  languageValue: defaultLanguage.value,
10505
- hotkeyDefinitions: resolvedHotkeyDefaults
10738
+ hotkeyDefinitions: resolvedHotkeyDefaults,
10739
+ crosshairModifier: getModifierFromBindings(defaultCrosshairBindings, 1)
10506
10740
  }));
10507
10741
  hotkeysManager.restoreDefaultBindings();
10742
+ if (toolGroupService && defaultCrosshairBindings?.length) {
10743
+ toolGroupService.setToolBindings('mpr', 'Crosshairs', defaultCrosshairBindings);
10744
+ toolGroupService.applyToolBindings('mpr', 'Crosshairs', {
10745
+ replaceExisting: true
10746
+ });
10747
+ }
10748
+ toolGroupService?.removePersistedToolBindings('mpr', 'Crosshairs');
10508
10749
  };
10509
10750
  const displayNames = react.useMemo(() => {
10510
10751
  if (typeof Intl === 'undefined' || typeof Intl.DisplayNames !== 'function') {
@@ -10561,7 +10802,32 @@ function UserPreferencesModalDefault({
10561
10802
  onChange: newKeys => onHotkeyChangeHandler(id, newKeys),
10562
10803
  placeholder: definition.keys,
10563
10804
  hotkeys: src/* hotkeys */.ot
10564
- })))), /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu, null, /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu.Left, null, /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu.Auxiliary, {
10805
+ }))), state.crosshairModifier != null && /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement(ui_next_src/* UserPreferencesModal */.xMy.SubHeading, null, t('ModifierKeys', {
10806
+ defaultValue: 'Modifier Keys'
10807
+ })), /*#__PURE__*/react.createElement(ui_next_src/* UserPreferencesModal */.xMy.HotkeysGrid, null, /*#__PURE__*/react.createElement("div", {
10808
+ className: "flex items-center justify-between gap-2"
10809
+ }, /*#__PURE__*/react.createElement("span", {
10810
+ className: "text-foreground text-base"
10811
+ }, t('CrosshairsModifier', {
10812
+ defaultValue: 'Crosshairs'
10813
+ })), /*#__PURE__*/react.createElement("div", {
10814
+ className: "flex items-center gap-1.5"
10815
+ }, /*#__PURE__*/react.createElement("span", {
10816
+ className: "text-muted-foreground text-sm"
10817
+ }, t('PlusLeftClick', {
10818
+ defaultValue: 'Left Click +'
10819
+ })), /*#__PURE__*/react.createElement(ui_next_src/* Select */.l6P, {
10820
+ value: state.crosshairModifier,
10821
+ onValueChange: val => setState(s => ({
10822
+ ...s,
10823
+ crosshairModifier: val
10824
+ }))
10825
+ }, /*#__PURE__*/react.createElement(ui_next_src/* SelectTrigger */.bqE, {
10826
+ className: "w-16"
10827
+ }, /*#__PURE__*/react.createElement(ui_next_src/* SelectValue */.yvm, null)), /*#__PURE__*/react.createElement(ui_next_src/* SelectContent */.gCo, null, MODIFIER_OPTIONS.map(opt => /*#__PURE__*/react.createElement(ui_next_src/* SelectItem */.ebT, {
10828
+ key: opt.value,
10829
+ value: opt.value
10830
+ }, opt.label))))))))), /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu, null, /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu.Left, null, /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu.Auxiliary, {
10565
10831
  onClick: onResetHandler
10566
10832
  }, t('Reset to defaults'))), /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu.Right, null, /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu.Secondary, {
10567
10833
  onClick: () => {
@@ -10578,6 +10844,17 @@ function UserPreferencesModalDefault({
10578
10844
  return; // Exit early since we're reloading
10579
10845
  }
10580
10846
  hotkeysManager.setHotkeys(state.hotkeyDefinitions);
10847
+ if (toolGroupService && state.crosshairModifier != null) {
10848
+ const bindings = [{
10849
+ mouseButton: 1,
10850
+ modifierKey: Number(state.crosshairModifier)
10851
+ }];
10852
+ toolGroupService.setToolBindings('mpr', 'Crosshairs', bindings);
10853
+ toolGroupService.applyToolBindings('mpr', 'Crosshairs', {
10854
+ replaceExisting: true
10855
+ });
10856
+ toolGroupService.persistToolBindings('mpr', 'Crosshairs', bindings);
10857
+ }
10581
10858
  src/* hotkeys */.ot.stopRecord();
10582
10859
  src/* hotkeys */.ot.unpause();
10583
10860
  hide();
@@ -10585,13 +10862,15 @@ function UserPreferencesModalDefault({
10585
10862
  }, t('Save')))));
10586
10863
  }
10587
10864
  /* harmony default export */ const userPreferencesCustomization = ({
10588
- 'ohif.userPreferencesModal': UserPreferencesModalDefault
10865
+ 'ohif.userPreferencesModal': UserPreferencesModalDefault,
10866
+ 'ohif.userPreferences.toolBindingsStorageKey': DEFAULT_TOOL_BINDINGS_STORAGE_KEY
10589
10867
  });
10590
10868
  ;// ../../../extensions/default/src/customizations/reportDialogCustomization.tsx
10591
10869
 
10592
10870
 
10593
10871
 
10594
10872
 
10873
+
10595
10874
  function ReportDialog({
10596
10875
  dataSources,
10597
10876
  modality = 'SR',
@@ -10599,11 +10878,16 @@ function ReportDialog({
10599
10878
  minSeriesNumber = 3000,
10600
10879
  hide,
10601
10880
  onSave,
10602
- onCancel
10881
+ onCancel,
10882
+ enableDownload = false
10603
10883
  }) {
10884
+ const {
10885
+ t
10886
+ } = (0,es/* useTranslation */.Bd)('Buttons');
10604
10887
  const {
10605
10888
  servicesManager
10606
10889
  } = (0,src/* useSystem */.Jg)();
10890
+ const actionTakenRef = (0,react.useRef)(false);
10607
10891
  const [selectedDataSource, setSelectedDataSource] = (0,react.useState)(dataSources?.[0]?.value ?? null);
10608
10892
  const {
10609
10893
  displaySetService
@@ -10632,6 +10916,7 @@ function ReportDialog({
10632
10916
  setReportName(newReportName);
10633
10917
  }, [selectedSeries, seriesOptions]);
10634
10918
  const handleSave = (0,react.useCallback)(() => {
10919
+ actionTakenRef.current = true;
10635
10920
  onSave({
10636
10921
  reportName,
10637
10922
  dataSource: selectedDataSource,
@@ -10641,10 +10926,31 @@ function ReportDialog({
10641
10926
  hide();
10642
10927
  }, [selectedDataSource, selectedSeries, reportName, hide, onSave]);
10643
10928
  const handleCancel = (0,react.useCallback)(() => {
10929
+ actionTakenRef.current = true;
10644
10930
  onCancel();
10645
10931
  hide();
10646
10932
  }, [onCancel, hide]);
10933
+ const handleDownload = (0,react.useCallback)(() => {
10934
+ actionTakenRef.current = true;
10935
+ onSave({
10936
+ reportName,
10937
+ dataSource: 'download',
10938
+ priorSeriesNumber: Math.max(...seriesOptions.map(it => it.seriesNumber)),
10939
+ series: selectedSeries
10940
+ });
10941
+ hide();
10942
+ }, [selectedDataSource, selectedSeries, reportName, hide, onSave]);
10943
+
10944
+ // Handles the close dialog button/external close as a cancel
10945
+ (0,react.useEffect)(() => {
10946
+ return () => {
10947
+ if (!actionTakenRef.current) {
10948
+ onCancel();
10949
+ }
10950
+ };
10951
+ }, [onCancel]);
10647
10952
  const showDataSourceSelect = dataSources?.length > 1;
10953
+ const showDownloadButton = enableDownload;
10648
10954
  return /*#__PURE__*/react.createElement("div", {
10649
10955
  className: "text-foreground flex min-w-[400px] max-w-md flex-col"
10650
10956
  }, /*#__PURE__*/react.createElement("div", {
@@ -10701,9 +11007,9 @@ function ReportDialog({
10701
11007
  disabled: !!selectedSeries
10702
11008
  })))), /*#__PURE__*/react.createElement("div", {
10703
11009
  className: "flex justify-end gap-2"
10704
- }, /*#__PURE__*/react.createElement(ui_next_src/* InputDialog */.fa0, null, /*#__PURE__*/react.createElement(ui_next_src/* InputDialog */.fa0.Actions, null, /*#__PURE__*/react.createElement(ui_next_src/* InputDialog */.fa0.ActionsSecondary, {
10705
- onClick: handleCancel
10706
- }, "Cancel"), /*#__PURE__*/react.createElement(ui_next_src/* InputDialog */.fa0.ActionsPrimary, {
11010
+ }, /*#__PURE__*/react.createElement(ui_next_src/* InputDialog */.fa0, null, /*#__PURE__*/react.createElement(ui_next_src/* InputDialog */.fa0.Actions, null, showDownloadButton && /*#__PURE__*/react.createElement(ui_next_src/* InputDialog */.fa0.ActionsSecondary, {
11011
+ onClick: handleDownload
11012
+ }, t('Download')), /*#__PURE__*/react.createElement(ui_next_src/* InputDialog */.fa0.ActionsPrimary, {
10707
11013
  onClick: handleSave
10708
11014
  }, "Save"))))));
10709
11015
  }
@@ -11611,11 +11917,12 @@ function promptLabelAnnotation({
11611
11917
  // EXTERNAL MODULE: ../../../extensions/default/src/Panels/StudyBrowser/PanelStudyBrowserHeader.tsx
11612
11918
  var PanelStudyBrowserHeader = __webpack_require__(3329);
11613
11919
  ;// ../../../extensions/default/src/utils/addIcon.ts
11920
+ /* unused harmony import specifier */ var Icons;
11614
11921
 
11615
11922
 
11616
11923
  /** Adds the icon to both ui and ui-next */
11617
11924
  function addIcon(name, icon) {
11618
- ui_next_src/* Icons */.FI1.addIcon(name, icon);
11925
+ Icons.addIcon(name, icon);
11619
11926
  }
11620
11927
  ;// ../../../extensions/default/src/utils/Toolbox.tsx
11621
11928
  function Toolbox_extends() { return Toolbox_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; }, Toolbox_extends.apply(null, arguments); }
@@ -11723,7 +12030,7 @@ function Toolbox({
11723
12030
  })));
11724
12031
  }));
11725
12032
  }), activeToolOptions && /*#__PURE__*/react.createElement("div", {
11726
- className: "bg-primary-dark mt-1 h-auto px-2"
12033
+ className: "bg-muted mt-1 h-auto px-2"
11727
12034
  }, /*#__PURE__*/react.createElement(ui_next_src/* ToolSettings */.k_3, {
11728
12035
  options: activeToolOptions
11729
12036
  }))));
@@ -11807,10 +12114,10 @@ const defaultExtension = {
11807
12114
  /* harmony default export */ const default_src = (defaultExtension);
11808
12115
 
11809
12116
 
11810
- /***/ }),
12117
+ /***/ },
11811
12118
 
11812
- /***/ 96357:
11813
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
12119
+ /***/ 96357
12120
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
11814
12121
 
11815
12122
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
11816
12123
  /* harmony export */ A: () => (__WEBPACK_DEFAULT_EXPORT__)
@@ -11825,6 +12132,6 @@ const RESPONSE = {
11825
12132
  };
11826
12133
  /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (RESPONSE);
11827
12134
 
11828
- /***/ })
12135
+ /***/ }
11829
12136
 
11830
12137
  }]);