@ohif/app 3.8.0-beta.62 → 3.8.0-beta.64

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 (32) hide show
  1. package/dist/{121.bundle.ed23e7752a11005322e6.js → 121.bundle.5399d807995157d368b7.js} +4 -4
  2. package/dist/{155.bundle.19e63774cdf16306b5b6.js → 155.bundle.55fa02bfc411cc91e261.js} +12 -7
  3. package/dist/{188.bundle.7e085b90e138357e6789.js → 188.bundle.ec979013d89d90831c58.js} +2 -2
  4. package/dist/{270.bundle.36c4e95efb89ad8bd8ae.js → 270.bundle.58c74e58ad67b5069718.js} +51 -28
  5. package/dist/{295.bundle.462f3328c716cbe6c613.js → 295.bundle.c0a29ff64d86f707fc20.js} +4 -4
  6. package/dist/{339.bundle.2271a993c53d0728c816.js → 339.bundle.e31c81c7179d3d24f3dd.js} +27 -69
  7. package/dist/{68.bundle.0420d25b4736f20b15b2.js → 41.bundle.0696b28613c7d47833c9.js} +276 -486
  8. package/dist/{250.bundle.a064577944a0691bc77d.js → 448.bundle.e856d2b2bd979c7d9ac0.js} +238 -382
  9. package/dist/{530.bundle.ce13c30b93a28cc85098.js → 530.bundle.f00fd953dcd9d0afd10b.js} +2 -2
  10. package/dist/{544.bundle.3cf20da53f349abd8d67.js → 544.bundle.adfe5764f59b5fe0eba7.js} +5 -17
  11. package/dist/{559.bundle.42a8edafa1c7df761194.js → 559.bundle.4f55f5df04c418b2854e.js} +6 -10
  12. package/dist/{594.bundle.6667c5cc14b924d7bee6.js → 594.bundle.924cdc10e7435cf3e199.js} +147 -188
  13. package/dist/{50.bundle.a18826e121bdd0c2a707.js → 638.bundle.62f8f8ada74bd900abfc.js} +158 -394
  14. package/dist/{317.bundle.7ef949a52571bc04e7e1.js → 699.bundle.b3b25017819be681ef3d.js} +323 -186
  15. package/dist/{963.bundle.3daa5c08231526d905fb.js → 701.bundle.b7ebc1629fc121e13c58.js} +520 -210
  16. package/dist/{724.bundle.941cd2a3b43a84d5893f.js → 724.bundle.cd011bc1838a2bde1d66.js} +89 -152
  17. package/dist/{862.bundle.e3fe2aae7903cc2ae8df.js → 862.bundle.d2e78b70286b59569e83.js} +2 -2
  18. package/dist/{889.bundle.6850a0b8c412e3befab5.js → 889.bundle.2aefa0a3eb114db0de3f.js} +180 -207
  19. package/dist/{704.bundle.242ba4e0b0be7d1fec94.js → 90.bundle.7a9258532111121b5ee3.js} +228 -338
  20. package/dist/{905.bundle.eb7bdaec4276399e5bef.js → 905.bundle.d4bdcbd451de59b2191b.js} +119 -89
  21. package/dist/{907.bundle.fc8115500a085ab2bbec.js → 907.bundle.ca236b83967a8459b778.js} +2 -14
  22. package/dist/{961.bundle.f5d9e73fa771ce7e73f3.js → 961.bundle.a5541d8090cb8b22f7e6.js} +2 -15
  23. package/dist/{987.bundle.e7c041a6dfb4ddb41813.js → 987.bundle.91d4867efedd5b4d84cb.js} +5 -1
  24. package/dist/{app.bundle.a78a51e39321426c5460.js → app.bundle.039c4dc99821370f330d.js} +1991 -931
  25. package/dist/app.bundle.css +1 -1
  26. package/dist/index.html +1 -1
  27. package/dist/{polySeg.bundle.99be036bab9b7f011b0c.js → polySeg.bundle.c1cec6312eb6c6dc3701.js} +1 -1
  28. package/dist/sw.js +1 -1
  29. package/package.json +17 -17
  30. /package/dist/{164.bundle.0b17fced9916487eb49f.js → 164.bundle.0cfa2edabf8ef222f3ea.js} +0 -0
  31. /package/dist/{50.css → 638.css} +0 -0
  32. /package/dist/{963.css → 701.css} +0 -0
@@ -51,7 +51,7 @@ var useSearchParams = __webpack_require__(86669);
51
51
 
52
52
  /***/ }),
53
53
 
54
- /***/ 45573:
54
+ /***/ 68870:
55
55
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
56
56
 
57
57
  "use strict";
@@ -99,12 +99,12 @@ Compose.propTypes = {
99
99
  components: (prop_types_default()).array,
100
100
  children: (prop_types_default()).node.isRequired
101
101
  };
102
- // EXTERNAL MODULE: ../../ui/src/index.js + 487 modules
103
- var ui_src = __webpack_require__(55395);
102
+ // EXTERNAL MODULE: ../../ui/src/index.js + 495 modules
103
+ var ui_src = __webpack_require__(65967);
104
104
  // EXTERNAL MODULE: ./state/index.js + 1 modules
105
105
  var state = __webpack_require__(15575);
106
- // EXTERNAL MODULE: ../../core/src/index.ts + 66 modules
107
- var core_src = __webpack_require__(14283);
106
+ // EXTERNAL MODULE: ../../core/src/index.ts + 67 modules
107
+ var core_src = __webpack_require__(78198);
108
108
  // EXTERNAL MODULE: ../node_modules/react-router/dist/index.js
109
109
  var react_router_dist = __webpack_require__(10971);
110
110
  // EXTERNAL MODULE: ./hooks/useSearchParams.ts
@@ -993,7 +993,7 @@ function WorkList({
993
993
  }) // launch-arrow | launch-info
994
994
  ,
995
995
  onClick: () => {},
996
- "data-cy": `mode-${mode.routeName}-${studyInstanceUid}`,
996
+ dataCY: `mode-${mode.routeName}-${studyInstanceUid}`,
997
997
  className: isValidMode ? 'text-[13px]' : 'bg-[#222d44] text-[13px]'
998
998
  }, mode.displayName));
999
999
  }))),
@@ -1002,8 +1002,8 @@ function WorkList({
1002
1002
  };
1003
1003
  });
1004
1004
  const hasStudies = numOfStudies > 0;
1005
- const versionNumber = "3.8.0-beta.62";
1006
- const commitHash = "9bcd1ae6f51d61786cc1e99624f396b56a47cd69";
1005
+ const versionNumber = "3.8.0-beta.64";
1006
+ const commitHash = "566b25a54425399096864bd263193646556011a5";
1007
1007
  const menuOptions = [{
1008
1008
  title: t('Header:About'),
1009
1009
  icon: 'info',
@@ -1085,6 +1085,8 @@ function WorkList({
1085
1085
  menuOptions: menuOptions,
1086
1086
  isReturnEnabled: false,
1087
1087
  WhiteLabeling: appConfig.whiteLabeling
1088
+ }), /*#__PURE__*/react.createElement(ui_src/* InvestigationalUseDialog */.j, {
1089
+ dialogConfiguration: appConfig?.investigationalUseDialog
1088
1090
  }), /*#__PURE__*/react.createElement("div", {
1089
1091
  className: "ohif-scrollbar flex grow flex-col overflow-y-auto"
1090
1092
  }, /*#__PURE__*/react.createElement(ui_src/* StudyListFilter */.y_, {
@@ -1531,6 +1533,7 @@ function ViewerViewportGrid(props) {
1531
1533
  numRows
1532
1534
  } = layout;
1533
1535
  const elementRef = (0,react.useRef)(null);
1536
+ const layoutHash = (0,react.useRef)(null);
1534
1537
 
1535
1538
  // TODO -> Need some way of selecting which displaySets hit the viewports.
1536
1539
  const {
@@ -1539,6 +1542,7 @@ function ViewerViewportGrid(props) {
1539
1542
  hangingProtocolService,
1540
1543
  uiNotificationService
1541
1544
  } = servicesManager.services;
1545
+ const generateLayoutHash = () => `${numCols}-${numRows}`;
1542
1546
 
1543
1547
  /**
1544
1548
  * This callback runs after the viewports structure has changed in any way.
@@ -1639,6 +1643,16 @@ function ViewerViewportGrid(props) {
1639
1643
  unsubscribe();
1640
1644
  };
1641
1645
  }, []);
1646
+
1647
+ // Check viewport readiness in useEffect
1648
+ (0,react.useEffect)(() => {
1649
+ const allReady = viewportGridService.getGridViewportsReady();
1650
+ const sameLayoutHash = layoutHash.current === generateLayoutHash();
1651
+ if (allReady && !sameLayoutHash) {
1652
+ layoutHash.current = generateLayoutHash();
1653
+ viewportGridService.publishViewportsReady();
1654
+ }
1655
+ }, [viewportGridService, generateLayoutHash]);
1642
1656
  (0,react.useEffect)(() => {
1643
1657
  const {
1644
1658
  unsubscribe
@@ -1809,7 +1823,10 @@ function ViewerViewportGrid(props) {
1809
1823
  dataSource: dataSource,
1810
1824
  viewportOptions: viewportOptions,
1811
1825
  displaySetOptions: displaySetOptions,
1812
- needsRerendering: displaySetsNeedsRerendering
1826
+ needsRerendering: displaySetsNeedsRerendering,
1827
+ onReady: () => {
1828
+ viewportGridService.setViewportIsReady(viewportId, true);
1829
+ }
1813
1830
  })));
1814
1831
  }
1815
1832
  return viewportPanes;
@@ -1874,68 +1891,6 @@ function _getViewportComponent(displaySets, viewportComponents, uiNotificationSe
1874
1891
  return components_EmptyViewport;
1875
1892
  }
1876
1893
  /* harmony default export */ const ViewportGrid = (ViewerViewportGrid);
1877
- ;// CONCATENATED MODULE: ./routes/Mode/studiesList.ts
1878
-
1879
- /**
1880
- * Compare function for sorting
1881
- *
1882
- * @param a - some simple value (string, number, timestamp)
1883
- * @param b - some simple value
1884
- * @param defaultCompare - default return value as a fallback when a===b
1885
- * @returns - compare a and b, returning 1 if a<b -1 if a>b and defaultCompare otherwise
1886
- */
1887
- const compare = (a, b, defaultCompare = 0) => {
1888
- if (a === b) {
1889
- return defaultCompare;
1890
- }
1891
- if (a < b) {
1892
- return 1;
1893
- }
1894
- return -1;
1895
- };
1896
-
1897
- /**
1898
- * The studies from display sets gets the studies in study date
1899
- * order or in study instance UID order - not very useful, but
1900
- * if not specifically specified then at least making it consistent is useful.
1901
- */
1902
- const getStudiesfromDisplaySets = displaysets => {
1903
- const studyMap = {};
1904
- const ret = displaySets.reduce((prev, curr) => {
1905
- const {
1906
- StudyInstanceUID
1907
- } = curr;
1908
- if (!studyMap[StudyInstanceUID]) {
1909
- const study = core_src.DicomMetadataStore.getStudy(StudyInstanceUID);
1910
- studyMap[StudyInstanceUID] = study;
1911
- prev.push(study);
1912
- }
1913
- return prev;
1914
- }, []);
1915
- // Return the sorted studies, first on study date and second on study instance UID
1916
- ret.sort((a, b) => {
1917
- return compare(a.StudyDate, b.StudyDate, compare(a.StudyInstanceUID, b.StudyInstanceUID));
1918
- });
1919
- return ret;
1920
- };
1921
-
1922
- /**
1923
- * The studies retrieve from the Uids is faster and gets the studies
1924
- * in the original order, as specified.
1925
- */
1926
- const getStudiesFromUIDs = studyUids => {
1927
- if (!studyUids?.length) {
1928
- return;
1929
- }
1930
- return studyUids.map(uid => core_src.DicomMetadataStore.getStudy(uid));
1931
- };
1932
-
1933
- /** Gets the array of studies */
1934
- const getStudies = (studyUids, displaySets) => {
1935
- return getStudiesFromUIDs(studyUids) || getStudiesfromDisplaySets(displaySets);
1936
- };
1937
- /* harmony default export */ const studiesList = (getStudies);
1938
-
1939
1894
  ;// CONCATENATED MODULE: ./utils/history.ts
1940
1895
  const history_history = {
1941
1896
  navigate: null
@@ -1960,15 +1915,15 @@ modes.push("@ohif/mode-microscopy");
1960
1915
  async function loadModule(module) {
1961
1916
  if (typeof module !== 'string') return module;
1962
1917
  if (module === "@ohif/extension-default") {
1963
- const imported = await Promise.all(/* import() */[__webpack_require__.e(504), __webpack_require__.e(191), __webpack_require__.e(644), __webpack_require__.e(931), __webpack_require__.e(704), __webpack_require__.e(481)]).then(__webpack_require__.bind(__webpack_require__, 49704));
1918
+ const imported = await Promise.all(/* import() */[__webpack_require__.e(504), __webpack_require__.e(191), __webpack_require__.e(644), __webpack_require__.e(931), __webpack_require__.e(90), __webpack_require__.e(481)]).then(__webpack_require__.bind(__webpack_require__, 54090));
1964
1919
  return imported.default;
1965
1920
  }
1966
1921
  if (module === "@ohif/extension-cornerstone") {
1967
- const imported = await Promise.all(/* import() */[__webpack_require__.e(504), __webpack_require__.e(191), __webpack_require__.e(644), __webpack_require__.e(290), __webpack_require__.e(963)]).then(__webpack_require__.bind(__webpack_require__, 34963));
1922
+ const imported = await Promise.all(/* import() */[__webpack_require__.e(504), __webpack_require__.e(191), __webpack_require__.e(644), __webpack_require__.e(290), __webpack_require__.e(701)]).then(__webpack_require__.bind(__webpack_require__, 20701));
1968
1923
  return imported.default;
1969
1924
  }
1970
1925
  if (module === "@ohif/extension-measurement-tracking") {
1971
- const imported = await Promise.all(/* import() */[__webpack_require__.e(504), __webpack_require__.e(191), __webpack_require__.e(644), __webpack_require__.e(342), __webpack_require__.e(931), __webpack_require__.e(835), __webpack_require__.e(704), __webpack_require__.e(559), __webpack_require__.e(155)]).then(__webpack_require__.bind(__webpack_require__, 63934));
1926
+ const imported = await Promise.all(/* import() */[__webpack_require__.e(504), __webpack_require__.e(191), __webpack_require__.e(644), __webpack_require__.e(342), __webpack_require__.e(931), __webpack_require__.e(835), __webpack_require__.e(90), __webpack_require__.e(559), __webpack_require__.e(155)]).then(__webpack_require__.bind(__webpack_require__, 63934));
1972
1927
  return imported.default;
1973
1928
  }
1974
1929
  if (module === "@ohif/extension-cornerstone-dicom-sr") {
@@ -1976,7 +1931,7 @@ async function loadModule(module) {
1976
1931
  return imported.default;
1977
1932
  }
1978
1933
  if (module === "@ohif/extension-cornerstone-dicom-seg") {
1979
- const imported = await Promise.all(/* import() */[__webpack_require__.e(504), __webpack_require__.e(191), __webpack_require__.e(644), __webpack_require__.e(342), __webpack_require__.e(931), __webpack_require__.e(726), __webpack_require__.e(704), __webpack_require__.e(50)]).then(__webpack_require__.bind(__webpack_require__, 71093));
1934
+ const imported = await Promise.all(/* import() */[__webpack_require__.e(504), __webpack_require__.e(191), __webpack_require__.e(644), __webpack_require__.e(342), __webpack_require__.e(931), __webpack_require__.e(726), __webpack_require__.e(90), __webpack_require__.e(638)]).then(__webpack_require__.bind(__webpack_require__, 92169));
1980
1935
  return imported.default;
1981
1936
  }
1982
1937
  if (module === "@ohif/extension-dicom-microscopy") {
@@ -2004,11 +1959,11 @@ async function loadModule(module) {
2004
1959
  return imported.default;
2005
1960
  }
2006
1961
  if (module === "@ohif/mode-longitudinal") {
2007
- const imported = await __webpack_require__.e(/* import() */ 68).then(__webpack_require__.bind(__webpack_require__, 76068));
1962
+ const imported = await __webpack_require__.e(/* import() */ 41).then(__webpack_require__.bind(__webpack_require__, 97041));
2008
1963
  return imported.default;
2009
1964
  }
2010
1965
  if (module === "@ohif/mode-segmentation") {
2011
- const imported = await __webpack_require__.e(/* import() */ 317).then(__webpack_require__.bind(__webpack_require__, 55317));
1966
+ const imported = await __webpack_require__.e(/* import() */ 699).then(__webpack_require__.bind(__webpack_require__, 40080));
2012
1967
  return imported.default;
2013
1968
  }
2014
1969
  if (module === "@ohif/mode-tmtv") {
@@ -2020,7 +1975,7 @@ async function loadModule(module) {
2020
1975
  return imported.default;
2021
1976
  }
2022
1977
  if (module === "@ohif/mode-test") {
2023
- const imported = await __webpack_require__.e(/* import() */ 250).then(__webpack_require__.bind(__webpack_require__, 11250));
1978
+ const imported = await __webpack_require__.e(/* import() */ 448).then(__webpack_require__.bind(__webpack_require__, 14448));
2024
1979
  return imported.default;
2025
1980
  }
2026
1981
  if (module === "@ohif/mode-basic-dev-mode") {
@@ -2036,6 +1991,68 @@ function importItems(modules) {
2036
1991
  return Promise.all(modules.map(loadModule));
2037
1992
  }
2038
1993
 
1994
+ ;// CONCATENATED MODULE: ./routes/Mode/studiesList.ts
1995
+
1996
+ /**
1997
+ * Compare function for sorting
1998
+ *
1999
+ * @param a - some simple value (string, number, timestamp)
2000
+ * @param b - some simple value
2001
+ * @param defaultCompare - default return value as a fallback when a===b
2002
+ * @returns - compare a and b, returning 1 if a<b -1 if a>b and defaultCompare otherwise
2003
+ */
2004
+ const compare = (a, b, defaultCompare = 0) => {
2005
+ if (a === b) {
2006
+ return defaultCompare;
2007
+ }
2008
+ if (a < b) {
2009
+ return 1;
2010
+ }
2011
+ return -1;
2012
+ };
2013
+
2014
+ /**
2015
+ * The studies from display sets gets the studies in study date
2016
+ * order or in study instance UID order - not very useful, but
2017
+ * if not specifically specified then at least making it consistent is useful.
2018
+ */
2019
+ const getStudiesfromDisplaySets = displaysets => {
2020
+ const studyMap = {};
2021
+ const ret = displaySets.reduce((prev, curr) => {
2022
+ const {
2023
+ StudyInstanceUID
2024
+ } = curr;
2025
+ if (!studyMap[StudyInstanceUID]) {
2026
+ const study = core_src.DicomMetadataStore.getStudy(StudyInstanceUID);
2027
+ studyMap[StudyInstanceUID] = study;
2028
+ prev.push(study);
2029
+ }
2030
+ return prev;
2031
+ }, []);
2032
+ // Return the sorted studies, first on study date and second on study instance UID
2033
+ ret.sort((a, b) => {
2034
+ return compare(a.StudyDate, b.StudyDate, compare(a.StudyInstanceUID, b.StudyInstanceUID));
2035
+ });
2036
+ return ret;
2037
+ };
2038
+
2039
+ /**
2040
+ * The studies retrieve from the Uids is faster and gets the studies
2041
+ * in the original order, as specified.
2042
+ */
2043
+ const getStudiesFromUIDs = studyUids => {
2044
+ if (!studyUids?.length) {
2045
+ return;
2046
+ }
2047
+ return studyUids.map(uid => core_src.DicomMetadataStore.getStudy(uid));
2048
+ };
2049
+
2050
+ /** Gets the array of studies */
2051
+ const getStudies = (studyUids, displaySets) => {
2052
+ return getStudiesFromUIDs(studyUids) || getStudiesfromDisplaySets(displaySets);
2053
+ };
2054
+ /* harmony default export */ const studiesList = (getStudies);
2055
+
2039
2056
  ;// CONCATENATED MODULE: ./utils/isSeriesFilterUsed.ts
2040
2057
  /**
2041
2058
  * This function is used to check if the filter is used. Its intend is to
@@ -2053,23 +2070,12 @@ function isSeriesFilterUsed(instances, filters) {
2053
2070
  }
2054
2071
  return seriesInstanceUIDs.includes(instances[0].SeriesInstanceUID);
2055
2072
  }
2056
- ;// CONCATENATED MODULE: ./routes/Mode/Mode.tsx
2057
-
2058
-
2059
-
2060
- // TODO: DicomMetadataStore should be injected?
2061
-
2062
-
2063
-
2064
-
2065
-
2066
-
2073
+ ;// CONCATENATED MODULE: ./routes/Mode/defaultRouteInit.ts
2067
2074
 
2068
2075
 
2069
2076
 
2070
2077
 
2071
2078
  const {
2072
- getSplitParam,
2073
2079
  sortingCriteria
2074
2080
  } = core_src.utils;
2075
2081
 
@@ -2188,6 +2194,55 @@ function defaultRouteInit({
2188
2194
  });
2189
2195
  return unsubscriptions;
2190
2196
  }
2197
+ ;// CONCATENATED MODULE: ./routes/Mode/updateAuthServiceAndCleanUrl.ts
2198
+ /**
2199
+ * Updates the user authentication service with the provided token and cleans the token from the URL.
2200
+ * @param token - The token to set in the user authentication service.
2201
+ * @param location - The location object from the router.
2202
+ * @param userAuthenticationService - The user authentication service instance.
2203
+ */
2204
+ function updateAuthServiceAndCleanUrl(token, location, userAuthenticationService) {
2205
+ if (!token) {
2206
+ return;
2207
+ }
2208
+
2209
+ // if a token is passed in, set the userAuthenticationService to use it
2210
+ // for the Authorization header for all requests
2211
+ userAuthenticationService.setServiceImplementation({
2212
+ getAuthorizationHeader: () => ({
2213
+ Authorization: 'Bearer ' + token
2214
+ })
2215
+ });
2216
+
2217
+ // Create a URL object with the current location
2218
+ const urlObj = new URL(window.location.origin + window.location.pathname + location.search);
2219
+
2220
+ // Remove the token from the URL object
2221
+ urlObj.searchParams.delete('token');
2222
+ const cleanUrl = urlObj.toString();
2223
+
2224
+ // Update the browser's history without the token
2225
+ if (window.history && window.history.replaceState) {
2226
+ window.history.replaceState(null, '', cleanUrl);
2227
+ }
2228
+ }
2229
+ ;// CONCATENATED MODULE: ./routes/Mode/Mode.tsx
2230
+
2231
+
2232
+
2233
+
2234
+
2235
+
2236
+
2237
+
2238
+
2239
+
2240
+
2241
+
2242
+
2243
+ const {
2244
+ getSplitParam
2245
+ } = core_src.utils;
2191
2246
  function ModeRoute({
2192
2247
  mode,
2193
2248
  dataSourceName,
@@ -2217,7 +2272,7 @@ function ModeRoute({
2217
2272
  const lowerCaseSearchParams = (0,hooks/* useSearchParams */.o)({
2218
2273
  lowerCaseKeys: true
2219
2274
  });
2220
- const [studyInstanceUIDs, setStudyInstanceUIDs] = (0,react.useState)();
2275
+ const [studyInstanceUIDs, setStudyInstanceUIDs] = (0,react.useState)(null);
2221
2276
  const [refresh, setRefresh] = (0,react.useState)(false);
2222
2277
  const [ExtensionDependenciesLoaded, setExtensionDependenciesLoaded] = (0,react.useState)(false);
2223
2278
  const layoutTemplateData = (0,react.useRef)(false);
@@ -2244,25 +2299,7 @@ function ModeRoute({
2244
2299
  const runTimeHangingProtocolId = lowerCaseSearchParams.get('hangingprotocolid');
2245
2300
  const token = lowerCaseSearchParams.get('token');
2246
2301
  if (token) {
2247
- // if a token is passed in, set the userAuthenticationService to use it
2248
- // for the Authorization header for all requests
2249
- userAuthenticationService.setServiceImplementation({
2250
- getAuthorizationHeader: () => ({
2251
- Authorization: 'Bearer ' + token
2252
- })
2253
- });
2254
-
2255
- // Create a URL object with the current location
2256
- const urlObj = new URL(window.location.origin + window.location.pathname + location.search);
2257
-
2258
- // Remove the token from the URL object
2259
- urlObj.searchParams.delete('token');
2260
- const cleanUrl = urlObj.toString();
2261
-
2262
- // Update the browser's history without the token
2263
- if (window.history && window.history.replaceState) {
2264
- window.history.replaceState(null, '', cleanUrl);
2265
- }
2302
+ updateAuthServiceAndCleanUrl(token, location, userAuthenticationService);
2266
2303
  }
2267
2304
 
2268
2305
  // Preserve the old array interface for hotkeys
@@ -2277,32 +2314,6 @@ function ModeRoute({
2277
2314
 
2278
2315
  // Only handling one route per mode for now
2279
2316
  const route = mode.routes[0];
2280
-
2281
- // For each extension, look up their context modules
2282
- // TODO: move to extension manager.
2283
- let contextModules = [];
2284
- Object.keys(extensions).forEach(extensionId => {
2285
- const allRegisteredModuleIds = Object.keys(extensionManager.modulesMap);
2286
- const moduleIds = allRegisteredModuleIds.filter(id => id.includes(`${extensionId}.contextModule.`));
2287
- if (!moduleIds || !moduleIds.length) {
2288
- return;
2289
- }
2290
- const modules = moduleIds.map(extensionManager.getModuleEntry);
2291
- contextModules = contextModules.concat(modules);
2292
- });
2293
- const contextModuleProviders = contextModules.map(a => a.provider);
2294
- const CombinedContextProvider = ({
2295
- children
2296
- }) => Compose({
2297
- components: contextModuleProviders,
2298
- children
2299
- });
2300
- function ViewportGridWithDataSource(props) {
2301
- return ViewportGrid({
2302
- ...props,
2303
- dataSource
2304
- });
2305
- }
2306
2317
  (0,react.useEffect)(() => {
2307
2318
  const loadExtensions = async () => {
2308
2319
  const loadedExtensions = await importItems(Object.keys(extensions));
@@ -2347,7 +2358,7 @@ function ModeRoute({
2347
2358
  };
2348
2359
  }, [location, ExtensionDependenciesLoaded]);
2349
2360
  (0,react.useEffect)(() => {
2350
- if (!ExtensionDependenciesLoaded) {
2361
+ if (!ExtensionDependenciesLoaded || !studyInstanceUIDs?.length) {
2351
2362
  return;
2352
2363
  }
2353
2364
  const retrieveLayoutData = async () => {
@@ -2361,7 +2372,7 @@ function ModeRoute({
2361
2372
  setRefresh(!refresh);
2362
2373
  }
2363
2374
  };
2364
- if (studyInstanceUIDs?.length && studyInstanceUIDs[0] !== undefined) {
2375
+ if (Array.isArray(studyInstanceUIDs) && studyInstanceUIDs[0]) {
2365
2376
  retrieveLayoutData();
2366
2377
  }
2367
2378
  return () => {
@@ -2369,7 +2380,7 @@ function ModeRoute({
2369
2380
  };
2370
2381
  }, [studyInstanceUIDs, ExtensionDependenciesLoaded]);
2371
2382
  (0,react.useEffect)(() => {
2372
- if (!hotkeys || !ExtensionDependenciesLoaded) {
2383
+ if (!hotkeys || !ExtensionDependenciesLoaded || !studyInstanceUIDs?.length) {
2373
2384
  return;
2374
2385
  }
2375
2386
  hotkeysManager.setDefaultHotKeys(hotkeys);
@@ -2382,9 +2393,9 @@ function ModeRoute({
2382
2393
  return () => {
2383
2394
  hotkeysManager.destroy();
2384
2395
  };
2385
- }, [ExtensionDependenciesLoaded]);
2396
+ }, [ExtensionDependenciesLoaded, hotkeys, studyInstanceUIDs]);
2386
2397
  (0,react.useEffect)(() => {
2387
- if (!layoutTemplateData.current || !ExtensionDependenciesLoaded) {
2398
+ if (!layoutTemplateData.current || !ExtensionDependenciesLoaded || !studyInstanceUIDs?.length) {
2388
2399
  return;
2389
2400
  }
2390
2401
  const setupRouteInit = async () => {
@@ -2491,20 +2502,57 @@ function ModeRoute({
2491
2502
  extensionManager.onModeExit();
2492
2503
  };
2493
2504
  }, [mode, dataSourceName, location, ExtensionDependenciesLoaded, route, servicesManager, extensionManager, hotkeysManager, studyInstanceUIDs, refresh]);
2494
- const renderLayoutData = props => {
2505
+ if (!studyInstanceUIDs || !layoutTemplateData.current || !ExtensionDependenciesLoaded) {
2506
+ return null;
2507
+ }
2508
+ const ViewportGridWithDataSource = props => {
2509
+ return ViewportGrid({
2510
+ ...props,
2511
+ dataSource
2512
+ });
2513
+ };
2514
+ const CombinedExtensionsContextProvider = createCombinedContextProvider(extensionManager, servicesManager, commandsManager);
2515
+ const getLayoutComponent = props => {
2495
2516
  const layoutTemplateModuleEntry = extensionManager.getModuleEntry(layoutTemplateData.current.id);
2496
2517
  const LayoutComponent = layoutTemplateModuleEntry.component;
2497
2518
  return /*#__PURE__*/react.createElement(LayoutComponent, props);
2498
2519
  };
2499
- return /*#__PURE__*/react.createElement(ui_src/* ImageViewerProvider */.xy
2500
- // initialState={{ StudyInstanceUIDs: StudyInstanceUIDs }}
2501
- , {
2502
- StudyInstanceUIDs: studyInstanceUIDs
2503
- // reducer={reducer}
2504
- }, /*#__PURE__*/react.createElement(CombinedContextProvider, null, /*#__PURE__*/react.createElement(ui_src/* DragAndDropProvider */.G8, null, layoutTemplateData.current && studyInstanceUIDs?.[0] !== undefined && ExtensionDependenciesLoaded && renderLayoutData({
2520
+ const LayoutComponent = getLayoutComponent({
2505
2521
  ...layoutTemplateData.current.props,
2506
2522
  ViewportGridComp: ViewportGridWithDataSource
2507
- }))));
2523
+ });
2524
+ return /*#__PURE__*/react.createElement(ui_src/* ImageViewerProvider */.xy, {
2525
+ StudyInstanceUIDs: studyInstanceUIDs
2526
+ }, CombinedExtensionsContextProvider ? /*#__PURE__*/react.createElement(CombinedExtensionsContextProvider, null, /*#__PURE__*/react.createElement(ui_src/* DragAndDropProvider */.G8, null, LayoutComponent)) : /*#__PURE__*/react.createElement(ui_src/* DragAndDropProvider */.G8, null, LayoutComponent));
2527
+ }
2528
+
2529
+ /**
2530
+ * Creates a combined context provider using the context modules from the extension manager.
2531
+ * @param {object} extensionManager - The extension manager instance.
2532
+ * @param {object} servicesManager - The services manager instance.
2533
+ * @param {object} commandsManager - The commands manager instance.
2534
+ * @returns {React.Component} - A React component that provides combined contexts to its children.
2535
+ */
2536
+ function createCombinedContextProvider(extensionManager, servicesManager, commandsManager) {
2537
+ const extensionsContextModules = extensionManager.getModulesByType(extensionManager.constructor.MODULE_TYPES.CONTEXT);
2538
+ if (!extensionsContextModules?.length) {
2539
+ return;
2540
+ }
2541
+ const contextModuleProviders = extensionsContextModules.flatMap(({
2542
+ module
2543
+ }) => {
2544
+ return module.map(aContextModule => {
2545
+ return aContextModule.provider;
2546
+ });
2547
+ });
2548
+ return ({
2549
+ children
2550
+ }) => {
2551
+ return Compose({
2552
+ components: contextModuleProviders,
2553
+ children
2554
+ });
2555
+ };
2508
2556
  }
2509
2557
  ModeRoute.propTypes = {
2510
2558
  mode: (prop_types_default()).object.isRequired,
@@ -2779,7 +2827,8 @@ async function appInit(appConfigOrFunc, defaultExtensions, defaultModes) {
2779
2827
  hotkeysManager,
2780
2828
  appConfig
2781
2829
  });
2782
- servicesManager.registerServices([core_src/* UINotificationService */.v4.REGISTRATION, core_src/* UIModalService */.zo.REGISTRATION, core_src/* UIDialogService */.u$.REGISTRATION, core_src/* UIViewportDialogService */.A$.REGISTRATION, core_src.MeasurementService.REGISTRATION, core_src/* DisplaySetService */.IO.REGISTRATION, [core_src/* CustomizationService */.V0.REGISTRATION, appConfig.customizationService], core_src/* ToolbarService */.hx.REGISTRATION, core_src/* ViewportGridService */.sI.REGISTRATION, core_src/* HangingProtocolService */.Qe.REGISTRATION, core_src/* CineService */.xx.REGISTRATION, core_src/* UserAuthenticationService */.pS.REGISTRATION, core_src/* PanelService */.Mr.REGISTRATION, core_src/* StateSyncService */.wb.REGISTRATION]);
2830
+ servicesManager.setExtensionManager(extensionManager);
2831
+ servicesManager.registerServices([core_src/* UINotificationService */.v4.REGISTRATION, core_src/* UIModalService */.zo.REGISTRATION, core_src/* UIDialogService */.u$.REGISTRATION, core_src/* UIViewportDialogService */.A$.REGISTRATION, core_src.MeasurementService.REGISTRATION, core_src/* DisplaySetService */.IO.REGISTRATION, [core_src/* CustomizationService */.V0.REGISTRATION, appConfig.customizationService], core_src.ToolbarService.REGISTRATION, core_src/* ViewportGridService */.sI.REGISTRATION, core_src/* HangingProtocolService */.Qe.REGISTRATION, core_src/* CineService */.xx.REGISTRATION, core_src/* UserAuthenticationService */.pS.REGISTRATION, core_src/* PanelService */.Mr.REGISTRATION, core_src/* StateSyncService */.wb.REGISTRATION]);
2783
2832
  core_src/* errorHandler */.r_.getHTTPErrorHandler = () => {
2784
2833
  if (typeof appConfig.httpErrorHandler === 'function') {
2785
2834
  return appConfig.httpErrorHandler;
@@ -3173,7 +3222,7 @@ function App({
3173
3222
  service: userAuthenticationService
3174
3223
  }], [es/* I18nextProvider */.xC, {
3175
3224
  i18n: src/* default */.A
3176
- }], [ui_src/* ThemeWrapper */.L$], [ui_src/* ViewportGridProvider */.ql, {
3225
+ }], [ui_src/* ThemeWrapper */.L$], [ui_src/* ToolboxProvider */.nB], [ui_src/* ViewportGridProvider */.ql, {
3177
3226
  service: viewportGridService
3178
3227
  }], [ui_src/* ViewportDialogProvider */.cm, {
3179
3228
  service: uiViewportDialogService
@@ -6484,7 +6533,7 @@ const detectionOptions = {
6484
6533
  }
6485
6534
  });
6486
6535
  ;// CONCATENATED MODULE: ../../i18n/package.json
6487
- const package_namespaceObject = /*#__PURE__*/JSON.parse('{"rE":"3.8.0-beta.61"}');
6536
+ const package_namespaceObject = /*#__PURE__*/JSON.parse('{"rE":"3.8.0-beta.63"}');
6488
6537
  ;// CONCATENATED MODULE: ../../i18n/src/utils.js
6489
6538
  const languagesMap = {
6490
6539
  ar: 'Arabic',
@@ -9966,19 +10015,19 @@ var iconToolBrush = function iconToolBrush(props) {
9966
10015
  fill: "none",
9967
10016
  fillRule: "evenodd"
9968
10017
  }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("path", {
9969
- d: "M3.246 22.329a.432.432 0 0 1 .024-.79c2.056-.833 1.394-3.177 2.004-4.43a3.075 3.075 0 0 1 4.083-1.405c4.592 2.238-.874 9.117-6.11 6.625ZM21.597 3.302a1.194 1.194 0 0 0-1.635.045L9.692 13.589a5.196 5.196 0 0 1 3.129 2.646l8.92-11.298a1.194 1.194 0 0 0-.144-1.635Z",
10018
+ d: "M0 0h24v24H0z"
10019
+ }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("path", {
10020
+ d: "M3.246 21.829a.432.432 0 0 1 .024-.79c2.056-.833 1.394-3.177 2.004-4.43a3.075 3.075 0 0 1 4.083-1.405c4.592 2.238-.874 9.117-6.11 6.625ZM21.597 2.302a1.194 1.194 0 0 0-1.635.045L9.692 12.589a5.196 5.196 0 0 1 3.129 2.646l8.92-11.298a1.194 1.194 0 0 0-.144-1.635Z",
9970
10021
  stroke: "currentColor",
9971
- strokeWidth: "1.25",
10022
+ strokeWidth: "1.5",
9972
10023
  strokeLinecap: "round",
9973
10024
  strokeLinejoin: "round"
9974
- }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("path", {
9975
- d: "M0 0h25v25H0z"
9976
10025
  })));
9977
10026
  };
9978
10027
  iconToolBrush.defaultProps = {
9979
- width: "25",
9980
- height: "25",
9981
- viewBox: "0 0 25 25",
10028
+ width: "24",
10029
+ height: "24",
10030
+ viewBox: "0 0 24 24",
9982
10031
  xmlns: "http://www.w3.org/2000/svg"
9983
10032
  };
9984
10033
  var iconToolEraser = function iconToolEraser(props) {
@@ -9986,19 +10035,19 @@ var iconToolEraser = function iconToolEraser(props) {
9986
10035
  fill: "none",
9987
10036
  fillRule: "evenodd"
9988
10037
  }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("path", {
9989
- d: "M8.391 20.504a5.08 5.08 0 0 1-3.118-1.291l-1.982-1.984a1.832 1.832 0 0 1 0-2.583L14.404 3.533a1.832 1.832 0 0 1 2.583 0l4.721 4.721c.71.715.71 1.869 0 2.583l-8.373 8.374a5.08 5.08 0 0 1-3.118 1.293H8.391ZM10.217 7.719l7.305 7.305M2 22.328h21",
10038
+ d: "M0 0h24v24H0z"
10039
+ }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("path", {
10040
+ d: "M8.478 18.003a4.354 4.354 0 0 1-2.672-1.107l-1.7-1.7a1.57 1.57 0 0 1 0-2.214l9.526-9.525a1.57 1.57 0 0 1 2.214 0l4.047 4.047a1.57 1.57 0 0 1 0 2.214l-7.178 7.177a4.354 4.354 0 0 1-2.672 1.108H8.478ZM10.043 7.045l6.261 6.261M3 20.567h18",
9990
10041
  stroke: "currentColor",
9991
- strokeWidth: "1.25",
10042
+ strokeWidth: "1.5",
9992
10043
  strokeLinecap: "round",
9993
10044
  strokeLinejoin: "round"
9994
- }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("path", {
9995
- d: "M0 0h25v25H0z"
9996
10045
  })));
9997
10046
  };
9998
10047
  iconToolEraser.defaultProps = {
9999
- width: "25",
10000
- height: "25",
10001
- viewBox: "0 0 25 25",
10048
+ width: "24",
10049
+ height: "24",
10050
+ viewBox: "0 0 24 24",
10002
10051
  xmlns: "http://www.w3.org/2000/svg"
10003
10052
  };
10004
10053
  var iconToolScissor = function iconToolScissor(props) {
@@ -10038,7 +10087,13 @@ var iconToolShape = function iconToolShape(props) {
10038
10087
  fill: "none",
10039
10088
  fillRule: "evenodd"
10040
10089
  }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("path", {
10041
- d: "M0 0h25v25H0z"
10090
+ d: "M0 0h24v24H0z"
10091
+ }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("circle", {
10092
+ stroke: "currentColor",
10093
+ strokeWidth: "1.5",
10094
+ cx: "16",
10095
+ cy: "15",
10096
+ r: "6"
10042
10097
  }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("rect", {
10043
10098
  stroke: "currentColor",
10044
10099
  strokeWidth: "1.5",
@@ -10046,19 +10101,13 @@ var iconToolShape = function iconToolShape(props) {
10046
10101
  y: "3",
10047
10102
  width: "13",
10048
10103
  height: "13",
10049
- rx: "1"
10050
- }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("circle", {
10051
- stroke: "currentColor",
10052
- strokeWidth: "1.5",
10053
- cx: "16.5",
10054
- cy: "16.5",
10055
- r: "6.5"
10104
+ rx: "2"
10056
10105
  })));
10057
10106
  };
10058
10107
  iconToolShape.defaultProps = {
10059
- width: "25",
10060
- height: "25",
10061
- viewBox: "0 0 25 25",
10108
+ width: "24",
10109
+ height: "24",
10110
+ viewBox: "0 0 24 24",
10062
10111
  xmlns: "http://www.w3.org/2000/svg"
10063
10112
  };
10064
10113
  var iconToolThreshold = function iconToolThreshold(props) {
@@ -10066,35 +10115,35 @@ var iconToolThreshold = function iconToolThreshold(props) {
10066
10115
  fill: "none",
10067
10116
  fillRule: "evenodd"
10068
10117
  }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("path", {
10118
+ d: "M0 0h24v24H0z"
10119
+ }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("g", {
10120
+ transform: "translate(2.418 14.367)",
10069
10121
  stroke: "currentColor",
10070
- strokeWidth: "1.25",
10122
+ strokeWidth: "1.5"
10123
+ }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("path", {
10071
10124
  strokeLinecap: "round",
10072
- d: "M19.457 16.87H22.5M2.5 16.87h12.174"
10125
+ d: "M16.582 2.133h2.5M.082 2.133h12"
10073
10126
  }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("circle", {
10127
+ cx: "14.224",
10128
+ cy: "2.092",
10129
+ r: "2.092"
10130
+ })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("g", {
10131
+ transform: "matrix(-1 0 0 1 21.5 5.367)",
10074
10132
  stroke: "currentColor",
10075
- strokeWidth: "1.25",
10076
- cx: "16.848",
10077
- cy: "16.87",
10078
- r: "2.174"
10079
- }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("path", {
10080
- stroke: "currentColor",
10081
- strokeWidth: "1.25",
10133
+ strokeWidth: "1.5"
10134
+ }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("path", {
10082
10135
  strokeLinecap: "round",
10083
- d: "M11.63 8.174h10.435M2.5 8.174h4.783"
10136
+ d: "M16 2.133h3.082M.082 2.133H11"
10084
10137
  }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("circle", {
10085
- stroke: "currentColor",
10086
- strokeWidth: "1.25",
10087
- cx: "9.457",
10088
- cy: "8.174",
10089
- r: "2.174"
10090
- }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("path", {
10091
- d: "M0 0h25v25H0z"
10092
- })));
10138
+ cx: "13.224",
10139
+ cy: "2.092",
10140
+ r: "2.092"
10141
+ }))));
10093
10142
  };
10094
10143
  iconToolThreshold.defaultProps = {
10095
- width: "25",
10096
- height: "25",
10097
- viewBox: "0 0 25 25",
10144
+ width: "24",
10145
+ height: "24",
10146
+ viewBox: "0 0 24 24",
10098
10147
  xmlns: "http://www.w3.org/2000/svg"
10099
10148
  };
10100
10149
  /** Old OHIF */
@@ -10131,6 +10180,41 @@ oldStop.defaultProps = {
10131
10180
  'aria-labelledby': "title",
10132
10181
  fill: "currentColor"
10133
10182
  };
10183
+ /** New investigational use */
10184
+ var investigationalUse = function investigationalUse(props) {
10185
+ return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("svg", props, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("g", {
10186
+ fill: "none",
10187
+ fillRule: "evenodd"
10188
+ }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("rect", {
10189
+ fill: "#090C29",
10190
+ opacity: ".9",
10191
+ width: "68",
10192
+ height: "68",
10193
+ rx: "34"
10194
+ }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("g", {
10195
+ transform: "translate(15 16)",
10196
+ strokeLinecap: "round",
10197
+ strokeLinejoin: "round",
10198
+ strokeWidth: "2"
10199
+ }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("circle", {
10200
+ stroke: "#3A3F99",
10201
+ cx: "16.074",
10202
+ cy: "16.074",
10203
+ r: "16.074"
10204
+ }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("path", {
10205
+ stroke: "#3A3F99",
10206
+ d: "m37 37-9.705-9.705"
10207
+ }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__.createElement("path", {
10208
+ d: "M24.869 24.869s-3.23-1.413-5.488-2.242c-1.481-.545-1.27-3.02-.413-3.95a6.748 6.748 0 0 0 2.013-5.594 4.725 4.725 0 0 0-1.273-3.692 4.82 4.82 0 0 0-3.634-1.504A4.82 4.82 0 0 0 12.44 9.39a4.725 4.725 0 0 0-1.274 3.691 6.748 6.748 0 0 0 2.013 5.594c.858.93 1.069 3.406-.412 3.95-2.258.83-5.488 2.244-5.488 2.244",
10209
+ stroke: "#348CFD"
10210
+ }))));
10211
+ };
10212
+ investigationalUse.defaultProps = {
10213
+ width: "68",
10214
+ height: "68",
10215
+ viewBox: "0 0 68 68",
10216
+ xmlns: "http://www.w3.org/2000/svg"
10217
+ };
10134
10218
  const ICONS = {
10135
10219
  'arrow-down': arrowDown,
10136
10220
  'arrow-left': arrowLeft,
@@ -10216,7 +10300,7 @@ const ICONS = {
10216
10300
  'tool-window-level': toolWindow,
10217
10301
  'tool-annotate': toolAnnotate,
10218
10302
  'tool-bidirectional': toolBidirectional,
10219
- 'tool-elipse': toolElipse,
10303
+ 'tool-ellipse': toolElipse,
10220
10304
  'tool-circle': toolCircle,
10221
10305
  'tool-length': toolLength,
10222
10306
  'tool-stack-scroll': toolStackScroll,
@@ -10273,7 +10357,9 @@ const ICONS = {
10273
10357
  /** Old OHIF */
10274
10358
  'old-trash': oldTrash,
10275
10359
  'old-play': oldPlay,
10276
- 'old-stop': oldStop
10360
+ 'old-stop': oldStop,
10361
+ /** New investigational use */
10362
+ 'illustration-investigational-use': investigationalUse
10277
10363
  };
10278
10364
  function addIcon(iconName, iconSVG) {
10279
10365
  if (ICONS[iconName]) {
@@ -10466,7 +10552,7 @@ Typography.propTypes = {
10466
10552
 
10467
10553
  /***/ }),
10468
10554
 
10469
- /***/ 55395:
10555
+ /***/ 65967:
10470
10556
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
10471
10557
 
10472
10558
  "use strict";
@@ -10474,9 +10560,9 @@ Typography.propTypes = {
10474
10560
  // EXPORTS
10475
10561
  __webpack_require__.d(__webpack_exports__, {
10476
10562
  VT: () => (/* reexport */ components_AboutModal),
10477
- om: () => (/* reexport */ components_AdvancedToolbox),
10478
10563
  $n: () => (/* reexport */ components_Button),
10479
10564
  Ny: () => (/* reexport */ ButtonEnums_namespaceObject),
10565
+ e2: () => (/* reexport */ components_ButtonGroup),
10480
10566
  F0: () => (/* reexport */ components_CinePlayer),
10481
10567
  p: () => (/* reexport */ CineProvider),
10482
10568
  lG: () => (/* reexport */ components_Dialog),
@@ -10489,9 +10575,9 @@ __webpack_require__.d(__webpack_exports__, {
10489
10575
  uq: () => (/* reexport */ components_ImageScrollbar),
10490
10576
  xy: () => (/* reexport */ ImageViewerProvider),
10491
10577
  pd: () => (/* reexport */ components_Input),
10492
- Z5: () => (/* reexport */ components_InputDoubleRange),
10493
10578
  Cv: () => (/* reexport */ components_InputFilterText),
10494
10579
  Qr: () => (/* reexport */ components_InputRange),
10580
+ j: () => (/* reexport */ components_InvestigationalUseDialog),
10495
10581
  JU: () => (/* reexport */ components_Label),
10496
10582
  sG: () => (/* reexport */ components_LayoutSelector),
10497
10583
  _H: () => (/* reexport */ components_LegacyButton),
@@ -10517,6 +10603,8 @@ __webpack_require__.d(__webpack_exports__, {
10517
10603
  u3: () => (/* reexport */ components_StudySummary),
10518
10604
  L$: () => (/* reexport */ components_ThemeWrapper),
10519
10605
  IB: () => (/* reexport */ components_ToolbarButton),
10606
+ OO: () => (/* reexport */ Toolbox_Toolbox),
10607
+ nB: () => (/* reexport */ ToolboxProvider),
10520
10608
  m_: () => (/* reexport */ components_Tooltip),
10521
10609
  ax: () => (/* reexport */ TooltipClipboard_TooltipClipboard),
10522
10610
  o5: () => (/* reexport */ Typography/* default */.A),
@@ -10539,7 +10627,7 @@ __webpack_require__.d(__webpack_exports__, {
10539
10627
  ih: () => (/* reexport */ useViewportGrid)
10540
10628
  });
10541
10629
 
10542
- // UNUSED EXPORTS: BackgroundColor, ButtonGroup, CheckBox, ContextMenu, DateRange, Dropdown, ExpandableToolbarButton, HotkeyField, HotkeysPreferences, ICONS, IconButton, ImageViewerContext, InputDateRange, InputGroup, InputLabelWrapper, InputMultiSelect, InputNumber, InputText, LegacyCinePlayer, LegacySidePanel, LegacyViewportActionBar, ListMenu, MeasurementItem, ModalComponent, ModalConsumer, NavBar, PanelSection, StudyItem, StudyListTableRow, Svg, Table, TableBody, TableCell, TableHead, TableRow, Thumbnail, ThumbnailList, ThumbnailNoImage, ThumbnailTracked, Types, UserAuthenticationContext, Viewport, ViewportGridContext, addIcon, getIcon, useDialog, useSnackbar, withDialog, withModal, withSnackbar
10630
+ // UNUSED EXPORTS: AdvancedToolbox, BackgroundColor, CheckBox, ContextMenu, DateRange, Dropdown, ExpandableToolbarButton, HotkeyField, HotkeysPreferences, ICONS, IconButton, ImageViewerContext, InputDateRange, InputDoubleRange, InputGroup, InputLabelWrapper, InputMultiSelect, InputNumber, InputText, LegacyCinePlayer, LegacySidePanel, LegacySplitButton, LegacyViewportActionBar, ListMenu, MeasurementItem, ModalComponent, ModalConsumer, NavBar, PanelSection, StudyItem, StudyListTableRow, Svg, Table, TableBody, TableCell, TableHead, TableRow, Thumbnail, ThumbnailList, ThumbnailNoImage, ThumbnailTracked, ToolSettings, Types, UserAuthenticationContext, Viewport, ViewportGridContext, addIcon, getIcon, useDialog, useSnackbar, useToolbox, withDialog, withModal, withSnackbar
10543
10631
 
10544
10632
  // NAMESPACE OBJECT: ../../../node_modules/react-dnd-html5-backend/dist/esm/NativeTypes.js
10545
10633
  var NativeTypes_namespaceObject = {};
@@ -17500,17 +17588,10 @@ ModalProvider.propTypes = {
17500
17588
  const ModalConsumer = ModalContext.Consumer;
17501
17589
  ;// CONCATENATED MODULE: ../../ui/src/contextProviders/ImageViewerProvider.tsx
17502
17590
 
17503
-
17504
- // export const IMAGE_VIEWER_DEFAULT_VALUE = {
17505
- // StudyInstanceUIDs: [],
17506
- // setImageViewer: () => {},
17507
- // };
17508
-
17509
- const ImageViewerContext = /*#__PURE__*/(0,react.createContext)();
17591
+ const ImageViewerContext = /*#__PURE__*/(0,react.createContext)(null);
17592
+ const useImageViewer = () => (0,react.useContext)(ImageViewerContext);
17510
17593
  function ImageViewerProvider({
17511
17594
  StudyInstanceUIDs,
17512
- reducer,
17513
- initialState,
17514
17595
  children
17515
17596
  }) {
17516
17597
  const value = (0,react.useMemo)(() => {
@@ -17522,7 +17603,6 @@ function ImageViewerProvider({
17522
17603
  value: value
17523
17604
  }, children);
17524
17605
  }
17525
- const useImageViewer = () => (0,react.useContext)(ImageViewerContext);
17526
17606
  ;// CONCATENATED MODULE: ../../ui/src/contextProviders/CineProvider.tsx
17527
17607
 
17528
17608
 
@@ -17617,7 +17697,7 @@ function CineProvider({
17617
17697
  const api = {
17618
17698
  getState,
17619
17699
  setCine,
17620
- setIsCineEnabled,
17700
+ setIsCineEnabled: isCineEnabled => service.setIsCineEnabled(isCineEnabled),
17621
17701
  playClip: (element, playClipOptions) => service.playClip(element, playClipOptions),
17622
17702
  stopClip: element => service.stopClip(element)
17623
17703
  };
@@ -17915,8 +17995,8 @@ ViewportDialogProvider.propTypes = {
17915
17995
  // EXTERNAL MODULE: ../../../node_modules/lodash.merge/index.js
17916
17996
  var lodash_merge = __webpack_require__(40592);
17917
17997
  var lodash_merge_default = /*#__PURE__*/__webpack_require__.n(lodash_merge);
17918
- // EXTERNAL MODULE: ../../core/src/index.ts + 66 modules
17919
- var src = __webpack_require__(14283);
17998
+ // EXTERNAL MODULE: ../../core/src/index.ts + 67 modules
17999
+ var src = __webpack_require__(78198);
17920
18000
  ;// CONCATENATED MODULE: ../../ui/src/utils/viewportLabels.ts
17921
18001
  const viewportLabels = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
17922
18002
  /* harmony default export */ const utils_viewportLabels = (viewportLabels);
@@ -17940,6 +18020,7 @@ const ViewportGridProvider_DEFAULT_STATE = {
17940
18020
  default: {
17941
18021
  viewportId: 'default',
17942
18022
  displaySetInstanceUIDs: [],
18023
+ isReady: false,
17943
18024
  viewportOptions: {
17944
18025
  viewportId: 'default'
17945
18026
  },
@@ -18137,6 +18218,7 @@ function ViewportGridProvider({
18137
18218
  y: yPos
18138
18219
  });
18139
18220
  viewport.viewportLabel = getViewportLabel(viewports, viewport.viewportId);
18221
+ viewport.isReady = false;
18140
18222
  if (!viewport.viewportOptions.presentationIds) {
18141
18223
  viewport.viewportOptions.presentationIds = src/* ViewportGridService */.sI.getPresentationIds(viewport, viewports);
18142
18224
  }
@@ -18167,6 +18249,26 @@ function ViewportGridProvider({
18167
18249
  ...action.payload
18168
18250
  };
18169
18251
  }
18252
+ case 'VIEWPORT_IS_READY':
18253
+ {
18254
+ const {
18255
+ viewportId,
18256
+ isReady
18257
+ } = action.payload;
18258
+ const viewports = new Map(state.viewports);
18259
+ const viewport = viewports.get(viewportId);
18260
+ if (!viewport) {
18261
+ return;
18262
+ }
18263
+ viewports.set(viewportId, {
18264
+ ...viewport,
18265
+ isReady
18266
+ });
18267
+ return {
18268
+ ...state,
18269
+ viewports
18270
+ };
18271
+ }
18170
18272
  default:
18171
18273
  return action.payload;
18172
18274
  }
@@ -18190,6 +18292,22 @@ function ViewportGridProvider({
18190
18292
  type: 'SET_DISPLAYSETS_FOR_VIEWPORTS',
18191
18293
  payload: viewports
18192
18294
  }), [dispatch]);
18295
+ const setViewportIsReady = (0,react.useCallback)((viewportId, isReady) => {
18296
+ dispatch({
18297
+ type: 'VIEWPORT_IS_READY',
18298
+ payload: {
18299
+ viewportId,
18300
+ isReady
18301
+ }
18302
+ });
18303
+ }, [dispatch, viewportGridState]);
18304
+ const getGridViewportsReady = (0,react.useCallback)(() => {
18305
+ const {
18306
+ viewports
18307
+ } = viewportGridState;
18308
+ const readyViewports = Array.from(viewports.values()).filter(viewport => viewport.isReady);
18309
+ return readyViewports.length === viewports.size;
18310
+ }, [viewportGridState]);
18193
18311
  const setLayout = (0,react.useCallback)(({
18194
18312
  layoutType,
18195
18313
  numRows,
@@ -18243,10 +18361,12 @@ function ViewportGridProvider({
18243
18361
  reset,
18244
18362
  onModeExit: reset,
18245
18363
  set,
18246
- getNumViewportPanes
18364
+ getNumViewportPanes,
18365
+ setViewportIsReady,
18366
+ getGridViewportsReady
18247
18367
  });
18248
18368
  }
18249
- }, [getState, service, setActiveViewportId, setDisplaySetsForViewports, setLayout, reset, set, getNumViewportPanes]);
18369
+ }, [getState, service, setActiveViewportId, setDisplaySetsForViewports, setLayout, reset, set, getNumViewportPanes, setViewportIsReady, getGridViewportsReady]);
18250
18370
 
18251
18371
  // run many of the calls through the service itself since we want to publish events
18252
18372
  const api = {
@@ -18259,8 +18379,11 @@ function ViewportGridProvider({
18259
18379
  set: gridLayoutState => service.setState(gridLayoutState),
18260
18380
  // run it through the service itself since we want to publish events
18261
18381
  getNumViewportPanes,
18382
+ setViewportIsReady,
18383
+ getGridViewportsReady,
18262
18384
  getActiveViewportOptionByKey,
18263
- setViewportGridSizeChanged: props => service.setViewportGridSizeChanged(props)
18385
+ setViewportGridSizeChanged: props => service.setViewportGridSizeChanged(props),
18386
+ publishViewportsReady: () => service.publishViewportsReady()
18264
18387
  };
18265
18388
  return /*#__PURE__*/react.createElement(ViewportGridContext.Provider, {
18266
18389
  value: [viewportGridState, api]
@@ -18271,6 +18394,133 @@ ViewportGridProvider.propTypes = {
18271
18394
  service: prop_types_default().instanceOf(src/* ViewportGridService */.sI).isRequired
18272
18395
  };
18273
18396
  const useViewportGrid = () => (0,react.useContext)(ViewportGridContext);
18397
+ ;// CONCATENATED MODULE: ../../ui/src/contextProviders/Toolbox/ToolboxContext.tsx
18398
+
18399
+ const ToolboxContext_initialState = {};
18400
+ const toolboxReducer = (state, action) => {
18401
+ const {
18402
+ toolbarSectionId
18403
+ } = action.payload;
18404
+ if (!state[toolbarSectionId]) {
18405
+ state[toolbarSectionId] = {
18406
+ activeTool: null,
18407
+ toolOptions: {}
18408
+ };
18409
+ }
18410
+ switch (action.type) {
18411
+ case 'SET_ACTIVE_TOOL':
18412
+ return {
18413
+ ...state,
18414
+ [toolbarSectionId]: {
18415
+ ...state[toolbarSectionId],
18416
+ activeTool: action.payload.activeTool
18417
+ }
18418
+ };
18419
+ case 'UPDATE_TOOL_OPTION':
18420
+ const {
18421
+ toolName,
18422
+ optionName,
18423
+ value
18424
+ } = action.payload;
18425
+ return {
18426
+ ...state,
18427
+ [toolbarSectionId]: {
18428
+ ...state[toolbarSectionId],
18429
+ toolOptions: {
18430
+ ...state[toolbarSectionId].toolOptions,
18431
+ [toolName]: state[toolbarSectionId].toolOptions[toolName].map(option => option.id === optionName ? {
18432
+ ...option,
18433
+ value
18434
+ } : option)
18435
+ }
18436
+ }
18437
+ };
18438
+ case 'INITIALIZE_TOOL_OPTIONS':
18439
+ // Initialize tool options for each toolbarSectionId
18440
+ return {
18441
+ ...state,
18442
+ [action.toolbarSectionId]: {
18443
+ ...state[action.toolbarSectionId],
18444
+ toolOptions: action.payload
18445
+ }
18446
+ };
18447
+ default:
18448
+ return state;
18449
+ }
18450
+ };
18451
+ const ToolboxContext = /*#__PURE__*/(0,react.createContext)();
18452
+ const ToolboxProvider = ({
18453
+ children
18454
+ }) => {
18455
+ const [state, dispatch] = (0,react.useReducer)(toolboxReducer, ToolboxContext_initialState);
18456
+ const handleToolSelect = (toolbarSectionId, toolName) => {
18457
+ dispatch({
18458
+ type: 'SET_ACTIVE_TOOL',
18459
+ payload: {
18460
+ toolbarSectionId,
18461
+ activeTool: toolName
18462
+ }
18463
+ });
18464
+ };
18465
+ const handleToolOptionChange = (toolbarSectionId, toolName, optionName, newValue) => {
18466
+ dispatch({
18467
+ type: 'UPDATE_TOOL_OPTION',
18468
+ payload: {
18469
+ toolbarSectionId,
18470
+ toolName,
18471
+ optionName,
18472
+ value: newValue
18473
+ }
18474
+ });
18475
+ };
18476
+ const initializeToolOptions = (toolbarSectionId, toolOptions) => {
18477
+ dispatch({
18478
+ type: 'INITIALIZE_TOOL_OPTIONS',
18479
+ toolbarSectionId,
18480
+ payload: toolOptions
18481
+ });
18482
+ };
18483
+ const api = {
18484
+ handleToolSelect,
18485
+ handleToolOptionChange,
18486
+ initializeToolOptions
18487
+ };
18488
+ const value = {
18489
+ state,
18490
+ api
18491
+ };
18492
+ return /*#__PURE__*/react.createElement(ToolboxContext.Provider, {
18493
+ value: value
18494
+ }, children);
18495
+ };
18496
+
18497
+ /**
18498
+ * Custom hook for accessing toolbox state and actions for a specific toolbar section.
18499
+ * You can use this hook to access the state and actions for a specific toolbar section (
18500
+ * defined by the toolbarSectionId) in your custom toolbar components. This hook
18501
+ * helps to manage the state and actions for the tools and their options in the toolbar.
18502
+ */
18503
+ const useToolbox = toolbarSectionId => {
18504
+ const context = (0,react.useContext)(ToolboxContext);
18505
+ if (context === undefined) {
18506
+ throw new Error('useToolbox must be used within a ToolboxProvider');
18507
+ }
18508
+ const {
18509
+ state,
18510
+ api
18511
+ } = context;
18512
+ return {
18513
+ state: state[toolbarSectionId] || {
18514
+ activeTool: null,
18515
+ toolOptions: {}
18516
+ },
18517
+ api: {
18518
+ handleToolSelect: toolName => api.handleToolSelect(toolbarSectionId, toolName),
18519
+ handleToolOptionChange: (toolName, optionName, value) => api.handleToolOptionChange(toolbarSectionId, toolName, optionName, value),
18520
+ initializeToolOptions: toolOptions => api.initializeToolOptions(toolbarSectionId, toolOptions)
18521
+ }
18522
+ };
18523
+ };
18274
18524
  ;// CONCATENATED MODULE: ../../ui/src/contextProviders/UserAuthenticationProvider.tsx
18275
18525
 
18276
18526
 
@@ -18392,6 +18642,7 @@ const useUserAuthentication = () => (0,react.useContext)(UserAuthenticationConte
18392
18642
 
18393
18643
 
18394
18644
 
18645
+
18395
18646
  ;// CONCATENATED MODULE: ../../../node_modules/browser-detect/dist/browser-detect.es5.js
18396
18647
  /*! *****************************************************************************
18397
18648
  Copyright (c) Microsoft Corporation. All rights reserved.
@@ -19214,6 +19465,7 @@ const arrowPositionStyle = {
19214
19465
  };
19215
19466
  const Tooltip = ({
19216
19467
  content,
19468
+ secondaryContent = null,
19217
19469
  isSticky,
19218
19470
  position,
19219
19471
  className,
@@ -19250,9 +19502,11 @@ const Tooltip = ({
19250
19502
  })
19251
19503
  }, /*#__PURE__*/react.createElement("div", {
19252
19504
  className: classnames_default()('tooltip-box bg-primary-dark border-secondary-light w-max-content relative inset-x-auto top-full rounded border text-base text-white', {
19253
- 'py-1 px-4': !tight
19505
+ 'py-[6px] px-[8px]': !tight
19254
19506
  })
19255
- }, typeof content === 'string' ? t(content) : content, /*#__PURE__*/react.createElement("svg", {
19507
+ }, /*#__PURE__*/react.createElement("div", null, typeof content === 'string' ? t(content) : content), /*#__PURE__*/react.createElement("div", {
19508
+ className: "text-aqua-pale"
19509
+ }, typeof secondaryContent === 'string' ? t(secondaryContent) : secondaryContent), /*#__PURE__*/react.createElement("svg", {
19256
19510
  className: "text-primary-dark stroke-secondary-light absolute h-4",
19257
19511
  style: arrowPositionStyle[position],
19258
19512
  xmlns: "http://www.w3.org/2000/svg",
@@ -19323,9 +19577,11 @@ const Button = ({
19323
19577
  name,
19324
19578
  className,
19325
19579
  onClick,
19580
+ dataCY,
19326
19581
  startIconTooltip = null,
19327
19582
  endIconTooltip = null
19328
19583
  }) => {
19584
+ dataCY = dataCY || `${name}-btn`;
19329
19585
  const startIcon = startIconProp && /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.cloneElement(startIconProp, {
19330
19586
  className: classnames_default()('w-4 h-4 fill-current', startIconProp?.props?.className)
19331
19587
  }));
@@ -19347,7 +19603,7 @@ const Button = ({
19347
19603
  disabled: disabled,
19348
19604
  ref: buttonElement,
19349
19605
  onClick: handleOnClick,
19350
- "data-cy": `${name}-btn`
19606
+ "data-cy": dataCY
19351
19607
  }, startIconTooltip ? /*#__PURE__*/react.createElement(Tooltip_Tooltip, {
19352
19608
  content: startIconTooltip
19353
19609
  }, startIcon) : startIcon, children, endIconTooltip ? /*#__PURE__*/react.createElement(Tooltip_Tooltip, {
@@ -19382,7 +19638,9 @@ Button.propTypes = {
19382
19638
  /** Tooltip for the start icon */
19383
19639
  startIconTooltip: (prop_types_default()).node,
19384
19640
  /** Tooltip for the end icon */
19385
- endIconTooltip: (prop_types_default()).node
19641
+ endIconTooltip: (prop_types_default()).node,
19642
+ /** Data attribute for testing */
19643
+ dataCY: (prop_types_default()).string
19386
19644
  };
19387
19645
  /* harmony default export */ const Button_Button = (Button);
19388
19646
  ;// CONCATENATED MODULE: ../../ui/src/components/Button/index.js
@@ -19391,23 +19649,25 @@ Button.propTypes = {
19391
19649
 
19392
19650
  /* harmony default export */ const components_Button = (Button_Button);
19393
19651
  ;// CONCATENATED MODULE: ../../ui/src/components/ButtonGroup/ButtonGroup.tsx
19394
- function ButtonGroup_extends() { ButtonGroup_extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return ButtonGroup_extends.apply(this, arguments); }
19395
19652
 
19396
19653
 
19397
19654
 
19398
19655
 
19399
19656
  const ButtonGroup = ({
19400
- buttons,
19401
- onActiveIndexChange,
19657
+ children,
19402
19658
  className,
19403
19659
  orientation = ButtonEnums_orientation.horizontal,
19404
- defaultActiveIndex = 0
19660
+ activeIndex: defaultActiveIndex = 0,
19661
+ onActiveIndexChange,
19662
+ disabled = false
19405
19663
  }) => {
19406
19664
  const [activeIndex, setActiveIndex] = (0,react.useState)(defaultActiveIndex);
19407
- const handleButtonClick = (e, index) => {
19665
+ (0,react.useEffect)(() => {
19666
+ setActiveIndex(defaultActiveIndex);
19667
+ }, [defaultActiveIndex]);
19668
+ const handleButtonClick = index => {
19408
19669
  setActiveIndex(index);
19409
19670
  onActiveIndexChange && onActiveIndexChange(index);
19410
- buttons[index].onClick && buttons[index].onClick(e);
19411
19671
  };
19412
19672
  const orientationClasses = {
19413
19673
  horizontal: 'flex-row',
@@ -19415,24 +19675,28 @@ const ButtonGroup = ({
19415
19675
  };
19416
19676
  const wrapperClasses = classnames_default()('inline-flex', orientationClasses[orientation], className);
19417
19677
  return /*#__PURE__*/react.createElement("div", {
19418
- className: classnames_default()(wrapperClasses, 'border-secondary-light rounded-[5px] border bg-black text-[13px] ')
19419
- }, buttons.map((buttonProps, index) => {
19420
- const isActive = index === activeIndex;
19421
- return /*#__PURE__*/react.createElement("button", ButtonGroup_extends({}, buttonProps, {
19422
- key: index,
19423
- className: classnames_default()('rounded-[4px] px-2 py-1', isActive ? 'bg-customblue-40 text-white' : 'text-primary-active bg-black'),
19424
- onClick: e => handleButtonClick(e, index)
19425
- }));
19678
+ className: classnames_default()(wrapperClasses, 'border-secondary-light rounded-[5px] border bg-black text-[13px]')
19679
+ }, react.Children.map(children, (child, index) => {
19680
+ if ( /*#__PURE__*/react.isValidElement(child)) {
19681
+ return /*#__PURE__*/(0,react.cloneElement)(child, {
19682
+ key: index,
19683
+ className: classnames_default()('rounded-[4px] px-2 py-1', index === activeIndex ? 'bg-customblue-40 text-white' : 'text-primary-active bg-black', child.props.className, disabled ? 'ohif-disabled' : ''),
19684
+ onClick: e => {
19685
+ child.props.onClick && child.props.onClick(e);
19686
+ handleButtonClick(index);
19687
+ }
19688
+ });
19689
+ }
19690
+ return child;
19426
19691
  }));
19427
19692
  };
19428
19693
  ButtonGroup.propTypes = {
19429
- buttons: prop_types_default().arrayOf((prop_types_default()).object).isRequired,
19694
+ children: (prop_types_default()).node.isRequired,
19430
19695
  orientation: prop_types_default().oneOf(Object.values(ButtonEnums_orientation)),
19431
- type: prop_types_default().oneOf(Object.values(type)),
19432
- size: prop_types_default().oneOf(Object.values(size)),
19433
- defaultActiveIndex: (prop_types_default()).number,
19696
+ activeIndex: (prop_types_default()).number,
19434
19697
  onActiveIndexChange: (prop_types_default()).func,
19435
- className: (prop_types_default()).string
19698
+ className: (prop_types_default()).string,
19699
+ disabled: (prop_types_default()).bool
19436
19700
  };
19437
19701
  /* harmony default export */ const ButtonGroup_ButtonGroup = (ButtonGroup);
19438
19702
  ;// CONCATENATED MODULE: ../../ui/src/components/ButtonGroup/index.js
@@ -20452,7 +20716,7 @@ const roundedClasses = {
20452
20716
  full: 'rounded-full'
20453
20717
  };
20454
20718
  const IconButton_disabledClasses = {
20455
- true: 'cursor-not-allowed',
20719
+ true: 'ohif-disabled',
20456
20720
  false: ''
20457
20721
  };
20458
20722
  const variantClasses = {
@@ -20471,36 +20735,13 @@ const variantClasses = {
20471
20735
  black: 'border border-primary-main text-white hover:bg-primary-main focus:bg-primary-main hover:border-black focus:border-black'
20472
20736
  },
20473
20737
  contained: {
20474
- default: 'text-black hover:opacity-80 active:opacity-100 focus:opacity-80',
20738
+ default: 'text-common-bright hover:opacity-80 active:opacity-100 focus:opacity-80',
20475
20739
  primary: 'text-white hover:opacity-80 active:opacity-100 focus:opacity-80',
20476
20740
  secondary: 'text-white hover:opacity-80 active:opacity-100 focus:opacity-80',
20477
20741
  white: 'text-black hover:opacity-80 active:opacity-100 focus:opacity-80',
20478
20742
  black: 'text-white hover:opacity-80 active:opacity-100 focus:opacity-80'
20479
20743
  }
20480
20744
  };
20481
- const backgroundClasses = {
20482
- text: {
20483
- default: '',
20484
- primary: '',
20485
- secondary: '',
20486
- white: '',
20487
- black: ''
20488
- },
20489
- outlined: {
20490
- default: 'bg-transparent',
20491
- primary: 'bg-transparent',
20492
- secondary: 'bg-transparent',
20493
- white: 'bg-transparent',
20494
- black: 'bg-black'
20495
- },
20496
- contained: {
20497
- default: 'bg-primary-light',
20498
- primary: 'bg-primary-main',
20499
- secondary: 'bg-secondary-light',
20500
- white: 'bg-white',
20501
- black: 'bg-black'
20502
- }
20503
- };
20504
20745
  const IconButton_sizeClasses = {
20505
20746
  small: 'py-2 px-2 text-base',
20506
20747
  medium: 'py-3 px-3 text-lg',
@@ -20512,7 +20753,7 @@ const iconSizeClasses = {
20512
20753
  small: 'w-4 h-4',
20513
20754
  medium: 'w-5 h-5',
20514
20755
  large: 'w-6 h-6',
20515
- toolbar: 'w-5 h-5'
20756
+ toolbar: 'w-[24px] h-[24px]'
20516
20757
  };
20517
20758
  const fullWidthClasses = {
20518
20759
  true: 'flex w-full',
@@ -20529,9 +20770,7 @@ const IconButton = ({
20529
20770
  fullWidth,
20530
20771
  onClick,
20531
20772
  className,
20532
- name,
20533
20773
  id,
20534
- bgColor,
20535
20774
  ...rest
20536
20775
  }) => {
20537
20776
  const buttonElement = (0,react.useRef)(null);
@@ -20539,11 +20778,11 @@ const IconButton = ({
20539
20778
  buttonElement.current.blur();
20540
20779
  onClick(e);
20541
20780
  };
20542
- const bgColorToUse = bgColor ? bgColor : backgroundClasses[variant][color];
20781
+ const padding = size === 'toolbar' ? '8px' : size === 'toolbox' ? '4px' : null;
20543
20782
  return /*#__PURE__*/react.createElement("button", {
20544
- className: classnames_default()(baseClasses, variantClasses[variant][color], roundedClasses[rounded], IconButton_sizeClasses[size], fullWidthClasses[fullWidth], IconButton_disabledClasses[disabled], bgColorToUse, className),
20783
+ className: classnames_default()(baseClasses, variantClasses[variant][color], roundedClasses[rounded], IconButton_sizeClasses[size], fullWidthClasses[fullWidth], IconButton_disabledClasses[disabled], className),
20545
20784
  style: {
20546
- padding: size === 'toolbar' ? '10px' : null
20785
+ padding
20547
20786
  },
20548
20787
  ref: buttonElement,
20549
20788
  onClick: handleOnClick,
@@ -20566,7 +20805,7 @@ IconButton.defaultProps = {
20566
20805
  };
20567
20806
  IconButton.propTypes = {
20568
20807
  children: (prop_types_default()).node.isRequired,
20569
- size: prop_types_default().oneOf(['small', 'medium', 'large', 'initial', 'toolbar']),
20808
+ size: prop_types_default().oneOf(['small', 'medium', 'large', 'initial', 'toolbar', 'toolbox']),
20570
20809
  rounded: prop_types_default().oneOf(['none', 'small', 'medium', 'large', 'full']),
20571
20810
  variant: prop_types_default().oneOf(['text', 'outlined', 'contained']),
20572
20811
  color: prop_types_default().oneOf(['default', 'primary', 'secondary', 'white', 'black', 'inherit']),
@@ -23222,7 +23461,7 @@ var emotion_use_insertion_effect_with_fallbacks_browser_esm_useInsertionEffectWi
23222
23461
 
23223
23462
 
23224
23463
 
23225
- ;// CONCATENATED MODULE: ../../../node_modules/@emotion/react/dist/emotion-element-c39617d8.browser.esm.js
23464
+ ;// CONCATENATED MODULE: ../../../node_modules/@emotion/react/dist/emotion-element-43c6fea0.browser.esm.js
23226
23465
 
23227
23466
 
23228
23467
 
@@ -23233,8 +23472,8 @@ var emotion_use_insertion_effect_with_fallbacks_browser_esm_useInsertionEffectWi
23233
23472
 
23234
23473
 
23235
23474
 
23236
- var emotion_element_c39617d8_browser_esm_isBrowser = "object" !== 'undefined';
23237
- var emotion_element_c39617d8_browser_esm_hasOwnProperty = {}.hasOwnProperty;
23475
+ var emotion_element_43c6fea0_browser_esm_isBrowser = "object" !== 'undefined';
23476
+ var hasOwn = {}.hasOwnProperty;
23238
23477
 
23239
23478
  var EmotionCacheContext = /* #__PURE__ */react.createContext( // we're doing this to avoid preconstruct's dead code elimination in this one case
23240
23479
  // because this module is primarily intended for the browser and node
@@ -23248,12 +23487,12 @@ typeof HTMLElement !== 'undefined' ? /* #__PURE__ */emotion_cache_browser_esm_cr
23248
23487
 
23249
23488
  if (false) {}
23250
23489
 
23251
- var emotion_element_c39617d8_browser_esm_CacheProvider = EmotionCacheContext.Provider;
23490
+ var emotion_element_43c6fea0_browser_esm_CacheProvider = EmotionCacheContext.Provider;
23252
23491
  var __unsafe_useEmotionCache = function useEmotionCache() {
23253
23492
  return useContext(EmotionCacheContext);
23254
23493
  };
23255
23494
 
23256
- var emotion_element_c39617d8_browser_esm_withEmotionCache = function withEmotionCache(func) {
23495
+ var emotion_element_43c6fea0_browser_esm_withEmotionCache = function withEmotionCache(func) {
23257
23496
  // $FlowFixMe
23258
23497
  return /*#__PURE__*/(0,react.forwardRef)(function (props, ref) {
23259
23498
  // the cache will never be null in the browser
@@ -23262,8 +23501,8 @@ var emotion_element_c39617d8_browser_esm_withEmotionCache = function withEmotion
23262
23501
  });
23263
23502
  };
23264
23503
 
23265
- if (!emotion_element_c39617d8_browser_esm_isBrowser) {
23266
- emotion_element_c39617d8_browser_esm_withEmotionCache = function withEmotionCache(func) {
23504
+ if (!emotion_element_43c6fea0_browser_esm_isBrowser) {
23505
+ emotion_element_43c6fea0_browser_esm_withEmotionCache = function withEmotionCache(func) {
23267
23506
  return function (props) {
23268
23507
  var cache = (0,react.useContext)(EmotionCacheContext);
23269
23508
 
@@ -23286,12 +23525,12 @@ if (!emotion_element_c39617d8_browser_esm_isBrowser) {
23286
23525
  };
23287
23526
  }
23288
23527
 
23289
- var emotion_element_c39617d8_browser_esm_ThemeContext = /* #__PURE__ */react.createContext({});
23528
+ var emotion_element_43c6fea0_browser_esm_ThemeContext = /* #__PURE__ */react.createContext({});
23290
23529
 
23291
23530
  if (false) {}
23292
23531
 
23293
23532
  var useTheme = function useTheme() {
23294
- return React.useContext(emotion_element_c39617d8_browser_esm_ThemeContext);
23533
+ return React.useContext(emotion_element_43c6fea0_browser_esm_ThemeContext);
23295
23534
  };
23296
23535
 
23297
23536
  var getTheme = function getTheme(outerTheme, theme) {
@@ -23314,13 +23553,13 @@ var createCacheWithTheme = /* #__PURE__ */(/* unused pure expression or super */
23314
23553
  });
23315
23554
  })));
23316
23555
  var ThemeProvider = function ThemeProvider(props) {
23317
- var theme = React.useContext(emotion_element_c39617d8_browser_esm_ThemeContext);
23556
+ var theme = React.useContext(emotion_element_43c6fea0_browser_esm_ThemeContext);
23318
23557
 
23319
23558
  if (props.theme !== theme) {
23320
23559
  theme = createCacheWithTheme(theme)(props.theme);
23321
23560
  }
23322
23561
 
23323
- return /*#__PURE__*/React.createElement(emotion_element_c39617d8_browser_esm_ThemeContext.Provider, {
23562
+ return /*#__PURE__*/React.createElement(emotion_element_43c6fea0_browser_esm_ThemeContext.Provider, {
23324
23563
  value: theme
23325
23564
  }, props.children);
23326
23565
  };
@@ -23328,7 +23567,7 @@ function withTheme(Component) {
23328
23567
  var componentName = Component.displayName || Component.name || 'Component';
23329
23568
 
23330
23569
  var render = function render(props, ref) {
23331
- var theme = React.useContext(emotion_element_c39617d8_browser_esm_ThemeContext);
23570
+ var theme = React.useContext(emotion_element_43c6fea0_browser_esm_ThemeContext);
23332
23571
  return /*#__PURE__*/React.createElement(Component, _extends({
23333
23572
  theme: theme,
23334
23573
  ref: ref
@@ -23392,7 +23631,7 @@ var createEmotionProps = function createEmotionProps(type, props) {
23392
23631
  var newProps = {};
23393
23632
 
23394
23633
  for (var key in props) {
23395
- if (emotion_element_c39617d8_browser_esm_hasOwnProperty.call(props, key)) {
23634
+ if (hasOwn.call(props, key)) {
23396
23635
  newProps[key] = props[key];
23397
23636
  }
23398
23637
  }
@@ -23417,7 +23656,7 @@ var Insertion = function Insertion(_ref) {
23417
23656
  return null;
23418
23657
  };
23419
23658
 
23420
- var Emotion = /* #__PURE__ */emotion_element_c39617d8_browser_esm_withEmotionCache(function (props, cache, ref) {
23659
+ var Emotion = /* #__PURE__ */emotion_element_43c6fea0_browser_esm_withEmotionCache(function (props, cache, ref) {
23421
23660
  var cssProp = props.css; // so that using `css` from `emotion` and passing the result to the css prop works
23422
23661
  // not passing the registered cache to serializeStyles because it would
23423
23662
  // make certain babel optimisations not possible
@@ -23436,7 +23675,7 @@ var Emotion = /* #__PURE__ */emotion_element_c39617d8_browser_esm_withEmotionCac
23436
23675
  className = props.className + " ";
23437
23676
  }
23438
23677
 
23439
- var serialized = emotion_serialize_browser_esm_serializeStyles(registeredStyles, undefined, react.useContext(emotion_element_c39617d8_browser_esm_ThemeContext));
23678
+ var serialized = emotion_serialize_browser_esm_serializeStyles(registeredStyles, undefined, react.useContext(emotion_element_43c6fea0_browser_esm_ThemeContext));
23440
23679
 
23441
23680
  if (false) { var labelFromStack; }
23442
23681
 
@@ -23444,7 +23683,7 @@ var Emotion = /* #__PURE__ */emotion_element_c39617d8_browser_esm_withEmotionCac
23444
23683
  var newProps = {};
23445
23684
 
23446
23685
  for (var key in props) {
23447
- if (emotion_element_c39617d8_browser_esm_hasOwnProperty.call(props, key) && key !== 'css' && key !== typePropName && ( true || 0)) {
23686
+ if (hasOwn.call(props, key) && key !== 'css' && key !== typePropName && ( true || 0)) {
23448
23687
  newProps[key] = props[key];
23449
23688
  }
23450
23689
  }
@@ -23479,7 +23718,7 @@ var Emotion$1 = Emotion;
23479
23718
 
23480
23719
  var pkg = {
23481
23720
  name: "@emotion/react",
23482
- version: "11.11.3",
23721
+ version: "11.11.4",
23483
23722
  main: "dist/emotion-react.cjs.js",
23484
23723
  module: "dist/emotion-react.esm.js",
23485
23724
  browser: {
@@ -23612,7 +23851,7 @@ var pkg = {
23612
23851
  var jsx = function jsx(type, props) {
23613
23852
  var args = arguments;
23614
23853
 
23615
- if (props == null || !emotion_element_c39617d8_browser_esm_hasOwnProperty.call(props, 'css')) {
23854
+ if (props == null || !hasOwn.call(props, 'css')) {
23616
23855
  // $FlowFixMe
23617
23856
  return react.createElement.apply(undefined, args);
23618
23857
  }
@@ -31211,12 +31450,7 @@ const NavBar = ({
31211
31450
  isSticky
31212
31451
  }) => {
31213
31452
  return /*#__PURE__*/react.createElement("div", {
31214
- className: classnames_default()('bg-secondary-dark z-20 flex flex-row items-center border-b-4 border-black px-1', isSticky && stickyClasses, !isSticky && notStickyClasses, className),
31215
- style: {
31216
- paddingTop: '4px',
31217
- paddingBottom: '4px',
31218
- minHeight: '52px'
31219
- }
31453
+ className: classnames_default()('bg-secondary-dark z-20 border-black px-1', isSticky && stickyClasses, !isSticky && notStickyClasses, className)
31220
31454
  }, children);
31221
31455
  };
31222
31456
  NavBar.propTypes = {
@@ -32116,7 +32350,7 @@ const SegmentItem = ({
32116
32350
  "data-cy": 'segment-item'
32117
32351
  }, /*#__PURE__*/react.createElement("div", {
32118
32352
  className: classnames_default()('bg-primary-dark group/number grid w-[32px] place-items-center', {
32119
- 'bg-primary-light border-primary-light rounded-l-[4px] border text-black': isActive,
32353
+ '!bg-primary-light border-primary-light rounded-l-[4px] border text-black': isActive,
32120
32354
  'border-primary-dark border': !isActive
32121
32355
  }),
32122
32356
  onMouseEnter: () => setIsNumberBoxHovering(true),
@@ -32526,8 +32760,8 @@ const getGridStyle = (side, numTabs = 0, gridWidth, expandedWidth) => {
32526
32760
  width: `${gridWidth}px`
32527
32761
  };
32528
32762
  };
32529
- const getTabClassNames = (numColumns, numTabs, tabIndex, isActiveTab) => classnames_default()('h-[28px] mb-[2px] cursor-pointer text-white bg-black', {
32530
- 'hover:text-primary-active': !isActiveTab,
32763
+ const getTabClassNames = (numColumns, numTabs, tabIndex, isActiveTab, isTabDisabled) => classnames_default()('h-[28px] mb-[2px] cursor-pointer text-white bg-black', {
32764
+ 'hover:text-primary-active': !isActiveTab && !isTabDisabled,
32531
32765
  'rounded-l': tabIndex % numColumns === 0,
32532
32766
  'rounded-r': (tabIndex + 1) % numColumns === 0 || tabIndex === numTabs - 1
32533
32767
  });
@@ -32563,6 +32797,11 @@ const createStyleMap = (expandedWidth, borderSize, collapsedWidth) => {
32563
32797
  }
32564
32798
  };
32565
32799
  };
32800
+ const getToolTipContent = (label, disabled) => {
32801
+ return /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement("div", null, label), disabled && /*#__PURE__*/react.createElement("div", {
32802
+ className: "text-white"
32803
+ }, 'Not available based on current context'));
32804
+ };
32566
32805
  const createBaseStyle = expandedWidth => {
32567
32806
  return {
32568
32807
  maxWidth: `${expandedWidth}px`,
@@ -32627,18 +32866,21 @@ const SidePanel = ({
32627
32866
  }, _childComponents.map((childComponent, index) => /*#__PURE__*/react.createElement(components_Tooltip, {
32628
32867
  position: side === 'left' ? 'right' : 'left',
32629
32868
  key: index,
32630
- content: `${childComponent.label}`,
32869
+ content: getToolTipContent(childComponent.label, childComponent.disabled),
32631
32870
  className: classnames_default()('flex items-center', side === 'left' ? 'justify-end ' : 'justify-start ')
32632
32871
  }, /*#__PURE__*/react.createElement("div", {
32633
32872
  id: `${childComponent.name}-btn`,
32634
32873
  "data-cy": `${childComponent.name}-btn`,
32635
32874
  className: "text-primary-active hover:cursor-pointer",
32636
32875
  onClick: () => {
32637
- updateActiveTabIndex(index);
32876
+ return childComponent.disabled ? null : updateActiveTabIndex(index);
32638
32877
  }
32639
32878
  }, /*#__PURE__*/react.createElement(Icon/* default */.A, {
32640
32879
  name: childComponent.iconName,
32641
- className: "text-primary-active",
32880
+ className: classnames_default()({
32881
+ 'text-primary-active': true,
32882
+ 'ohif-disabled': childComponent.disabled
32883
+ }),
32642
32884
  style: {
32643
32885
  width: '22px',
32644
32886
  height: '22px'
@@ -32668,6 +32910,9 @@ const SidePanel = ({
32668
32910
  className: classnames_default()('bg-primary-dark text-primary-active flex flex-wrap'),
32669
32911
  style: getGridStyle(side, tabs.length, gridWidth, expandedWidth)
32670
32912
  }, tabs.map((tab, tabIndex) => {
32913
+ const {
32914
+ disabled
32915
+ } = tab;
32671
32916
  return /*#__PURE__*/react.createElement(react.Fragment, {
32672
32917
  key: tabIndex
32673
32918
  }, tabIndex % numCols !== 0 && /*#__PURE__*/react.createElement("div", {
@@ -32677,16 +32922,19 @@ const SidePanel = ({
32677
32922
  })), /*#__PURE__*/react.createElement(components_Tooltip, {
32678
32923
  position: 'bottom',
32679
32924
  key: tabIndex,
32680
- content: `${tab.label}`
32925
+ content: getToolTipContent(tab.label, disabled)
32681
32926
  }, /*#__PURE__*/react.createElement("div", {
32682
- className: getTabClassNames(numCols, tabs.length, tabIndex, tabIndex === activeTabIndex),
32927
+ className: getTabClassNames(numCols, tabs.length, tabIndex, tabIndex === activeTabIndex, disabled),
32683
32928
  style: getTabStyle(tabs.length),
32684
- onClick: () => updateActiveTabIndex(tabIndex),
32929
+ onClick: () => {
32930
+ return disabled ? null : updateActiveTabIndex(tabIndex);
32931
+ },
32685
32932
  "data-cy": `${tab.name}-btn`
32686
32933
  }, /*#__PURE__*/react.createElement("div", {
32687
32934
  className: getTabIconClassNames(tabs.length, tabIndex === activeTabIndex)
32688
32935
  }, /*#__PURE__*/react.createElement(Icon/* default */.A, {
32689
32936
  name: tab.iconName,
32937
+ className: `${tab.disabled && 'ohif-disabled'}`,
32690
32938
  style: {
32691
32939
  width: '22px',
32692
32940
  height: '22px'
@@ -32746,6 +32994,8 @@ var react_outside_click_handler = __webpack_require__(17076);
32746
32994
 
32747
32995
 
32748
32996
 
32997
+ const flex = 'flex flex-row justify-between items-center';
32998
+ const theme = 'bg-indigo-dark text-white';
32749
32999
  const ListMenu = ({
32750
33000
  items = [],
32751
33001
  renderer,
@@ -32757,24 +33007,23 @@ const ListMenu = ({
32757
33007
  index,
32758
33008
  isSelected
32759
33009
  }) => {
32760
- const flex = 'flex flex-row justify-between items-center';
32761
- const theme = 'bg-indigo-dark';
32762
33010
  const onClickHandler = () => {
32763
33011
  setSelectedIndex(index);
32764
33012
  onClick({
32765
33013
  item,
32766
33014
  selectedIndex: index
32767
33015
  });
32768
- if (item.onClick) {
32769
- item.onClick({
32770
- ...item,
32771
- index,
32772
- isSelected
32773
- });
32774
- }
33016
+ item.onClick?.({
33017
+ ...item,
33018
+ index,
33019
+ isSelected
33020
+ });
32775
33021
  };
32776
33022
  return /*#__PURE__*/react.createElement("div", {
32777
- className: classnames_default()(flex, theme, 'cursor-pointer'),
33023
+ className: classnames_default()(flex, theme, {
33024
+ 'cursor-pointer': !item.disabled,
33025
+ 'ohif-disabled': item.disabled
33026
+ }),
32778
33027
  onClick: onClickHandler,
32779
33028
  "data-cy": item.id
32780
33029
  }, renderer && renderer({
@@ -32819,36 +33068,28 @@ function SplitButton_extends() { SplitButton_extends = Object.assign ? Object.as
32819
33068
 
32820
33069
  const SplitButton_baseClasses = {
32821
33070
  Button: 'flex items-center rounded-md border-transparent cursor-pointer group/button',
32822
- Primary:
32823
- // By default border on left, top and bottom for hover effect and only rounded on left side.
32824
- // Extra padding on right to compensate for no right border.
32825
- 'h-full border-l-2 border-t-2 border-b-2 rounded-tl-md rounded-bl-md group/primary !pl-2 !py-2',
33071
+ Primary: 'h-full border-l-2 border-t-2 border-b-2 rounded-tl-md rounded-bl-md group/primary !pl-2 !py-2',
32826
33072
  Secondary: 'h-full flex items-center justify-center rounded-tr-md rounded-br-md w-4 border-2 border-transparent group/secondary',
32827
33073
  SecondaryIcon: 'w-4 h-full stroke-1',
32828
- Separator: 'border-l py-2.5',
33074
+ Separator: 'border-l py-3 ml-0.5',
32829
33075
  Content: 'absolute z-10 top-0 mt-12'
32830
33076
  };
32831
33077
  const SplitButton_classes = {
32832
33078
  Button: ({
32833
- isExpanded,
32834
- primary
32835
- }) => classnames_default()(SplitButton_baseClasses.Button, !isExpanded && !primary.isActive && 'hover:!bg-primary-dark hover:border-primary-dark'),
33079
+ isExpanded
33080
+ }) => classnames_default()(SplitButton_baseClasses.Button, !isExpanded && 'hover:!bg-primary-dark hover:border-primary-dark'),
32836
33081
  Interface: 'h-full flex flex-row items-center',
32837
33082
  Primary: ({
32838
- primary,
32839
- isExpanded
32840
- }) => classnames_default()(SplitButton_baseClasses.Primary, primary.isActive ? isExpanded ? 'border-primary-dark !bg-primary-dark hover:border-primary-dark !text-primary-light' : `${primary.isToggle ? 'border-secondary-dark bg-secondary-light' : 'border-primary-light bg-primary-light'}
32841
- border-2 rounded-md !p-2` // Full, rounded border with less right padding when active.
32842
- : `focus:!text-black focus:!rounded-md focus:!border-primary-light focus:!bg-primary-light
32843
- ${isExpanded ? 'border-primary-dark bg-primary-dark !text-primary-light' : 'border-secondary-dark bg-secondary-dark group-hover/button:border-primary-dark group-hover/button:text-primary-light hover:!bg-primary-dark hover:border-primary-dark focus:!text-black'}
32844
- `),
33083
+ isExpanded,
33084
+ isActive
33085
+ }) => classnames_default()(SplitButton_baseClasses.Primary, isActive ? isExpanded ? 'border-primary-dark !bg-primary-dark hover:border-primary-dark !text-primary-light' : 'border-primary-light bg-primary-light border-2 rounded-md !p-2' : `focus:!text-black focus:!rounded-md focus:!border-primary-light focus:!bg-primary-light ${isExpanded ? 'border-primary-dark bg-primary-dark !text-primary-light' : 'border-secondary-dark bg-secondary-dark group-hover/button:border-primary-dark group-hover/button:text-primary-light hover:!bg-primary-dark hover:border-primary-dark focus:!text-black'}`),
32845
33086
  Secondary: ({
32846
33087
  isExpanded,
32847
33088
  primary
32848
33089
  }) => classnames_default()(SplitButton_baseClasses.Secondary, isExpanded ? 'bg-primary-light !rounded-tr-md !rounded-br-md' : primary.isActive ? 'bg-secondary-dark' : 'hover:bg-primary-dark bg-secondary-dark group-hover/button:border-primary-dark'),
32849
33090
  SecondaryIcon: ({
32850
33091
  isExpanded
32851
- }) => classnames_default()(SplitButton_baseClasses.SecondaryIcon, isExpanded ? 'text-primary-dark' : 'text-[#348cfd] group-hover/secondary:text-primary-light'),
33092
+ }) => classnames_default()(SplitButton_baseClasses.SecondaryIcon, isExpanded ? 'text-primary-dark' : 'text-primary-active group-hover/secondary:text-primary-light'),
32852
33093
  Separator: ({
32853
33094
  primary,
32854
33095
  isExpanded,
@@ -32858,14 +33099,36 @@ const SplitButton_classes = {
32858
33099
  isExpanded
32859
33100
  }) => classnames_default()(SplitButton_baseClasses.Content, isExpanded ? 'block' : 'hidden')
32860
33101
  };
33102
+ const DefaultListItemRenderer = props => {
33103
+ const {
33104
+ t,
33105
+ icon,
33106
+ label,
33107
+ className,
33108
+ isActive
33109
+ } = props;
33110
+ return /*#__PURE__*/react.createElement("div", {
33111
+ className: classnames_default()('flex h-8 w-full flex-row items-center p-3', 'whitespace-pre text-base', className, `${isActive ? 'hover:opacity-80' : 'hover:bg-primary-dark '}`)
33112
+ }, icon && /*#__PURE__*/react.createElement("span", {
33113
+ className: "mr-4"
33114
+ }, /*#__PURE__*/react.createElement(Icon/* default */.A, {
33115
+ name: icon,
33116
+ className: "h-5 w-5"
33117
+ })), /*#__PURE__*/react.createElement("span", {
33118
+ className: "mr-5"
33119
+ }, t?.(label)));
33120
+ };
33121
+
33122
+ /**
33123
+ * This is a more generic version of SplitButton without the isActive
33124
+ * and other interaction props
33125
+ */
32861
33126
  const SplitButton = ({
32862
- isToggle,
32863
33127
  groupId,
32864
33128
  primary,
32865
33129
  secondary,
32866
33130
  items,
32867
33131
  renderer,
32868
- isActive,
32869
33132
  onInteraction,
32870
33133
  Component
32871
33134
  }) => {
@@ -32888,22 +33151,11 @@ const SplitButton = ({
32888
33151
  ...state,
32889
33152
  isExpanded: false
32890
33153
  });
32891
- const renderPrimaryButton = () => /*#__PURE__*/react.createElement(Component, SplitButton_extends({
32892
- key: primary.id
32893
- }, primary, {
32894
- isActive: isActive,
32895
- onInteraction: onInteraction,
32896
- rounded: "none",
32897
- className: SplitButton_classes.Primary({
32898
- ...state,
32899
- primary: {
32900
- isActive,
32901
- isToggle
32902
- }
32903
- }),
32904
- "data-tool": primary.id,
32905
- "data-cy": `${groupId}-split-button-primary`
32906
- }));
33154
+ const listItemRenderer = renderer || DefaultListItemRenderer;
33155
+ const primaryClassNames = classnames_default()(SplitButton_classes.Primary({
33156
+ isExpanded: state.isExpanded,
33157
+ isActive: primary.isActive
33158
+ }), primary.className);
32907
33159
  return /*#__PURE__*/react.createElement(react_outside_click_handler["default"], {
32908
33160
  onOutsideClick: collapse,
32909
33161
  disabled: !state.isExpanded
@@ -32912,10 +33164,7 @@ const SplitButton = ({
32912
33164
  className: "relative"
32913
33165
  }, /*#__PURE__*/react.createElement("div", {
32914
33166
  className: SplitButton_classes.Button({
32915
- ...state,
32916
- primary: {
32917
- isActive
32918
- }
33167
+ ...state
32919
33168
  }),
32920
33169
  style: {
32921
33170
  height: '40px'
@@ -32926,19 +33175,23 @@ const SplitButton = ({
32926
33175
  className: SplitButton_classes.Interface
32927
33176
  }, /*#__PURE__*/react.createElement("div", {
32928
33177
  onClick: collapse
32929
- }, renderPrimaryButton()), /*#__PURE__*/react.createElement("div", {
33178
+ }, /*#__PURE__*/react.createElement(Component, SplitButton_extends({
33179
+ key: primary.id
33180
+ }, primary, {
33181
+ onInteraction: onInteraction,
33182
+ rounded: "none",
33183
+ className: primaryClassNames,
33184
+ "data-tool": primary.id,
33185
+ "data-cy": `${groupId}-split-button-primary`
33186
+ }))), /*#__PURE__*/react.createElement("div", {
32930
33187
  className: SplitButton_classes.Separator({
32931
33188
  ...state,
32932
- primary: {
32933
- isActive
32934
- }
33189
+ primary
32935
33190
  })
32936
33191
  }), /*#__PURE__*/react.createElement("div", {
32937
33192
  className: SplitButton_classes.Secondary({
32938
33193
  ...state,
32939
- primary: {
32940
- isActive
32941
- }
33194
+ primary
32942
33195
  }),
32943
33196
  onClick: toggleExpanded,
32944
33197
  "data-cy": `${groupId}-split-button-secondary`
@@ -32949,10 +33202,7 @@ const SplitButton = ({
32949
33202
  }, /*#__PURE__*/react.createElement(Icon/* default */.A, {
32950
33203
  name: secondary.icon,
32951
33204
  className: SplitButton_classes.SecondaryIcon({
32952
- ...state,
32953
- primary: {
32954
- isActive
32955
- }
33205
+ ...state
32956
33206
  })
32957
33207
  }))))), /*#__PURE__*/react.createElement("div", {
32958
33208
  className: SplitButton_classes.Content({
@@ -32962,7 +33212,7 @@ const SplitButton = ({
32962
33212
  }, /*#__PURE__*/react.createElement(components_ListMenu, {
32963
33213
  items: items,
32964
33214
  onClick: collapse,
32965
- renderer: args => renderer({
33215
+ renderer: args => listItemRenderer({
32966
33216
  ...args,
32967
33217
  t
32968
33218
  })
@@ -32977,7 +33227,8 @@ SplitButton.propTypes = {
32977
33227
  renderer: (prop_types_default()).func,
32978
33228
  isActive: (prop_types_default()).bool,
32979
33229
  onInteraction: (prop_types_default()).func.isRequired,
32980
- Component: (prop_types_default()).elementType
33230
+ Component: (prop_types_default()).elementType,
33231
+ interactionType: prop_types_default().oneOf(['action', 'tool', 'toggle'])
32981
33232
  };
32982
33233
  SplitButton.defaultProps = {
32983
33234
  isToggle: false,
@@ -33626,7 +33877,7 @@ const Thumbnail = ({
33626
33877
  }, imageSrc ? /*#__PURE__*/react.createElement("img", {
33627
33878
  src: imageSrc,
33628
33879
  alt: imageAltText,
33629
- className: "min-h-32 object-none",
33880
+ className: "min-h-32 object-contain",
33630
33881
  crossOrigin: "anonymous"
33631
33882
  }) : /*#__PURE__*/react.createElement("div", null, imageAltText)), /*#__PURE__*/react.createElement("div", {
33632
33883
  className: "flex flex-1 flex-row items-center pt-2 text-base text-blue-300"
@@ -33790,6 +34041,9 @@ ThumbnailNoImage.propTypes = {
33790
34041
 
33791
34042
 
33792
34043
 
34044
+
34045
+ // Todo: This class to me feels like it belongs in an extension, not in platform/ui
34046
+ // because it is dealing with mode specific components/information
33793
34047
  function ThumbnailTracked({
33794
34048
  displaySetInstanceUID,
33795
34049
  className,
@@ -33880,7 +34134,6 @@ function ThumbnailTracked({
33880
34134
  onDoubleClick: onDoubleClick
33881
34135
  }));
33882
34136
  }
33883
- ;
33884
34137
  ThumbnailTracked.propTypes = {
33885
34138
  /**
33886
34139
  * Data the thumbnail should expose to a receiving drop target. Use a matching
@@ -34919,9 +35172,7 @@ function ToolbarButton_extends() { ToolbarButton_extends = Object.assign ? Objec
34919
35172
 
34920
35173
 
34921
35174
 
34922
-
34923
35175
  const ToolbarButton = ({
34924
- type = 'tool',
34925
35176
  id,
34926
35177
  icon,
34927
35178
  label,
@@ -34929,39 +35180,31 @@ const ToolbarButton = ({
34929
35180
  onInteraction,
34930
35181
  dropdownContent,
34931
35182
  //
34932
- isActive,
34933
35183
  className,
35184
+ size,
35185
+ toolTipClassName,
34934
35186
  ...rest
34935
35187
  //
34936
35188
  }) => {
34937
- const classes = {
34938
- tool: isActive ? 'text-black' : 'text-common-bright hover:!bg-primary-dark hover:text-primary-light',
34939
- toggle: isActive ? '!text-[#348CFD]' : 'text-common-bright hover:!bg-primary-dark hover:text-primary-light',
34940
- action: isActive ? 'text-black' : 'text-common-bright hover:!bg-primary-dark hover:text-primary-light'
34941
- };
34942
- const bgClasses = {
34943
- toggle: isActive && 'bg-transparent'
34944
- };
34945
- const activeClass = isActive ? 'active' : '';
34946
- const shouldShowDropdown = !!isActive && !!dropdownContent;
35189
+ const shouldShowDropdown = !!dropdownContent;
34947
35190
  const iconEl = icon ? /*#__PURE__*/react.createElement(Icon/* default */.A, {
34948
35191
  name: icon
34949
35192
  }) : /*#__PURE__*/react.createElement("div", null, label || 'Missing icon and label');
35193
+ const sizeToUse = size ?? 'toolbar';
35194
+ const toolTipClassNameToUse = toolTipClassName !== undefined ? toolTipClassName : sizeToUse === 'toolbar' ? 'w-[40px] h-[40px]' : 'w-[32px] h-[32px]';
34950
35195
  return /*#__PURE__*/react.createElement("div", {
34951
35196
  key: id
34952
35197
  }, /*#__PURE__*/react.createElement(components_Tooltip, {
34953
35198
  isSticky: shouldShowDropdown,
34954
35199
  content: shouldShowDropdown ? dropdownContent : label,
34955
- tight: shouldShowDropdown
35200
+ tight: shouldShowDropdown,
35201
+ className: toolTipClassNameToUse
34956
35202
  }, /*#__PURE__*/react.createElement(components_IconButton, ToolbarButton_extends({
34957
- variant: isActive ? 'contained' : 'text',
34958
- bgColor: bgClasses[type],
34959
- size: "toolbar",
34960
- className: classnames_default()(activeClass, classes[type], className),
35203
+ size: sizeToUse,
35204
+ className: className,
34961
35205
  onClick: () => {
34962
35206
  onInteraction({
34963
35207
  itemId: id,
34964
- interactionType: type,
34965
35208
  commands
34966
35209
  });
34967
35210
  },
@@ -34971,25 +35214,20 @@ const ToolbarButton = ({
34971
35214
  }, rest), iconEl)));
34972
35215
  };
34973
35216
  ToolbarButton.defaultProps = {
34974
- dropdownContent: null,
34975
- isActive: false,
34976
- type: 'action'
35217
+ dropdownContent: null
34977
35218
  };
34978
35219
  ToolbarButton.propTypes = {
34979
35220
  /* Influences background/hover styling */
34980
- type: prop_types_default().oneOf(['action', 'toggle', 'tool']),
34981
35221
  id: (prop_types_default()).string.isRequired,
34982
- isActive: (prop_types_default()).bool,
34983
35222
  className: (prop_types_default()).string,
34984
- commands: prop_types_default().arrayOf(prop_types_default().shape({
34985
- commandName: (prop_types_default()).string.isRequired,
34986
- commandOptions: (prop_types_default()).object
34987
- })),
34988
- onInteraction: (prop_types_default()).func.isRequired,
35223
+ commands: prop_types_default().oneOfType([(prop_types_default()).array, (prop_types_default()).object, (prop_types_default()).string]),
35224
+ onInteraction: (prop_types_default()).func,
34989
35225
  icon: (prop_types_default()).string.isRequired,
34990
35226
  label: (prop_types_default()).string.isRequired,
34991
35227
  /** Tooltip content can be replaced for a customized content by passing a node to this value. */
34992
- dropdownContent: prop_types_default().oneOfType([(prop_types_default()).node, (prop_types_default()).func])
35228
+ dropdownContent: prop_types_default().oneOfType([(prop_types_default()).node, (prop_types_default()).func]),
35229
+ size: (prop_types_default()).string,
35230
+ toolTipClassName: (prop_types_default()).string
34993
35231
  };
34994
35232
  /* harmony default export */ const ToolbarButton_ToolbarButton = (ToolbarButton);
34995
35233
  ;// CONCATENATED MODULE: ../../ui/src/components/ToolbarButton/index.js
@@ -36289,6 +36527,7 @@ UserPreferences.defaultProps = {
36289
36527
 
36290
36528
  /* harmony default export */ const components_UserPreferences = (UserPreferences_UserPreferences);
36291
36529
  ;// CONCATENATED MODULE: ../../ui/src/components/Header/Header.tsx
36530
+ function Header_extends() { Header_extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return Header_extends.apply(this, arguments); }
36292
36531
 
36293
36532
 
36294
36533
 
@@ -36318,13 +36557,12 @@ function Header_Header({
36318
36557
  onClickReturnButton();
36319
36558
  }
36320
36559
  };
36321
- return /*#__PURE__*/react.createElement(components_NavBar, {
36322
- className: "justify-between border-b-4 border-black",
36560
+ return /*#__PURE__*/react.createElement(components_NavBar, Header_extends({
36323
36561
  isSticky: isSticky
36562
+ }, props), /*#__PURE__*/react.createElement("div", {
36563
+ className: "relative h-[48px] items-center "
36324
36564
  }, /*#__PURE__*/react.createElement("div", {
36325
- className: "flex flex-1 justify-between"
36326
- }, /*#__PURE__*/react.createElement("div", {
36327
- className: "flex items-center"
36565
+ className: "absolute left-0 top-1/2 -translate-y-1/2 "
36328
36566
  }, /*#__PURE__*/react.createElement("div", {
36329
36567
  className: classnames_default()('mr-3 inline-flex items-center', isReturnEnabled && 'cursor-pointer'),
36330
36568
  onClick: onClickReturn,
@@ -36337,12 +36575,12 @@ function Header_Header({
36337
36575
  }, WhiteLabeling?.createLogoComponentFn?.(react, props) || /*#__PURE__*/react.createElement(components_Svg, {
36338
36576
  name: "logo-ohif"
36339
36577
  })))), /*#__PURE__*/react.createElement("div", {
36340
- className: "flex items-center"
36341
- }, children), /*#__PURE__*/react.createElement("div", {
36342
- className: "flex items-center"
36343
- }, /*#__PURE__*/react.createElement("span", {
36344
- className: "text-common-light mr-3 text-lg"
36345
- }, t('INVESTIGATIONAL USE ONLY')), /*#__PURE__*/react.createElement(Dropdown_Dropdown, {
36578
+ className: "absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 transform"
36579
+ }, /*#__PURE__*/react.createElement("div", {
36580
+ className: "flex items-center justify-center space-x-2"
36581
+ }, children)), /*#__PURE__*/react.createElement("div", {
36582
+ className: "absolute right-0 top-1/2 -translate-y-1/2 "
36583
+ }, /*#__PURE__*/react.createElement(Dropdown_Dropdown, {
36346
36584
  id: "options",
36347
36585
  showDropdownIcon: false,
36348
36586
  list: menuOptions,
@@ -36478,11 +36716,11 @@ const ViewportOverlay = ({
36478
36716
  topRight,
36479
36717
  bottomRight,
36480
36718
  bottomLeft,
36481
- color
36719
+ color = 'text-primary-light'
36482
36720
  }) => {
36483
36721
  const overlay = 'absolute pointer-events-none viewport-overlay';
36484
36722
  return /*#__PURE__*/react.createElement("div", {
36485
- className: classnames_default()(color ? color : 'text-primary-light')
36723
+ className: color
36486
36724
  }, /*#__PURE__*/react.createElement("div", {
36487
36725
  "data-cy": 'viewport-overlay-top-left',
36488
36726
  className: classnames_default()(overlay, ViewportOverlay_classes.topLeft)
@@ -49442,7 +49680,8 @@ PanelSection.propTypes = {
49442
49680
  const SETTING_TYPES = {
49443
49681
  RANGE: 'range',
49444
49682
  RADIO: 'radio',
49445
- CUSTOM: 'custom'
49683
+ CUSTOM: 'custom',
49684
+ DOUBLE_RANGE: 'double-range'
49446
49685
  };
49447
49686
  function ToolSettings({
49448
49687
  options
@@ -49450,68 +49689,103 @@ function ToolSettings({
49450
49689
  if (!options) {
49451
49690
  return null;
49452
49691
  }
49453
- const getButtons = option => {
49454
- const buttons = [];
49455
- option.values?.map(({
49456
- label,
49457
- value: optionValue
49458
- }, index) => {
49459
- buttons.push({
49460
- children: label,
49461
- onClick: () => option.onChange(optionValue),
49462
- key: `button-${option.id}-${index}` // A unique key
49463
- });
49464
- });
49465
- return buttons;
49466
- };
49467
49692
  return /*#__PURE__*/react.createElement("div", {
49468
49693
  className: "space-y-2 py-2 text-white"
49469
49694
  }, options?.map(option => {
49470
- if (option.type === SETTING_TYPES.RANGE) {
49471
- return /*#__PURE__*/react.createElement("div", {
49472
- className: "flex items-center",
49473
- key: option.id
49474
- }, /*#__PURE__*/react.createElement("div", {
49475
- className: "w-1/3 text-[13px]"
49476
- }, option.name), /*#__PURE__*/react.createElement("div", {
49477
- className: "w-2/3"
49478
- }, /*#__PURE__*/react.createElement(components_InputRange, {
49479
- minValue: option.min,
49480
- maxValue: option.max,
49481
- step: option.step,
49482
- value: option.value,
49483
- onChange: e => option.onChange(e),
49484
- allowNumberEdit: true,
49485
- showAdjustmentArrows: false,
49486
- inputClassName: "ml-1 w-4/5 cursor-pointer"
49487
- })));
49488
- }
49489
- if (option.type === SETTING_TYPES.RADIO) {
49490
- return /*#__PURE__*/react.createElement("div", {
49491
- className: "flex items-center justify-between text-[13px]",
49492
- key: option.id
49493
- }, /*#__PURE__*/react.createElement("span", null, option.name), /*#__PURE__*/react.createElement("div", {
49494
- className: "max-w-1/2"
49495
- }, /*#__PURE__*/react.createElement(components_ButtonGroup, {
49496
- buttons: getButtons(option),
49497
- defaultActiveIndex: option.defaultActiveIndex,
49498
- size: size.small
49499
- })));
49695
+ if (option.condition && option.condition?.({
49696
+ options
49697
+ }) === false) {
49698
+ return null;
49500
49699
  }
49501
- if (option.type === SETTING_TYPES.CUSTOM) {
49502
- return /*#__PURE__*/react.createElement("div", {
49503
- key: option.id
49504
- }, typeof option.children === 'function' ? option.children() : option.children);
49700
+ switch (option.type) {
49701
+ case SETTING_TYPES.RANGE:
49702
+ return renderRangeSetting(option);
49703
+ case SETTING_TYPES.RADIO:
49704
+ return renderRadioSetting(option);
49705
+ case SETTING_TYPES.DOUBLE_RANGE:
49706
+ return renderDoubleRangeSetting(option);
49707
+ case SETTING_TYPES.CUSTOM:
49708
+ return renderCustomSetting(option);
49709
+ default:
49710
+ return null;
49505
49711
  }
49506
49712
  }));
49507
49713
  }
49714
+ const renderRangeSetting = option => {
49715
+ return /*#__PURE__*/react.createElement("div", {
49716
+ className: "flex items-center",
49717
+ key: option.id
49718
+ }, /*#__PURE__*/react.createElement("div", {
49719
+ className: "w-1/3 text-[13px]"
49720
+ }, option.name), /*#__PURE__*/react.createElement("div", {
49721
+ className: "w-2/3"
49722
+ }, /*#__PURE__*/react.createElement(components_InputRange, {
49723
+ minValue: option.min,
49724
+ maxValue: option.max,
49725
+ step: option.step,
49726
+ value: option.value,
49727
+ onChange: value => option.commands?.(value),
49728
+ allowNumberEdit: true,
49729
+ showAdjustmentArrows: false,
49730
+ inputClassName: "ml-1 w-4/5 cursor-pointer"
49731
+ })));
49732
+ };
49733
+ const renderRadioSetting = option => {
49734
+ const renderButtons = option => {
49735
+ return option.values?.map(({
49736
+ label,
49737
+ value: optionValue
49738
+ }, index) => /*#__PURE__*/react.createElement("button", {
49739
+ onClick: () => {
49740
+ option.commands?.(optionValue);
49741
+ },
49742
+ key: `button-${option.id}-${index}`
49743
+ }, label));
49744
+ };
49745
+ return /*#__PURE__*/react.createElement("div", {
49746
+ className: "flex items-center justify-between text-[13px]",
49747
+ key: option.id
49748
+ }, /*#__PURE__*/react.createElement("span", null, option.name), /*#__PURE__*/react.createElement("div", {
49749
+ className: "max-w-1/2"
49750
+ }, /*#__PURE__*/react.createElement(components_ButtonGroup, {
49751
+ activeIndex: option.values.findIndex(({
49752
+ value
49753
+ }) => value === option.value) || 0
49754
+ }, renderButtons(option))));
49755
+ };
49756
+ const renderDoubleRangeSetting = option => {
49757
+ return /*#__PURE__*/react.createElement("div", {
49758
+ className: "flex w-full items-center",
49759
+ key: option.id
49760
+ }, /*#__PURE__*/react.createElement(components_InputDoubleRange, {
49761
+ values: option.values,
49762
+ onChange: option.commands,
49763
+ minValue: option.min,
49764
+ maxValue: option.max,
49765
+ step: option.step,
49766
+ showLabel: true,
49767
+ allowNumberEdit: true,
49768
+ showAdjustmentArrows: false,
49769
+ containerClassName: "w-full"
49770
+ }));
49771
+ };
49772
+ const renderCustomSetting = option => {
49773
+ return /*#__PURE__*/react.createElement("div", {
49774
+ key: option.id
49775
+ }, typeof option.children === 'function' ? option.children() : option.children);
49776
+ };
49508
49777
  /* harmony default export */ const AdvancedToolbox_ToolSettings = (ToolSettings);
49509
49778
  ;// CONCATENATED MODULE: ../../ui/src/components/AdvancedToolbox/AdvancedToolbox.tsx
49510
49779
 
49511
49780
 
49512
49781
 
49513
49782
 
49514
- const AdvancedToolbox = ({
49783
+
49784
+ /**
49785
+ * Use Toolbox component instead of this although it doesn't have "Advanced" in its name
49786
+ * it is better to use it instead of this one
49787
+ */
49788
+ const AdvancedToolbox_AdvancedToolbox = ({
49515
49789
  title,
49516
49790
  items
49517
49791
  }) => {
@@ -49555,11 +49829,13 @@ const AdvancedToolbox = ({
49555
49829
  options: activeItemOptions
49556
49830
  }))));
49557
49831
  };
49558
- AdvancedToolbox.propTypes = {};
49559
- /* harmony default export */ const AdvancedToolbox_AdvancedToolbox = (AdvancedToolbox);
49832
+ AdvancedToolbox_AdvancedToolbox.propTypes = {};
49833
+ /* harmony default export */ const components_AdvancedToolbox_AdvancedToolbox = ((/* unused pure expression or super */ null && (AdvancedToolbox_AdvancedToolbox)));
49560
49834
  ;// CONCATENATED MODULE: ../../ui/src/components/AdvancedToolbox/index.js
49561
49835
 
49562
- /* harmony default export */ const components_AdvancedToolbox = (AdvancedToolbox_AdvancedToolbox);
49836
+
49837
+ /* harmony default export */ const components_AdvancedToolbox = ((/* unused pure expression or super */ null && (AdvancedToolbox)));
49838
+
49563
49839
  ;// CONCATENATED MODULE: ../../ui/src/components/InputDoubleRange/InputDoubleRange.css
49564
49840
  // extracted by mini-css-extract-plugin
49565
49841
 
@@ -49734,6 +50010,476 @@ InputDoubleRange.defaultProps = {
49734
50010
  ;// CONCATENATED MODULE: ../../ui/src/components/InputDoubleRange/index.js
49735
50011
 
49736
50012
  /* harmony default export */ const components_InputDoubleRange = (InputDoubleRange_InputDoubleRange);
50013
+ ;// CONCATENATED MODULE: ../../ui/src/components/LegacySplitButton/LegacySplitButton.tsx
50014
+ function LegacySplitButton_extends() { LegacySplitButton_extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return LegacySplitButton_extends.apply(this, arguments); }
50015
+
50016
+
50017
+
50018
+
50019
+
50020
+
50021
+
50022
+
50023
+ const LegacySplitButton_baseClasses = {
50024
+ Button: 'flex items-center rounded-md border-transparent cursor-pointer group/button',
50025
+ Primary:
50026
+ // By default border on left, top and bottom for hover effect and only rounded on left side.
50027
+ // Extra padding on right to compensate for no right border.
50028
+ 'h-full border-l-2 border-t-2 border-b-2 rounded-tl-md rounded-bl-md group/primary !pl-2 !py-2',
50029
+ Secondary: 'h-full flex items-center justify-center rounded-tr-md rounded-br-md w-4 border-2 border-transparent group/secondary',
50030
+ SecondaryIcon: 'w-4 h-full stroke-1',
50031
+ Separator: 'border-l py-2.5',
50032
+ Content: 'absolute z-10 top-0 mt-12'
50033
+ };
50034
+ const LegacySplitButton_classes = {
50035
+ Button: ({
50036
+ isExpanded,
50037
+ primary
50038
+ }) => classnames_default()(LegacySplitButton_baseClasses.Button, !isExpanded && !primary.isActive && 'hover:!bg-primary-dark hover:border-primary-dark'),
50039
+ Interface: 'h-full flex flex-row items-center',
50040
+ Primary: ({
50041
+ isActive,
50042
+ isExpanded
50043
+ }) => classnames_default()(LegacySplitButton_baseClasses.Primary, isActive ? isExpanded ? 'border-primary-dark !bg-primary-dark hover:border-primary-dark !text-primary-light' : 'border-primary-light bg-primary-light border-2 rounded-md !p-2' : `focus:!text-black focus:!rounded-md focus:!border-primary-light focus:!bg-primary-light
50044
+ ${isExpanded ? 'border-primary-dark bg-primary-dark !text-primary-light' : 'border-secondary-dark bg-secondary-dark group-hover/button:border-primary-dark group-hover/button:text-primary-light hover:!bg-primary-dark hover:border-primary-dark focus:!text-black'}
50045
+ `),
50046
+ Secondary: ({
50047
+ isExpanded,
50048
+ primary
50049
+ }) => classnames_default()(LegacySplitButton_baseClasses.Secondary, isExpanded ? 'bg-primary-light !rounded-tr-md !rounded-br-md' : primary.isActive ? 'bg-secondary-dark' : 'hover:bg-primary-dark bg-secondary-dark group-hover/button:border-primary-dark'),
50050
+ SecondaryIcon: ({
50051
+ isExpanded
50052
+ }) => classnames_default()(LegacySplitButton_baseClasses.SecondaryIcon, isExpanded ? 'text-primary-dark' : 'text-primary-active group-hover/secondary:text-primary-light'),
50053
+ Separator: ({
50054
+ primary,
50055
+ isExpanded,
50056
+ isHovering
50057
+ }) => classnames_default()(LegacySplitButton_baseClasses.Separator, isHovering || isExpanded || primary.isActive ? 'border-transparent' : 'border-primary-active'),
50058
+ Content: ({
50059
+ isExpanded
50060
+ }) => classnames_default()(LegacySplitButton_baseClasses.Content, isExpanded ? 'block' : 'hidden')
50061
+ };
50062
+ const LegacySplitButton_SplitButton = ({
50063
+ groupId,
50064
+ primary,
50065
+ secondary,
50066
+ items,
50067
+ renderer,
50068
+ onInteraction,
50069
+ Component,
50070
+ isActive
50071
+ }) => {
50072
+ const {
50073
+ t
50074
+ } = (0,es/* useTranslation */.Bd)('Buttons');
50075
+ const [state, setState] = (0,react.useState)({
50076
+ isHovering: false,
50077
+ isExpanded: false
50078
+ });
50079
+ const toggleExpanded = () => setState({
50080
+ ...state,
50081
+ isExpanded: !state.isExpanded
50082
+ });
50083
+ const setHover = hovering => setState({
50084
+ ...state,
50085
+ isHovering: hovering
50086
+ });
50087
+ const collapse = () => setState({
50088
+ ...state,
50089
+ isExpanded: false
50090
+ });
50091
+ const renderPrimaryButton = () => /*#__PURE__*/react.createElement(Component, LegacySplitButton_extends({
50092
+ key: primary.id
50093
+ }, primary, {
50094
+ isActive: isActive,
50095
+ onInteraction: onInteraction,
50096
+ rounded: "none",
50097
+ className: LegacySplitButton_classes.Primary({
50098
+ isActive,
50099
+ isExpanded: state.isExpanded
50100
+ }),
50101
+ "data-tool": primary.id,
50102
+ "data-cy": `${groupId}-split-button-primary`
50103
+ }));
50104
+ return /*#__PURE__*/react.createElement(react_outside_click_handler["default"], {
50105
+ onOutsideClick: collapse,
50106
+ disabled: !state.isExpanded
50107
+ }, /*#__PURE__*/react.createElement("div", {
50108
+ id: "SplitButton",
50109
+ className: "relative"
50110
+ }, /*#__PURE__*/react.createElement("div", {
50111
+ className: LegacySplitButton_classes.Button({
50112
+ ...state,
50113
+ primary: {
50114
+ isActive
50115
+ }
50116
+ }),
50117
+ style: {
50118
+ height: '40px'
50119
+ },
50120
+ onMouseEnter: () => setHover(true),
50121
+ onMouseLeave: () => setHover(false)
50122
+ }, /*#__PURE__*/react.createElement("div", {
50123
+ className: LegacySplitButton_classes.Interface
50124
+ }, /*#__PURE__*/react.createElement("div", {
50125
+ onClick: collapse
50126
+ }, renderPrimaryButton()), /*#__PURE__*/react.createElement("div", {
50127
+ className: LegacySplitButton_classes.Separator({
50128
+ ...state,
50129
+ primary: {
50130
+ isActive
50131
+ }
50132
+ })
50133
+ }), /*#__PURE__*/react.createElement("div", {
50134
+ className: LegacySplitButton_classes.Secondary({
50135
+ ...state,
50136
+ primary: {
50137
+ isActive
50138
+ }
50139
+ }),
50140
+ onClick: toggleExpanded,
50141
+ "data-cy": `${groupId}-split-button-secondary`
50142
+ }, /*#__PURE__*/react.createElement(components_Tooltip, {
50143
+ isDisabled: state.isExpanded || !secondary.tooltip,
50144
+ content: secondary.tooltip,
50145
+ className: "h-full"
50146
+ }, /*#__PURE__*/react.createElement(Icon/* default */.A, {
50147
+ name: secondary.icon,
50148
+ className: LegacySplitButton_classes.SecondaryIcon({
50149
+ ...state
50150
+ })
50151
+ }))))), /*#__PURE__*/react.createElement("div", {
50152
+ className: LegacySplitButton_classes.Content({
50153
+ ...state
50154
+ }),
50155
+ "data-cy": `${groupId}-list-menu`
50156
+ }, /*#__PURE__*/react.createElement(components_ListMenu, {
50157
+ items: items,
50158
+ onClick: collapse,
50159
+ renderer: args => renderer({
50160
+ ...args,
50161
+ t
50162
+ })
50163
+ }))));
50164
+ };
50165
+ LegacySplitButton_SplitButton.propTypes = {
50166
+ isToggle: (prop_types_default()).bool,
50167
+ groupId: (prop_types_default()).string.isRequired,
50168
+ primary: (prop_types_default()).object.isRequired,
50169
+ secondary: (prop_types_default()).object.isRequired,
50170
+ items: (prop_types_default()).array.isRequired,
50171
+ renderer: (prop_types_default()).func,
50172
+ isActive: (prop_types_default()).bool,
50173
+ onInteraction: (prop_types_default()).func.isRequired,
50174
+ Component: (prop_types_default()).elementType
50175
+ };
50176
+ LegacySplitButton_SplitButton.defaultProps = {
50177
+ isToggle: false,
50178
+ renderer: null,
50179
+ isActive: false,
50180
+ Component: null
50181
+ };
50182
+ /* harmony default export */ const LegacySplitButton_LegacySplitButton = ((/* unused pure expression or super */ null && (LegacySplitButton_SplitButton)));
50183
+ ;// CONCATENATED MODULE: ../../ui/src/components/LegacySplitButton/index.js
50184
+
50185
+ /* harmony default export */ const components_LegacySplitButton = ((/* unused pure expression or super */ null && (LegacySplitButton)));
50186
+ ;// CONCATENATED MODULE: ../../ui/src/components/Toolbox/ToolboxUI.tsx
50187
+ function ToolboxUI_extends() { ToolboxUI_extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return ToolboxUI_extends.apply(this, arguments); }
50188
+
50189
+
50190
+
50191
+ const ItemsPerRow = 4;
50192
+
50193
+ /**
50194
+ * Just refactoring from the toolbox component to make it more readable
50195
+ */
50196
+ function ToolboxUI(props) {
50197
+ const {
50198
+ toolbarButtons,
50199
+ handleToolSelect,
50200
+ activeToolOptions,
50201
+ numRows,
50202
+ servicesManager,
50203
+ title,
50204
+ useCollapsedPanel = true
50205
+ } = props;
50206
+ const render = () => {
50207
+ return /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement("div", {
50208
+ className: "flex flex-col bg-black"
50209
+ }, /*#__PURE__*/react.createElement("div", {
50210
+ className: "bg-primary-dark mt-0.5 flex flex-wrap py-2"
50211
+ }, toolbarButtons.map((toolDef, index) => {
50212
+ if (!toolDef) {
50213
+ return null;
50214
+ }
50215
+ const {
50216
+ id,
50217
+ Component,
50218
+ componentProps
50219
+ } = toolDef;
50220
+ const isLastRow = Math.floor(index / ItemsPerRow) + 1 === numRows;
50221
+ const toolClasses = `ml-1 ${isLastRow ? '' : 'mb-2'}`;
50222
+ const onInteraction = ({
50223
+ itemId,
50224
+ id,
50225
+ commands
50226
+ }) => {
50227
+ handleToolSelect(itemId || id);
50228
+ props.onInteraction({
50229
+ itemId,
50230
+ commands
50231
+ });
50232
+ };
50233
+ return /*#__PURE__*/react.createElement("div", {
50234
+ key: id,
50235
+ className: classnames_default()({
50236
+ [toolClasses]: true,
50237
+ 'flex flex-col items-center justify-center': true
50238
+ })
50239
+ }, componentProps.disabled ? /*#__PURE__*/react.createElement(components_Tooltip, {
50240
+ position: "bottom",
50241
+ content: componentProps.label,
50242
+ secondaryContent: 'Not available on the current viewport'
50243
+ }, /*#__PURE__*/react.createElement(Component, ToolboxUI_extends({}, componentProps, props, {
50244
+ id: id,
50245
+ servicesManager: servicesManager,
50246
+ onInteraction: onInteraction,
50247
+ size: "toolbox"
50248
+ }))) : /*#__PURE__*/react.createElement(Component, ToolboxUI_extends({}, componentProps, props, {
50249
+ id: id,
50250
+ servicesManager: servicesManager,
50251
+ onInteraction: onInteraction,
50252
+ size: "toolbox"
50253
+ })));
50254
+ }))), /*#__PURE__*/react.createElement("div", {
50255
+ className: "bg-primary-dark h-auto px-2"
50256
+ }, activeToolOptions && /*#__PURE__*/react.createElement(AdvancedToolbox_ToolSettings, {
50257
+ options: activeToolOptions
50258
+ })));
50259
+ };
50260
+ return useCollapsedPanel ? /*#__PURE__*/react.createElement(components_PanelSection, {
50261
+ title: title
50262
+ }, render()) : render();
50263
+ }
50264
+
50265
+ ;// CONCATENATED MODULE: ../../ui/src/components/Toolbox/Toolbox.tsx
50266
+ function Toolbox_extends() { Toolbox_extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return Toolbox_extends.apply(this, arguments); }
50267
+
50268
+
50269
+
50270
+
50271
+
50272
+ /**
50273
+ * A toolbox is a collection of buttons and commands that they invoke, used to provide
50274
+ * custom control panels to users. This component is a generic UI component that
50275
+ * interacts with services and commands in a generic fashion. While it might
50276
+ * seem unconventional to import it from the UI and integrate it into the JSX,
50277
+ * it belongs in the UI components as there isn't anything in this component that
50278
+ * couldn't be used for a completely different type of app. It plays a crucial
50279
+ * role in enhancing the app with a toolbox by providing a way to integrate
50280
+ * and display various tools and their corresponding options
50281
+ */
50282
+ function Toolbox({
50283
+ servicesManager,
50284
+ buttonSectionId,
50285
+ commandsManager,
50286
+ title,
50287
+ ...props
50288
+ }) {
50289
+ const {
50290
+ state: toolboxState,
50291
+ api
50292
+ } = useToolbox(buttonSectionId);
50293
+ const {
50294
+ onInteraction,
50295
+ toolbarButtons
50296
+ } = (0,src/* useToolbar */.tR)({
50297
+ servicesManager,
50298
+ buttonSection: buttonSectionId
50299
+ });
50300
+ const prevButtonIdsRef = (0,react.useRef)();
50301
+ (0,react.useEffect)(() => {
50302
+ const currentButtonIdsStr = JSON.stringify(toolbarButtons.map(button => {
50303
+ const {
50304
+ id,
50305
+ componentProps
50306
+ } = button;
50307
+ if (componentProps.items?.length) {
50308
+ return componentProps.items.map(item => `${item.id}-${item.disabled}`);
50309
+ }
50310
+ return `${id}-${componentProps.disabled}`;
50311
+ }));
50312
+ if (prevButtonIdsRef.current === currentButtonIdsStr) {
50313
+ return;
50314
+ }
50315
+ prevButtonIdsRef.current = currentButtonIdsStr;
50316
+ const initializeOptionsWithEnhancements = toolbarButtons.reduce((accumulator, toolbarButton) => {
50317
+ const {
50318
+ id: buttonId,
50319
+ componentProps
50320
+ } = toolbarButton;
50321
+ const createEnhancedOptions = (options, parentId) => options.map(option => {
50322
+ return {
50323
+ ...option,
50324
+ value: toolboxState.toolOptions?.[parentId]?.find(prop => prop.id === option.id)?.value ?? option.value,
50325
+ commands: value => {
50326
+ api.handleToolOptionChange(parentId, option.id, value);
50327
+ const {
50328
+ isArray
50329
+ } = Array;
50330
+ const cmds = isArray(option.commands) ? option.commands : [option.commands];
50331
+ cmds.forEach(command => {
50332
+ const isString = typeof command === 'string';
50333
+ const isObject = typeof command === 'object';
50334
+ if (isString) {
50335
+ commandsManager.run(command, {
50336
+ value
50337
+ });
50338
+ } else if (isObject) {
50339
+ commandsManager.run({
50340
+ ...command,
50341
+ commandOptions: {
50342
+ ...command.commandOptions,
50343
+ ...option,
50344
+ value
50345
+ }
50346
+ });
50347
+ }
50348
+ });
50349
+ }
50350
+ };
50351
+ });
50352
+ if (componentProps.items?.length) {
50353
+ componentProps.items.forEach(item => {
50354
+ accumulator[item.id] = createEnhancedOptions(item.options, item.id);
50355
+ });
50356
+ } else if (componentProps.options?.length) {
50357
+ accumulator[buttonId] = createEnhancedOptions(componentProps.options, buttonId);
50358
+ }
50359
+ return accumulator;
50360
+ }, {});
50361
+ api.initializeToolOptions(initializeOptionsWithEnhancements);
50362
+ }, [toolbarButtons, api]);
50363
+ const handleToolOptionChange = (toolName, optionName, newValue) => {
50364
+ api.handleToolOptionChange(toolName, optionName, newValue);
50365
+ };
50366
+ return /*#__PURE__*/react.createElement(ToolboxUI, Toolbox_extends({}, props, {
50367
+ title: title,
50368
+ toolbarButtons: toolbarButtons,
50369
+ activeToolOptions: toolboxState.toolOptions?.[toolboxState.activeTool],
50370
+ handleToolSelect: id => api.handleToolSelect(id),
50371
+ handleToolOptionChange: handleToolOptionChange,
50372
+ onInteraction: onInteraction
50373
+ }));
50374
+ }
50375
+ /* harmony default export */ const Toolbox_Toolbox = (Toolbox);
50376
+ ;// CONCATENATED MODULE: ../../ui/src/components/Toolbox/index.js
50377
+
50378
+
50379
+
50380
+ ;// CONCATENATED MODULE: ../../ui/src/components/InvestigationalUseDialog/InvestigationalUseDialog.tsx
50381
+
50382
+
50383
+
50384
+
50385
+ let showDialogOption = /*#__PURE__*/function (showDialogOption) {
50386
+ showDialogOption["NeverShowDialog"] = "never";
50387
+ showDialogOption["AlwaysShowDialog"] = "always";
50388
+ showDialogOption["ShowOnceAndConfigure"] = "configure";
50389
+ return showDialogOption;
50390
+ }({});
50391
+ const InvestigationalUseDialog = ({
50392
+ dialogConfiguration
50393
+ }) => {
50394
+ const {
50395
+ option,
50396
+ days
50397
+ } = dialogConfiguration;
50398
+ const [isHidden, setIsHidden] = (0,react.useState)(true);
50399
+ (0,react.useEffect)(() => {
50400
+ const dialogLocalState = localStorage.getItem('investigationalUseDialog');
50401
+ const dialogSessionState = sessionStorage.getItem('investigationalUseDialog');
50402
+ switch (option) {
50403
+ case showDialogOption.NeverShowDialog:
50404
+ setIsHidden(true);
50405
+ break;
50406
+ case showDialogOption.AlwaysShowDialog:
50407
+ setIsHidden(!!dialogSessionState);
50408
+ break;
50409
+ case showDialogOption.ShowOnceAndConfigure:
50410
+ if (dialogLocalState) {
50411
+ const {
50412
+ expiryDate
50413
+ } = JSON.parse(dialogLocalState);
50414
+ const isExpired = new Date() > new Date(expiryDate);
50415
+ setIsHidden(!isExpired);
50416
+ } else {
50417
+ setIsHidden(false);
50418
+ }
50419
+ break;
50420
+ default:
50421
+ setIsHidden(true);
50422
+ }
50423
+ }, [option, days]);
50424
+ const handleConfirmAndHide = () => {
50425
+ const expiryDate = new Date();
50426
+ switch (option) {
50427
+ case showDialogOption.ShowOnceAndConfigure:
50428
+ expiryDate.setDate(expiryDate.getDate() + days);
50429
+ localStorage.setItem('investigationalUseDialog', JSON.stringify({
50430
+ expiryDate
50431
+ }));
50432
+ break;
50433
+ case showDialogOption.AlwaysShowDialog:
50434
+ sessionStorage.setItem('investigationalUseDialog', 'hidden');
50435
+ break;
50436
+ }
50437
+ setIsHidden(true);
50438
+ };
50439
+ if (isHidden) {
50440
+ return null;
50441
+ }
50442
+ return /*#__PURE__*/react.createElement("div", {
50443
+ className: "fixed bottom-2 z-50 flex h-[86px] w-full justify-center"
50444
+ }, /*#__PURE__*/react.createElement("div", {
50445
+ className: "bg-secondary-dark border-primary-dark flex w-[90%] items-center justify-between rounded-lg border-2 pl-[22px] pr-[22px] pt-[10px] pb-[10px] shadow-lg"
50446
+ }, /*#__PURE__*/react.createElement("div", {
50447
+ className: "flex items-center gap-4"
50448
+ }, /*#__PURE__*/react.createElement(Icon/* default */.A, {
50449
+ name: "illustration-investigational-use",
50450
+ className: "h-18 w-18"
50451
+ }), /*#__PURE__*/react.createElement("div", {
50452
+ className: "flex flex-col"
50453
+ }, /*#__PURE__*/react.createElement("div", {
50454
+ className: "text-[19px] text-white"
50455
+ }, "OHIF Viewer is", ' ', /*#__PURE__*/react.createElement("span", {
50456
+ className: "text-primary-light"
50457
+ }, "for investigational use only")), /*#__PURE__*/react.createElement("div", {
50458
+ className: "text-[13px] text-white"
50459
+ }, /*#__PURE__*/react.createElement("span", {
50460
+ className: "text-primary-active cursor-pointer",
50461
+ onClick: () => window.open('https://ohif.org/', '_blank')
50462
+ }, "Learn more about OHIF Viewer")))), /*#__PURE__*/react.createElement(components_Button, {
50463
+ type: type.primary,
50464
+ onClick: handleConfirmAndHide,
50465
+ className: "bg-primary-main"
50466
+ }, "Confirm and Hide")));
50467
+ };
50468
+ InvestigationalUseDialog.propTypes = {
50469
+ dialogConfiguration: prop_types_default().shape({
50470
+ option: prop_types_default().oneOf(Object.values(showDialogOption)).isRequired,
50471
+ days: (prop_types_default()).number
50472
+ }).isRequired
50473
+ };
50474
+ InvestigationalUseDialog.defaultProps = {
50475
+ dialogConfiguration: {
50476
+ option: showDialogOption.AlwaysShowDialog
50477
+ }
50478
+ };
50479
+ /* harmony default export */ const InvestigationalUseDialog_InvestigationalUseDialog = (InvestigationalUseDialog);
50480
+ ;// CONCATENATED MODULE: ../../ui/src/components/InvestigationalUseDialog/index.js
50481
+
50482
+ /* harmony default export */ const components_InvestigationalUseDialog = (InvestigationalUseDialog_InvestigationalUseDialog);
49737
50483
  ;// CONCATENATED MODULE: ../../ui/src/components/index.js
49738
50484
 
49739
50485
 
@@ -49813,6 +50559,10 @@ InputDoubleRange.defaultProps = {
49813
50559
 
49814
50560
 
49815
50561
 
50562
+
50563
+
50564
+
50565
+
49816
50566
 
49817
50567
 
49818
50568
 
@@ -49869,12 +50619,6 @@ ModalComponent.propTypes = {
49869
50619
  };
49870
50620
  /* harmony default export */ const contextProviders_ModalComponent = ((/* unused pure expression or super */ null && (ModalComponent)));
49871
50621
  ;// CONCATENATED MODULE: ../../ui/src/index.js
49872
- /** UTILS */
49873
- //import utils from './utils';
49874
- //export { utils };
49875
-
49876
- /** CONTEXT/HOOKS */
49877
- // Export types - need to do as two lines due to a bug in babel
49878
50622
 
49879
50623
 
49880
50624
 
@@ -50031,7 +50775,7 @@ function _getImageOrientationPatient(image) {
50031
50775
 
50032
50776
  /***/ }),
50033
50777
 
50034
- /***/ 14283:
50778
+ /***/ 78198:
50035
50779
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
50036
50780
 
50037
50781
  "use strict";
@@ -50057,7 +50801,7 @@ __webpack_require__.d(__webpack_exports__, {
50057
50801
  Rc: () => (/* reexport */ pubSubServiceInterface/* PubSubService */.R),
50058
50802
  CS: () => (/* reexport */ ServicesManager),
50059
50803
  wb: () => (/* reexport */ services_StateSyncService),
50060
- hx: () => (/* reexport */ ToolBarService),
50804
+ ToolbarService: () => (/* reexport */ ToolBarService),
50061
50805
  u$: () => (/* reexport */ UIDialogService),
50062
50806
  zo: () => (/* reexport */ services_UIModalService),
50063
50807
  v4: () => (/* reexport */ services_UINotificationService),
@@ -50071,6 +50815,7 @@ __webpack_require__.d(__webpack_exports__, {
50071
50815
  ot: () => (/* binding */ hotkeys),
50072
50816
  Rm: () => (/* reexport */ src_log),
50073
50817
  Ml: () => (/* reexport */ pubSubServiceInterface/* default */.A),
50818
+ tR: () => (/* reexport */ useToolbar),
50074
50819
  utils: () => (/* reexport */ utils/* default */.Ay)
50075
50820
  });
50076
50821
 
@@ -50212,7 +50957,7 @@ class MeasurementService extends pubSubServiceInterface/* PubSubService */.R {
50212
50957
  super(EVENTS);
50213
50958
  this.VALUE_TYPES = VALUE_TYPES;
50214
50959
  this.measurements = new Map();
50215
- this.unmappedMeasurements = new Set();
50960
+ this.unmappedMeasurements = new Map();
50216
50961
  /**
50217
50962
  * Check if a given measurement service event is valid.
50218
50963
  *
@@ -50554,7 +51299,15 @@ class MeasurementService extends pubSubServiceInterface/* PubSubService */.R {
50554
51299
  measurement = toMeasurementSchema(sourceAnnotationDetail);
50555
51300
  measurement.source = source;
50556
51301
  } catch (error) {
50557
- this.unmappedMeasurements.add(sourceAnnotationDetail.uid);
51302
+ // Todo: handle other
51303
+ this.unmappedMeasurements.set(sourceAnnotationDetail.uid, {
51304
+ ...sourceAnnotationDetail,
51305
+ source: {
51306
+ name: source.name,
51307
+ version: source.version,
51308
+ uid: source.uid
51309
+ }
51310
+ });
50558
51311
  console.log('Failed to map', error);
50559
51312
  throw new Error(`Failed to map '${sourceInfo}' measurement for annotationType ${annotationType}: ${error.message}`);
50560
51313
  }
@@ -50619,10 +51372,9 @@ class MeasurementService extends pubSubServiceInterface/* PubSubService */.R {
50619
51372
  });
50620
51373
  }
50621
51374
  clearMeasurements() {
50622
- this.unmappedMeasurements.clear();
50623
-
50624
51375
  // Make a copy of the measurements
50625
- const measurements = [...this.measurements.values()];
51376
+ const measurements = [...this.measurements.values(), ...this.unmappedMeasurements.values()];
51377
+ this.unmappedMeasurements.clear();
50626
51378
  this.measurements.clear();
50627
51379
  this._broadcastEvent(this.EVENTS.MEASUREMENTS_CLEARED, {
50628
51380
  measurements
@@ -50771,10 +51523,16 @@ MeasurementService.VALUE_TYPES = VALUE_TYPES;
50771
51523
  class ServicesManager {
50772
51524
  constructor(commandsManager) {
50773
51525
  this.services = {};
51526
+ this.registeredServiceNames = [];
51527
+ this._commandsManager = void 0;
51528
+ this._extensionManager = void 0;
50774
51529
  this._commandsManager = commandsManager;
50775
51530
  this.services = {};
50776
51531
  this.registeredServiceNames = [];
50777
51532
  }
51533
+ setExtensionManager(extensionManager) {
51534
+ this._extensionManager = extensionManager;
51535
+ }
50778
51536
 
50779
51537
  /**
50780
51538
  * Registers a new service.
@@ -50799,7 +51557,8 @@ class ServicesManager {
50799
51557
  this.services[service.name] = service.create({
50800
51558
  configuration,
50801
51559
  commandsManager: this._commandsManager,
50802
- servicesManager: this
51560
+ servicesManager: this,
51561
+ extensionManager: this._extensionManager
50803
51562
  });
50804
51563
  if (service.altName) {
50805
51564
  console.log('Registering old name', service.altName);
@@ -51672,76 +52431,154 @@ class DisplaySetMessageList {
51672
52431
 
51673
52432
  /* harmony default export */ const services_DisplaySetService = (DisplaySetService);
51674
52433
 
51675
- // EXTERNAL MODULE: ../../../node_modules/lodash.merge/index.js
51676
- var lodash_merge = __webpack_require__(40592);
51677
- var lodash_merge_default = /*#__PURE__*/__webpack_require__.n(lodash_merge);
51678
52434
  ;// CONCATENATED MODULE: ../../core/src/services/ToolBarService/ToolbarService.ts
51679
52435
  var ToolbarService_class;
51680
52436
 
51681
-
51682
52437
  const ToolbarService_EVENTS = {
51683
52438
  TOOL_BAR_MODIFIED: 'event::toolBarService:toolBarModified',
51684
52439
  TOOL_BAR_STATE_MODIFIED: 'event::toolBarService:toolBarStateModified'
51685
52440
  };
51686
52441
  class ToolbarService extends pubSubServiceInterface/* PubSubService */.R {
51687
- static _createButton(type, id, icon, label, commands, tooltip, extraOptions) {
51688
- return {
52442
+ static createButton(options) {
52443
+ const {
51689
52444
  id,
51690
52445
  icon,
51691
52446
  label,
51692
- type,
51693
52447
  commands,
51694
52448
  tooltip,
51695
- ...extraOptions
52449
+ evaluate,
52450
+ listeners
52451
+ } = options;
52452
+ return {
52453
+ id,
52454
+ icon,
52455
+ label,
52456
+ commands,
52457
+ tooltip: tooltip || label,
52458
+ evaluate,
52459
+ listeners
51696
52460
  };
51697
52461
  }
51698
- constructor(commandsManager) {
52462
+ constructor(commandsManager, extensionManager, servicesManager) {
51699
52463
  super(ToolbarService_EVENTS);
51700
- this.buttons = {};
51701
52464
  this.state = {
51702
- primaryToolId: '',
51703
- toggles: {},
51704
- groups: {}
51705
- };
51706
- this.buttonSections = {
51707
- /**
51708
- * primary: ['Zoom', 'Wwwc'],
51709
- * secondary: ['Length', 'RectangleRoi']
51710
- */
52465
+ buttons: {},
52466
+ buttonSections: {}
51711
52467
  };
51712
52468
  this._commandsManager = void 0;
51713
- this.extensionManager = void 0;
51714
- this.defaultTool = void 0;
52469
+ this._extensionManager = void 0;
52470
+ this._servicesManager = void 0;
52471
+ this._evaluateFunction = {};
52472
+ this._serviceSubscriptions = [];
52473
+ this.handleEvaluateNested = props => {
52474
+ const {
52475
+ primary,
52476
+ items
52477
+ } = props;
52478
+ // handle group evaluate function
52479
+ this.handleEvaluate(props);
52480
+
52481
+ // primary and items evaluate functions
52482
+ if (primary) {
52483
+ this.handleEvaluate(primary);
52484
+ }
52485
+ items.forEach(item => this.handleEvaluate(item));
52486
+ };
52487
+ this.handleEvaluate = props => {
52488
+ const {
52489
+ evaluate
52490
+ } = props;
52491
+ if (typeof evaluate === 'function') {
52492
+ return;
52493
+ }
52494
+ if (typeof evaluate === 'string') {
52495
+ const evaluateFunction = this._evaluateFunction[evaluate];
52496
+ if (evaluateFunction) {
52497
+ props.evaluate = evaluateFunction;
52498
+ return;
52499
+ }
52500
+ throw new Error(`Evaluate function not found for name: ${evaluate}, you can register an evaluate function with the getToolbarModule in your extensions`);
52501
+ }
52502
+ if (typeof evaluate === 'object') {
52503
+ const {
52504
+ name,
52505
+ options
52506
+ } = evaluate;
52507
+ const evaluateFunction = this._evaluateFunction[name];
52508
+ if (evaluateFunction) {
52509
+ props.evaluate = args => evaluateFunction({
52510
+ ...args,
52511
+ ...options
52512
+ });
52513
+ return;
52514
+ }
52515
+ throw new Error(`Evaluate function not found for name: ${name}, you can register an evaluate function with the getToolbarModule in your extensions`);
52516
+ }
52517
+ };
51715
52518
  this._commandsManager = commandsManager;
51716
- }
51717
- init(extensionManager) {
51718
- this.extensionManager = extensionManager;
52519
+ this._extensionManager = extensionManager;
52520
+ this._servicesManager = servicesManager;
51719
52521
  }
51720
52522
  reset() {
51721
52523
  this.unsubscriptions.forEach(unsub => unsub());
51722
52524
  this.state = {
51723
- primaryToolId: 'WindowLevel',
51724
- toggles: {},
51725
- groups: {}
52525
+ buttons: {},
52526
+ buttonSections: {}
51726
52527
  };
51727
52528
  this.unsubscriptions = [];
51728
- this.buttonSections = {};
51729
- this.buttons = {};
51730
52529
  }
51731
52530
  onModeEnter() {
51732
52531
  this.reset();
51733
52532
  }
51734
52533
 
51735
52534
  /**
51736
- * Sets the default tool that will be activated whenever the primary tool is
51737
- * deactivated without activating another/different tool.
51738
- * @param interaction the interaction command that will set the default tool active
52535
+ * Registers an evaluate function with the specified name.
52536
+ *
52537
+ * @param name - The name of the evaluate function.
52538
+ * @param handler - The evaluate function handler.
51739
52539
  */
51740
- setDefaultTool(interaction) {
51741
- this.defaultTool = interaction;
52540
+ registerEvaluateFunction(name, handler) {
52541
+ this._evaluateFunction[name] = handler;
51742
52542
  }
51743
- getDefaultTool() {
51744
- return this.defaultTool;
52543
+
52544
+ /**
52545
+ * Registers a service and its event to listen for updates and refreshes the toolbar state when the event is triggered.
52546
+ * @param service - The service to register.
52547
+ * @param event - The event to listen for.
52548
+ */
52549
+ registerEventForToolbarUpdate(service, events) {
52550
+ const {
52551
+ viewportGridService
52552
+ } = this._servicesManager.services;
52553
+ const callback = () => {
52554
+ const viewportId = viewportGridService.getActiveViewportId();
52555
+ this.refreshToolbarState({
52556
+ viewportId
52557
+ });
52558
+ };
52559
+ const unsubscriptions = events.map(event => {
52560
+ if (service.subscribe) {
52561
+ return service.subscribe(event, callback);
52562
+ } else if (service.addEventListener) {
52563
+ return service.addEventListener(event, callback);
52564
+ }
52565
+ });
52566
+ unsubscriptions.forEach(unsub => this._serviceSubscriptions.push(unsub));
52567
+ }
52568
+
52569
+ /**
52570
+ * Adds buttons to the toolbar.
52571
+ * @param buttons - The buttons to be added.
52572
+ */
52573
+ addButtons(buttons) {
52574
+ buttons.forEach(button => {
52575
+ if (!this.state.buttons[button.id]) {
52576
+ this.state.buttons[button.id] = button;
52577
+ }
52578
+ });
52579
+ this._broadcastEvent(this.EVENTS.TOOL_BAR_MODIFIED, {
52580
+ ...this.state
52581
+ });
51745
52582
  }
51746
52583
 
51747
52584
  /**
@@ -51752,162 +52589,182 @@ class ToolbarService extends pubSubServiceInterface/* PubSubService */.R {
51752
52589
  * called with {...commandOptions,...options}
51753
52590
  */
51754
52591
  recordInteraction(interaction, options) {
51755
- if (!interaction) {
51756
- return;
51757
- }
51758
- const commandsManager = this._commandsManager;
51759
- const {
51760
- groupId,
51761
- itemId,
51762
- commands,
51763
- type
51764
- } = interaction;
51765
- let {
51766
- interactionType
51767
- } = interaction;
51768
-
51769
- // if not interaction type, assume the type can be used
51770
- if (!interactionType) {
51771
- interactionType = type;
51772
- }
51773
- switch (interactionType) {
51774
- case 'action':
51775
- {
51776
- commandsManager.run(commands, options);
51777
- break;
51778
- }
51779
- case 'tool':
51780
- {
51781
- try {
51782
- const alternateInteraction = this.state.primaryToolId === itemId && this.defaultTool?.itemId !== itemId && this.getDefaultTool();
51783
- if (alternateInteraction) {
51784
- // Allow toggling the mode off
51785
- return this.recordInteraction(alternateInteraction, options);
51786
- }
51787
- commandsManager.run(commands, options);
51788
-
51789
- // only set the primary tool if no error was thrown.
51790
- // if the itemId is not undefined use it; otherwise, set the first tool in
51791
- // the commands as the primary tool
51792
- this.state.primaryToolId = itemId || commands[0].commandOptions?.toolName;
51793
- } catch (error) {
51794
- console.warn(error);
51795
- }
51796
- break;
51797
- }
51798
- case 'toggle':
51799
- {
51800
- const {
51801
- commands
51802
- } = interaction;
51803
- let commandExecuted;
51804
-
51805
- // only toggle if a command was executed
51806
- this.state.toggles[itemId] = this.state.toggles[itemId] === undefined ? true : !this.state.toggles[itemId];
51807
- if (!commands) {
51808
- break;
51809
- }
51810
- commands.forEach(({
51811
- commandName,
51812
- commandOptions,
51813
- context
51814
- }) => {
51815
- if (!commandOptions) {
51816
- commandOptions = {};
51817
- }
51818
- if (commandName) {
51819
- commandOptions.toggledState = this.state.toggles[itemId];
51820
- try {
51821
- commandsManager.runCommand(commandName, commandOptions, context);
51822
- commandExecuted = true;
51823
- } catch (error) {
51824
- console.warn(error);
51825
- }
51826
- }
51827
- });
51828
- if (!commandExecuted) {
51829
- // If no command was executed, we need to toggle the state back
51830
- this.state.toggles[itemId] = !this.state.toggles[itemId];
51831
- }
51832
- break;
51833
- }
51834
- default:
51835
- throw new Error(`Invalid interaction type: ${interactionType}`);
51836
- }
51837
-
51838
- // Todo: comment out for now
51839
- // Run command if there's one associated
51840
- //
51841
- // NOTE: Should probably just do this for tools as well?
51842
- // But would be nice if we could enforce at least the command name?
51843
- // let unsubscribe;
51844
- // if (commandName) {
51845
- // unsubscribe = commandsManager.runCommand(commandName, commandOptions);
51846
- // }
51847
-
51848
- // // Storing the unsubscribe for later resetting
51849
- // if (unsubscribe && typeof unsubscribe === 'function') {
51850
- // if (this.unsubscriptions.indexOf(unsubscribe) === -1) {
51851
- // this.unsubscriptions.push(unsubscribe);
51852
- // }
51853
- // }
52592
+ // if interaction is a string, we can assume it is the itemId
52593
+ // and get the props to get the other properties
52594
+ if (typeof interaction === 'string') {
52595
+ interaction = this.getButtonProps(interaction);
52596
+ }
52597
+ const itemId = interaction.itemId ?? interaction.id;
52598
+ interaction.itemId = itemId;
52599
+ const commands = Array.isArray(interaction.commands) ? interaction.commands : [interaction.commands];
52600
+ if (!commands?.length) {
52601
+ this.refreshToolbarState({
52602
+ ...options?.refreshProps,
52603
+ itemId,
52604
+ interaction
52605
+ });
52606
+ }
52607
+ const commandOptions = {
52608
+ ...options,
52609
+ ...interaction
52610
+ };
51854
52611
 
51855
- // Track last touched id for each group
51856
- if (groupId) {
51857
- this.state.groups[groupId] = itemId;
51858
- }
51859
- this._broadcastEvent(this.EVENTS.TOOL_BAR_STATE_MODIFIED, {
51860
- ...this.state
52612
+ // Loop through commands and run them with the combined options
52613
+ this._commandsManager.run(commands, commandOptions);
52614
+ this.refreshToolbarState({
52615
+ ...options?.refreshProps,
52616
+ itemId,
52617
+ interaction
51861
52618
  });
51862
52619
  }
51863
- getButtons() {
51864
- return this.buttons;
51865
- }
51866
- getActiveTools() {
51867
- const activeTools = [this.state.primaryToolId];
51868
- Object.keys(this.state.toggles).forEach(key => {
51869
- if (this.state.toggles[key]) {
51870
- activeTools.push(key);
52620
+
52621
+ /**
52622
+ * Consolidates the state of the toolbar after an interaction, it accepts
52623
+ * props that get passed to the buttons
52624
+ *
52625
+ * @param refreshProps - The props that buttons need to get evaluated, they can be
52626
+ * { viewportId, toolGroup} for cornerstoneTools.
52627
+ *
52628
+ * Todo: right now refreshToolbarState should be used in the context where
52629
+ * we have access to the toolGroup and viewportId, but we should be able to
52630
+ * pass the props to the toolbar service and it should be able to decide
52631
+ * which buttons to evaluate based on the props
52632
+ */
52633
+ refreshToolbarState(refreshProps) {
52634
+ const buttons = this.state.buttons;
52635
+
52636
+ // Tracks evaluated buttons to avoid re-evaluating them (this will
52637
+ // cause issue for toggles where if the button is in primary
52638
+ // and secondary it will be evaluated twice)
52639
+ const evaluationResults = new Map();
52640
+ const evaluateButtonProps = (button, props, refreshProps) => {
52641
+ if (evaluationResults.has(button.id)) {
52642
+ const {
52643
+ disabled,
52644
+ className,
52645
+ isActive
52646
+ } = evaluationResults.get(button.id);
52647
+ return {
52648
+ ...props,
52649
+ disabled,
52650
+ className,
52651
+ isActive
52652
+ };
52653
+ } else {
52654
+ const evaluated = props.evaluate?.({
52655
+ ...refreshProps,
52656
+ button
52657
+ });
52658
+ const updatedProps = {
52659
+ ...props,
52660
+ disabled: evaluated?.disabled || false,
52661
+ className: evaluated?.className || '',
52662
+ isActive: evaluated?.isActive // isActive will be undefined for buttons without this prop
52663
+ };
52664
+ evaluationResults.set(button.id, updatedProps);
52665
+ return updatedProps;
52666
+ }
52667
+ };
52668
+ const refreshedButtons = Object.values(buttons).reduce((acc, button) => {
52669
+ const isNested = button.props?.groupId;
52670
+ if (!isNested) {
52671
+ this.handleEvaluate(button.props);
52672
+ const buttonProps = button.props;
52673
+ const updatedProps = evaluateButtonProps(button, buttonProps, refreshProps);
52674
+ acc[button.id] = {
52675
+ ...button,
52676
+ props: updatedProps
52677
+ };
52678
+ } else {
52679
+ let buttonProps = button.props;
52680
+ // if it is nested we should perform evaluate on each item in the group
52681
+ this.handleEvaluateNested(buttonProps);
52682
+ const {
52683
+ evaluate: groupEvaluate
52684
+ } = buttonProps;
52685
+ const groupEvaluated = groupEvaluate?.({
52686
+ ...refreshProps,
52687
+ button
52688
+ });
52689
+ // handle group evaluate function which might switch the primary
52690
+ // item in the group
52691
+ buttonProps = {
52692
+ ...buttonProps,
52693
+ primary: groupEvaluated?.primary || buttonProps.primary
52694
+ };
52695
+ const {
52696
+ primary,
52697
+ items
52698
+ } = buttonProps;
52699
+
52700
+ // primary and items evaluate functions
52701
+ let updatedPrimary;
52702
+ if (primary) {
52703
+ updatedPrimary = evaluateButtonProps(primary, primary, refreshProps);
52704
+ }
52705
+ const updatedItems = items.map(item => evaluateButtonProps(item, item, refreshProps));
52706
+ buttonProps = {
52707
+ ...buttonProps,
52708
+ primary: updatedPrimary,
52709
+ items: updatedItems
52710
+ };
52711
+ acc[button.id] = {
52712
+ ...button,
52713
+ props: buttonProps
52714
+ };
51871
52715
  }
51872
- });
51873
- return activeTools;
51874
- }
51875
- getActivePrimaryTool() {
51876
- return this.state.primaryToolId;
52716
+ return acc;
52717
+ }, {});
52718
+ this.setButtons(refreshedButtons);
52719
+ return this.state;
51877
52720
  }
51878
52721
 
51879
- /** Sets the toggle state of a button to the isToggled state */
51880
- setToggled(id, isToggled) {
51881
- if (isToggled) {
51882
- this.state.toggles[id] = true;
51883
- } else {
51884
- delete this.state.toggles[id];
51885
- }
51886
- }
51887
- setButton(id, button) {
51888
- if (this.buttons[id]) {
51889
- this.buttons[id] = lodash_merge_default()(this.buttons[id], button);
51890
- this._broadcastEvent(this.EVENTS.TOOL_BAR_MODIFIED, {
51891
- buttons: this.buttons,
51892
- button: this.buttons[id],
51893
- buttonSections: this.buttonSections
51894
- });
51895
- }
52722
+ /**
52723
+ * Sets the buttons for the toolbar, don't use this method to record an
52724
+ * interaction, since it doesn't update the state of the buttons, use
52725
+ * this if you know the buttons you want to set and you want to set them
52726
+ * all at once.
52727
+ * @param buttons - The buttons to set.
52728
+ */
52729
+ setButtons(buttons) {
52730
+ this.state.buttons = buttons;
52731
+ this._broadcastEvent(this.EVENTS.TOOL_BAR_MODIFIED, {
52732
+ buttons: this.state.buttons,
52733
+ buttonSections: this.state.buttonSections
52734
+ });
51896
52735
  }
52736
+
52737
+ /**
52738
+ * Retrieves a button by its ID.
52739
+ * @param id - The ID of the button to retrieve.
52740
+ * @returns The button with the specified ID.
52741
+ */
51897
52742
  getButton(id) {
51898
- return this.buttons[id];
52743
+ return this.state.buttons[id];
51899
52744
  }
51900
52745
 
51901
- /** Gets a nested button, found in the items/props for the children */
51902
- getNestedButton(id) {
51903
- if (this.buttons[id]) {
51904
- return this.buttons[id];
51905
- }
51906
- for (const buttonId of Object.keys(this.buttons)) {
52746
+ /**
52747
+ * Retrieves the buttons from the toolbar service.
52748
+ * @returns An array of buttons.
52749
+ */
52750
+ getButtons() {
52751
+ return this.state.buttons;
52752
+ }
52753
+
52754
+ /**
52755
+ * Retrieves the button properties for the specified button ID.
52756
+ * It prioritizes nested buttons over regular buttons if the ID is found
52757
+ * in both.
52758
+ *
52759
+ * @param id - The ID of the button.
52760
+ * @returns The button properties.
52761
+ */
52762
+ getButtonProps(id) {
52763
+ for (const buttonId of Object.keys(this.state.buttons)) {
51907
52764
  const {
51908
52765
  primary,
51909
52766
  items
51910
- } = this.buttons[buttonId].props || {};
52767
+ } = this.state.buttons[buttonId].props || {};
51911
52768
  if (primary?.id === id) {
51912
52769
  return primary;
51913
52770
  }
@@ -51916,79 +52773,52 @@ class ToolbarService extends pubSubServiceInterface/* PubSubService */.R {
51916
52773
  return found;
51917
52774
  }
51918
52775
  }
51919
- }
51920
- setButtons(buttons) {
51921
- this.buttons = buttons;
51922
- this._broadcastEvent(this.EVENTS.TOOL_BAR_MODIFIED, {
51923
- buttons: this.buttons,
51924
- buttonSections: this.buttonSections
51925
- });
51926
- }
51927
- _buttonTypes() {
51928
- const buttonTypes = {};
51929
- const registeredToolbarModules = this.extensionManager.modules['toolbarModule'];
51930
- if (Array.isArray(registeredToolbarModules) && registeredToolbarModules.length) {
51931
- registeredToolbarModules.forEach(toolbarModule => toolbarModule.module.forEach(def => {
51932
- buttonTypes[def.name] = def;
51933
- }));
52776
+
52777
+ // This should be checked after we checked the nested buttons, since
52778
+ // we are checking based on the ids, the nested objects are higher priority
52779
+ // and more specific
52780
+ if (this.state.buttons[id]) {
52781
+ return this.state.buttons[id].props;
51934
52782
  }
51935
- return buttonTypes;
51936
52783
  }
51937
- createButtonSection(key, buttons) {
51938
- // Maybe do this mapping at time of return, instead of time of create
51939
- // Props check important for validation here...
51940
-
51941
- this.buttonSections[key] = buttons;
51942
- this._broadcastEvent(this.EVENTS.TOOL_BAR_MODIFIED, {});
52784
+ _getButtonUITypes() {
52785
+ const registeredToolbarModules = this._extensionManager.modules['toolbarModule'];
52786
+ if (!Array.isArray(registeredToolbarModules)) {
52787
+ return {};
52788
+ }
52789
+ return registeredToolbarModules.reduce((buttonTypes, toolbarModule) => {
52790
+ toolbarModule.module.forEach(def => {
52791
+ buttonTypes[def.name] = def;
52792
+ });
52793
+ return buttonTypes;
52794
+ }, {});
51943
52795
  }
51944
52796
 
51945
52797
  /**
51946
- *
51947
- * Finds a button section by it's name/tool group id, then maps the list of string name
51948
- * identifiers to schema/values that can be used to render the buttons.
51949
- *
51950
- * @param toolGroupId - the tool group id
51951
- * @param props - optional properties to apply to every button of the section
51952
- * @param defaultToolGroupId - the fallback section to return if the given toolGroupId section is not available
52798
+ * Creates a button section with the specified key and buttons.
52799
+ * @param {string} key - The key of the button section.
52800
+ * @param {Array} buttons - The buttons to be added to the section.
51953
52801
  */
51954
- getButtonSection(toolGroupId, props, defaultToolGroupId = 'primary') {
51955
- const buttonSectionIds = this.buttonSections[toolGroupId] || this.buttonSections[defaultToolGroupId];
51956
- const buttonsInSection = [];
51957
- if (buttonSectionIds && buttonSectionIds.length !== 0) {
51958
- buttonSectionIds.forEach(btnId => {
51959
- const btn = this.buttons[btnId];
51960
- const metadata = {};
51961
- const mappedBtn = this._mapButtonToDisplay(btn, toolGroupId, metadata, props);
51962
- buttonsInSection.push(mappedBtn);
51963
- });
51964
- }
51965
- return buttonsInSection;
52802
+ createButtonSection(key, buttons) {
52803
+ this.state.buttonSections[key] = buttons;
52804
+ this._broadcastEvent(this.EVENTS.TOOL_BAR_MODIFIED, {
52805
+ ...this.state
52806
+ });
51966
52807
  }
51967
52808
 
51968
52809
  /**
52810
+ * Retrieves the button section with the specified sectionId.
51969
52811
  *
51970
- * @param {object[]} buttons
51971
- * @param {string} buttons[].id
52812
+ * @param sectionId - The ID of the button section to retrieve.
52813
+ * @param props - Optional additional properties for mapping the button to display.
52814
+ * @returns An array of buttons in the specified section, mapped to their display representation.
51972
52815
  */
51973
- addButtons(buttons) {
51974
- buttons.forEach(button => {
51975
- if (!this.buttons[button.id]) {
51976
- this.buttons[button.id] = button;
51977
- }
51978
- });
51979
- this._setTogglesForButtonItems(buttons);
51980
- this._broadcastEvent(this.EVENTS.TOOL_BAR_MODIFIED, {});
51981
- }
51982
- _setTogglesForButtonItems(buttons) {
51983
- if (!buttons) {
51984
- return;
51985
- }
51986
- buttons.forEach(buttonItem => {
51987
- if (buttonItem.type === 'toggle') {
51988
- this.setToggled(buttonItem.id, buttonItem.isActive);
51989
- }
51990
- this._setTogglesForButtonItems(buttonItem.props?.items);
51991
- });
52816
+ getButtonSection(sectionId, props) {
52817
+ const buttonSectionIds = this.state.buttonSections[sectionId];
52818
+ return buttonSectionIds?.map(btnId => {
52819
+ const btn = this.state.buttons[btnId];
52820
+ return this._mapButtonToDisplay(btn, props);
52821
+ }) || [];
51992
52822
  }
51993
52823
 
51994
52824
  /**
@@ -51998,19 +52828,23 @@ class ToolbarService extends pubSubServiceInterface/* PubSubService */.R {
51998
52828
  * @param {*} metadata
51999
52829
  * @param {*} props - Props set by the Viewer layer
52000
52830
  */
52001
- _mapButtonToDisplay(btn, btnSection, metadata, props) {
52831
+ _mapButtonToDisplay(btn, props) {
52002
52832
  if (!btn) {
52003
52833
  return;
52004
52834
  }
52005
52835
  const {
52006
52836
  id,
52007
- type,
52837
+ uiType,
52008
52838
  component
52009
52839
  } = btn;
52010
- const buttonType = this._buttonTypes()[type];
52840
+ const {
52841
+ groupId
52842
+ } = btn.props;
52843
+ const buttonType = this._getButtonUITypes()[uiType];
52011
52844
  if (!buttonType) {
52012
52845
  return;
52013
52846
  }
52847
+ !groupId ? this.handleEvaluate(btn.props) : this.handleEvaluateNested(btn.props);
52014
52848
  return {
52015
52849
  id,
52016
52850
  Component: component || buttonType.defaultComponent,
@@ -52018,23 +52852,21 @@ class ToolbarService extends pubSubServiceInterface/* PubSubService */.R {
52018
52852
  };
52019
52853
  }
52020
52854
  getButtonComponentForUIType(uiType) {
52021
- return uiType ? this._buttonTypes()[uiType]?.defaultComponent ?? null : null;
52855
+ return uiType ? this._getButtonUITypes()[uiType]?.defaultComponent ?? null : null;
52022
52856
  }
52023
52857
  }
52024
52858
  ToolbarService_class = ToolbarService;
52025
52859
  ToolbarService.REGISTRATION = {
52026
52860
  name: 'toolbarService',
52027
- // Note the old name is ToolBarService, with an upper B
52028
52861
  altName: 'ToolBarService',
52029
52862
  create: ({
52030
- commandsManager
52863
+ commandsManager,
52864
+ extensionManager,
52865
+ servicesManager
52031
52866
  }) => {
52032
- return new ToolbarService_class(commandsManager);
52867
+ return new ToolbarService_class(commandsManager, extensionManager, servicesManager);
52033
52868
  }
52034
52869
  };
52035
- ToolbarService._createActionButton = ToolbarService_class._createButton.bind(null, 'action');
52036
- ToolbarService._createToggleButton = ToolbarService_class._createButton.bind(null, 'toggle');
52037
- ToolbarService._createToolButton = ToolbarService_class._createButton.bind(null, 'tool');
52038
52870
  ;// CONCATENATED MODULE: ../../core/src/services/ToolBarService/index.ts
52039
52871
 
52040
52872
  /* harmony default export */ const ToolBarService = (ToolbarService);
@@ -52192,7 +53024,8 @@ class ViewportGridService extends pubSubServiceInterface/* PubSubService */.R {
52192
53024
  reset: resetImplementation,
52193
53025
  onModeExit: onModeExitImplementation,
52194
53026
  set: setImplementation,
52195
- getNumViewportPanes: getNumViewportPanesImplementation
53027
+ getNumViewportPanes: getNumViewportPanesImplementation,
53028
+ setViewportIsReady: setViewportIsReadyImplementation
52196
53029
  }) {
52197
53030
  if (getStateImplementation) {
52198
53031
  this.serviceImplementation._getState = getStateImplementation;
@@ -52218,6 +53051,12 @@ class ViewportGridService extends pubSubServiceInterface/* PubSubService */.R {
52218
53051
  if (getNumViewportPanesImplementation) {
52219
53052
  this.serviceImplementation._getNumViewportPanes = getNumViewportPanesImplementation;
52220
53053
  }
53054
+ if (setViewportIsReadyImplementation) {
53055
+ this.serviceImplementation._setViewportIsReady = setViewportIsReadyImplementation;
53056
+ }
53057
+ }
53058
+ publishViewportsReady() {
53059
+ this._broadcastEvent(this.EVENTS.VIEWPORTS_READY, {});
52221
53060
  }
52222
53061
  setActiveViewportId(id) {
52223
53062
  this.serviceImplementation._setActiveViewport(id);
@@ -52228,6 +53067,9 @@ class ViewportGridService extends pubSubServiceInterface/* PubSubService */.R {
52228
53067
  getState() {
52229
53068
  return this.serviceImplementation._getState();
52230
53069
  }
53070
+ setViewportIsReady(viewportId, callback) {
53071
+ this.serviceImplementation._setViewportIsReady(viewportId, callback);
53072
+ }
52231
53073
  getActiveViewportId() {
52232
53074
  const state = this.getState();
52233
53075
  return state.activeViewportId;
@@ -52260,6 +53102,17 @@ class ViewportGridService extends pubSubServiceInterface/* PubSubService */.R {
52260
53102
  });
52261
53103
  }
52262
53104
 
53105
+ /**
53106
+ * Retrieves the display set instance UIDs for a given viewport.
53107
+ * @param viewportId The ID of the viewport.
53108
+ * @returns An array of display set instance UIDs.
53109
+ */
53110
+ getDisplaySetsUIDsForViewport(viewportId) {
53111
+ const state = this.getState();
53112
+ const viewport = state.viewports.get(viewportId);
53113
+ return viewport?.displaySetInstanceUIDs;
53114
+ }
53115
+
52263
53116
  /**
52264
53117
  *
52265
53118
  * @param numCols, numRows - the number of columns and rows to apply
@@ -52327,7 +53180,8 @@ ViewportGridService.EVENTS = {
52327
53180
  ACTIVE_VIEWPORT_ID_CHANGED: 'event::activeviewportidchanged',
52328
53181
  LAYOUT_CHANGED: 'event::layoutChanged',
52329
53182
  GRID_STATE_CHANGED: 'event::gridStateChanged',
52330
- GRID_SIZE_CHANGED: 'event::gridSizeChanged'
53183
+ GRID_SIZE_CHANGED: 'event::gridSizeChanged',
53184
+ VIEWPORTS_READY: 'event::viewportsReady'
52331
53185
  };
52332
53186
  ViewportGridService.REGISTRATION = {
52333
53187
  name: 'viewportGridService',
@@ -52344,82 +53198,81 @@ ViewportGridService.getPresentationIds = getPresentationIds;
52344
53198
 
52345
53199
  /* harmony default export */ const services_ViewportGridService = (ViewportGridService_ViewportGridService);
52346
53200
  ;// CONCATENATED MODULE: ../../core/src/services/CineService/CineService.ts
52347
- const CineService_name = 'CineService';
52348
- const CineService_publicAPI = {
52349
- name: CineService_name,
52350
- getState: _getState,
52351
- setCine: _setCine,
52352
- setIsCineEnabled: _setIsCineEnabled,
52353
- playClip: _playClip,
52354
- stopClip: _stopClip,
52355
- onModeExit: _onModeExit,
52356
- setServiceImplementation: CineService_setServiceImplementation
52357
- };
52358
- const CineService_serviceImplementation = {
52359
- _getState: () => console.warn('getState() NOT IMPLEMENTED'),
52360
- _setCine: () => console.warn('setCine() NOT IMPLEMENTED'),
52361
- _playClip: () => console.warn('playClip() NOT IMPLEMENTED'),
52362
- _stopClip: () => console.warn('stopClip() NOT IMPLEMENTED'),
52363
- _setIsCineEnabled: () => console.warn('setIsCineEnabled() NOT IMPLEMENTED')
52364
- };
52365
- function _getState() {
52366
- return CineService_serviceImplementation._getState();
52367
- }
52368
- function _setCine({
52369
- id,
52370
- frameRate,
52371
- isPlaying
52372
- }) {
52373
- return CineService_serviceImplementation._setCine({
53201
+ var CineService_class;
53202
+
53203
+ class CineService extends pubSubServiceInterface/* PubSubService */.R {
53204
+ constructor() {
53205
+ super(CineService.EVENTS);
53206
+ this.serviceImplementation = {};
53207
+ this.serviceImplementation = {};
53208
+ }
53209
+ getState() {
53210
+ return this.serviceImplementation._getState();
53211
+ }
53212
+ setCine({
52374
53213
  id,
52375
53214
  frameRate,
52376
53215
  isPlaying
52377
- });
52378
- }
52379
- function _setIsCineEnabled(isCineEnabled) {
52380
- return CineService_serviceImplementation._setIsCineEnabled(isCineEnabled);
52381
- }
52382
- function _playClip(element, playClipOptions) {
52383
- return CineService_serviceImplementation._playClip(element, playClipOptions);
52384
- }
52385
- function _stopClip(element) {
52386
- return CineService_serviceImplementation._stopClip(element);
52387
- }
52388
- function _onModeExit() {
52389
- _setIsCineEnabled(false);
52390
- }
52391
- function CineService_setServiceImplementation({
52392
- getState: getStateImplementation,
52393
- setCine: setCineImplementation,
52394
- setIsCineEnabled: setIsCineEnabledImplementation,
52395
- playClip: playClipImplementation,
52396
- stopClip: stopClipImplementation
52397
- }) {
52398
- if (getStateImplementation) {
52399
- CineService_serviceImplementation._getState = getStateImplementation;
53216
+ }) {
53217
+ return this.serviceImplementation._setCine({
53218
+ id,
53219
+ frameRate,
53220
+ isPlaying
53221
+ });
52400
53222
  }
52401
- if (setCineImplementation) {
52402
- CineService_serviceImplementation._setCine = setCineImplementation;
53223
+ setIsCineEnabled(isCineEnabled) {
53224
+ this.serviceImplementation._setIsCineEnabled(isCineEnabled);
53225
+ // Todo: for some reason i need to do this setTimeout since the
53226
+ // reducer state does not get updated right away and if we publish the
53227
+ // event and we use the cineService.getState() it will return the old state
53228
+ setTimeout(() => {
53229
+ this._broadcastEvent(this.EVENTS.CINE_STATE_CHANGED, isCineEnabled);
53230
+ }, 0);
52403
53231
  }
52404
- if (setIsCineEnabledImplementation) {
52405
- CineService_serviceImplementation._setIsCineEnabled = setIsCineEnabledImplementation;
53232
+ playClip(element, playClipOptions) {
53233
+ return this.serviceImplementation._playClip(element, playClipOptions);
52406
53234
  }
52407
- if (playClipImplementation) {
52408
- CineService_serviceImplementation._playClip = playClipImplementation;
53235
+ stopClip(element) {
53236
+ return this.serviceImplementation._stopClip(element);
52409
53237
  }
52410
- if (stopClipImplementation) {
52411
- CineService_serviceImplementation._stopClip = stopClipImplementation;
53238
+ _onModeExit() {
53239
+ this.setIsCineEnabled(false);
52412
53240
  }
52413
- }
52414
- const CineService = {
52415
- REGISTRATION: {
52416
- altName: CineService_name,
52417
- name: 'cineService',
52418
- create: ({
52419
- configuration = {}
52420
- }) => {
52421
- return CineService_publicAPI;
53241
+ setServiceImplementation({
53242
+ getState: getStateImplementation,
53243
+ setCine: setCineImplementation,
53244
+ setIsCineEnabled: setIsCineEnabledImplementation,
53245
+ playClip: playClipImplementation,
53246
+ stopClip: stopClipImplementation
53247
+ }) {
53248
+ if (getStateImplementation) {
53249
+ this.serviceImplementation._getState = getStateImplementation;
53250
+ }
53251
+ if (setCineImplementation) {
53252
+ this.serviceImplementation._setCine = setCineImplementation;
53253
+ }
53254
+ if (setIsCineEnabledImplementation) {
53255
+ this.serviceImplementation._setIsCineEnabled = setIsCineEnabledImplementation;
53256
+ }
53257
+ if (playClipImplementation) {
53258
+ this.serviceImplementation._playClip = playClipImplementation;
52422
53259
  }
53260
+ if (stopClipImplementation) {
53261
+ this.serviceImplementation._stopClip = stopClipImplementation;
53262
+ }
53263
+ }
53264
+ }
53265
+ CineService_class = CineService;
53266
+ CineService.EVENTS = {
53267
+ CINE_STATE_CHANGED: 'event::cineStateChanged'
53268
+ };
53269
+ CineService.REGISTRATION = {
53270
+ name: 'cineService',
53271
+ altName: 'CineService',
53272
+ create: ({
53273
+ configuration = {}
53274
+ }) => {
53275
+ return new CineService_class();
52423
53276
  }
52424
53277
  };
52425
53278
  /* harmony default export */ const CineService_CineService = (CineService);
@@ -54648,7 +55501,7 @@ HangingProtocolService.REGISTRATION = {
54648
55501
  const UserAuthenticationService_name = 'userAuthenticationService';
54649
55502
  const UserAuthenticationService_publicAPI = {
54650
55503
  name: UserAuthenticationService_name,
54651
- getState: UserAuthenticationService_getState,
55504
+ getState: _getState,
54652
55505
  setUser: _setUser,
54653
55506
  getUser: _getUser,
54654
55507
  getAuthorizationHeader: _getAuthorizationHeader,
@@ -54668,7 +55521,7 @@ const UserAuthenticationService_serviceImplementation = {
54668
55521
  _reset: () => console.warn('reset() NOT IMPLEMENTED'),
54669
55522
  _set: () => console.warn('set() NOT IMPLEMENTED')
54670
55523
  };
54671
- function UserAuthenticationService_getState() {
55524
+ function _getState() {
54672
55525
  return UserAuthenticationService_serviceImplementation._getState();
54673
55526
  }
54674
55527
  function _setUser(user) {
@@ -54734,6 +55587,9 @@ function UserAuthenticationService_setServiceImplementation({
54734
55587
  ;// CONCATENATED MODULE: ../../core/src/services/UserAuthenticationService/index.js
54735
55588
 
54736
55589
  /* harmony default export */ const services_UserAuthenticationService = (UserAuthenticationService);
55590
+ // EXTERNAL MODULE: ../../../node_modules/lodash.merge/index.js
55591
+ var lodash_merge = __webpack_require__(40592);
55592
+ var lodash_merge_default = /*#__PURE__*/__webpack_require__.n(lodash_merge);
54737
55593
  ;// CONCATENATED MODULE: ../../core/src/services/CustomizationService/CustomizationService.ts
54738
55594
  var CustomizationService_class;
54739
55595
 
@@ -54860,10 +55716,10 @@ class CustomizationService extends pubSubServiceInterface/* PubSubService */.R {
54860
55716
  return this.getModeCustomization(customizationId, defaultValue);
54861
55717
  }
54862
55718
 
54863
- /** Mode customizations are changes to the behaviour of the extensions
55719
+ /** Mode customizations are changes to the behavior of the extensions
54864
55720
  * when running in a given mode. Reset clears mode customizations.
54865
55721
  * Note that global customizations over-ride mode customizations.
54866
- * @param defautlValue to return if no customization specified.
55722
+ * @param defaultValue to return if no customization specified.
54867
55723
  */
54868
55724
  getModeCustomization(customizationId, defaultValue) {
54869
55725
  const customization = this.globalCustomizations[customizationId] ?? this.modeCustomizations[customizationId] ?? defaultValue;
@@ -54992,8 +55848,6 @@ CustomizationService.REGISTRATION = {
54992
55848
  ;// CONCATENATED MODULE: ../../core/src/services/CustomizationService/index.ts
54993
55849
 
54994
55850
  /* harmony default export */ const services_CustomizationService = (CustomizationService);
54995
- // EXTERNAL MODULE: ../../core/src/types/Services.ts
54996
- var Services = __webpack_require__(53857);
54997
55851
  ;// CONCATENATED MODULE: ../../core/src/services/StateSyncService/StateSyncService.ts
54998
55852
  var StateSyncService_class;
54999
55853
 
@@ -55146,7 +56000,6 @@ PanelService.REGISTRATION = {
55146
56000
 
55147
56001
 
55148
56002
 
55149
-
55150
56003
  ;// CONCATENATED MODULE: ../../core/src/extensions/ExtensionManager.ts
55151
56004
 
55152
56005
 
@@ -55183,6 +56036,16 @@ class ExtensionManager extends pubSubServiceInterface/* PubSubService */.R {
55183
56036
  this._commandsManager = void 0;
55184
56037
  this._servicesManager = void 0;
55185
56038
  this._hotkeysManager = void 0;
56039
+ this.modulesMap = void 0;
56040
+ this.modules = void 0;
56041
+ this.registeredExtensionIds = void 0;
56042
+ this.moduleTypeNames = void 0;
56043
+ this._appConfig = void 0;
56044
+ this._extensionLifeCycleHooks = void 0;
56045
+ this.dataSourceMap = void 0;
56046
+ this.dataSourceDefs = void 0;
56047
+ this.defaultDataSourceName = void 0;
56048
+ this.activeDataSource = void 0;
55186
56049
  /**
55187
56050
  * An array of extensions, or an array of arrays that contains extension
55188
56051
  * configuration pairs.
@@ -55257,52 +56120,64 @@ class ExtensionManager extends pubSubServiceInterface/* PubSubService */.R {
55257
56120
  // Register Modules
55258
56121
  this.moduleTypeNames.forEach(moduleType => {
55259
56122
  const extensionModule = this._getExtensionModule(moduleType, extension, extensionId, configuration);
55260
- if (extensionModule) {
55261
- switch (moduleType) {
55262
- case MODULE_TYPES.COMMANDS:
55263
- this._initCommandsModule(extensionModule);
55264
- break;
55265
- case MODULE_TYPES.DATA_SOURCE:
55266
- this._initDataSourcesModule(extensionModule, extensionId, dataSources);
55267
- break;
55268
- case MODULE_TYPES.HANGING_PROTOCOL:
55269
- this._initHangingProtocolsModule(extensionModule, extensionId);
55270
- case MODULE_TYPES.TOOLBAR:
55271
- case MODULE_TYPES.VIEWPORT:
55272
- case MODULE_TYPES.PANEL:
55273
- case MODULE_TYPES.SOP_CLASS_HANDLER:
55274
- case MODULE_TYPES.CONTEXT:
55275
- case MODULE_TYPES.LAYOUT_TEMPLATE:
55276
- case MODULE_TYPES.CUSTOMIZATION:
55277
- case MODULE_TYPES.STATE_SYNC:
55278
- case MODULE_TYPES.UTILITY:
55279
- // Default for most extension points,
55280
- // Just adds each entry ready for consumption by mode.
55281
- extensionModule.forEach(element => {
55282
- if (!element.name) {
55283
- throw new Error(`Extension ID ${extensionId} module ${moduleType} element has no name`);
55284
- }
55285
- const id = `${extensionId}.${moduleType}.${element.name}`;
55286
- element.id = id;
55287
- this.modulesMap[id] = element;
55288
- });
55289
- break;
55290
- default:
55291
- throw new Error(`Module type invalid: ${moduleType}`);
55292
- }
55293
- this.modules[moduleType].push({
55294
- extensionId,
55295
- module: extensionModule
55296
- });
56123
+ if (!extensionModule) {
56124
+ return;
55297
56125
  }
56126
+ switch (moduleType) {
56127
+ case MODULE_TYPES.COMMANDS:
56128
+ this._initCommandsModule(extensionModule);
56129
+ break;
56130
+ case MODULE_TYPES.DATA_SOURCE:
56131
+ this._initDataSourcesModule(extensionModule, extensionId, dataSources);
56132
+ break;
56133
+ case MODULE_TYPES.HANGING_PROTOCOL:
56134
+ this._initHangingProtocolsModule(extensionModule, extensionId);
56135
+ break;
56136
+ case MODULE_TYPES.PANEL:
56137
+ this._initPanelModule(extensionModule, extensionId);
56138
+ break;
56139
+ case MODULE_TYPES.TOOLBAR:
56140
+ this._initToolbarModule(extensionModule, extensionId);
56141
+ break;
56142
+ case MODULE_TYPES.VIEWPORT:
56143
+ case MODULE_TYPES.SOP_CLASS_HANDLER:
56144
+ case MODULE_TYPES.CONTEXT:
56145
+ case MODULE_TYPES.LAYOUT_TEMPLATE:
56146
+ case MODULE_TYPES.CUSTOMIZATION:
56147
+ case MODULE_TYPES.STATE_SYNC:
56148
+ case MODULE_TYPES.UTILITY:
56149
+ this.processExtensionModule(extensionModule, extensionId, moduleType);
56150
+ break;
56151
+ default:
56152
+ throw new Error(`Module type invalid: ${moduleType}`);
56153
+ }
56154
+ this.modules[moduleType].push({
56155
+ extensionId,
56156
+ module: extensionModule
56157
+ });
55298
56158
  });
55299
56159
 
55300
56160
  // Track extension registration
55301
56161
  this.registeredExtensionIds.push(extensionId);
55302
56162
  };
56163
+ /**
56164
+ * Retrieves the module entry associated with the given string entry
56165
+ * @param stringEntry - The string entry to retrieve the module entry for which is
56166
+ * in the format of `${extensionId}.${moduleType}.${moduleName}`
56167
+ * @returns The module entry associated with the given string entry.
56168
+ */
55303
56169
  this.getModuleEntry = stringEntry => {
55304
56170
  return this.modulesMap[stringEntry];
55305
56171
  };
56172
+ /**
56173
+ * Retrieves all modules of a given type for all registered extensions.
56174
+ *
56175
+ * @param moduleType - The type of modules to retrieve.
56176
+ * @returns An array of modules of the specified type.
56177
+ */
56178
+ this.getModulesByType = moduleType => {
56179
+ return this.modules[moduleType];
56180
+ };
55306
56181
  this.getDataSources = dataSourceName => {
55307
56182
  if (dataSourceName === undefined) {
55308
56183
  // Default to the activeDataSource
@@ -55379,6 +56254,21 @@ class ExtensionManager extends pubSubServiceInterface/* PubSubService */.R {
55379
56254
  }
55380
56255
  });
55381
56256
  };
56257
+ this._initPanelModule = (extensionModule, extensionId) => {
56258
+ this.processExtensionModule(extensionModule, extensionId, MODULE_TYPES.PANEL);
56259
+ };
56260
+ this._initToolbarModule = (extensionModule, extensionId) => {
56261
+ // check if the toolbar module has a handler function for evaluation of
56262
+ // the toolbar button state
56263
+ const {
56264
+ toolbarService
56265
+ } = this._servicesManager.services;
56266
+ extensionModule.forEach(toolbarButton => {
56267
+ if (toolbarButton.evaluate) {
56268
+ toolbarService.registerEvaluateFunction(toolbarButton.name, toolbarButton.evaluate);
56269
+ }
56270
+ });
56271
+ };
55382
56272
  /**
55383
56273
  *
55384
56274
  * @private
@@ -55494,6 +56384,23 @@ class ExtensionManager extends pubSubServiceInterface/* PubSubService */.R {
55494
56384
  }
55495
56385
  }
55496
56386
  }
56387
+ /**
56388
+ * Processes an extension module.
56389
+ * @param extensionModule - The extension module to process.
56390
+ * @param extensionId - The ID of the extension.
56391
+ * @param moduleType - The type of the module.
56392
+ */
56393
+ processExtensionModule(extensionModule, extensionId, moduleType) {
56394
+ extensionModule.forEach(element => {
56395
+ if (!element.name) {
56396
+ throw new Error(`Extension ID ${extensionId} module ${moduleType} element has no name`);
56397
+ }
56398
+ const id = `${extensionId}.${moduleType}.${element.name}`;
56399
+ element.id = id;
56400
+ this.modulesMap[id] = element;
56401
+ });
56402
+ }
56403
+
55497
56404
  /**
55498
56405
  * Adds the given data source and optionally sets it as the active data source.
55499
56406
  * The method does this by first creating the data source.
@@ -55573,6 +56480,7 @@ class ExtensionManager extends pubSubServiceInterface/* PubSubService */.R {
55573
56480
  ExtensionManager.EVENTS = {
55574
56481
  ACTIVE_DATA_SOURCE_CHANGED: 'event::activedatasourcechanged'
55575
56482
  };
56483
+ ExtensionManager.MODULE_TYPES = MODULE_TYPES;
55576
56484
  function _capitalizeFirstCharacter(lower) {
55577
56485
  return lower.charAt(0).toUpperCase() + lower.substring(1);
55578
56486
  }
@@ -55739,7 +56647,10 @@ class CommandsManager {
55739
56647
  * Run one or more commands with specified extra options.
55740
56648
  * Returns the result of the last command run.
55741
56649
  *
55742
- * @param toRun - A specification of one or more commands
56650
+ * @param toRun - A specification of one or more commands,
56651
+ * typically an object of { commandName, commandOptions, context }
56652
+ * or an array of such objects. It can also be a single commandName as string
56653
+ * if no options are needed.
55743
56654
  * @param options - to include in the commands run beyond
55744
56655
  * the commandOptions specified in the base.
55745
56656
  */
@@ -55747,11 +56658,33 @@ class CommandsManager {
55747
56658
  if (!toRun) {
55748
56659
  return;
55749
56660
  }
55750
- const commands = Array.isArray(toRun) && toRun || toRun.commandName && [toRun] || Array.isArray(toRun.commands) && toRun.commands;
55751
- if (!commands) {
56661
+
56662
+ // Normalize `toRun` to an array of `ComplexCommand`
56663
+ let commands = [];
56664
+ if (typeof toRun === 'string') {
56665
+ commands = [{
56666
+ commandName: toRun
56667
+ }];
56668
+ } else if ('commandName' in toRun) {
56669
+ commands = [toRun];
56670
+ } else if ('commands' in toRun) {
56671
+ const commandsInput = toRun.commands;
56672
+ commands = Array.isArray(commandsInput) ? commandsInput.map(cmd => typeof cmd === 'string' ? {
56673
+ commandName: cmd
56674
+ } : cmd) : [{
56675
+ commandName: commandsInput
56676
+ }];
56677
+ } else if (Array.isArray(toRun)) {
56678
+ commands = toRun.map(cmd => typeof cmd === 'string' ? {
56679
+ commandName: cmd
56680
+ } : cmd);
56681
+ }
56682
+ if (commands.length === 0) {
55752
56683
  console.log("Command isn't runnable", toRun);
55753
56684
  return;
55754
56685
  }
56686
+
56687
+ // Execute each command in the array
55755
56688
  let result;
55756
56689
  commands.forEach(({
55757
56690
  commandName,
@@ -56055,13 +56988,6 @@ class HotkeysManager {
56055
56988
  }
56056
56989
  }
56057
56990
  /* harmony default export */ const classes_HotkeysManager = (HotkeysManager);
56058
-
56059
- // Commands Contexts:
56060
-
56061
- // --> Name and Priority
56062
- // GLOBAL: 0
56063
- // VIEWER::CORNERSTONE: 1
56064
- // VIEWER::VTK: 1
56065
56991
  // EXTERNAL MODULE: ../../core/src/classes/ImageSet.ts
56066
56992
  var ImageSet = __webpack_require__(14169);
56067
56993
  // EXTERNAL MODULE: ../../../node_modules/query-string/index.js
@@ -57389,6 +58315,67 @@ let TimingEnum = /*#__PURE__*/function (TimingEnum) {
57389
58315
  ;// CONCATENATED MODULE: ../../core/src/enums/index.ts
57390
58316
 
57391
58317
 
58318
+ // EXTERNAL MODULE: ../../../node_modules/react/index.js
58319
+ var react = __webpack_require__(41766);
58320
+ ;// CONCATENATED MODULE: ../../core/src/hooks/useToolbar.tsx
58321
+
58322
+ function useToolbar({
58323
+ servicesManager,
58324
+ buttonSection = 'primary'
58325
+ }) {
58326
+ const {
58327
+ toolbarService,
58328
+ viewportGridService
58329
+ } = servicesManager.services;
58330
+ const {
58331
+ EVENTS
58332
+ } = toolbarService;
58333
+ const [toolbarButtons, setToolbarButtons] = (0,react.useState)(toolbarService.getButtonSection(buttonSection));
58334
+
58335
+ // Callback function for handling toolbar interactions
58336
+ const onInteraction = (0,react.useCallback)(args => {
58337
+ const viewportId = viewportGridService.getActiveViewportId();
58338
+ const refreshProps = {
58339
+ viewportId
58340
+ };
58341
+ toolbarService.recordInteraction(args, {
58342
+ refreshProps
58343
+ });
58344
+ }, [toolbarService, viewportGridService]);
58345
+
58346
+ // Effect to handle toolbar modification events
58347
+ (0,react.useEffect)(() => {
58348
+ const handleToolbarModified = () => {
58349
+ setToolbarButtons(toolbarService.getButtonSection(buttonSection));
58350
+ };
58351
+ const subs = [EVENTS.TOOL_BAR_MODIFIED, EVENTS.TOOL_BAR_STATE_MODIFIED].map(event => {
58352
+ return toolbarService.subscribe(event, handleToolbarModified);
58353
+ });
58354
+ return () => {
58355
+ subs.forEach(sub => sub.unsubscribe());
58356
+ };
58357
+ }, [toolbarService]);
58358
+
58359
+ // Effect to handle active viewportId change event
58360
+ (0,react.useEffect)(() => {
58361
+ const events = [viewportGridService.EVENTS.ACTIVE_VIEWPORT_ID_CHANGED, viewportGridService.EVENTS.VIEWPORTS_READY];
58362
+ const subscriptions = events.map(event => {
58363
+ return viewportGridService.subscribe(event, ({
58364
+ viewportId
58365
+ }) => {
58366
+ viewportId = viewportId || viewportGridService.getActiveViewportId();
58367
+ toolbarService.refreshToolbarState({
58368
+ viewportId
58369
+ });
58370
+ });
58371
+ });
58372
+ return () => subscriptions.forEach(sub => sub.unsubscribe());
58373
+ }, [viewportGridService, toolbarService]);
58374
+ return {
58375
+ toolbarButtons,
58376
+ onInteraction
58377
+ };
58378
+ }
57392
58379
  ;// CONCATENATED MODULE: ../../core/src/DataSources/IWebApiDataSource.js
57393
58380
  // TODO: Use above to inject so dependent datasources don't need to import or
57394
58381
  // depend on @ohif/core?
@@ -57484,6 +58471,7 @@ const IWebApiDataSource = {
57484
58471
 
57485
58472
 
57486
58473
 
58474
+
57487
58475
  const hotkeys = {
57488
58476
  ...utils/* default.hotkeys */.Ay.hotkeys,
57489
58477
  defaults: {
@@ -57527,7 +58515,8 @@ const OHIF = {
57527
58515
  DicomMetadataStore: services_DicomMetadataStore,
57528
58516
  pubSubServiceInterface: pubSubServiceInterface/* default */.A,
57529
58517
  PubSubService: pubSubServiceInterface/* PubSubService */.R,
57530
- PanelService: services_PanelService
58518
+ PanelService: services_PanelService,
58519
+ useToolbar: useToolbar
57531
58520
  };
57532
58521
 
57533
58522
 
@@ -58016,13 +59005,6 @@ class PubSubService {
58016
59005
  }
58017
59006
  }
58018
59007
 
58019
- /***/ }),
58020
-
58021
- /***/ 53857:
58022
- /***/ (() => {
58023
-
58024
-
58025
-
58026
59008
  /***/ }),
58027
59009
 
58028
59010
  /***/ 44563:
@@ -135354,7 +136336,7 @@ vtk.register = register;
135354
136336
  /* harmony export */ });
135355
136337
  /* unused harmony exports IDLE_BLOCKER, IDLE_FETCHER, IDLE_NAVIGATION, UNSAFE_DEFERRED_SYMBOL, UNSAFE_DeferredData, UNSAFE_ErrorResponseImpl, UNSAFE_convertRouteMatchToUiMatch, UNSAFE_convertRoutesToDataRoutes, UNSAFE_warning, createHashHistory, createMemoryHistory, createRouter, createStaticHandler, defer, generatePath, getStaticContextFromError, getToPathname, isDeferredData, json, matchPath, normalizePathname, redirect, redirectDocument, resolvePath */
135356
136338
  /**
135357
- * @remix-run/router v1.15.0
136339
+ * @remix-run/router v1.15.3
135358
136340
  *
135359
136341
  * Copyright (c) Remix Software Inc.
135360
136342
  *
@@ -135772,6 +136754,10 @@ function getUrlBasedHistory(getLocation, createHref, validateLocation, options)
135772
136754
  // See https://bugzilla.mozilla.org/show_bug.cgi?id=878297
135773
136755
  let base = window.location.origin !== "null" ? window.location.origin : window.location.href;
135774
136756
  let href = typeof to === "string" ? to : createPath(to);
136757
+ // Treating this as a full URL will strip any trailing spaces so we need to
136758
+ // pre-encode them since they might be part of a matching splat param from
136759
+ // an ancestor route
136760
+ href = href.replace(/ $/, "%20");
135775
136761
  invariant(base, "No window.location.(origin|href) available to create URL for href: " + href);
135776
136762
  return new URL(href, base);
135777
136763
  }
@@ -135878,14 +136864,14 @@ function matchRoutes(routes, locationArg, basename) {
135878
136864
  rankRouteBranches(branches);
135879
136865
  let matches = null;
135880
136866
  for (let i = 0; matches == null && i < branches.length; ++i) {
135881
- matches = matchRouteBranch(branches[i],
135882
136867
  // Incoming pathnames are generally encoded from either window.location
135883
136868
  // or from router.navigate, but we want to match against the unencoded
135884
136869
  // paths in the route definitions. Memory router locations won't be
135885
136870
  // encoded here but there also shouldn't be anything to decode so this
135886
136871
  // should be a safe operation. This avoids needing matchRoutes to be
135887
136872
  // history-aware.
135888
- safelyDecodeURI(pathname));
136873
+ let decoded = decodePath(pathname);
136874
+ matches = matchRouteBranch(branches[i], decoded);
135889
136875
  }
135890
136876
  return matches;
135891
136877
  }
@@ -136144,7 +137130,7 @@ function matchPath(pattern, pathname) {
136144
137130
  if (isOptional && !value) {
136145
137131
  memo[paramName] = undefined;
136146
137132
  } else {
136147
- memo[paramName] = safelyDecodeURIComponent(value || "", paramName);
137133
+ memo[paramName] = (value || "").replace(/%2F/g, "/");
136148
137134
  }
136149
137135
  return memo;
136150
137136
  }, {});
@@ -136196,22 +137182,14 @@ function compilePath(path, caseSensitive, end) {
136196
137182
  let matcher = new RegExp(regexpSource, caseSensitive ? undefined : "i");
136197
137183
  return [matcher, params];
136198
137184
  }
136199
- function safelyDecodeURI(value) {
137185
+ function decodePath(value) {
136200
137186
  try {
136201
- return decodeURI(value);
137187
+ return value.split("/").map(v => decodeURIComponent(v).replace(/\//g, "%2F")).join("/");
136202
137188
  } catch (error) {
136203
137189
  warning(false, "The URL path \"" + value + "\" could not be decoded because it is is a " + "malformed URL segment. This is probably due to a bad percent " + ("encoding (" + error + ")."));
136204
137190
  return value;
136205
137191
  }
136206
137192
  }
136207
- function safelyDecodeURIComponent(value, paramName) {
136208
- try {
136209
- return decodeURIComponent(value);
136210
- } catch (error) {
136211
- warning(false, "The value for the URL param \"" + paramName + "\" will not be decoded because" + (" the string \"" + value + "\" is a malformed URL segment. This is probably") + (" due to a bad percent encoding (" + error + ")."));
136212
- return value;
136213
- }
136214
- }
136215
137193
  /**
136216
137194
  * @private
136217
137195
  */
@@ -136737,7 +137715,21 @@ function createRouter(init) {
136737
137715
  // were marked for explicit hydration
136738
137716
  let loaderData = init.hydrationData ? init.hydrationData.loaderData : null;
136739
137717
  let errors = init.hydrationData ? init.hydrationData.errors : null;
136740
- initialized = initialMatches.every(m => m.route.loader && m.route.loader.hydrate !== true && (loaderData && loaderData[m.route.id] !== undefined || errors && errors[m.route.id] !== undefined));
137718
+ let isRouteInitialized = m => {
137719
+ // No loader, nothing to initialize
137720
+ if (!m.route.loader) return true;
137721
+ // Explicitly opting-in to running on hydration
137722
+ if (m.route.loader.hydrate === true) return false;
137723
+ // Otherwise, initialized if hydrated with data or an error
137724
+ return loaderData && loaderData[m.route.id] !== undefined || errors && errors[m.route.id] !== undefined;
137725
+ };
137726
+ // If errors exist, don't consider routes below the boundary
137727
+ if (errors) {
137728
+ let idx = initialMatches.findIndex(m => errors[m.route.id] !== undefined);
137729
+ initialized = initialMatches.slice(0, idx + 1).every(isRouteInitialized);
137730
+ } else {
137731
+ initialized = initialMatches.every(isRouteInitialized);
137732
+ }
136741
137733
  } else {
136742
137734
  // Without partial hydration - we're initialized if we were provided any
136743
137735
  // hydrationData - which is expected to be complete
@@ -137390,7 +138382,7 @@ function createRouter(init) {
137390
138382
  // preserving any new action data or existing action data (in the case of
137391
138383
  // a revalidation interrupting an actionReload)
137392
138384
  // If we have partialHydration enabled, then don't update the state for the
137393
- // initial data load since iot's not a "navigation"
138385
+ // initial data load since it's not a "navigation"
137394
138386
  if (!isUninterruptedRevalidation && (!future.v7_partialHydration || !initialHydration)) {
137395
138387
  revalidatingFetchers.forEach(rf => {
137396
138388
  let fetcher = state.fetchers.get(rf.key);
@@ -137476,6 +138468,18 @@ function createRouter(init) {
137476
138468
  }
137477
138469
  });
137478
138470
  });
138471
+ // During partial hydration, preserve SSR errors for routes that don't re-run
138472
+ if (future.v7_partialHydration && initialHydration && state.errors) {
138473
+ Object.entries(state.errors).filter(_ref2 => {
138474
+ let [id] = _ref2;
138475
+ return !matchesToLoad.some(m => m.route.id === id);
138476
+ }).forEach(_ref3 => {
138477
+ let [routeId, error] = _ref3;
138478
+ errors = Object.assign(errors || {}, {
138479
+ [routeId]: error
138480
+ });
138481
+ });
138482
+ }
137479
138483
  let updatedFetchers = markFetchRedirectsDone();
137480
138484
  let didAbortFetchLoads = abortStaleFetchLoads(pendingNavigationLoadId);
137481
138485
  let shouldUpdateFetchers = updatedFetchers || didAbortFetchLoads || revalidatingFetchers.length > 0;
@@ -138018,12 +139022,12 @@ function createRouter(init) {
138018
139022
  blockers
138019
139023
  });
138020
139024
  }
138021
- function shouldBlockNavigation(_ref2) {
139025
+ function shouldBlockNavigation(_ref4) {
138022
139026
  let {
138023
139027
  currentLocation,
138024
139028
  nextLocation,
138025
139029
  historyAction
138026
- } = _ref2;
139030
+ } = _ref4;
138027
139031
  if (blockerFunctions.size === 0) {
138028
139032
  return;
138029
139033
  }
@@ -138634,8 +139638,8 @@ function normalizeNavigateOptions(normalizeFormMethod, isFetcher, path, opts) {
138634
139638
  }
138635
139639
  let text = typeof opts.body === "string" ? opts.body : opts.body instanceof FormData || opts.body instanceof URLSearchParams ?
138636
139640
  // https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#plain-text-form-data
138637
- Array.from(opts.body.entries()).reduce((acc, _ref3) => {
138638
- let [name, value] = _ref3;
139641
+ Array.from(opts.body.entries()).reduce((acc, _ref5) => {
139642
+ let [name, value] = _ref5;
138639
139643
  return "" + acc + name + "=" + value + "\n";
138640
139644
  }, "") : String(opts.body);
138641
139645
  return {
@@ -166234,6 +167238,55 @@ module.exports = TypeError;
166234
167238
  module.exports = URIError;
166235
167239
 
166236
167240
 
167241
+ /***/ }),
167242
+
167243
+ /***/ 65902:
167244
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
167245
+
167246
+ "use strict";
167247
+
167248
+
167249
+ var $TypeError = __webpack_require__(18709);
167250
+
167251
+ /** @type {import('./RequireObjectCoercible')} */
167252
+ module.exports = function RequireObjectCoercible(value) {
167253
+ if (value == null) {
167254
+ throw new $TypeError((arguments.length > 0 && arguments[1]) || ('Cannot call method on ' + value));
167255
+ }
167256
+ return value;
167257
+ };
167258
+
167259
+
167260
+ /***/ }),
167261
+
167262
+ /***/ 44566:
167263
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
167264
+
167265
+ "use strict";
167266
+
167267
+
167268
+ var $Object = __webpack_require__(89170);
167269
+ var RequireObjectCoercible = __webpack_require__(65902);
167270
+
167271
+ /** @type {import('./ToObject')} */
167272
+ module.exports = function ToObject(value) {
167273
+ RequireObjectCoercible(value);
167274
+ return $Object(value);
167275
+ };
167276
+
167277
+
167278
+ /***/ }),
167279
+
167280
+ /***/ 89170:
167281
+ /***/ ((module) => {
167282
+
167283
+ "use strict";
167284
+
167285
+
167286
+ /** @type {import('.')} */
167287
+ module.exports = Object;
167288
+
167289
+
166237
167290
  /***/ }),
166238
167291
 
166239
167292
  /***/ 75153:
@@ -175035,13 +176088,17 @@ module.exports = hasPropertyDescriptors;
175035
176088
 
175036
176089
 
175037
176090
  var test = {
176091
+ __proto__: null,
175038
176092
  foo: {}
175039
176093
  };
175040
176094
 
175041
176095
  var $Object = Object;
175042
176096
 
176097
+ /** @type {import('.')} */
175043
176098
  module.exports = function hasProto() {
175044
- return { __proto__: test }.foo === test.foo && !({ __proto__: null } instanceof $Object);
176099
+ // @ts-expect-error: TS errors on an inherited property for some reason
176100
+ return { __proto__: test }.foo === test.foo
176101
+ && !(test instanceof $Object);
175045
176102
  };
175046
176103
 
175047
176104
 
@@ -208154,7 +209211,7 @@ module.exports = function shimAssign() {
208154
209211
  "use strict";
208155
209212
 
208156
209213
 
208157
- var RequireObjectCoercible = __webpack_require__(70867);
209214
+ var RequireObjectCoercible = __webpack_require__(65902);
208158
209215
  var callBound = __webpack_require__(61389);
208159
209216
 
208160
209217
  var $isEnumerable = callBound('Object.prototype.propertyIsEnumerable');
@@ -229151,9 +230208,7 @@ var gOPD = __webpack_require__(95121);
229151
230208
  var $TypeError = __webpack_require__(18709);
229152
230209
  var $floor = GetIntrinsic('%Math.floor%');
229153
230210
 
229154
- /** @typedef {(...args: unknown[]) => unknown} Func */
229155
-
229156
- /** @type {<T extends Func = Func>(fn: T, length: number, loose?: boolean) => T} */
230211
+ /** @type {import('.')} */
229157
230212
  module.exports = function setFunctionLength(fn, length) {
229158
230213
  if (typeof fn !== 'function') {
229159
230214
  throw new $TypeError('`fn` is not a function');
@@ -229979,8 +231034,8 @@ module.exports = str => encodeURIComponent(str).replace(/[!'()*]/g, x => `%${x.c
229979
231034
  "use strict";
229980
231035
 
229981
231036
 
229982
- var RequireObjectCoercible = __webpack_require__(70867);
229983
- var ToString = __webpack_require__(52169);
231037
+ var RequireObjectCoercible = __webpack_require__(65902);
231038
+ var ToString = __webpack_require__(78382);
229984
231039
  var callBound = __webpack_require__(61389);
229985
231040
  var $replace = callBound('String.prototype.replace');
229986
231041
 
@@ -230010,7 +231065,7 @@ module.exports = function trim() {
230010
231065
 
230011
231066
  var callBind = __webpack_require__(20325);
230012
231067
  var define = __webpack_require__(27086);
230013
- var RequireObjectCoercible = __webpack_require__(70867);
231068
+ var RequireObjectCoercible = __webpack_require__(65902);
230014
231069
 
230015
231070
  var implementation = __webpack_require__(32900);
230016
231071
  var getPolyfill = __webpack_require__(45937);
@@ -231410,7 +232465,7 @@ var react_dom__WEBPACK_IMPORTED_MODULE_1___namespace_cache;
231410
232465
  /* harmony import */ var react_router__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(10971);
231411
232466
  /* harmony import */ var _remix_run_router__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(29042);
231412
232467
  /**
231413
- * React Router DOM v6.22.0
232468
+ * React Router DOM v6.22.3
231414
232469
  *
231415
232470
  * Copyright (c) Remix Software Inc.
231416
232471
  *
@@ -232859,7 +233914,7 @@ var react__WEBPACK_IMPORTED_MODULE_0___namespace_cache;
232859
233914
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(41766);
232860
233915
  /* harmony import */ var _remix_run_router__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(29042);
232861
233916
  /**
232862
- * React Router v6.22.0
233917
+ * React Router v6.22.3
232863
233918
  *
232864
233919
  * Copyright (c) Remix Software Inc.
232865
233920
  *
@@ -233185,7 +234240,26 @@ function useRoutesImpl(routes, locationArg, dataRouterState, future) {
233185
234240
  location = locationFromContext;
233186
234241
  }
233187
234242
  let pathname = location.pathname || "/";
233188
- let remainingPathname = parentPathnameBase === "/" ? pathname : pathname.slice(parentPathnameBase.length) || "/";
234243
+ let remainingPathname = pathname;
234244
+ if (parentPathnameBase !== "/") {
234245
+ // Determine the remaining pathname by removing the # of URL segments the
234246
+ // parentPathnameBase has, instead of removing based on character count.
234247
+ // This is because we can't guarantee that incoming/outgoing encodings/
234248
+ // decodings will match exactly.
234249
+ // We decode paths before matching on a per-segment basis with
234250
+ // decodeURIComponent(), but we re-encode pathnames via `new URL()` so they
234251
+ // match what `window.location.pathname` would reflect. Those don't 100%
234252
+ // align when it comes to encoded URI characters such as % and &.
234253
+ //
234254
+ // So we may end up with:
234255
+ // pathname: "/descendant/a%25b/match"
234256
+ // parentPathnameBase: "/descendant/a%b"
234257
+ //
234258
+ // And the direct substring removal approach won't work :/
234259
+ let parentSegments = parentPathnameBase.replace(/^\//, "").split("/");
234260
+ let segments = pathname.replace(/^\//, "").split("/");
234261
+ remainingPathname = "/" + segments.slice(parentSegments.length).join("/");
234262
+ }
233189
234263
  let matches = (0,_remix_run_router__WEBPACK_IMPORTED_MODULE_1__/* .matchRoutes */ .ue)(routes, {
233190
234264
  pathname: remainingPathname
233191
234265
  });
@@ -235416,17 +236490,6 @@ module.exports = function OrdinaryDefineOwnProperty(O, P, Desc) {
235416
236490
  };
235417
236491
 
235418
236492
 
235419
- /***/ }),
235420
-
235421
- /***/ 70867:
235422
- /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
235423
-
235424
- "use strict";
235425
-
235426
-
235427
- module.exports = __webpack_require__(71776);
235428
-
235429
-
235430
236493
  /***/ }),
235431
236494
 
235432
236495
  /***/ 62074:
@@ -235598,18 +236661,9 @@ module.exports = function ToNumber(argument) {
235598
236661
  "use strict";
235599
236662
 
235600
236663
 
235601
- var GetIntrinsic = __webpack_require__(45159);
235602
-
235603
- var $Object = GetIntrinsic('%Object%');
235604
-
235605
- var RequireObjectCoercible = __webpack_require__(70867);
235606
-
235607
236664
  // https://262.ecma-international.org/6.0/#sec-toobject
235608
236665
 
235609
- module.exports = function ToObject(value) {
235610
- RequireObjectCoercible(value);
235611
- return $Object(value);
235612
- };
236666
+ module.exports = __webpack_require__(44566);
235613
236667
 
235614
236668
 
235615
236669
  /***/ }),
@@ -235963,21 +237017,24 @@ module.exports = function truncate(x) {
235963
237017
 
235964
237018
  /***/ }),
235965
237019
 
235966
- /***/ 71776:
237020
+ /***/ 78382:
235967
237021
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
235968
237022
 
235969
237023
  "use strict";
235970
237024
 
235971
237025
 
237026
+ var GetIntrinsic = __webpack_require__(45159);
237027
+
237028
+ var $String = GetIntrinsic('%String%');
235972
237029
  var $TypeError = __webpack_require__(18709);
235973
237030
 
235974
- // http://262.ecma-international.org/5.1/#sec-9.10
237031
+ // https://262.ecma-international.org/6.0/#sec-tostring
235975
237032
 
235976
- module.exports = function CheckObjectCoercible(value, optMessage) {
235977
- if (value == null) {
235978
- throw new $TypeError(optMessage || ('Cannot call method on ' + value));
237033
+ module.exports = function ToString(argument) {
237034
+ if (typeof argument === 'symbol') {
237035
+ throw new $TypeError('Cannot convert a Symbol value to a string');
235979
237036
  }
235980
- return value;
237037
+ return $String(argument);
235981
237038
  };
235982
237039
 
235983
237040
 
@@ -236266,7 +237323,7 @@ module.exports = function isPropertyDescriptor(Desc) {
236266
237323
  return false;
236267
237324
  }
236268
237325
 
236269
- for (var key in Desc) { // eslint-disable-line
237326
+ for (var key in Desc) { // eslint-disable-line
236270
237327
  if (hasOwn(Desc, key) && !allowed[key]) {
236271
237328
  return false;
236272
237329
  }
@@ -241028,7 +242085,7 @@ var selectOrdinal = function selectOrdinal() {
241028
242085
  /******/ // This function allow to reference async chunks
241029
242086
  /******/ __webpack_require__.u = (chunkId) => {
241030
242087
  /******/ // return url for filenames based on template
241031
- /******/ return "" + ({"525":"dicom-microscopy-viewer","572":"polySeg"}[chunkId] || chunkId) + ".bundle." + {"50":"a18826e121bdd0c2a707","68":"0420d25b4736f20b15b2","109":"b4fee2a22b622839baf5","121":"ed23e7752a11005322e6","155":"19e63774cdf16306b5b6","164":"0b17fced9916487eb49f","188":"7e085b90e138357e6789","191":"4850ab82949bb6f0eb73","250":"a064577944a0691bc77d","270":"36c4e95efb89ad8bd8ae","290":"8b4d7dfbc7cfe418a0f1","295":"462f3328c716cbe6c613","297":"81d63bb0b66d63df6d86","317":"7ef949a52571bc04e7e1","339":"2271a993c53d0728c816","342":"a039c24e9f661f3b884d","481":"a2b01ffe06a262fa9375","504":"aa165082e2acc5ccf080","525":"d3a56dc9f62df5e11019","530":"ce13c30b93a28cc85098","544":"3cf20da53f349abd8d67","559":"42a8edafa1c7df761194","572":"99be036bab9b7f011b0c","594":"6667c5cc14b924d7bee6","644":"1e77691d2eeb96a423b0","704":"242ba4e0b0be7d1fec94","724":"941cd2a3b43a84d5893f","726":"2bdb443d1b5620d74e6e","835":"15aff0b7433bb0dd6d6d","862":"e3fe2aae7903cc2ae8df","889":"6850a0b8c412e3befab5","905":"eb7bdaec4276399e5bef","907":"fc8115500a085ab2bbec","931":"d270a1fda9a2836c3cc5","939":"84ee0b844023d924a22b","961":"f5d9e73fa771ce7e73f3","963":"3daa5c08231526d905fb"}[chunkId] + ".js";
242088
+ /******/ return "" + ({"525":"dicom-microscopy-viewer","572":"polySeg"}[chunkId] || chunkId) + ".bundle." + {"41":"0696b28613c7d47833c9","90":"7a9258532111121b5ee3","109":"b4fee2a22b622839baf5","121":"5399d807995157d368b7","155":"55fa02bfc411cc91e261","164":"0cfa2edabf8ef222f3ea","188":"ec979013d89d90831c58","191":"4850ab82949bb6f0eb73","270":"58c74e58ad67b5069718","290":"8b4d7dfbc7cfe418a0f1","295":"c0a29ff64d86f707fc20","297":"81d63bb0b66d63df6d86","339":"e31c81c7179d3d24f3dd","342":"a039c24e9f661f3b884d","448":"e856d2b2bd979c7d9ac0","481":"a2b01ffe06a262fa9375","504":"aa165082e2acc5ccf080","525":"d3a56dc9f62df5e11019","530":"f00fd953dcd9d0afd10b","544":"adfe5764f59b5fe0eba7","559":"4f55f5df04c418b2854e","572":"c1cec6312eb6c6dc3701","594":"924cdc10e7435cf3e199","638":"62f8f8ada74bd900abfc","644":"1e77691d2eeb96a423b0","699":"b3b25017819be681ef3d","701":"b7ebc1629fc121e13c58","724":"cd011bc1838a2bde1d66","726":"2bdb443d1b5620d74e6e","835":"15aff0b7433bb0dd6d6d","862":"d2e78b70286b59569e83","889":"2aefa0a3eb114db0de3f","905":"d4bdcbd451de59b2191b","907":"ca236b83967a8459b778","931":"d270a1fda9a2836c3cc5","939":"84ee0b844023d924a22b","961":"a5541d8090cb8b22f7e6"}[chunkId] + ".js";
241032
242089
  /******/ };
241033
242090
  /******/ })();
241034
242091
  /******/
@@ -241137,6 +242194,9 @@ var selectOrdinal = function selectOrdinal() {
241137
242194
  /******/
241138
242195
  /******/ linkTag.rel = "stylesheet";
241139
242196
  /******/ linkTag.type = "text/css";
242197
+ /******/ if (__webpack_require__.nc) {
242198
+ /******/ linkTag.nonce = __webpack_require__.nc;
242199
+ /******/ }
241140
242200
  /******/ var onLinkComplete = (event) => {
241141
242201
  /******/ // avoid mem leaks.
241142
242202
  /******/ linkTag.onerror = linkTag.onload = null;
@@ -241194,7 +242254,7 @@ var selectOrdinal = function selectOrdinal() {
241194
242254
  /******/ };
241195
242255
  /******/
241196
242256
  /******/ __webpack_require__.f.miniCss = (chunkId, promises) => {
241197
- /******/ var cssChunks = {"50":1,"155":1,"481":1,"544":1,"889":1,"963":1};
242257
+ /******/ var cssChunks = {"155":1,"481":1,"544":1,"638":1,"701":1,"889":1};
241198
242258
  /******/ if(installedCssChunks[chunkId]) promises.push(installedCssChunks[chunkId]);
241199
242259
  /******/ else if(installedCssChunks[chunkId] !== 0 && cssChunks[chunkId]) {
241200
242260
  /******/ promises.push(installedCssChunks[chunkId] = loadStylesheet(chunkId).then(() => {
@@ -241316,9 +242376,6 @@ var selectOrdinal = function selectOrdinal() {
241316
242376
  /******/ /* webpack/runtime/chunk prefetch trigger */
241317
242377
  /******/ (() => {
241318
242378
  /******/ var chunkToChildrenMap = {
241319
- /******/ "50": [
241320
- /******/ 295
241321
- /******/ ],
241322
242379
  /******/ "155": [
241323
242380
  /******/ 530,
241324
242381
  /******/ 862
@@ -241329,14 +242386,17 @@ var selectOrdinal = function selectOrdinal() {
241329
242386
  /******/ "559": [
241330
242387
  /******/ 530
241331
242388
  /******/ ],
242389
+ /******/ "638": [
242390
+ /******/ 295
242391
+ /******/ ],
242392
+ /******/ "701": [
242393
+ /******/ 889
242394
+ /******/ ],
241332
242395
  /******/ "907": [
241333
242396
  /******/ 297
241334
242397
  /******/ ],
241335
242398
  /******/ "961": [
241336
242399
  /******/ 939
241337
- /******/ ],
241338
- /******/ "963": [
241339
- /******/ 889
241340
242400
  /******/ ]
241341
242401
  /******/ };
241342
242402
  /******/ __webpack_require__.f.prefetch = (chunkId, promises) => (Promise.all(promises).then(() => {
@@ -241350,7 +242410,7 @@ var selectOrdinal = function selectOrdinal() {
241350
242410
  /******/ // startup
241351
242411
  /******/ // Load entry module and return exports
241352
242412
  /******/ // This entry module is referenced by other modules so it can't be inlined
241353
- /******/ var __webpack_exports__ = __webpack_require__(45573);
242413
+ /******/ var __webpack_exports__ = __webpack_require__(68870);
241354
242414
  /******/
241355
242415
  /******/ })()
241356
242416
  ;