@ohif/app 3.13.0-beta.116 → 3.13.0-beta.118

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 (47) hide show
  1. package/dist/{1206.bundle.47f070e2254d128c.js → 1206.bundle.e04ca1efe6f987ba.js} +1 -1
  2. package/dist/1483.bundle.5a98bf0d4c26aa01.js +470 -0
  3. package/dist/{1602.bundle.097ec19e8e61516f.js → 1602.bundle.2a0e1a9a73063ab5.js} +2 -2
  4. package/dist/{7701.bundle.945445d6681ddd20.js → 2343.bundle.931645133f98ca47.js} +990 -7
  5. package/dist/{3500.bundle.1e063b7b4910d6cf.js → 3500.bundle.7afd6d2e9345fca0.js} +1 -1
  6. package/dist/{3760.bundle.6c7eeb4b7f1583ca.js → 3760.bundle.553d1b88392a20b4.js} +2 -2
  7. package/dist/{5448.bundle.1e50777e4c4e122a.js → 5448.bundle.5686ebb99c379f64.js} +1 -1
  8. package/dist/{5696.bundle.9f0366ad867385bc.js → 5696.bundle.615658b8dead54ce.js} +7 -4
  9. package/dist/{5910.bundle.5561806884c95754.js → 5910.bundle.0f19608f3e76859b.js} +2 -2
  10. package/dist/{419.bundle.9d0e6a72e1e3a17b.js → 6749.bundle.ed2f94d2dd4c9a24.js} +288 -62
  11. package/dist/{7248.bundle.f761b21f343d4b9f.js → 7248.bundle.4c7d834f2ec140c7.js} +2 -2
  12. package/dist/{7295.bundle.4d4b6de4d2bb8856.js → 7499.bundle.743782416c5f430e.js} +502 -5
  13. package/dist/{781.bundle.efb0a6981676cebb.js → 781.bundle.d353624c7a811425.js} +2 -2
  14. package/dist/{8423.bundle.5d1b3092bc9562c9.js → 8423.bundle.1f3a472a7f691c1a.js} +2 -2
  15. package/dist/8492.bundle.44a55a259584d665.js +504 -0
  16. package/dist/8595.css +2 -0
  17. package/dist/{899.bundle.e786f8dfb66d74ca.js → 899.bundle.50c16f860acbc848.js} +2 -2
  18. package/dist/{9068.bundle.cd36fcb4e15a153e.js → 9068.bundle.95f1e638ef694ea9.js} +2 -2
  19. package/dist/{9402.bundle.6549cc304496cd5c.js → 9402.bundle.57041a8d06a36e8e.js} +2 -2
  20. package/dist/{9415.bundle.2a970c71de4014bf.js → 9415.bundle.770426487f8c0dfa.js} +2 -2
  21. package/dist/{9437.bundle.0fff227a859992ea.js → 9437.bundle.0045fb70b8fa0e7b.js} +107 -123
  22. package/dist/app-config.js +1 -1
  23. package/dist/{app.bundle.55057e411d635dc3.js → app.bundle.707ae3540bb211e8.js} +203 -36
  24. package/dist/customizations/index.html +400 -0
  25. package/dist/customizations/segmentation/segmentationAnnotationTools.jsonc +48 -0
  26. package/dist/customizations/segmentation/segmentationEditing.jsonc +59 -0
  27. package/dist/customizations/{ctPresets.jsonc → tools/ctPresets.jsonc} +1 -1
  28. package/dist/customizations/{measurementLabels.jsonc → tools/measurementLabels.jsonc} +1 -1
  29. package/dist/customizations/{smoothRotate.jsonc → tools/smoothRotate.jsonc} +1 -1
  30. package/dist/customizations/veterinary/veterinary.jsonc +5 -0
  31. package/dist/customizations/{veterinaryOverlay.jsonc → veterinary/veterinaryOverlay.jsonc} +3 -3
  32. package/dist/customizations/{patientBirthDate.jsonc → worklist/patientBirthDate.jsonc} +2 -2
  33. package/dist/index.html +1 -1
  34. package/dist/sw.js +1 -1
  35. package/package.json +5 -5
  36. package/dist/4834.bundle.a91450199d0f45e4.js +0 -900
  37. package/dist/6001.bundle.0789789db5410764.js +0 -1529
  38. package/dist/customizations/veterinary.jsonc +0 -5
  39. /package/dist/{100.bundle.ac04a425c0851574.js → 100.bundle.6ba1a0be02710b9f.js} +0 -0
  40. /package/dist/{1180.bundle.c19c443fe8d26719.js → 1180.bundle.25017eea64524896.js} +0 -0
  41. /package/dist/{2779.bundle.dca036a18399be96.js → 2779.bundle.56f7da594c887ff6.js} +0 -0
  42. /package/dist/{4556.bundle.b705ab15473128c7.js → 4556.bundle.454bc9719a06bc3f.js} +0 -0
  43. /package/dist/{4683.bundle.5d12928efa9f70f4.js → 4683.bundle.bfb5c3739e9886b5.js} +0 -0
  44. /package/dist/{7295.css → 8492.css} +0 -0
  45. /package/dist/{8832.bundle.ede981706cac8e15.js → 8832.bundle.6f31a982f82b96da.js} +0 -0
  46. /package/dist/{9116.bundle.225e003c28c550c1.js → 9116.bundle.079a64a12966429c.js} +0 -0
  47. /package/dist/{9290.bundle.a18c40b82772a3c6.js → 9290.bundle.db0d1eb62fa6ee8b.js} +0 -0
@@ -17409,7 +17409,7 @@ var state_0 = __webpack_require__(55461);
17409
17409
  * multiple occurrences as an array (see preserveQueryStrings).
17410
17410
  */
17411
17411
  const PRESERVE_CUSTOMIZATION_KEYS_KEY = 'ohif.preserveCustomizationKeys';
17412
- const preserveKeys = ['configUrl', 'multimonitor', 'screenNumber', 'hangingProtocolId', 'customization'];
17412
+ const preserveKeys = ['configUrl', 'multimonitor', 'screenNumber', 'hangingProtocolId', 'customization', 'theme'];
17413
17413
  function preserveKey(query, current, key) {
17414
17414
  const values = current.getAll(key);
17415
17415
  for (const value of values) {
@@ -20169,27 +20169,27 @@ async function loadModule(module) {
20169
20169
  return imported.default;
20170
20170
  }
20171
20171
  if (module === "@ohif/extension-cornerstone") {
20172
- const imported = await Promise.all(/* import() */ [__webpack_require__.e(9560), __webpack_require__.e(2690), __webpack_require__.e(6489), __webpack_require__.e(6495), __webpack_require__.e(8432), __webpack_require__.e(5642), __webpack_require__.e(9402), __webpack_require__.e(7701), __webpack_require__.e(3833)]).then(__webpack_require__.bind(__webpack_require__, 28772));
20172
+ const imported = await Promise.all(/* import() */ [__webpack_require__.e(9560), __webpack_require__.e(2690), __webpack_require__.e(6489), __webpack_require__.e(6495), __webpack_require__.e(8432), __webpack_require__.e(5642), __webpack_require__.e(9402), __webpack_require__.e(2343), __webpack_require__.e(3833)]).then(__webpack_require__.bind(__webpack_require__, 86714));
20173
20173
  return imported.default;
20174
20174
  }
20175
20175
  if (module === "@ohif/extension-measurement-tracking") {
20176
- const imported = await Promise.all(/* import() */ [__webpack_require__.e(9560), __webpack_require__.e(2690), __webpack_require__.e(6489), __webpack_require__.e(6495), __webpack_require__.e(8432), __webpack_require__.e(5642), __webpack_require__.e(9383), __webpack_require__.e(5406), __webpack_require__.e(9402), __webpack_require__.e(7701), __webpack_require__.e(7248), __webpack_require__.e(3760)]).then(__webpack_require__.bind(__webpack_require__, 34879));
20176
+ const imported = await Promise.all(/* import() */ [__webpack_require__.e(9560), __webpack_require__.e(2690), __webpack_require__.e(6489), __webpack_require__.e(6495), __webpack_require__.e(8432), __webpack_require__.e(5642), __webpack_require__.e(9383), __webpack_require__.e(5406), __webpack_require__.e(9402), __webpack_require__.e(2343), __webpack_require__.e(7248), __webpack_require__.e(3760)]).then(__webpack_require__.bind(__webpack_require__, 34879));
20177
20177
  return imported.default;
20178
20178
  }
20179
20179
  if (module === "@ohif/extension-cornerstone-dicom-sr") {
20180
- const imported = await Promise.all(/* import() */ [__webpack_require__.e(9560), __webpack_require__.e(2690), __webpack_require__.e(6489), __webpack_require__.e(6495), __webpack_require__.e(8432), __webpack_require__.e(5642), __webpack_require__.e(9383), __webpack_require__.e(9402), __webpack_require__.e(7701), __webpack_require__.e(7248), __webpack_require__.e(976)]).then(__webpack_require__.bind(__webpack_require__, 81107));
20180
+ const imported = await Promise.all(/* import() */ [__webpack_require__.e(9560), __webpack_require__.e(2690), __webpack_require__.e(6489), __webpack_require__.e(6495), __webpack_require__.e(8432), __webpack_require__.e(5642), __webpack_require__.e(9383), __webpack_require__.e(9402), __webpack_require__.e(2343), __webpack_require__.e(7248), __webpack_require__.e(976)]).then(__webpack_require__.bind(__webpack_require__, 81107));
20181
20181
  return imported.default;
20182
20182
  }
20183
20183
  if (module === "@ohif/extension-cornerstone-dicom-seg") {
20184
- const imported = await Promise.all(/* import() */ [__webpack_require__.e(9560), __webpack_require__.e(2690), __webpack_require__.e(6489), __webpack_require__.e(6495), __webpack_require__.e(8432), __webpack_require__.e(5642), __webpack_require__.e(9383), __webpack_require__.e(9402), __webpack_require__.e(7701), __webpack_require__.e(781)]).then(__webpack_require__.bind(__webpack_require__, 76360));
20184
+ const imported = await Promise.all(/* import() */ [__webpack_require__.e(9560), __webpack_require__.e(2690), __webpack_require__.e(6489), __webpack_require__.e(6495), __webpack_require__.e(8432), __webpack_require__.e(5642), __webpack_require__.e(9383), __webpack_require__.e(9402), __webpack_require__.e(2343), __webpack_require__.e(781)]).then(__webpack_require__.bind(__webpack_require__, 76360));
20185
20185
  return imported.default;
20186
20186
  }
20187
20187
  if (module === "@ohif/extension-cornerstone-dicom-pmap") {
20188
- const imported = await Promise.all(/* import() */ [__webpack_require__.e(9560), __webpack_require__.e(2690), __webpack_require__.e(6489), __webpack_require__.e(6495), __webpack_require__.e(8432), __webpack_require__.e(5642), __webpack_require__.e(9383), __webpack_require__.e(9402), __webpack_require__.e(7701), __webpack_require__.e(9415)]).then(__webpack_require__.bind(__webpack_require__, 76494));
20188
+ const imported = await Promise.all(/* import() */ [__webpack_require__.e(9560), __webpack_require__.e(2690), __webpack_require__.e(6489), __webpack_require__.e(6495), __webpack_require__.e(8432), __webpack_require__.e(5642), __webpack_require__.e(9383), __webpack_require__.e(9402), __webpack_require__.e(2343), __webpack_require__.e(9415)]).then(__webpack_require__.bind(__webpack_require__, 76494));
20189
20189
  return imported.default;
20190
20190
  }
20191
20191
  if (module === "@ohif/extension-cornerstone-dynamic-volume") {
20192
- const imported = await Promise.all(/* import() */ [__webpack_require__.e(9560), __webpack_require__.e(2690), __webpack_require__.e(6489), __webpack_require__.e(6495), __webpack_require__.e(8432), __webpack_require__.e(5642), __webpack_require__.e(9402), __webpack_require__.e(7701), __webpack_require__.e(1602)]).then(__webpack_require__.bind(__webpack_require__, 42061));
20192
+ const imported = await Promise.all(/* import() */ [__webpack_require__.e(9560), __webpack_require__.e(2690), __webpack_require__.e(6489), __webpack_require__.e(6495), __webpack_require__.e(8432), __webpack_require__.e(5642), __webpack_require__.e(9402), __webpack_require__.e(2343), __webpack_require__.e(1602)]).then(__webpack_require__.bind(__webpack_require__, 42061));
20193
20193
  return imported.default;
20194
20194
  }
20195
20195
  if (module === "@ohif/extension-dicom-microscopy") {
@@ -20205,11 +20205,11 @@ async function loadModule(module) {
20205
20205
  return imported.default;
20206
20206
  }
20207
20207
  if (module === "@ohif/extension-tmtv") {
20208
- const imported = await Promise.all(/* import() */ [__webpack_require__.e(9560), __webpack_require__.e(2690), __webpack_require__.e(6489), __webpack_require__.e(6495), __webpack_require__.e(8432), __webpack_require__.e(5642), __webpack_require__.e(9383), __webpack_require__.e(9402), __webpack_require__.e(7701), __webpack_require__.e(7295)]).then(__webpack_require__.bind(__webpack_require__, 75366));
20208
+ const imported = await Promise.all(/* import() */ [__webpack_require__.e(9560), __webpack_require__.e(2690), __webpack_require__.e(6489), __webpack_require__.e(6495), __webpack_require__.e(8432), __webpack_require__.e(5642), __webpack_require__.e(9383), __webpack_require__.e(9402), __webpack_require__.e(2343), __webpack_require__.e(7499), __webpack_require__.e(8595)]).then(__webpack_require__.bind(__webpack_require__, 87110));
20209
20209
  return imported.default;
20210
20210
  }
20211
20211
  if (module === "@ohif/extension-test") {
20212
- const imported = await Promise.all(/* import() */ [__webpack_require__.e(9560), __webpack_require__.e(2690), __webpack_require__.e(6489), __webpack_require__.e(6495), __webpack_require__.e(8432), __webpack_require__.e(5642), __webpack_require__.e(9402), __webpack_require__.e(7701), __webpack_require__.e(8423)]).then(__webpack_require__.bind(__webpack_require__, 49182));
20212
+ const imported = await Promise.all(/* import() */ [__webpack_require__.e(9560), __webpack_require__.e(2690), __webpack_require__.e(6489), __webpack_require__.e(6495), __webpack_require__.e(8432), __webpack_require__.e(5642), __webpack_require__.e(9402), __webpack_require__.e(2343), __webpack_require__.e(8423)]).then(__webpack_require__.bind(__webpack_require__, 49182));
20213
20213
  return imported.default;
20214
20214
  }
20215
20215
  if (module === "@ohif/extension-cornerstone-dicom-rt") {
@@ -20221,19 +20221,19 @@ async function loadModule(module) {
20221
20221
  return imported.default;
20222
20222
  }
20223
20223
  if (module === "@ohif/mode-longitudinal") {
20224
- const imported = await Promise.all(/* import() */ [__webpack_require__.e(419), __webpack_require__.e(5696)]).then(__webpack_require__.bind(__webpack_require__, 63683));
20224
+ const imported = await Promise.all(/* import() */ [__webpack_require__.e(6749), __webpack_require__.e(5696)]).then(__webpack_require__.bind(__webpack_require__, 63683));
20225
20225
  return imported.default;
20226
20226
  }
20227
20227
  if (module === "@ohif/mode-basic") {
20228
- const imported = await __webpack_require__.e(/* import() */ 419).then(__webpack_require__.bind(__webpack_require__, 86750));
20228
+ const imported = await __webpack_require__.e(/* import() */ 6749).then(__webpack_require__.bind(__webpack_require__, 69932));
20229
20229
  return imported.default;
20230
20230
  }
20231
20231
  if (module === "@ohif/mode-segmentation") {
20232
- const imported = await Promise.all(/* import() */ [__webpack_require__.e(419), __webpack_require__.e(6001)]).then(__webpack_require__.bind(__webpack_require__, 21992));
20232
+ const imported = await Promise.all(/* import() */ [__webpack_require__.e(6749), __webpack_require__.e(1483)]).then(__webpack_require__.bind(__webpack_require__, 77798));
20233
20233
  return imported.default;
20234
20234
  }
20235
20235
  if (module === "@ohif/mode-tmtv") {
20236
- const imported = await __webpack_require__.e(/* import() */ 4834).then(__webpack_require__.bind(__webpack_require__, 74137));
20236
+ const imported = await Promise.all(/* import() */ [__webpack_require__.e(9560), __webpack_require__.e(2690), __webpack_require__.e(6489), __webpack_require__.e(6495), __webpack_require__.e(8432), __webpack_require__.e(5642), __webpack_require__.e(9383), __webpack_require__.e(9402), __webpack_require__.e(2343), __webpack_require__.e(6749), __webpack_require__.e(7499), __webpack_require__.e(8492)]).then(__webpack_require__.bind(__webpack_require__, 69387));
20237
20237
  return imported.default;
20238
20238
  }
20239
20239
  if (module === "@ohif/mode-microscopy") {
@@ -20245,7 +20245,7 @@ async function loadModule(module) {
20245
20245
  return imported.default;
20246
20246
  }
20247
20247
  if (module === "@ohif/mode-test") {
20248
- const imported = await __webpack_require__.e(/* import() */ 9437).then(__webpack_require__.bind(__webpack_require__, 48284));
20248
+ const imported = await Promise.all(/* import() */ [__webpack_require__.e(6749), __webpack_require__.e(9437)]).then(__webpack_require__.bind(__webpack_require__, 48284));
20249
20249
  return imported.default;
20250
20250
  }
20251
20251
  if (module === "@ohif/mode-basic-dev-mode") {
@@ -20621,6 +20621,15 @@ function ModeRoute({
20621
20621
  await extensionManager.registerExtension(extension);
20622
20622
  }
20623
20623
  }
20624
+
20625
+ // Mode dependency extensions register their customization modules here,
20626
+ // but `registerExtension` does not merge them into the customization
20627
+ // service — that otherwise only happens later in
20628
+ // `extensionManager.onModeEnter`. Merge them now so anything that runs
20629
+ // before setupRouteInit (e.g. a mode's layoutTemplate) can already read
20630
+ // the defaults these extensions provide.
20631
+ // `init` is idempotent — each extension module is merged at most once.
20632
+ customizationService.init(extensionManager);
20624
20633
  if (isMounted.current) {
20625
20634
  setExtensionDependenciesLoaded(true);
20626
20635
  }
@@ -20700,10 +20709,23 @@ function ModeRoute({
20700
20709
  rightPanels = [],
20701
20710
  ...layoutProps
20702
20711
  } = layoutData.props;
20712
+
20713
+ // Register panels immediately so ViewerLayout's first render sees them.
20714
+ // ResizablePanelsHook only auto-expands side panels on the initial mount;
20715
+ // if panels are added later, the viewport grid keeps the wrong width.
20716
+ // setupRouteInit (below) resets and re-applies them after customizations
20717
+ // are layered on, so URL/config modules can still modify the lists.
20703
20718
  panelService.reset();
20704
20719
  panelService.addPanels(panelService.PanelPosition.Left, leftPanels);
20705
20720
  panelService.addPanels(panelService.PanelPosition.Right, rightPanels);
20706
20721
 
20722
+ // Stash the layout lists for setupRouteInit to seed into the
20723
+ // `leftPanels` / `rightPanels` customizations.
20724
+ layoutData.panels = {
20725
+ leftPanels,
20726
+ rightPanels
20727
+ };
20728
+
20707
20729
  // layoutProps contains all props but leftPanels and rightPanels
20708
20730
  layoutData.props = layoutProps;
20709
20731
  layoutTemplateData.current = layoutData;
@@ -20738,11 +20760,51 @@ function ModeRoute({
20738
20760
  });
20739
20761
 
20740
20762
  // `extensionManager.onModeEnter` resets the customization mode scope via
20741
- // `customizationService.onModeEnter`; now layer on the `mode` phase blocks
20742
- // for this mode — the general (`*`) block first, then any block keyed by
20743
- // this mode's id / routeName so a single mode can override the general one.
20763
+ // `customizationService.onModeEnter`; the mode scope is then layered
20764
+ // bottom-up so the final value of every key is decided by scope
20765
+ // precedence (global > mode > default) and application order alone:
20766
+ // 1. the mode's own values — its layout panel lists, seeded as the
20767
+ // standard `leftPanels` / `rightPanels` customizations;
20768
+ // its toolbar/tool-group composition, seeded as the plain
20769
+ // `toolbarButtons` / `toolbarSections` / `toolGroupAdditions`
20770
+ // customizations (resolved to concrete definitions later, when the
20771
+ // mode's `onModeEnter` registers the toolbar); and its
20772
+ // `modeCustomizations` block (declared as data on the mode
20773
+ // instance, usually as a customization name registered at default
20774
+ // scope when the mode loaded, so bootstrap/global customizations
20775
+ // can modify the block itself before it is applied);
20776
+ // 2. the app config / URL `mode` phase blocks — the general (`*`)
20777
+ // block first, then any block keyed by this mode's id / routeName.
20778
+ const {
20779
+ leftPanels = [],
20780
+ rightPanels = []
20781
+ } = layoutTemplateData.current.panels ?? {};
20782
+ customizationService.setCustomizations({
20783
+ leftPanels,
20784
+ rightPanels,
20785
+ toolbarButtons: mode.toolbarButtons ?? [],
20786
+ toolbarSections: mode.toolbarSections ?? [],
20787
+ toolGroupAdditions: mode.toolGroupAdditions ?? {}
20788
+ });
20789
+ const modeCustomizations = typeof mode.modeCustomizations === 'string' ? customizationService.getCustomization(mode.modeCustomizations) : mode.modeCustomizations;
20790
+ if (modeCustomizations) {
20791
+ customizationService.setCustomizations(modeCustomizations);
20792
+ }
20744
20793
  customizationService.applyModeCustomizations([mode.id, mode.routeName]);
20745
20794
 
20795
+ // Re-apply panels only when customizations changed the lists. When they
20796
+ // match the layout, the panels registered in retrieveLayoutData are left
20797
+ // in place so ViewerLayout's ResizablePanelsHook keeps the correct sizes
20798
+ // from its one-time initial expand.
20799
+ const resolvedLeftPanels = customizationService.getValue('leftPanels') ?? [];
20800
+ const resolvedRightPanels = customizationService.getValue('rightPanels') ?? [];
20801
+ const panelsChanged = JSON.stringify(resolvedLeftPanels) !== JSON.stringify(leftPanels) || JSON.stringify(resolvedRightPanels) !== JSON.stringify(rightPanels);
20802
+ if (panelsChanged) {
20803
+ panelService.reset();
20804
+ panelService.addPanels(panelService.PanelPosition.Left, resolvedLeftPanels);
20805
+ panelService.addPanels(panelService.PanelPosition.Right, resolvedRightPanels);
20806
+ }
20807
+
20746
20808
  // use the URL hangingProtocolId if it exists, otherwise use the one
20747
20809
  // defined in the mode configuration
20748
20810
  const hangingProtocolIdToUse = hangingProtocolService.getProtocolById(runTimeHangingProtocolId) ? runTimeHangingProtocolId : hangingProtocol;
@@ -21242,13 +21304,30 @@ async function appInit(appConfigOrFunc, defaultExtensions, defaultModes) {
21242
21304
  const {
21243
21305
  customizationService
21244
21306
  } = servicesManager.services;
21307
+ if (!appConfig.modes) {
21308
+ throw new Error('No modes are defined! Check your app-config.js');
21309
+ }
21310
+
21311
+ // Load the mode modules and register the customizations they carry (plain
21312
+ // `customizationId -> value` maps on the mode definition) at Default scope
21313
+ // BEFORE the bootstrap phase applies, so bootstrap / `?customization=`
21314
+ // modules can modify a mode's registered values before anything reads them.
21315
+ // The mode *instances* are only created after the global phase (below), so
21316
+ // they too see any modifications.
21317
+ const loadedModes = await importItems([...(appConfig.modes || []), ...defaultModes]);
21318
+ for (const mode of loadedModes) {
21319
+ if (mode?.customizations) {
21320
+ customizationService.addReferences(mode.customizations, customizationService.Scope.Default);
21321
+ }
21322
+ }
21323
+
21245
21324
  // Resolve every customization module up front — from
21246
21325
  // `appConfig.customizationService.requires` and the `?customization=` URL
21247
- // parameter — long before any mode loads, then apply the `bootstrap` phase
21248
- // BEFORE extensions register so it is in place while they initialize. Modules
21249
- // are only loaded when `appConfig.customizationUrlPrefixes` allows their
21250
- // prefix; the feature is off by default, and a value with an unconfigured
21251
- // prefix throws here (aborting startup) rather than being silently ignored.
21326
+ // parameter — then apply the `bootstrap` phase BEFORE extensions register so
21327
+ // it is in place while they initialize. Modules are only loaded when
21328
+ // `appConfig.customizationUrlPrefixes` allows their prefix; the feature is
21329
+ // off by default, and a value with an unconfigured prefix throws here
21330
+ // (aborting startup) rather than being silently ignored.
21252
21331
  await customizationService.loadAndApplyBootstrapCustomizations(extensionManager);
21253
21332
  await extensionManager.registerExtensions(loadedExtensions, appConfig.dataSources);
21254
21333
 
@@ -21262,11 +21341,6 @@ async function appInit(appConfigOrFunc, defaultExtensions, defaultModes) {
21262
21341
  // TODO: We no longer init webWorkers at app level
21263
21342
  // TODO: We no longer init the user Manager
21264
21343
 
21265
- if (!appConfig.modes) {
21266
- throw new Error('No modes are defined! Check your app-config.js');
21267
- }
21268
- const loadedModes = await importItems([...(appConfig.modes || []), ...defaultModes]);
21269
-
21270
21344
  // This is the name for the loaded instance object
21271
21345
  appConfig.loadedModes = [];
21272
21346
  const modesById = new Set();
@@ -32401,13 +32475,92 @@ class CustomizationService extends pubSubServiceInterface/* .PubSubService */.R
32401
32475
  return transformed;
32402
32476
  }
32403
32477
  const customization = this.globalCustomizations.get(customizationId) ?? this.modeCustomizations.get(customizationId) ?? this.defaultCustomizations.get(customizationId);
32404
- const newTransformed = this.transform(customization);
32478
+ // Apply `inheritsFrom` / `$transform`, then expand any `$reference`
32479
+ // markers (see `_resolveReferences`). `seen` starts with the id being read
32480
+ // so a value that references itself is caught as a cycle.
32481
+ const newTransformed = this._resolveReferences(this.transform(customization), new Set([customizationId]));
32405
32482
  if (newTransformed !== undefined) {
32406
32483
  this.transformedCustomizations.set(customizationId, newTransformed);
32407
32484
  }
32408
32485
  return newTransformed;
32409
32486
  }
32410
32487
 
32488
+ /**
32489
+ * Expands `$reference` markers inside a resolved customization value.
32490
+ *
32491
+ * A `{ $reference: '<name>' }` object is replaced by the value of the
32492
+ * customization `<name>` (itself resolved recursively, so references can
32493
+ * chain). References may appear anywhere in a value:
32494
+ * - as the whole value — an alias for another customization;
32495
+ * - as an item in an **array** — if the referenced value is itself an
32496
+ * array it is spread (flattened) into the parent, so a list can compose
32497
+ * several capability packs by name (e.g. a mode's `toolbarButtons`);
32498
+ * - as a property value of a **plain object** (e.g. each list under a
32499
+ * `toolGroupAdditions` map).
32500
+ *
32501
+ * Because expansion happens at read time (not when customizations are
32502
+ * merged), a later `$set` replaces the reference wholesale — with a different
32503
+ * `{ $reference }` or a hard-coded value — and edits to the referenced target
32504
+ * are picked up live. Only plain arrays/objects are walked; class instances,
32505
+ * functions and React elements are returned untouched, and unchanged values
32506
+ * are returned by identity so non-referencing customizations are not cloned.
32507
+ * Cycles are broken and warned via `seen`.
32508
+ */
32509
+ _resolveReferences(value, seen) {
32510
+ if (!value || typeof value !== 'object' || value.$$typeof) {
32511
+ return value;
32512
+ }
32513
+ if (typeof value.$reference === 'string') {
32514
+ return this._resolveReferenceName(value.$reference, seen);
32515
+ }
32516
+ if (Array.isArray(value)) {
32517
+ let changed = false;
32518
+ const result = [];
32519
+ for (const item of value) {
32520
+ if (item && typeof item === 'object' && !item.$$typeof && typeof item.$reference === 'string') {
32521
+ changed = true;
32522
+ const resolved = this._resolveReferenceName(item.$reference, seen);
32523
+ if (Array.isArray(resolved)) {
32524
+ result.push(...resolved);
32525
+ } else if (resolved !== undefined) {
32526
+ result.push(resolved);
32527
+ }
32528
+ } else {
32529
+ const resolved = this._resolveReferences(item, seen);
32530
+ changed ||= resolved !== item;
32531
+ result.push(resolved);
32532
+ }
32533
+ }
32534
+ return changed ? result : value;
32535
+ }
32536
+ if (!isPlainObject(value)) {
32537
+ return value;
32538
+ }
32539
+ let changed = false;
32540
+ const result = {};
32541
+ for (const [key, val] of Object.entries(value)) {
32542
+ const resolved = this._resolveReferences(val, seen);
32543
+ changed ||= resolved !== val;
32544
+ result[key] = resolved;
32545
+ }
32546
+ return changed ? result : value;
32547
+ }
32548
+
32549
+ /** Resolves a single `$reference` target name, guarding against cycles. */
32550
+ _resolveReferenceName(name, seen) {
32551
+ if (seen.has(name)) {
32552
+ console.warn(`CustomizationService: $reference cycle detected at "${name}"`);
32553
+ return undefined;
32554
+ }
32555
+ const raw = this.globalCustomizations.get(name) ?? this.modeCustomizations.get(name) ?? this.defaultCustomizations.get(name);
32556
+ if (raw === undefined) {
32557
+ console.warn(`CustomizationService: no customization registered for $reference "${name}"`);
32558
+ return undefined;
32559
+ }
32560
+ const nextSeen = new Set(seen).add(name);
32561
+ return this._resolveReferences(this.transform(raw), nextSeen);
32562
+ }
32563
+
32411
32564
  /**
32412
32565
  * Returns a customization value, or the provided fallback when unset.
32413
32566
  */
@@ -32955,6 +33108,15 @@ function normalizeCustomizationConfig(configuration) {
32955
33108
  }
32956
33109
  return {};
32957
33110
  }
33111
+
33112
+ /** True for `{}`-literal / null-prototype objects (not arrays or class instances). */
33113
+ function isPlainObject(value) {
33114
+ if (value === null || typeof value !== 'object') {
33115
+ return false;
33116
+ }
33117
+ const proto = Object.getPrototypeOf(value);
33118
+ return proto === Object.prototype || proto === null;
33119
+ }
32958
33120
  function hasDollarKey(value) {
32959
33121
  if (Array.isArray(value)) {
32960
33122
  for (const item of value) {
@@ -32971,7 +33133,11 @@ function hasDollarKey(value) {
32971
33133
  return false;
32972
33134
  }
32973
33135
  for (const key of Object.keys(value)) {
32974
- if (key.startsWith('$') && key !== '$transform') {
33136
+ // `$transform` and `$reference` are read-time markers resolved by the
33137
+ // service (in `transform` / `_resolveReferences`), not immutability-helper
33138
+ // merge commands — so a value carrying them is stored verbatim rather than
33139
+ // being run through `update()`.
33140
+ if (key.startsWith('$') && key !== '$transform' && key !== '$reference') {
32975
33141
  return true;
32976
33142
  }
32977
33143
  if (hasDollarKey(value[key])) {
@@ -43373,7 +43539,7 @@ const detectionOptions = {
43373
43539
  }
43374
43540
  });
43375
43541
  ;// CONCATENATED MODULE: ../../i18n/package.json
43376
- var package_namespaceObject = JSON.parse('{"rE":"3.13.0-beta.115"}')
43542
+ var package_namespaceObject = JSON.parse('{"rE":"3.13.0-beta.117"}')
43377
43543
  ;// CONCATENATED MODULE: ../../i18n/src/utils.js
43378
43544
  const languagesMap = {
43379
43545
  ar: 'Arabic',
@@ -447718,7 +447884,7 @@ __webpack_require__.u = (chunkId) => {
447718
447884
  // return url for filenames not based on template
447719
447885
 
447720
447886
  // return url for filenames based on template
447721
- return "" + ({1644: "interpolation",6915: "histogram-worker",8547: "compute",8781: "polySeg",}[chunkId] || chunkId) + ".bundle." + {100: "ac04a425c0851574",1180: "c19c443fe8d26719",1206: "47f070e2254d128c",1229: "f721ec472f3d61bf",1602: "097ec19e8e61516f",1644: "f522fc61851f35ed",2690: "f5dc28ac498de122",2779: "dca036a18399be96",3500: "1e063b7b4910d6cf",3760: "6c7eeb4b7f1583ca",419: "9d0e6a72e1e3a17b",4556: "b705ab15473128c7",4683: "5d12928efa9f70f4",4834: "a91450199d0f45e4",5189: "2a0f740738759e32",5302: "d6194babac4a763e",5406: "4dcfa7c697973300",5448: "1e50777e4c4e122a",5642: "1622d255af1102d8",5696: "9f0366ad867385bc",5731: "a4e001a42e60e779",5910: "5561806884c95754",6001: "0789789db5410764",6489: "941eaec5bde178b6",6495: "84b83aa091c338cd",6915: "11211bad02ea21bb",7231: "46f843b74a964f89",7248: "f761b21f343d4b9f",7295: "4d4b6de4d2bb8856",7463: "40668aa8d083d077",7701: "945445d6681ddd20",781: "efb0a6981676cebb",8097: "8ae6404ba94890a0",8423: "5d1b3092bc9562c9",8432: "7d5ebe1ed1610bc3",8547: "77e80c1775429bd6",8781: "5e350e0723aa59b6",8832: "ede981706cac8e15",899: "e786f8dfb66d74ca",9068: "cd36fcb4e15a153e",9116: "225e003c28c550c1",9290: "a18c40b82772a3c6",9383: "9b1d03c71cc52f4f",9402: "6549cc304496cd5c",9415: "2a970c71de4014bf",9437: "0fff227a859992ea",9560: "bb39f946ea79cf0e",}[chunkId] + ".js"
447887
+ return "" + ({1644: "interpolation",6915: "histogram-worker",8547: "compute",8781: "polySeg",}[chunkId] || chunkId) + ".bundle." + {100: "6ba1a0be02710b9f",1180: "25017eea64524896",1206: "e04ca1efe6f987ba",1229: "f721ec472f3d61bf",1483: "5a98bf0d4c26aa01",1602: "2a0e1a9a73063ab5",1644: "f522fc61851f35ed",2343: "931645133f98ca47",2690: "f5dc28ac498de122",2779: "56f7da594c887ff6",3500: "7afd6d2e9345fca0",3760: "553d1b88392a20b4",4556: "454bc9719a06bc3f",4683: "bfb5c3739e9886b5",5189: "2a0f740738759e32",5302: "d6194babac4a763e",5406: "4dcfa7c697973300",5448: "5686ebb99c379f64",5642: "1622d255af1102d8",5696: "615658b8dead54ce",5731: "a4e001a42e60e779",5910: "0f19608f3e76859b",6489: "941eaec5bde178b6",6495: "84b83aa091c338cd",6749: "ed2f94d2dd4c9a24",6915: "11211bad02ea21bb",7231: "46f843b74a964f89",7248: "4c7d834f2ec140c7",7463: "40668aa8d083d077",7499: "743782416c5f430e",781: "d353624c7a811425",8097: "8ae6404ba94890a0",8423: "1f3a472a7f691c1a",8432: "7d5ebe1ed1610bc3",8492: "44a55a259584d665",8547: "77e80c1775429bd6",8781: "5e350e0723aa59b6",8832: "6f31a982f82b96da",899: "50c16f860acbc848",9068: "95f1e638ef694ea9",9116: "079a64a12966429c",9290: "db0d1eb62fa6ee8b",9383: "9b1d03c71cc52f4f",9402: "57041a8d06a36e8e",9415: "770426487f8c0dfa",9437: "0045fb70b8fa0e7b",9560: "bb39f946ea79cf0e",}[chunkId] + ".js"
447722
447888
  }
447723
447889
  })();
447724
447890
  // webpack/runtime/get mini-css chunk filename
@@ -447928,10 +448094,11 @@ __webpack_require__.f.miniCss = function (chunkId, promises) {
447928
448094
  5910: 1,
447929
448095
  6214: 1,
447930
448096
  7231: 1,
447931
- 7295: 1,
447932
448097
  7463: 1,
447933
448098
  781: 1,
447934
448099
  8423: 1,
448100
+ 8492: 1,
448101
+ 8595: 1,
447935
448102
  8832: 1,
447936
448103
  9415: 1,
447937
448104
  976: 1,
@@ -447954,7 +448121,7 @@ __webpack_require__.f.miniCss = function (chunkId, promises) {
447954
448121
 
447955
448122
  // no hmr
447956
448123
  __webpack_require__.F.miniCss = (chunkId) => {
447957
- if ((!__webpack_require__.o(installedCssChunks, chunkId) || installedCssChunks[chunkId] === undefined) && /^(7(231|295|463|81)|9(415|509|76)|1602|3760|3833|5189|5910|6214|8423|8832)$/.test(chunkId)) {
448124
+ if ((!__webpack_require__.o(installedCssChunks, chunkId) || installedCssChunks[chunkId] === undefined) && /^(7(231|463|81)|9(415|509|76)|8(423|492|595|832)|1602|3760|3833|5189|5910|6214)$/.test(chunkId)) {
447958
448125
  installedCssChunks[chunkId] = null;
447959
448126
 
447960
448127
  var link = document.createElement('link');
@@ -447991,7 +448158,7 @@ if (installedChunkData !== 0) {
447991
448158
  if (installedChunkData) {
447992
448159
  promises.push(installedChunkData[2]);
447993
448160
  } else {
447994
- if (!/^(3833|6214|976)$/.test(chunkId)) {
448161
+ if (!/^(3833|6214|8595|976)$/.test(chunkId)) {
447995
448162
  // setup Promise in chunk cache
447996
448163
  var promise = new Promise((resolve, reject) => (installedChunkData = installedChunks[chunkId] = [resolve, reject]));
447997
448164
  promises.push((installedChunkData[2] = promise));
@@ -448030,7 +448197,7 @@ if (installedChunkData !== 0) {
448030
448197
 
448031
448198
  }
448032
448199
  __webpack_require__.F.j = (chunkId) => {
448033
- if ((!__webpack_require__.o(installedChunks, chunkId) || installedChunks[chunkId] === undefined) && !/^(3833|6214|976)$/.test(chunkId)) {
448200
+ if ((!__webpack_require__.o(installedChunks, chunkId) || installedChunks[chunkId] === undefined) && !/^(3833|6214|8595|976)$/.test(chunkId)) {
448034
448201
  installedChunks[chunkId] = null;
448035
448202
  var link = document.createElement('link');
448036
448203
 
@@ -448078,7 +448245,7 @@ chunkLoadingGlobal.push = __rspack_jsonp.bind(null, chunkLoadingGlobal.push.bind
448078
448245
  })();
448079
448246
  // webpack/runtime/chunk_prefetch_trigger
448080
448247
  (() => {
448081
- var chunkToChildrenMap = {"3833":[7231],"3760":[7231,9068,1206],"976":[7231,9068],"781":[7231,899],"9415":[7231,5448],"1602":[7231],"9116":[7463],"7295":[7231],"8423":[7231],"3500":[8432,5642,9402,7701,5910],"5910":[7231]};
448248
+ var chunkToChildrenMap = {"3833":[7231],"3760":[7231,9068,1206],"976":[7231,9068],"781":[7231,899],"9415":[7231,5448],"1602":[7231],"9116":[7463],"8595":[7231],"8423":[7231],"3500":[8432,5642,9402,2343,5910],"5910":[7231],"8492":[7231]};
448082
448249
  __webpack_require__.f.prefetch = (chunkId, promises) => {
448083
448250
  Promise.all(promises).then(() => {
448084
448251
  var chunks = chunkToChildrenMap[chunkId];