From 9ad0d7fc8cf34867fa2cfc2bf2b2f63451ec03e5 Mon Sep 17 00:00:00 2001 From: Bill Wallace Date: Wed, 1 Oct 2025 14:31:26 -0400 Subject: [PATCH] feat: Add inherit from basic/longitudinal modes (#5435) Co-authored-by: Ibrahim --- bun.lock | 368 ++++++++--------- modes/basic/.gitignore | 104 +++++ modes/basic/.prettierrc | 11 + modes/basic/.webpack/webpack.prod.js | 52 +++ modes/basic/LICENSE | 18 + modes/basic/README.md | 7 + modes/basic/babel.config.js | 43 ++ modes/basic/package.json | 49 +++ modes/basic/src/id.js | 5 + modes/basic/src/index.tsx | 377 ++++++++++++++++++ .../src/initToolGroups.ts} | 2 - .../src/toolbarButtons.ts | 0 modes/longitudinal/.webpack/webpack.prod.js | 1 - modes/longitudinal/src/index.ts | 335 +++------------- package.json | 17 +- platform/app/pluginConfig.json | 3 + platform/app/public/config/kheops.js | 10 + platform/app/src/routes/WorkList/WorkList.tsx | 13 +- platform/cli/templates/mode/src/index.tsx | 170 +------- .../services/ToolBarService/ToolbarService.ts | 2 + platform/core/src/utils/index.ts | 3 + .../src/utils/structuredCloneWithFunctions.ts | 40 ++ .../migration-guide/3p11-to-3p12/index.md | 18 + platform/docs/docs/platform/modes/index.md | 131 +++++- platform/docs/docs/platform/modes/validity.md | 13 +- platform/ui/src/components/Button/Button.tsx | 1 + .../ui/src/components/Button/ButtonEnums.ts | 1 + yarn.lock | 102 ++--- 28 files changed, 1153 insertions(+), 743 deletions(-) create mode 100644 modes/basic/.gitignore create mode 100644 modes/basic/.prettierrc create mode 100644 modes/basic/.webpack/webpack.prod.js create mode 100644 modes/basic/LICENSE create mode 100644 modes/basic/README.md create mode 100644 modes/basic/babel.config.js create mode 100644 modes/basic/package.json create mode 100644 modes/basic/src/id.js create mode 100644 modes/basic/src/index.tsx rename modes/{longitudinal/src/initToolGroups.js => basic/src/initToolGroups.ts} (99%) rename modes/{longitudinal => basic}/src/toolbarButtons.ts (100%) create mode 100644 platform/core/src/utils/structuredCloneWithFunctions.ts diff --git a/bun.lock b/bun.lock index f3e6733f3..2c1df1ea9 100644 --- a/bun.lock +++ b/bun.lock @@ -26,6 +26,7 @@ "babel-loader": "8.4.1", "babel-plugin-istanbul": "^7.0.0", "babel-plugin-transform-import-meta": "2.3.3", + "cross-env": "7.0.3", "css-loader": "6.11.0", "cypress": "14.5.2", "cypress-file-upload": "^5.0.8", @@ -51,7 +52,7 @@ }, "addOns/externals/devDependencies": { "name": "@externals/devDependencies", - "version": "3.12.0-beta.36", + "version": "3.12.0-beta.38", "dependencies": { "@babel/runtime": "^7.20.13", "@kitware/vtk.js": "32.12.0", @@ -136,14 +137,14 @@ }, "addOns/externals/dicom-microscopy-viewer": { "name": "@externals/dicom-microscopy-viewer", - "version": "3.12.0-beta.36", + "version": "3.12.0-beta.38", "dependencies": { "dicom-microscopy-viewer": "^0.48.6", }, }, "extensions/cornerstone": { "name": "@ohif/extension-cornerstone", - "version": "3.12.0-beta.36", + "version": "3.12.0-beta.38", "dependencies": { "@babel/runtime": "^7.20.13", "@cornerstonejs/adapters": "4.3.14", @@ -169,8 +170,8 @@ "@cornerstonejs/codec-openjpeg": "^1.2.4", "@cornerstonejs/codec-openjph": "^2.4.5", "@cornerstonejs/dicom-image-loader": "4.3.14", - "@ohif/core": "3.12.0-beta.36", - "@ohif/ui": "3.12.0-beta.36", + "@ohif/core": "3.12.0-beta.38", + "@ohif/ui": "3.12.0-beta.38", "dcmjs": "0.43.1", "dicom-parser": "^1.8.21", "hammerjs": "^2.0.8", @@ -182,7 +183,7 @@ }, "extensions/cornerstone-dicom-pmap": { "name": "@ohif/extension-cornerstone-dicom-pmap", - "version": "3.12.0-beta.36", + "version": "3.12.0-beta.38", "dependencies": { "@babel/runtime": "^7.20.13", "@cornerstonejs/adapters": "4.3.14", @@ -191,10 +192,10 @@ "react-color": "^2.19.3", }, "peerDependencies": { - "@ohif/core": "3.12.0-beta.36", - "@ohif/extension-cornerstone": "3.12.0-beta.36", - "@ohif/extension-default": "3.12.0-beta.36", - "@ohif/i18n": "3.12.0-beta.36", + "@ohif/core": "3.12.0-beta.38", + "@ohif/extension-cornerstone": "3.12.0-beta.38", + "@ohif/extension-default": "3.12.0-beta.38", + "@ohif/i18n": "3.12.0-beta.38", "prop-types": "^15.6.2", "react": "^18.3.1", "react-dom": "^18.3.1", @@ -205,16 +206,16 @@ }, "extensions/cornerstone-dicom-rt": { "name": "@ohif/extension-cornerstone-dicom-rt", - "version": "3.12.0-beta.36", + "version": "3.12.0-beta.38", "dependencies": { "@babel/runtime": "^7.20.13", "react-color": "^2.19.3", }, "peerDependencies": { - "@ohif/core": "3.12.0-beta.36", - "@ohif/extension-cornerstone": "3.12.0-beta.36", - "@ohif/extension-default": "3.12.0-beta.36", - "@ohif/i18n": "3.12.0-beta.36", + "@ohif/core": "3.12.0-beta.38", + "@ohif/extension-cornerstone": "3.12.0-beta.38", + "@ohif/extension-default": "3.12.0-beta.38", + "@ohif/i18n": "3.12.0-beta.38", "prop-types": "^15.6.2", "react": "^18.3.1", "react-dom": "^18.3.1", @@ -225,7 +226,7 @@ }, "extensions/cornerstone-dicom-seg": { "name": "@ohif/extension-cornerstone-dicom-seg", - "version": "3.12.0-beta.36", + "version": "3.12.0-beta.38", "dependencies": { "@babel/runtime": "^7.20.13", "@cornerstonejs/adapters": "4.3.14", @@ -234,10 +235,10 @@ "react-color": "^2.19.3", }, "peerDependencies": { - "@ohif/core": "3.12.0-beta.36", - "@ohif/extension-cornerstone": "3.12.0-beta.36", - "@ohif/extension-default": "3.12.0-beta.36", - "@ohif/i18n": "3.12.0-beta.36", + "@ohif/core": "3.12.0-beta.38", + "@ohif/extension-cornerstone": "3.12.0-beta.38", + "@ohif/extension-default": "3.12.0-beta.38", + "@ohif/i18n": "3.12.0-beta.38", "prop-types": "^15.6.2", "react": "^18.3.1", "react-dom": "^18.3.1", @@ -248,7 +249,7 @@ }, "extensions/cornerstone-dicom-sr": { "name": "@ohif/extension-cornerstone-dicom-sr", - "version": "3.12.0-beta.36", + "version": "3.12.0-beta.38", "dependencies": { "@babel/runtime": "^7.20.13", "@cornerstonejs/adapters": "4.3.14", @@ -257,10 +258,10 @@ "classnames": "^2.3.2", }, "peerDependencies": { - "@ohif/core": "3.12.0-beta.36", - "@ohif/extension-cornerstone": "3.12.0-beta.36", - "@ohif/extension-measurement-tracking": "3.12.0-beta.36", - "@ohif/ui": "3.12.0-beta.36", + "@ohif/core": "3.12.0-beta.38", + "@ohif/extension-cornerstone": "3.12.0-beta.38", + "@ohif/extension-measurement-tracking": "3.12.0-beta.38", + "@ohif/ui": "3.12.0-beta.38", "dcmjs": "0.43.1", "dicom-parser": "^1.8.9", "hammerjs": "^2.0.8", @@ -270,7 +271,7 @@ }, "extensions/cornerstone-dynamic-volume": { "name": "@ohif/extension-cornerstone-dynamic-volume", - "version": "3.12.0-beta.36", + "version": "3.12.0-beta.38", "dependencies": { "@babel/runtime": "^7.20.13", "@cornerstonejs/core": "4.3.14", @@ -278,11 +279,11 @@ "classnames": "^2.3.2", }, "peerDependencies": { - "@ohif/core": "3.12.0-beta.36", - "@ohif/extension-cornerstone": "3.12.0-beta.36", - "@ohif/extension-default": "3.12.0-beta.36", - "@ohif/i18n": "3.12.0-beta.36", - "@ohif/ui": "3.12.0-beta.36", + "@ohif/core": "3.12.0-beta.38", + "@ohif/extension-cornerstone": "3.12.0-beta.38", + "@ohif/extension-default": "3.12.0-beta.38", + "@ohif/i18n": "3.12.0-beta.38", + "@ohif/ui": "3.12.0-beta.38", "dcmjs": "0.43.1", "dicom-parser": "^1.8.21", "hammerjs": "^2.0.8", @@ -292,7 +293,7 @@ }, "extensions/default": { "name": "@ohif/extension-default", - "version": "3.12.0-beta.36", + "version": "3.12.0-beta.38", "dependencies": { "@babel/runtime": "^7.20.13", "@cornerstonejs/calculate-suv": "^1.1.0", @@ -300,8 +301,8 @@ "lodash.uniqby": "^4.7.0", }, "peerDependencies": { - "@ohif/core": "3.12.0-beta.36", - "@ohif/i18n": "3.12.0-beta.36", + "@ohif/core": "3.12.0-beta.38", + "@ohif/i18n": "3.12.0-beta.38", "dcmjs": "0.43.1", "dicomweb-client": "^0.10.4", "prop-types": "^15.6.2", @@ -315,7 +316,7 @@ }, "extensions/dicom-microscopy": { "name": "@ohif/extension-dicom-microscopy", - "version": "3.12.0-beta.36", + "version": "3.12.0-beta.38", "dependencies": { "@babel/runtime": "^7.20.13", "@cornerstonejs/codec-charls": "^1.2.3", @@ -326,10 +327,10 @@ "mathjs": "^12.4.2", }, "peerDependencies": { - "@ohif/core": "3.12.0-beta.36", - "@ohif/extension-default": "3.12.0-beta.36", - "@ohif/i18n": "3.12.0-beta.36", - "@ohif/ui": "3.12.0-beta.36", + "@ohif/core": "3.12.0-beta.38", + "@ohif/extension-default": "3.12.0-beta.38", + "@ohif/i18n": "3.12.0-beta.38", + "@ohif/ui": "3.12.0-beta.38", "prop-types": "^15.6.2", "react": "^18.3.1", "react-dom": "^18.3.1", @@ -340,14 +341,14 @@ }, "extensions/dicom-pdf": { "name": "@ohif/extension-dicom-pdf", - "version": "3.12.0-beta.36", + "version": "3.12.0-beta.38", "dependencies": { "@babel/runtime": "^7.20.13", "classnames": "^2.3.2", }, "peerDependencies": { - "@ohif/core": "3.12.0-beta.36", - "@ohif/ui": "3.12.0-beta.36", + "@ohif/core": "3.12.0-beta.38", + "@ohif/ui": "3.12.0-beta.38", "dcmjs": "0.43.1", "dicom-parser": "^1.8.9", "hammerjs": "^2.0.8", @@ -357,14 +358,14 @@ }, "extensions/dicom-video": { "name": "@ohif/extension-dicom-video", - "version": "3.12.0-beta.36", + "version": "3.12.0-beta.38", "dependencies": { "@babel/runtime": "^7.20.13", "classnames": "^2.3.2", }, "peerDependencies": { - "@ohif/core": "3.12.0-beta.36", - "@ohif/ui": "3.12.0-beta.36", + "@ohif/core": "3.12.0-beta.38", + "@ohif/ui": "3.12.0-beta.38", "dcmjs": "0.43.1", "dicom-parser": "^1.8.9", "hammerjs": "^2.0.8", @@ -374,20 +375,20 @@ }, "extensions/measurement-tracking": { "name": "@ohif/extension-measurement-tracking", - "version": "3.12.0-beta.36", + "version": "3.12.0-beta.38", "dependencies": { "@babel/runtime": "^7.20.13", - "@ohif/ui": "3.12.0-beta.36", + "@ohif/ui": "3.12.0-beta.38", "@xstate/react": "^3.2.2", "xstate": "^4.10.0", }, "peerDependencies": { "@cornerstonejs/core": "4.3.14", "@cornerstonejs/tools": "4.3.14", - "@ohif/core": "3.12.0-beta.36", - "@ohif/extension-cornerstone-dicom-sr": "3.12.0-beta.36", - "@ohif/extension-default": "3.12.0-beta.36", - "@ohif/ui": "3.12.0-beta.36", + "@ohif/core": "3.12.0-beta.38", + "@ohif/extension-cornerstone-dicom-sr": "3.12.0-beta.38", + "@ohif/extension-default": "3.12.0-beta.38", + "@ohif/ui": "3.12.0-beta.38", "classnames": "^2.3.2", "dcmjs": "0.43.1", "lodash.debounce": "^4.0.8", @@ -400,14 +401,14 @@ }, "extensions/test-extension": { "name": "@ohif/extension-test", - "version": "3.12.0-beta.36", + "version": "3.12.0-beta.38", "dependencies": { "@babel/runtime": "^7.20.13", "classnames": "^2.3.2", }, "peerDependencies": { - "@ohif/core": "3.12.0-beta.36", - "@ohif/ui": "3.12.0-beta.36", + "@ohif/core": "3.12.0-beta.38", + "@ohif/ui": "3.12.0-beta.38", "dcmjs": "0.43.1", "dicom-parser": "^1.8.9", "hammerjs": "^2.0.8", @@ -417,14 +418,14 @@ }, "extensions/tmtv": { "name": "@ohif/extension-tmtv", - "version": "3.12.0-beta.36", + "version": "3.12.0-beta.38", "dependencies": { "@babel/runtime": "^7.20.13", "classnames": "^2.3.2", }, "peerDependencies": { - "@ohif/core": "3.12.0-beta.32", - "@ohif/ui": "3.12.0-beta.32", + "@ohif/core": "3.12.0-beta.38", + "@ohif/ui": "3.12.0-beta.38", "dcmjs": "0.43.1", "dicom-parser": "^1.8.9", "hammerjs": "^2.0.8", @@ -434,16 +435,16 @@ }, "extensions/usAnnotation": { "name": "@ohif/extension-ultrasound-pleura-bline", - "version": "3.12.0-beta.36", + "version": "3.12.0-beta.38", "dependencies": { "@babel/runtime": "^7.20.13", "@cornerstonejs/core": "4.3.14", "@cornerstonejs/tools": "4.3.14", - "@ohif/core": "3.12.0-beta.36", - "@ohif/extension-cornerstone": "3.12.0-beta.36", - "@ohif/extension-default": "3.12.0-beta.36", - "@ohif/i18n": "3.12.0-beta.36", - "@ohif/ui-next": "3.12.0-beta.36", + "@ohif/core": "3.12.0-beta.38", + "@ohif/extension-cornerstone": "3.12.0-beta.38", + "@ohif/extension-default": "3.12.0-beta.38", + "@ohif/i18n": "3.12.0-beta.38", + "@ohif/ui-next": "3.12.0-beta.38", }, "devDependencies": { "@babel/core": "7.28.0", @@ -484,9 +485,30 @@ "webpack-merge": "^5.7.3", }, }, + "modes/basic": { + "name": "@ohif/mode-basic", + "version": "3.12.0-beta.38", + "dependencies": { + "@babel/runtime": "^7.20.13", + }, + "devDependencies": { + "webpack": "5.95.0", + "webpack-merge": "^5.7.3", + }, + "peerDependencies": { + "@ohif/core": "3.12.0-beta.38", + "@ohif/extension-cornerstone": "3.12.0-beta.38", + "@ohif/extension-cornerstone-dicom-rt": "3.12.0-beta.38", + "@ohif/extension-cornerstone-dicom-seg": "3.12.0-beta.38", + "@ohif/extension-cornerstone-dicom-sr": "3.12.0-beta.38", + "@ohif/extension-default": "3.12.0-beta.38", + "@ohif/extension-dicom-pdf": "3.12.0-beta.38", + "@ohif/extension-dicom-video": "3.12.0-beta.38", + }, + }, "modes/basic-dev-mode": { "name": "@ohif/mode-basic-dev-mode", - "version": "3.12.0-beta.36", + "version": "3.12.0-beta.38", "dependencies": { "@babel/runtime": "^7.20.13", "i18next": "^17.0.3", @@ -496,17 +518,17 @@ "webpack-merge": "^5.7.3", }, "peerDependencies": { - "@ohif/core": "3.12.0-beta.36", - "@ohif/extension-cornerstone": "3.12.0-beta.36", - "@ohif/extension-cornerstone-dicom-sr": "3.12.0-beta.36", - "@ohif/extension-default": "3.12.0-beta.36", - "@ohif/extension-dicom-pdf": "3.12.0-beta.36", - "@ohif/extension-dicom-video": "3.12.0-beta.36", + "@ohif/core": "3.12.0-beta.38", + "@ohif/extension-cornerstone": "3.12.0-beta.38", + "@ohif/extension-cornerstone-dicom-sr": "3.12.0-beta.38", + "@ohif/extension-default": "3.12.0-beta.38", + "@ohif/extension-dicom-pdf": "3.12.0-beta.38", + "@ohif/extension-dicom-video": "3.12.0-beta.38", }, }, "modes/basic-test-mode": { "name": "@ohif/mode-test", - "version": "3.12.0-beta.36", + "version": "3.12.0-beta.38", "dependencies": { "@babel/runtime": "^7.20.13", "i18next": "^17.0.3", @@ -516,19 +538,19 @@ "webpack-merge": "^5.7.3", }, "peerDependencies": { - "@ohif/core": "3.12.0-beta.36", - "@ohif/extension-cornerstone": "3.12.0-beta.36", - "@ohif/extension-cornerstone-dicom-sr": "3.12.0-beta.36", - "@ohif/extension-default": "3.12.0-beta.36", - "@ohif/extension-dicom-pdf": "3.12.0-beta.36", - "@ohif/extension-dicom-video": "3.12.0-beta.36", - "@ohif/extension-measurement-tracking": "3.12.0-beta.36", - "@ohif/extension-test": "3.12.0-beta.36", + "@ohif/core": "3.12.0-beta.38", + "@ohif/extension-cornerstone": "3.12.0-beta.38", + "@ohif/extension-cornerstone-dicom-sr": "3.12.0-beta.38", + "@ohif/extension-default": "3.12.0-beta.38", + "@ohif/extension-dicom-pdf": "3.12.0-beta.38", + "@ohif/extension-dicom-video": "3.12.0-beta.38", + "@ohif/extension-measurement-tracking": "3.12.0-beta.38", + "@ohif/extension-test": "3.12.0-beta.38", }, }, "modes/longitudinal": { "name": "@ohif/mode-longitudinal", - "version": "3.12.0-beta.36", + "version": "3.12.0-beta.38", "dependencies": { "@babel/runtime": "^7.20.13", "i18next": "^17.0.3", @@ -538,32 +560,32 @@ "webpack-merge": "^5.7.3", }, "peerDependencies": { - "@ohif/core": "3.12.0-beta.36", - "@ohif/extension-cornerstone": "3.12.0-beta.36", - "@ohif/extension-cornerstone-dicom-rt": "3.12.0-beta.36", - "@ohif/extension-cornerstone-dicom-seg": "3.12.0-beta.36", - "@ohif/extension-cornerstone-dicom-sr": "3.12.0-beta.36", - "@ohif/extension-default": "3.12.0-beta.36", - "@ohif/extension-dicom-pdf": "3.12.0-beta.36", - "@ohif/extension-dicom-video": "3.12.0-beta.36", - "@ohif/extension-measurement-tracking": "3.12.0-beta.36", + "@ohif/core": "3.12.0-beta.38", + "@ohif/extension-cornerstone": "3.12.0-beta.38", + "@ohif/extension-cornerstone-dicom-rt": "3.12.0-beta.38", + "@ohif/extension-cornerstone-dicom-seg": "3.12.0-beta.38", + "@ohif/extension-cornerstone-dicom-sr": "3.12.0-beta.38", + "@ohif/extension-default": "3.12.0-beta.38", + "@ohif/extension-dicom-pdf": "3.12.0-beta.38", + "@ohif/extension-dicom-video": "3.12.0-beta.38", + "@ohif/extension-measurement-tracking": "3.12.0-beta.38", }, }, "modes/microscopy": { "name": "@ohif/mode-microscopy", - "version": "3.12.0-beta.36", + "version": "3.12.0-beta.38", "dependencies": { "@babel/runtime": "^7.20.13", "i18next": "^17.0.3", }, "peerDependencies": { - "@ohif/core": "3.12.0-beta.36", - "@ohif/extension-dicom-microscopy": "3.12.0-beta.36", + "@ohif/core": "3.12.0-beta.38", + "@ohif/extension-dicom-microscopy": "3.12.0-beta.38", }, }, "modes/preclinical-4d": { "name": "@ohif/mode-preclinical-4d", - "version": "3.12.0-beta.36", + "version": "3.12.0-beta.38", "dependencies": { "@babel/runtime": "^7.20.13", }, @@ -572,17 +594,17 @@ "webpack-merge": "^5.7.3", }, "peerDependencies": { - "@ohif/core": "3.12.0-beta.32", - "@ohif/extension-cornerstone": "3.12.0-beta.32", - "@ohif/extension-cornerstone-dicom-seg": "3.12.0-beta.32", - "@ohif/extension-cornerstone-dynamic-volume": "3.12.0-beta.32", - "@ohif/extension-default": "3.12.0-beta.32", - "@ohif/extension-tmtv": "3.12.0-beta.32", + "@ohif/core": "3.12.0-beta.38", + "@ohif/extension-cornerstone": "3.12.0-beta.38", + "@ohif/extension-cornerstone-dicom-seg": "3.12.0-beta.38", + "@ohif/extension-cornerstone-dynamic-volume": "3.12.0-beta.38", + "@ohif/extension-default": "3.12.0-beta.38", + "@ohif/extension-tmtv": "3.12.0-beta.38", }, }, "modes/segmentation": { "name": "@ohif/mode-segmentation", - "version": "3.12.0-beta.36", + "version": "3.12.0-beta.38", "dependencies": { "@babel/runtime": "^7.20.13", "i18next": "^17.0.3", @@ -614,19 +636,19 @@ "webpack-merge": "^5.7.3", }, "peerDependencies": { - "@ohif/core": "3.12.0-beta.32", - "@ohif/extension-cornerstone": "3.12.0-beta.32", - "@ohif/extension-cornerstone-dicom-rt": "3.12.0-beta.32", - "@ohif/extension-cornerstone-dicom-seg": "3.12.0-beta.32", - "@ohif/extension-cornerstone-dicom-sr": "3.12.0-beta.32", - "@ohif/extension-default": "3.12.0-beta.32", - "@ohif/extension-dicom-pdf": "3.12.0-beta.32", - "@ohif/extension-dicom-video": "3.12.0-beta.32", + "@ohif/core": "3.12.0-beta.38", + "@ohif/extension-cornerstone": "3.12.0-beta.38", + "@ohif/extension-cornerstone-dicom-rt": "3.12.0-beta.38", + "@ohif/extension-cornerstone-dicom-seg": "3.12.0-beta.38", + "@ohif/extension-cornerstone-dicom-sr": "3.12.0-beta.38", + "@ohif/extension-default": "3.12.0-beta.38", + "@ohif/extension-dicom-pdf": "3.12.0-beta.38", + "@ohif/extension-dicom-video": "3.12.0-beta.38", }, }, "modes/tmtv": { "name": "@ohif/mode-tmtv", - "version": "3.12.0-beta.36", + "version": "3.12.0-beta.38", "dependencies": { "@babel/runtime": "^7.20.13", "i18next": "^17.0.3", @@ -636,25 +658,25 @@ "webpack-merge": "^5.7.3", }, "peerDependencies": { - "@ohif/core": "3.12.0-beta.32", - "@ohif/extension-cornerstone": "3.12.0-beta.32", - "@ohif/extension-cornerstone-dicom-sr": "3.12.0-beta.32", - "@ohif/extension-default": "3.12.0-beta.32", - "@ohif/extension-dicom-pdf": "3.12.0-beta.32", - "@ohif/extension-dicom-video": "3.12.0-beta.32", - "@ohif/extension-measurement-tracking": "3.12.0-beta.32", + "@ohif/core": "3.12.0-beta.38", + "@ohif/extension-cornerstone": "3.12.0-beta.38", + "@ohif/extension-cornerstone-dicom-sr": "3.12.0-beta.38", + "@ohif/extension-default": "3.12.0-beta.38", + "@ohif/extension-dicom-pdf": "3.12.0-beta.38", + "@ohif/extension-dicom-video": "3.12.0-beta.38", + "@ohif/extension-measurement-tracking": "3.12.0-beta.38", }, }, "modes/usAnnotation": { "name": "@ohif/mode-ultrasound-pleura-bline", - "version": "3.12.0-beta.36", + "version": "3.12.0-beta.38", "dependencies": { "@babel/runtime": "^7.20.13", "@cornerstonejs/core": "4.3.14", "@cornerstonejs/tools": "4.3.14", - "@ohif/core": "3.12.0-beta.36", - "@ohif/extension-cornerstone-dicom-sr": "3.12.0-beta.36", - "@ohif/extension-ultrasound-pleura-bline": "3.12.0-beta.36", + "@ohif/core": "3.12.0-beta.38", + "@ohif/extension-cornerstone-dicom-sr": "3.12.0-beta.38", + "@ohif/extension-ultrasound-pleura-bline": "3.12.0-beta.38", "i18next": "^17.0.3", }, "devDependencies": { @@ -686,7 +708,7 @@ }, "platform/app": { "name": "@ohif/app", - "version": "3.12.0-beta.36", + "version": "3.12.0-beta.38", "dependencies": { "@babel/runtime": "^7.20.13", "@cornerstonejs/codec-charls": "^1.2.3", @@ -695,25 +717,25 @@ "@cornerstonejs/codec-openjph": "^2.4.5", "@cornerstonejs/dicom-image-loader": "4.3.14", "@emotion/serialize": "^1.1.3", - "@ohif/core": "3.12.0-beta.36", - "@ohif/extension-cornerstone": "3.12.0-beta.36", - "@ohif/extension-cornerstone-dicom-rt": "3.12.0-beta.36", - "@ohif/extension-cornerstone-dicom-seg": "3.12.0-beta.36", - "@ohif/extension-cornerstone-dicom-sr": "3.12.0-beta.36", - "@ohif/extension-default": "3.12.0-beta.36", - "@ohif/extension-dicom-microscopy": "3.12.0-beta.36", - "@ohif/extension-dicom-pdf": "3.12.0-beta.36", - "@ohif/extension-dicom-video": "3.12.0-beta.36", - "@ohif/extension-test": "3.12.0-beta.36", - "@ohif/extension-ultrasound-pleura-bline": "3.12.0-beta.36", - "@ohif/i18n": "3.12.0-beta.36", - "@ohif/mode-basic-dev-mode": "3.12.0-beta.36", - "@ohif/mode-longitudinal": "3.12.0-beta.36", - "@ohif/mode-microscopy": "3.12.0-beta.36", - "@ohif/mode-test": "3.12.0-beta.36", - "@ohif/mode-ultrasound-pleura-bline": "3.12.0-beta.36", - "@ohif/ui": "3.12.0-beta.36", - "@ohif/ui-next": "3.12.0-beta.36", + "@ohif/core": "3.12.0-beta.38", + "@ohif/extension-cornerstone": "3.12.0-beta.38", + "@ohif/extension-cornerstone-dicom-rt": "3.12.0-beta.38", + "@ohif/extension-cornerstone-dicom-seg": "3.12.0-beta.38", + "@ohif/extension-cornerstone-dicom-sr": "3.12.0-beta.38", + "@ohif/extension-default": "3.12.0-beta.38", + "@ohif/extension-dicom-microscopy": "3.12.0-beta.38", + "@ohif/extension-dicom-pdf": "3.12.0-beta.38", + "@ohif/extension-dicom-video": "3.12.0-beta.38", + "@ohif/extension-test": "3.12.0-beta.38", + "@ohif/extension-ultrasound-pleura-bline": "3.12.0-beta.38", + "@ohif/i18n": "3.12.0-beta.38", + "@ohif/mode-basic-dev-mode": "3.12.0-beta.38", + "@ohif/mode-longitudinal": "3.12.0-beta.38", + "@ohif/mode-microscopy": "3.12.0-beta.38", + "@ohif/mode-test": "3.12.0-beta.38", + "@ohif/mode-ultrasound-pleura-bline": "3.12.0-beta.38", + "@ohif/ui": "3.12.0-beta.38", + "@ohif/ui-next": "3.12.0-beta.38", "@svgr/webpack": "^8.1.0", "@types/react": "^18.3.3", "classnames": "^2.3.2", @@ -765,7 +787,7 @@ }, "platform/cli": { "name": "@ohif/cli", - "version": "3.12.0-beta.36", + "version": "3.12.0-beta.38", "bin": { "ohif-cli": "src/index.js", }, @@ -789,7 +811,7 @@ }, "platform/core": { "name": "@ohif/core", - "version": "3.12.0-beta.36", + "version": "3.12.0-beta.38", "dependencies": { "@babel/runtime": "^7.20.13", "dcmjs": "0.43.1", @@ -816,14 +838,14 @@ "@cornerstonejs/codec-openjph": "^2.4.5", "@cornerstonejs/core": "4.3.14", "@cornerstonejs/dicom-image-loader": "4.3.14", - "@ohif/ui": "3.12.0-beta.36", + "@ohif/ui": "3.12.0-beta.38", "cornerstone-math": "0.1.9", "dicom-parser": "^1.8.21", }, }, "platform/i18n": { "name": "@ohif/i18n", - "version": "3.12.0-beta.36", + "version": "3.12.0-beta.38", "dependencies": { "@babel/runtime": "^7.20.13", "i18next-locize-backend": "^2.0.0", @@ -848,7 +870,7 @@ }, "platform/ui": { "name": "@ohif/ui", - "version": "3.12.0-beta.36", + "version": "3.12.0-beta.38", "dependencies": { "@testing-library/react": "^13.1.0", "browser-detect": "^0.2.28", @@ -899,7 +921,7 @@ }, "platform/ui-next": { "name": "@ohif/ui-next", - "version": "3.12.0-beta.36", + "version": "3.12.0-beta.38", "dependencies": { "@radix-ui/react-accordion": "^1.2.0", "@radix-ui/react-checkbox": "^1.1.1", @@ -948,6 +970,8 @@ "body-parser": "1.20.3", "commander": "8.3.0", "core-js": "3.45.1", + "cross-env": "7.0.3", + "cross-spawn": "7.0.6", "dcmjs": "0.43.1", "form-data": ">=4.0.4", "glob-parent": "^6.0.2", @@ -1542,6 +1566,8 @@ "@ohif/i18n": ["@ohif/i18n@workspace:platform/i18n"], + "@ohif/mode-basic": ["@ohif/mode-basic@workspace:modes/basic"], + "@ohif/mode-basic-dev-mode": ["@ohif/mode-basic-dev-mode@workspace:modes/basic-dev-mode"], "@ohif/mode-longitudinal": ["@ohif/mode-longitudinal@workspace:modes/longitudinal"], @@ -2544,7 +2570,7 @@ "create-require": ["create-require@1.1.1", "", {}, "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ=="], - "cross-env": ["cross-env@5.2.1", "", { "dependencies": { "cross-spawn": "^6.0.5" }, "bin": { "cross-env": "dist/bin/cross-env.js", "cross-env-shell": "dist/bin/cross-env-shell.js" } }, "sha512-1yHhtcfAd1r4nwQgknowuUNfIT9E8dOMMspC36g45dN+iD1blloi7xp8X/xAIDnjHWyt1uQ8PHk2fkNaym7soQ=="], + "cross-env": ["cross-env@7.0.3", "", { "dependencies": { "cross-spawn": "^7.0.1" }, "bin": { "cross-env": "src/bin/cross-env.js", "cross-env-shell": "src/bin/cross-env-shell.js" } }, "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw=="], "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], @@ -3920,8 +3946,6 @@ "next-themes": ["next-themes@0.3.0", "", { "peerDependencies": { "react": "^16.8 || ^17 || ^18", "react-dom": "^16.8 || ^17 || ^18" } }, "sha512-/QHIrsYpd6Kfk7xakK4svpDI5mmXP0gfvCoJdGpZQ2TOrQZmsW0QxjaiLn8wbIKjtm4BTSqLoix4lxYYOnLJ/w=="], - "nice-try": ["nice-try@1.0.5", "", {}, "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="], - "no-case": ["no-case@3.0.4", "", { "dependencies": { "lower-case": "^2.0.2", "tslib": "^2.0.3" } }, "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg=="], "node-addon-api": ["node-addon-api@3.2.1", "", {}, "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A=="], @@ -4348,8 +4372,6 @@ "proxy-from-env": ["proxy-from-env@1.0.0", "", {}, "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A=="], - "pseudomap": ["pseudomap@1.0.2", "", {}, "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ=="], - "psl": ["psl@1.15.0", "", { "dependencies": { "punycode": "^2.3.1" } }, "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w=="], "public-encrypt": ["public-encrypt@4.0.3", "", { "dependencies": { "bn.js": "^4.1.0", "browserify-rsa": "^4.0.0", "create-hash": "^1.1.0", "parse-asn1": "^5.0.0", "randombytes": "^2.0.1", "safe-buffer": "^5.1.2" } }, "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q=="], @@ -5352,8 +5374,6 @@ "@ohif/app/copy-webpack-plugin": ["copy-webpack-plugin@10.2.4", "", { "dependencies": { "fast-glob": "^3.2.7", "glob-parent": "^6.0.1", "globby": "^12.0.2", "normalize-path": "^3.0.0", "schema-utils": "^4.0.0", "serialize-javascript": "^6.0.0" }, "peerDependencies": { "webpack": "^5.1.0" } }, "sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg=="], - "@ohif/app/cross-env": ["cross-env@7.0.3", "", { "dependencies": { "cross-spawn": "^7.0.1" }, "bin": { "cross-env": "src/bin/cross-env.js", "cross-env-shell": "src/bin/cross-env-shell.js" } }, "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw=="], - "@ohif/extension-default/webpack": ["webpack@5.101.0", "", { "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", "acorn": "^8.15.0", "acorn-import-phases": "^1.0.3", "browserslist": "^4.24.0", "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^5.17.2", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", "schema-utils": "^4.3.2", "tapable": "^2.1.1", "terser-webpack-plugin": "^5.3.11", "watchpack": "^2.4.1", "webpack-sources": "^3.3.3" }, "bin": { "webpack": "bin/webpack.js" } }, "sha512-B4t+nJqytPeuZlHuIKTbalhljIFXeNRqrUGAQgTGlfOl2lXXKXw+yZu6bicycP+PUlM44CxBjCFD6aciKFT3LQ=="], "@ohif/extension-measurement-tracking/webpack": ["webpack@5.101.0", "", { "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", "acorn": "^8.15.0", "acorn-import-phases": "^1.0.3", "browserslist": "^4.24.0", "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^5.17.2", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", "schema-utils": "^4.3.2", "tapable": "^2.1.1", "terser-webpack-plugin": "^5.3.11", "watchpack": "^2.4.1", "webpack-sources": "^3.3.3" }, "bin": { "webpack": "bin/webpack.js" } }, "sha512-B4t+nJqytPeuZlHuIKTbalhljIFXeNRqrUGAQgTGlfOl2lXXKXw+yZu6bicycP+PUlM44CxBjCFD6aciKFT3LQ=="], @@ -5362,16 +5382,12 @@ "@ohif/extension-ultrasound-pleura-bline/copy-webpack-plugin": ["copy-webpack-plugin@10.2.4", "", { "dependencies": { "fast-glob": "^3.2.7", "glob-parent": "^6.0.1", "globby": "^12.0.2", "normalize-path": "^3.0.0", "schema-utils": "^4.0.0", "serialize-javascript": "^6.0.0" }, "peerDependencies": { "webpack": "^5.1.0" } }, "sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg=="], - "@ohif/extension-ultrasound-pleura-bline/cross-env": ["cross-env@7.0.3", "", { "dependencies": { "cross-spawn": "^7.0.1" }, "bin": { "cross-env": "src/bin/cross-env.js", "cross-env-shell": "src/bin/cross-env-shell.js" } }, "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw=="], - "@ohif/extension-ultrasound-pleura-bline/dotenv": ["dotenv@14.3.2", "", {}, "sha512-vwEppIphpFdvaMCaHfCEv9IgwcxMljMw2TnAQBB4VWPvzXQLTb82jwmdOKzlEVUL3gNFT4l4TPKO+Bn+sqcrVQ=="], "@ohif/mode-segmentation/clean-webpack-plugin": ["clean-webpack-plugin@4.0.0", "", { "dependencies": { "del": "^4.1.1" }, "peerDependencies": { "webpack": ">=4.0.0 <6.0.0" } }, "sha512-WuWE1nyTNAyW5T7oNyys2EN0cfP2fdRxhxnIQWiAp0bMabPdHhoGxM8A6YL2GhqwgrPnnaemVE7nv5XJ2Fhh2w=="], "@ohif/mode-segmentation/copy-webpack-plugin": ["copy-webpack-plugin@10.2.4", "", { "dependencies": { "fast-glob": "^3.2.7", "glob-parent": "^6.0.1", "globby": "^12.0.2", "normalize-path": "^3.0.0", "schema-utils": "^4.0.0", "serialize-javascript": "^6.0.0" }, "peerDependencies": { "webpack": "^5.1.0" } }, "sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg=="], - "@ohif/mode-segmentation/cross-env": ["cross-env@7.0.3", "", { "dependencies": { "cross-spawn": "^7.0.1" }, "bin": { "cross-env": "src/bin/cross-env.js", "cross-env-shell": "src/bin/cross-env-shell.js" } }, "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw=="], - "@ohif/mode-segmentation/dotenv": ["dotenv@14.3.2", "", {}, "sha512-vwEppIphpFdvaMCaHfCEv9IgwcxMljMw2TnAQBB4VWPvzXQLTb82jwmdOKzlEVUL3gNFT4l4TPKO+Bn+sqcrVQ=="], "@ohif/mode-segmentation/webpack-cli": ["webpack-cli@4.10.0", "", { "dependencies": { "@discoveryjs/json-ext": "^0.5.0", "@webpack-cli/configtest": "^1.2.0", "@webpack-cli/info": "^1.5.0", "@webpack-cli/serve": "^1.7.0", "colorette": "^2.0.14", "commander": "^7.0.0", "cross-spawn": "^7.0.3", "fastest-levenshtein": "^1.0.12", "import-local": "^3.0.2", "interpret": "^2.2.0", "rechoir": "^0.7.0", "webpack-merge": "^5.7.3" }, "peerDependencies": { "webpack": "4.x.x || 5.x.x" }, "bin": { "webpack-cli": "bin/cli.js" } }, "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w=="], @@ -5380,8 +5396,6 @@ "@ohif/mode-ultrasound-pleura-bline/copy-webpack-plugin": ["copy-webpack-plugin@10.2.4", "", { "dependencies": { "fast-glob": "^3.2.7", "glob-parent": "^6.0.1", "globby": "^12.0.2", "normalize-path": "^3.0.0", "schema-utils": "^4.0.0", "serialize-javascript": "^6.0.0" }, "peerDependencies": { "webpack": "^5.1.0" } }, "sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg=="], - "@ohif/mode-ultrasound-pleura-bline/cross-env": ["cross-env@7.0.3", "", { "dependencies": { "cross-spawn": "^7.0.1" }, "bin": { "cross-env": "src/bin/cross-env.js", "cross-env-shell": "src/bin/cross-env-shell.js" } }, "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw=="], - "@ohif/mode-ultrasound-pleura-bline/dotenv": ["dotenv@14.3.2", "", {}, "sha512-vwEppIphpFdvaMCaHfCEv9IgwcxMljMw2TnAQBB4VWPvzXQLTb82jwmdOKzlEVUL3gNFT4l4TPKO+Bn+sqcrVQ=="], "@ohif/ui/babel-loader": ["babel-loader@9.2.1", "", { "dependencies": { "find-cache-dir": "^4.0.0", "schema-utils": "^4.0.0" }, "peerDependencies": { "@babel/core": "^7.12.0", "webpack": ">=5" } }, "sha512-fqe8naHt46e0yIdkjUZYqddSXfej3AHajX+CSO5X7oy0EmPc6o5Xh+RClNoHjnieWz9AW4kZxW9yyFMhVB1QLA=="], @@ -5502,8 +5516,6 @@ "chalk-template/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - "child-process-promise/cross-spawn": ["cross-spawn@4.0.2", "", { "dependencies": { "lru-cache": "^4.0.1", "which": "^1.2.9" } }, "sha512-yAXz/pA1tD8Gtg2S98Ekf/sewp3Lcp3YoFKJ4Hkp5h5yLWnKVTDU0kwjKJ8NDCYcfTLfyGkzTikst+jWypT1iA=="], - "clean-css/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], "clipboardy/execa": ["execa@5.1.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", "human-signals": "^2.1.0", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^4.0.1", "onetime": "^5.1.2", "signal-exit": "^3.0.3", "strip-final-newline": "^2.0.0" } }, "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg=="], @@ -5526,8 +5538,6 @@ "create-jest/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - "cross-env/cross-spawn": ["cross-spawn@6.0.6", "", { "dependencies": { "nice-try": "^1.0.4", "path-key": "^2.0.1", "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" } }, "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw=="], - "cross-spawn/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], "cssnano/yaml": ["yaml@1.10.2", "", {}, "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="], @@ -6510,8 +6520,6 @@ "chalk-template/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], - "child-process-promise/cross-spawn/lru-cache": ["lru-cache@4.1.5", "", { "dependencies": { "pseudomap": "^1.0.2", "yallist": "^2.1.2" } }, "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g=="], - "clipboardy/execa/get-stream": ["get-stream@6.0.0", "", {}, "sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg=="], "clipboardy/execa/human-signals": ["human-signals@2.1.0", "", {}, "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="], @@ -6538,12 +6546,6 @@ "create-jest/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], - "cross-env/cross-spawn/path-key": ["path-key@2.0.1", "", {}, "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw=="], - - "cross-env/cross-spawn/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="], - - "cross-env/cross-spawn/shebang-command": ["shebang-command@1.2.0", "", { "dependencies": { "shebang-regex": "^1.0.0" } }, "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg=="], - "csso/css-tree/mdn-data": ["mdn-data@2.0.28", "", {}, "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g=="], "cypress/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], @@ -6640,8 +6642,6 @@ "husky/cosmiconfig/parse-json": ["parse-json@4.0.0", "", { "dependencies": { "error-ex": "^1.3.1", "json-parse-better-errors": "^1.0.1" } }, "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw=="], - "husky/execa/cross-spawn": ["cross-spawn@6.0.6", "", { "dependencies": { "nice-try": "^1.0.4", "path-key": "^2.0.1", "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" } }, "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw=="], - "husky/execa/get-stream": ["get-stream@4.1.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w=="], "husky/execa/is-stream": ["is-stream@1.1.0", "", {}, "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ=="], @@ -6932,8 +6932,6 @@ "pbkdf2/ripemd160/hash-base": ["hash-base@2.0.2", "", { "dependencies": { "inherits": "^2.0.1" } }, "sha512-0TROgQ1/SxE6KmxWSvXHvRj90/Xo1JvZShofnYF+f6ZsGtR4eES7WfrQzPalmyagfKZCXpVnitiRebZulWsbiw=="], - "pkg-install/execa/cross-spawn": ["cross-spawn@6.0.6", "", { "dependencies": { "nice-try": "^1.0.4", "path-key": "^2.0.1", "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" } }, "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw=="], - "pkg-install/execa/get-stream": ["get-stream@4.1.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w=="], "pkg-install/execa/is-stream": ["is-stream@1.1.0", "", {}, "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ=="], @@ -7092,8 +7090,6 @@ "cacache/tar/fs-minipass/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], - "child-process-promise/cross-spawn/lru-cache/yallist": ["yallist@2.1.2", "", {}, "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A=="], - "clipboardy/execa/onetime/mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="], "conventional-changelog-core/normalize-package-data/hosted-git-info/lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="], @@ -7110,8 +7106,6 @@ "conventional-changelog-core/read-pkg/path-type/pify": ["pify@3.0.0", "", {}, "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg=="], - "cross-env/cross-spawn/shebang-command/shebang-regex": ["shebang-regex@1.0.0", "", {}, "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ=="], - "cypress/execa/onetime/mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="], "decompress-tar/tar-stream/readable-stream/isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="], @@ -7140,12 +7134,6 @@ "husky/cosmiconfig/import-fresh/resolve-from": ["resolve-from@3.0.0", "", {}, "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw=="], - "husky/execa/cross-spawn/path-key": ["path-key@2.0.1", "", {}, "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw=="], - - "husky/execa/cross-spawn/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="], - - "husky/execa/cross-spawn/shebang-command": ["shebang-command@1.2.0", "", { "dependencies": { "shebang-regex": "^1.0.0" } }, "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg=="], - "husky/execa/npm-run-path/path-key": ["path-key@2.0.1", "", {}, "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw=="], "init-package-json/npm-package-arg/hosted-git-info/lru-cache": ["lru-cache@7.18.3", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="], @@ -7240,12 +7228,6 @@ "pacote/npm-packlist/ignore-walk/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - "pkg-install/execa/cross-spawn/path-key": ["path-key@2.0.1", "", {}, "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw=="], - - "pkg-install/execa/cross-spawn/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="], - - "pkg-install/execa/cross-spawn/shebang-command": ["shebang-command@1.2.0", "", { "dependencies": { "shebang-regex": "^1.0.0" } }, "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg=="], - "pkg-install/execa/npm-run-path/path-key": ["path-key@2.0.1", "", {}, "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw=="], "pkg-up/find-up/locate-path/p-locate": ["p-locate@3.0.0", "", { "dependencies": { "p-limit": "^2.0.0" } }, "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ=="], @@ -7296,8 +7278,6 @@ "husky/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="], - "husky/execa/cross-spawn/shebang-command/shebang-regex": ["shebang-regex@1.0.0", "", {}, "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ=="], - "jest-validate/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="], "jest-validate/pretty-format/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="], @@ -7324,8 +7304,6 @@ "pacote/npm-packlist/ignore-walk/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], - "pkg-install/execa/cross-spawn/shebang-command/shebang-regex": ["shebang-regex@1.0.0", "", {}, "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ=="], - "pkg-up/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], "postcss-svgo/svgo/css-select/domutils/dom-serializer": ["dom-serializer@1.4.1", "", { "dependencies": { "domelementtype": "^2.0.1", "domhandler": "^4.2.0", "entities": "^2.0.0" } }, "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag=="], diff --git a/modes/basic/.gitignore b/modes/basic/.gitignore new file mode 100644 index 000000000..67045665d --- /dev/null +++ b/modes/basic/.gitignore @@ -0,0 +1,104 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env +.env.test + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# Next.js build output +.next + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and *not* Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port diff --git a/modes/basic/.prettierrc b/modes/basic/.prettierrc new file mode 100644 index 000000000..ef83baaef --- /dev/null +++ b/modes/basic/.prettierrc @@ -0,0 +1,11 @@ +{ + "plugins": ["prettier-plugin-tailwindcss"], + "trailingComma": "es5", + "printWidth": 100, + "proseWrap": "always", + "tabWidth": 2, + "semi": true, + "singleQuote": true, + "arrowParens": "avoid", + "endOfLine": "auto" +} diff --git a/modes/basic/.webpack/webpack.prod.js b/modes/basic/.webpack/webpack.prod.js new file mode 100644 index 000000000..565614cf1 --- /dev/null +++ b/modes/basic/.webpack/webpack.prod.js @@ -0,0 +1,52 @@ +const webpack = require('webpack'); +const { merge } = require('webpack-merge'); +const path = require('path'); + +const pkg = require('./../package.json'); +const webpackCommon = require('./../../../.webpack/webpack.base.js'); + +const ROOT_DIR = path.join(__dirname, './../'); +const SRC_DIR = path.join(__dirname, '../src'); +const DIST_DIR = path.join(__dirname, '../dist'); +const ENTRY = { + app: `${SRC_DIR}/index.tsx`, +}; + +module.exports = (env, argv) => { + const commonConfig = webpackCommon(env, argv, { SRC_DIR, DIST_DIR, ENTRY }); + + return merge(commonConfig, { + stats: { + colors: true, + hash: true, + timings: true, + assets: true, + chunks: false, + chunkModules: false, + modules: false, + children: false, + warnings: true, + }, + optimization: { + minimize: true, + sideEffects: false, + }, + output: { + path: ROOT_DIR, + library: 'ohif-mode-basic', + libraryTarget: 'umd', + libraryExport: 'default', + filename: pkg.main, + }, + externals: [/\b(vtk.js)/, /\b(dcmjs)/, /\b(gl-matrix)/, /^@ohif/, /^@cornerstonejs/], + plugins: [ + new webpack.optimize.LimitChunkCountPlugin({ + maxChunks: 1, + }), + // new MiniCssExtractPlugin({ + // filename: './dist/[name].css', + // chunkFilename: './dist/[id].css', + // }), + ], + }); +}; diff --git a/modes/basic/LICENSE b/modes/basic/LICENSE new file mode 100644 index 000000000..1ec16de8c --- /dev/null +++ b/modes/basic/LICENSE @@ -0,0 +1,18 @@ +MIT License + +Copyright (c) 2025 basic () + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the +following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial +portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO +EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/modes/basic/README.md b/modes/basic/README.md new file mode 100644 index 000000000..cfb643ba8 --- /dev/null +++ b/modes/basic/README.md @@ -0,0 +1,7 @@ +# basic +## Description +A basic mode used to build other modes on top of +## Author +OHIF Contributors +## License +MIT \ No newline at end of file diff --git a/modes/basic/babel.config.js b/modes/basic/babel.config.js new file mode 100644 index 000000000..24adaea8d --- /dev/null +++ b/modes/basic/babel.config.js @@ -0,0 +1,43 @@ +module.exports = { + plugins: ['@babel/plugin-transform-class-properties'], + env: { + test: { + presets: [ + [ + // TODO: https://babeljs.io/blog/2019/03/19/7.4.0#migration-from-core-js-2 + '@babel/preset-env', + { + modules: 'commonjs', + debug: false, + }, + '@babel/preset-typescript', + ], + '@babel/preset-react', + ], + plugins: [ + '@babel/plugin-transform-object-rest-spread', + '@babel/plugin-syntax-dynamic-import', + '@babel/plugin-transform-regenerator', + '@babel/plugin-transform-runtime', + ], + }, + production: { + presets: [ + // WebPack handles ES6 --> Target Syntax + ['@babel/preset-env', { modules: false }], + '@babel/preset-react', + '@babel/preset-typescript', + ], + ignore: ['**/*.test.jsx', '**/*.test.js', '__snapshots__', '__tests__'], + }, + development: { + presets: [ + // WebPack handles ES6 --> Target Syntax + ['@babel/preset-env', { modules: false }], + '@babel/preset-react', + '@babel/preset-typescript', + ], + ignore: ['**/*.test.jsx', '**/*.test.js', '__snapshots__', '__tests__'], + }, + }, +}; diff --git a/modes/basic/package.json b/modes/basic/package.json new file mode 100644 index 000000000..8b44de35f --- /dev/null +++ b/modes/basic/package.json @@ -0,0 +1,49 @@ +{ + "name": "@ohif/mode-basic", + "version": "3.12.0-beta.38", + "description": "A basic mode used to build other modes on top of", + "author": "OHIF Contributors", + "license": "MIT", + "main": "dist/ohif-mode-basic.js", + "files": [ + "dist/**", + "public/**", + "README.md" + ], + "repository": "OHIF/Viewers", + "keywords": [ + "ohif-mode" + ], + "module": "src/index.tsx", + "engines": { + "node": ">=14", + "npm": ">=6", + "yarn": ">=1.16.0" + }, + "peerDependencies": { + "@ohif/extension-cornerstone": "3.12.0-beta.38", + "@ohif/extension-cornerstone-dicom-rt": "3.12.0-beta.38", + "@ohif/extension-cornerstone-dicom-seg": "3.12.0-beta.38", + "@ohif/extension-cornerstone-dicom-sr": "3.12.0-beta.38", + "@ohif/extension-default": "3.12.0-beta.38", + "@ohif/extension-dicom-pdf": "3.12.0-beta.38", + "@ohif/extension-dicom-video": "3.12.0-beta.38", + "@ohif/core": "3.12.0-beta.38" + }, + "dependencies": { + "@babel/runtime": "^7.20.13" + }, + "devDependencies": { + "webpack": "5.95.0", + "webpack-merge": "^5.7.3" + }, + "scripts": { + "dev": "cross-env NODE_ENV=development webpack --config .webpack/webpack.dev.js --watch --output-pathinfo", + "dev:cornerstone": "yarn run dev", + "build": "cross-env NODE_ENV=production webpack --config .webpack/webpack.prod.js", + "build:package": "yarn run build", + "start": "yarn run dev", + "test:unit": "jest --watchAll", + "test:unit:ci": "jest --ci --runInBand --collectCoverage --passWithNoTests" + } +} diff --git a/modes/basic/src/id.js b/modes/basic/src/id.js new file mode 100644 index 000000000..ebe5acd98 --- /dev/null +++ b/modes/basic/src/id.js @@ -0,0 +1,5 @@ +import packageJson from '../package.json'; + +const id = packageJson.name; + +export { id }; diff --git a/modes/basic/src/index.tsx b/modes/basic/src/index.tsx new file mode 100644 index 000000000..5b999f5a8 --- /dev/null +++ b/modes/basic/src/index.tsx @@ -0,0 +1,377 @@ +import update from 'immutability-helper'; +import { ToolbarService, utils } from '@ohif/core'; + +import initToolGroups from './initToolGroups'; +import toolbarButtons from './toolbarButtons'; +import { id } from './id'; + +const { TOOLBAR_SECTIONS } = ToolbarService; +const { structuredCloneWithFunctions } = utils; + +/** + * Define non-imaging modalities. + * This can be used to exclude modes which have only these modalities, + * or it can be used to not display thumbnails for some of these. + * This list used to include SM, for whole slide imaging, but this is now supported + * by cornerstone. Others of these may get added. + */ +export const NON_IMAGE_MODALITIES = ['ECG', 'SEG', 'RTSTRUCT', 'RTPLAN', 'PR', 'SR', 'DOC']; + +export const ohif = { + layout: '@ohif/extension-default.layoutTemplateModule.viewerLayout', + sopClassHandler: '@ohif/extension-default.sopClassHandlerModule.stack', + thumbnailList: '@ohif/extension-default.panelModule.seriesList', + wsiSopClassHandler: + '@ohif/extension-cornerstone.sopClassHandlerModule.DicomMicroscopySopClassHandler', +}; + +export const cornerstone = { + measurements: '@ohif/extension-cornerstone.panelModule.panelMeasurement', + segmentation: '@ohif/extension-cornerstone.panelModule.panelSegmentation', + viewport: '@ohif/extension-cornerstone.viewportModule.cornerstone', +}; + +export const dicomsr = { + sopClassHandler: '@ohif/extension-cornerstone-dicom-sr.sopClassHandlerModule.dicom-sr', + sopClassHandler3D: '@ohif/extension-cornerstone-dicom-sr.sopClassHandlerModule.dicom-sr-3d', + viewport: '@ohif/extension-cornerstone-dicom-sr.viewportModule.dicom-sr', +}; + +export const dicomvideo = { + sopClassHandler: '@ohif/extension-dicom-video.sopClassHandlerModule.dicom-video', + viewport: '@ohif/extension-dicom-video.viewportModule.dicom-video', +}; + +export const dicompdf = { + sopClassHandler: '@ohif/extension-dicom-pdf.sopClassHandlerModule.dicom-pdf', + viewport: '@ohif/extension-dicom-pdf.viewportModule.dicom-pdf', +}; + +export const dicomSeg = { + sopClassHandler: '@ohif/extension-cornerstone-dicom-seg.sopClassHandlerModule.dicom-seg', + viewport: '@ohif/extension-cornerstone-dicom-seg.viewportModule.dicom-seg', +}; + +export const dicomPmap = { + sopClassHandler: '@ohif/extension-cornerstone-dicom-pmap.sopClassHandlerModule.dicom-pmap', + viewport: '@ohif/extension-cornerstone-dicom-pmap.viewportModule.dicom-pmap', +}; + +export const dicomRT = { + viewport: '@ohif/extension-cornerstone-dicom-rt.viewportModule.dicom-rt', + sopClassHandler: '@ohif/extension-cornerstone-dicom-rt.sopClassHandlerModule.dicom-rt', +}; + +export const extensionDependencies = { + // Can derive the versions at least process.env.from npm_package_version + '@ohif/extension-default': '^3.0.0', + '@ohif/extension-cornerstone': '^3.0.0', + '@ohif/extension-cornerstone-dicom-sr': '^3.0.0', + '@ohif/extension-cornerstone-dicom-seg': '^3.0.0', + '@ohif/extension-cornerstone-dicom-pmap': '^3.0.0', + '@ohif/extension-cornerstone-dicom-rt': '^3.0.0', + '@ohif/extension-dicom-pdf': '^3.0.1', + '@ohif/extension-dicom-video': '^3.0.1', +}; + +export const sopClassHandlers = [ + dicomvideo.sopClassHandler, + dicomSeg.sopClassHandler, + dicomPmap.sopClassHandler, + ohif.sopClassHandler, + ohif.wsiSopClassHandler, + dicompdf.sopClassHandler, + dicomsr.sopClassHandler3D, + dicomsr.sopClassHandler, + dicomRT.sopClassHandler, +]; + +/** + * Indicate this is a valid mode if: + * - it contains at least one of the modeModalities + * - it contains all of the array value in modeModalities + * Otherwise, if modeModalities is not defined: + * - it contains at least one modality other than the nonModeMOdalities. + */ +export function isValidMode({ modalities }) { + const modalities_list = modalities.split('\\'); + + if (this.modeModalities?.length) { + for (const modeModality of this.modeModalities) { + if (Array.isArray(modeModality) && modeModality.every(m => modalities.indexOf(m) !== -1)) { + return { valid: true, description: `Matches ${modeModality.join(', ')}` }; + } else if (modalities.indexOf(modeModality)) { + return { valid: true, description: `Matches ${modeModality}` }; + } + } + return { + valid: false, + description: `None of the mode modalities match: ${JSON.stringify(this.modeModalities)}`, + }; + } + + return { + valid: !!modalities_list.find(modality => this.nonModeModalities.indexOf(modality) === -1), + description: `The mode does not support studies that ONLY include the following modalities: ${this.nonModeModalities.join(', ')}`, + }; +} + +export function onModeEnter({ + servicesManager, + extensionManager, + commandsManager, + panelService, + segmentationService, +}: withAppTypes) { + const { measurementService, toolbarService, toolGroupService, customizationService } = + servicesManager.services; + + measurementService.clearMeasurements(); + + // Init Default and SR ToolGroups + initToolGroups(extensionManager, toolGroupService, commandsManager); + + toolbarService.register(this.toolbarButtons); + + for (const [key, section] of Object.entries(this.toolbarSections)) { + toolbarService.updateSection(key, section); + } + + if (!this.enableSegmentationEdit) { + customizationService.setCustomizations({ + 'panelSegmentation.disableEditing': { + $set: true, + }, + }); + } + + // // ActivatePanel event trigger for when a segmentation or measurement is added. + // // Do not force activation so as to respect the state the user may have left the UI in. + if (this.activatePanelTrigger) { + this._activatePanelTriggersSubscriptions = [ + ...panelService.addActivatePanelTriggers( + cornerstone.segmentation, + [ + { + sourcePubSubService: segmentationService, + sourceEvents: [segmentationService.EVENTS.SEGMENTATION_ADDED], + }, + ], + true + ), + ...panelService.addActivatePanelTriggers( + cornerstone.measurements, + [ + { + sourcePubSubService: measurementService, + sourceEvents: [ + measurementService.EVENTS.MEASUREMENT_ADDED, + measurementService.EVENTS.RAW_MEASUREMENT_ADDED, + ], + }, + ], + true + ), + true, + ]; + } +} + +export function onModeExit({ servicesManager }: withAppTypes) { + const { + toolGroupService, + syncGroupService, + segmentationService, + cornerstoneViewportService, + uiDialogService, + uiModalService, + } = servicesManager.services; + + this._activatePanelTriggersSubscriptions.forEach(sub => sub.unsubscribe()); + this._activatePanelTriggersSubscriptions.length = 0; + + uiDialogService.hideAll(); + uiModalService.hide(); + toolGroupService.destroy(); + syncGroupService.destroy(); + segmentationService.destroy(); + cornerstoneViewportService.destroy(); +} + +export const toolbarSections = { + [TOOLBAR_SECTIONS.primary]: [ + 'MeasurementTools', + 'Zoom', + 'Pan', + 'TrackballRotate', + 'WindowLevel', + 'Capture', + 'Layout', + 'Crosshairs', + 'MoreTools', + ], + + [TOOLBAR_SECTIONS.viewportActionMenu.topLeft]: ['orientationMenu', 'dataOverlayMenu'], + + [TOOLBAR_SECTIONS.viewportActionMenu.bottomMiddle]: ['AdvancedRenderingControls'], + + AdvancedRenderingControls: [ + 'windowLevelMenuEmbedded', + 'voiManualControlMenu', + 'Colorbar', + 'opacityMenu', + 'thresholdMenu', + ], + + [TOOLBAR_SECTIONS.viewportActionMenu.topRight]: [ + 'modalityLoadBadge', + 'trackingStatus', + 'navigationComponent', + ], + + [TOOLBAR_SECTIONS.viewportActionMenu.bottomLeft]: ['windowLevelMenu'], + + MeasurementTools: [ + 'Length', + 'Bidirectional', + 'ArrowAnnotate', + 'EllipticalROI', + 'RectangleROI', + 'CircleROI', + 'PlanarFreehandROI', + 'SplineROI', + 'LivewireContour', + ], + + MoreTools: [ + 'Reset', + 'rotate-right', + 'flipHorizontal', + 'ImageSliceSync', + 'ReferenceLines', + 'ImageOverlayViewer', + 'StackScroll', + 'invert', + 'Probe', + 'Cine', + 'Angle', + 'CobbAngle', + 'Magnify', + 'CalibrationLine', + 'TagBrowser', + 'AdvancedMagnify', + 'UltrasoundDirectionalTool', + 'WindowLevelRegion', + 'SegmentLabelTool', + ], +}; + +export const basicLayout = { + id: ohif.layout, + props: { + leftPanels: [ohif.thumbnailList], + leftPanelResizable: true, + rightPanels: [cornerstone.segmentation, cornerstone.measurements], + rightPanelClosed: true, + rightPanelResizable: true, + viewports: [ + { + namespace: cornerstone.viewport, + displaySetsToDisplay: [ + ohif.sopClassHandler, + dicomvideo.sopClassHandler, + ohif.wsiSopClassHandler, + ], + }, + { + namespace: dicomsr.viewport, + displaySetsToDisplay: [dicomsr.sopClassHandler, dicomsr.sopClassHandler3D], + }, + { + namespace: dicompdf.viewport, + displaySetsToDisplay: [dicompdf.sopClassHandler], + }, + { + namespace: dicomSeg.viewport, + displaySetsToDisplay: [dicomSeg.sopClassHandler], + }, + { + namespace: dicomPmap.viewport, + displaySetsToDisplay: [dicomPmap.sopClassHandler], + }, + { + namespace: dicomRT.viewport, + displaySetsToDisplay: [dicomRT.sopClassHandler], + }, + ], + }, +}; + +export function layoutTemplate() { + return structuredCloneWithFunctions(this.layoutInstance); +} + +export const basicRoute = { + path: 'basic', + layoutTemplate, + layoutInstance: basicLayout, +}; + +export const modeInstance = { + // TODO: We're using this as a route segment + // We should not be. + id, + routeName: 'basic', + // Don't hide this by default - see the registration later to hide the basic + // instance by default. + hide: false, + displayName: 'Non-Longitudinal Basic', + _activatePanelTriggersSubscriptions: [], + toolbarSections, + + /** + * Lifecycle hooks + */ + onModeEnter, + onModeExit, + validationTags: { + study: [], + series: [], + }, + + isValidMode, + routes: [basicRoute], + extensions: extensionDependencies, + // Default protocol gets self-registered by default in the init + hangingProtocol: 'default', + // Order is important in sop class handlers when two handlers both use + // the same sop class under different situations. In that case, the more + // general handler needs to come last. For this case, the dicomvideo must + // come first to remove video transfer syntax before ohif uses images + sopClassHandlers, + toolbarButtons, + enableSegmentationEdit: false, + nonModeModalities: NON_IMAGE_MODALITIES, +}; + +/** + * Creates a mode on this object, using immutability-helper to apply changes + * from modeConfiguration into the modeInstance. + */ +export function modeFactory({ modeConfiguration }) { + let modeInstance = this.modeInstance; + if (modeConfiguration) { + modeInstance = update(modeInstance, modeConfiguration); + } + return modeInstance; +} + +export const mode = { + id, + modeFactory, + modeInstance: { ...modeInstance, hide: true }, + extensionDependencies, +}; + +export default mode; +export { initToolGroups, toolbarButtons }; diff --git a/modes/longitudinal/src/initToolGroups.js b/modes/basic/src/initToolGroups.ts similarity index 99% rename from modes/longitudinal/src/initToolGroups.js rename to modes/basic/src/initToolGroups.ts index 6bc48719b..6278f6261 100644 --- a/modes/longitudinal/src/initToolGroups.js +++ b/modes/basic/src/initToolGroups.ts @@ -1,5 +1,3 @@ -import { toolNames as SRToolNames } from '@ohif/extension-cornerstone-dicom-sr'; - const colours = { 'viewport-0': 'rgb(200, 0, 0)', 'viewport-1': 'rgb(200, 200, 0)', diff --git a/modes/longitudinal/src/toolbarButtons.ts b/modes/basic/src/toolbarButtons.ts similarity index 100% rename from modes/longitudinal/src/toolbarButtons.ts rename to modes/basic/src/toolbarButtons.ts diff --git a/modes/longitudinal/.webpack/webpack.prod.js b/modes/longitudinal/.webpack/webpack.prod.js index b60b8908a..23ec5108e 100644 --- a/modes/longitudinal/.webpack/webpack.prod.js +++ b/modes/longitudinal/.webpack/webpack.prod.js @@ -1,7 +1,6 @@ const webpack = require('webpack'); const { merge } = require('webpack-merge'); const path = require('path'); -const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const pkg = require('./../package.json'); const webpackCommon = require('./../../../.webpack/webpack.base.js'); diff --git a/modes/longitudinal/src/index.ts b/modes/longitudinal/src/index.ts index 59a265e38..cb8b9a18a 100644 --- a/modes/longitudinal/src/index.ts +++ b/modes/longitudinal/src/index.ts @@ -1,315 +1,74 @@ import i18n from 'i18next'; import { id } from './id'; -import initToolGroups from './initToolGroups'; -import toolbarButtons from './toolbarButtons'; +import { initToolGroups, toolbarButtons, cornerstone, + ohif, + dicomsr, + dicomvideo, + basicLayout, + basicRoute, + extensionDependencies as basicDependencies, + mode as basicMode, + modeInstance as basicModeInstance, + } from '@ohif/mode-basic'; -// Allow this mode by excluding non-imaging modalities such as SR, SEG -// Also, SM is not a simple imaging modalities, so exclude it. -const NON_IMAGE_MODALITIES = ['ECG', 'SEG', 'RTSTRUCT', 'RTPLAN', 'PR']; - -const ohif = { - layout: '@ohif/extension-default.layoutTemplateModule.viewerLayout', - sopClassHandler: '@ohif/extension-default.sopClassHandlerModule.stack', - thumbnailList: '@ohif/extension-default.panelModule.seriesList', - wsiSopClassHandler: - '@ohif/extension-cornerstone.sopClassHandlerModule.DicomMicroscopySopClassHandler', -}; - -const cornerstone = { - measurements: '@ohif/extension-cornerstone.panelModule.panelMeasurement', - segmentation: '@ohif/extension-cornerstone.panelModule.panelSegmentation', -}; - -const tracked = { +export const tracked = { measurements: '@ohif/extension-measurement-tracking.panelModule.trackedMeasurements', thumbnailList: '@ohif/extension-measurement-tracking.panelModule.seriesList', viewport: '@ohif/extension-measurement-tracking.viewportModule.cornerstone-tracked', }; -const dicomsr = { - sopClassHandler: '@ohif/extension-cornerstone-dicom-sr.sopClassHandlerModule.dicom-sr', - sopClassHandler3D: '@ohif/extension-cornerstone-dicom-sr.sopClassHandlerModule.dicom-sr-3d', - viewport: '@ohif/extension-cornerstone-dicom-sr.viewportModule.dicom-sr', -}; - -const dicomvideo = { - sopClassHandler: '@ohif/extension-dicom-video.sopClassHandlerModule.dicom-video', - viewport: '@ohif/extension-dicom-video.viewportModule.dicom-video', -}; - -const dicompdf = { - sopClassHandler: '@ohif/extension-dicom-pdf.sopClassHandlerModule.dicom-pdf', - viewport: '@ohif/extension-dicom-pdf.viewportModule.dicom-pdf', -}; - -const dicomSeg = { - sopClassHandler: '@ohif/extension-cornerstone-dicom-seg.sopClassHandlerModule.dicom-seg', - viewport: '@ohif/extension-cornerstone-dicom-seg.viewportModule.dicom-seg', -}; - -const dicomPmap = { - sopClassHandler: '@ohif/extension-cornerstone-dicom-pmap.sopClassHandlerModule.dicom-pmap', - viewport: '@ohif/extension-cornerstone-dicom-pmap.viewportModule.dicom-pmap', -}; - -const dicomRT = { - viewport: '@ohif/extension-cornerstone-dicom-rt.viewportModule.dicom-rt', - sopClassHandler: '@ohif/extension-cornerstone-dicom-rt.sopClassHandlerModule.dicom-rt', -}; - -const extensionDependencies = { +export const extensionDependencies = { // Can derive the versions at least process.env.from npm_package_version - '@ohif/extension-default': '^3.0.0', - '@ohif/extension-cornerstone': '^3.0.0', + ...basicDependencies, '@ohif/extension-measurement-tracking': '^3.0.0', - '@ohif/extension-cornerstone-dicom-sr': '^3.0.0', - '@ohif/extension-cornerstone-dicom-seg': '^3.0.0', - '@ohif/extension-cornerstone-dicom-pmap': '^3.0.0', - '@ohif/extension-cornerstone-dicom-rt': '^3.0.0', - '@ohif/extension-dicom-pdf': '^3.0.1', - '@ohif/extension-dicom-video': '^3.0.1', }; -function modeFactory({ modeConfiguration }) { - let _activatePanelTriggersSubscriptions = []; - return { +export const longitudinalInstance = { + ...basicLayout, + id: ohif.layout, + props: { + ...basicLayout.props, + leftPanels: [tracked.thumbnailList], + rightPanels: [cornerstone.segmentation, tracked.measurements], + viewports: [ + { + namespace: tracked.viewport, + // Re-use the display sets from basic + displaySetsToDisplay: basicLayout.props.viewports[0].displaySetsToDisplay, + }, + ...basicLayout.props.viewports, + ], + } + }; + + +export const longitudinalRoute = + { + ...basicRoute, + path: 'longitudinal', + /*init: ({ servicesManager, extensionManager }) => { + //defaultViewerRouteInit + },*/ + layoutInstance: longitudinalInstance, + }; + +export const modeInstance = { + ...basicModeInstance, // TODO: We're using this as a route segment // We should not be. id, routeName: 'viewer', displayName: i18n.t('Modes:Basic Viewer'), - /** - * Lifecycle hooks - */ - onModeEnter: function ({ servicesManager, extensionManager, commandsManager }: withAppTypes) { - const { measurementService, toolbarService, toolGroupService, customizationService } = - servicesManager.services; - - measurementService.clearMeasurements(); - - // Init Default and SR ToolGroups - initToolGroups(extensionManager, toolGroupService, commandsManager); - - toolbarService.register(toolbarButtons); - toolbarService.updateSection(toolbarService.sections.primary, [ - 'MeasurementTools', - 'Zoom', - 'Pan', - 'TrackballRotate', - 'WindowLevel', - 'Capture', - 'Layout', - 'Crosshairs', - 'MoreTools', - ]); - - toolbarService.updateSection(toolbarService.sections.viewportActionMenu.topLeft, [ - 'orientationMenu', - 'dataOverlayMenu', - ]); - - toolbarService.updateSection(toolbarService.sections.viewportActionMenu.bottomMiddle, [ - 'AdvancedRenderingControls', - ]); - - toolbarService.updateSection('AdvancedRenderingControls', [ - 'windowLevelMenuEmbedded', - 'voiManualControlMenu', - 'Colorbar', - 'opacityMenu', - 'thresholdMenu', - ]); - - toolbarService.updateSection(toolbarService.sections.viewportActionMenu.topRight, [ - 'modalityLoadBadge', - 'trackingStatus', - 'navigationComponent', - ]); - - toolbarService.updateSection(toolbarService.sections.viewportActionMenu.bottomLeft, [ - 'windowLevelMenu', - ]); - - toolbarService.updateSection('MeasurementTools', [ - 'Length', - 'Bidirectional', - 'ArrowAnnotate', - 'EllipticalROI', - 'RectangleROI', - 'CircleROI', - 'PlanarFreehandROI', - 'SplineROI', - 'LivewireContour', - ]); - - toolbarService.updateSection('MoreTools', [ - 'Reset', - 'rotate-right', - 'flipHorizontal', - 'ImageSliceSync', - 'ReferenceLines', - 'ImageOverlayViewer', - 'StackScroll', - 'invert', - 'Probe', - 'Cine', - 'Angle', - 'CobbAngle', - 'Magnify', - 'CalibrationLine', - 'TagBrowser', - 'AdvancedMagnify', - 'UltrasoundDirectionalTool', - 'WindowLevelRegion', - 'SegmentLabelTool', - ]); - - customizationService.setCustomizations({ - 'panelSegmentation.disableEditing': { - $set: true, - }, - }); - - // // ActivatePanel event trigger for when a segmentation or measurement is added. - // // Do not force activation so as to respect the state the user may have left the UI in. - // _activatePanelTriggersSubscriptions = [ - // ...panelService.addActivatePanelTriggers( - // cornerstone.segmentation, - // [ - // { - // sourcePubSubService: segmentationService, - // sourceEvents: [segmentationService.EVENTS.SEGMENTATION_ADDED], - // }, - // ], - // true - // ), - // ...panelService.addActivatePanelTriggers( - // tracked.measurements, - // [ - // { - // sourcePubSubService: measurementService, - // sourceEvents: [ - // measurementService.EVENTS.MEASUREMENT_ADDED, - // measurementService.EVENTS.RAW_MEASUREMENT_ADDED, - // ], - // }, - // ], - // true - // ), - // true, - // ]; - }, - onModeExit: ({ servicesManager }: withAppTypes) => { - const { - toolGroupService, - syncGroupService, - segmentationService, - cornerstoneViewportService, - uiDialogService, - uiModalService, - } = servicesManager.services; - - _activatePanelTriggersSubscriptions.forEach(sub => sub.unsubscribe()); - _activatePanelTriggersSubscriptions = []; - - uiDialogService.hideAll(); - uiModalService.hide(); - toolGroupService.destroy(); - syncGroupService.destroy(); - segmentationService.destroy(); - cornerstoneViewportService.destroy(); - }, - validationTags: { - study: [], - series: [], - }, - - isValidMode: function ({ modalities }) { - const modalities_list = modalities.split('\\'); - - // Exclude non-image modalities - return { - valid: !!modalities_list.filter(modality => NON_IMAGE_MODALITIES.indexOf(modality) === -1) - .length, - description: - 'The mode does not support studies that ONLY include the following modalities: SM, ECG, SEG, RTSTRUCT', - }; - }, routes: [ - { - path: 'longitudinal', - /*init: ({ servicesManager, extensionManager }) => { - //defaultViewerRouteInit - },*/ - layoutTemplate: () => { - return { - id: ohif.layout, - props: { - leftPanels: [tracked.thumbnailList], - leftPanelResizable: true, - rightPanels: [cornerstone.segmentation, tracked.measurements], - rightPanelClosed: true, - rightPanelResizable: true, - viewports: [ - { - namespace: tracked.viewport, - displaySetsToDisplay: [ - ohif.sopClassHandler, - dicomvideo.sopClassHandler, - ohif.wsiSopClassHandler, - ], - }, - { - namespace: dicomsr.viewport, - displaySetsToDisplay: [dicomsr.sopClassHandler, dicomsr.sopClassHandler3D], - }, - { - namespace: dicompdf.viewport, - displaySetsToDisplay: [dicompdf.sopClassHandler], - }, - { - namespace: dicomSeg.viewport, - displaySetsToDisplay: [dicomSeg.sopClassHandler], - }, - { - namespace: dicomPmap.viewport, - displaySetsToDisplay: [dicomPmap.sopClassHandler], - }, - { - namespace: dicomRT.viewport, - displaySetsToDisplay: [dicomRT.sopClassHandler], - }, - ], - }, - }; - }, - }, + longitudinalRoute ], extensions: extensionDependencies, - // Default protocol gets self-registered by default in the init - hangingProtocol: 'default', - // Order is important in sop class handlers when two handlers both use - // the same sop class under different situations. In that case, the more - // general handler needs to come last. For this case, the dicomvideo must - // come first to remove video transfer syntax before ohif uses images - sopClassHandlers: [ - dicomvideo.sopClassHandler, - dicomSeg.sopClassHandler, - dicomPmap.sopClassHandler, - ohif.sopClassHandler, - ohif.wsiSopClassHandler, - dicompdf.sopClassHandler, - dicomsr.sopClassHandler3D, - dicomsr.sopClassHandler, - dicomRT.sopClassHandler, - ], - ...modeConfiguration, }; -} const mode = { + ...basicMode, id, - modeFactory, + modeInstance, extensionDependencies, }; diff --git a/package.json b/package.json index 9e903b7fe..f44f0b7da 100644 --- a/package.json +++ b/package.json @@ -55,13 +55,13 @@ "test:unit:ci": "lerna run test:unit:ci --parallel --stream", "test:e2e": "lerna run test:e2e --stream", "test:e2e:coverage": "nyc --reporter=html yarn run test:e2e:ci", - "test:e2e:ci": "TEST_ENV=true npx playwright test", - "test:e2e:ui": "TEST_ENV=true npx playwright test --ui", - "test:e2e:reporter": "TEST_ENV=true npx playwright test --reporter=html", - "test:e2e:update": "TEST_ENV=true npx playwright test --reporter=html --update-snapshots -g shouldUpdateThis", - "test:e2e:update:debug": "TEST_ENV=true npx playwright test -g @debug --reporter=html --update-snapshots -g shouldUpdateThis", - "test:e2e:headed": "TEST_ENV=true npx playwright test --headed", - "test:e2e:debug": "TEST_ENV=true npx playwright test --debug", + "test:e2e:ci": "cross-env TEST_ENV=true npx playwright test", + "test:e2e:ui": "cross-env TEST_ENV=true npx playwright test --ui", + "test:e2e:reporter": "cross-env TEST_ENV=true npx playwright test --reporter=html", + "test:e2e:update": "cross-env TEST_ENV=true npx playwright test --reporter=html --update-snapshots -g shouldUpdateThis", + "test:e2e:update:debug": "cross-env TEST_ENV=true npx playwright test -g @debug --reporter=html --update-snapshots -g shouldUpdateThis", + "test:e2e:headed": "cross-env TEST_ENV=true npx playwright test --headed", + "test:e2e:debug": "cross-env TEST_ENV=true npx playwright test --debug", "test:e2e:dist": "lerna run test:e2e:dist --stream", "test:e2e:serve": "yarn test:data && lerna run test:e2e:serve --stream", "see-changed": "lerna changed", @@ -101,6 +101,7 @@ "babel-loader": "8.4.1", "babel-plugin-istanbul": "^7.0.0", "babel-plugin-transform-import-meta": "2.3.3", + "cross-env": "7.0.3", "css-loader": "6.11.0", "cypress": "14.5.2", "cypress-file-upload": "^5.0.8", @@ -132,6 +133,8 @@ }, "resolutions": { "commander": "8.3.0", + "cross-env": "7.0.3", + "cross-spawn": "7.0.6", "dcmjs": "0.43.1", "path-to-regexp": "0.1.12", "nth-check": "^2.1.1", diff --git a/platform/app/pluginConfig.json b/platform/app/pluginConfig.json index b1058b14e..fd56a748c 100644 --- a/platform/app/pluginConfig.json +++ b/platform/app/pluginConfig.json @@ -71,6 +71,9 @@ { "packageName": "@ohif/mode-longitudinal" }, + { + "packageName": "@ohif/mode-basic" + }, { "packageName": "@ohif/mode-segmentation" }, diff --git a/platform/app/public/config/kheops.js b/platform/app/public/config/kheops.js index 154e957cf..56f2214f9 100644 --- a/platform/app/public/config/kheops.js +++ b/platform/app/public/config/kheops.js @@ -27,6 +27,16 @@ window.config = { // Uses the ohif datasource as the default - this requires that KHEOPS be // configured with an OHIF path to .../viewer/dicomwebproxy defaultDataSourceName: 'ohif', + // Show basic as 'Basic' and hide the longiutdinal mode for kheops + modesConfiguration: { + '@ohif/mode-basic': { + hide: { $set: false }, + displayName: { $set: 'Basic' }, + }, + '@ohif/mode-longitudinal': { + hide: { $set: true }, + }, + }, /* Dynamic config allows user to pass "configUrl" query string this allows to load config without recompiling application. The regex will ensure valid configuration source */ // dangerouslyUseDynamicConfig: { // enabled: true, diff --git a/platform/app/src/routes/WorkList/WorkList.tsx b/platform/app/src/routes/WorkList/WorkList.tsx index 0ea85fa38..f86bdf6f7 100644 --- a/platform/app/src/routes/WorkList/WorkList.tsx +++ b/platform/app/src/routes/WorkList/WorkList.tsx @@ -391,12 +391,21 @@ function WorkList({ }) : appConfig.loadedModes ).map((mode, i) => { + if (mode.hide) { + // Hide this mode from display + return null; + } const modalitiesToCheck = modalities.replaceAll('/', '\\'); const { valid: isValidMode, description: invalidModeDescription } = mode.isValidMode({ modalities: modalitiesToCheck, study, }); + if (isValidMode === null) { + // Hide this as a computed result. + return null; + } + // TODO: Modes need a default/target route? We mostly support a single one for now. // We should also be using the route path, but currently are not // mode.routeName @@ -428,7 +437,7 @@ function WorkList({ {/* TODO revisit the completely rounded style of buttons used for launching a mode from the worklist later */} diff --git a/platform/cli/templates/mode/src/index.tsx b/platform/cli/templates/mode/src/index.tsx index c0046a29c..e8d73a590 100644 --- a/platform/cli/templates/mode/src/index.tsx +++ b/platform/cli/templates/mode/src/index.tsx @@ -1,174 +1,22 @@ -import { hotkeys } from '@ohif/core'; -import { initToolGroups, toolbarButtons } from '@ohif/mode-longitudinal'; import { id } from './id'; +import { longitudinalMode, longitudinalModeInstance, longitudinalRoute } from '@ohif/mode-longitudinal'; -const ohif = { - layout: '@ohif/extension-default.layoutTemplateModule.viewerLayout', - sopClassHandler: '@ohif/extension-default.sopClassHandlerModule.stack', - hangingProtocol: '@ohif/extension-default.hangingProtocolModule.default', - leftPanel: '@ohif/extension-default.panelModule.seriesList', - rightPanel: '@ohif/extension-cornerstone.panelModule.panelMeasurement', -}; - -const cornerstone = { - viewport: '@ohif/extension-cornerstone.viewportModule.cornerstone', -}; - -/** - * Just two dependencies to be able to render a viewport with panels in order - * to make sure that the mode is working. - */ -const extensionDependencies = { - '@ohif/extension-default': '^3.0.0', - '@ohif/extension-cornerstone': '^3.0.0', -}; - -function modeFactory({ modeConfiguration }) { - return { - /** - * Mode ID, which should be unique among modes used by the viewer. This ID - * is used to identify the mode in the viewer's state. - */ +export const modeInstance = { + ...longitudinalModeInstance, + // TODO: We're using this as a route segment + // We should not be. id, routeName: 'template', - /** - * Mode name, which is displayed in the viewer's UI in the workList, for the - * user to select the mode. - */ displayName: 'Template Mode', - /** - * Runs when the Mode Route is mounted to the DOM. Usually used to initialize - * Services and other resources. - */ - onModeEnter: ({ servicesManager, extensionManager, commandsManager }: withAppTypes) => { - const { measurementService, toolbarService, toolGroupService } = servicesManager.services; - - measurementService.clearMeasurements(); - - // Init Default and SR ToolGroups - initToolGroups(extensionManager, toolGroupService, commandsManager); - - toolbarService.register([...toolbarButtons]); - toolbarService.updateSection('primary', [ - 'MeasurementTools', - 'Zoom', - 'Pan', - 'TrackballRotate', - 'WindowLevel', - 'Capture', - 'Layout', - 'Crosshairs', - 'MoreTools', - ]); - - toolbarService.updateSection('MeasurementTools', [ - 'Length', - 'Bidirectional', - 'ArrowAnnotate', - 'EllipticalROI', - 'RectangleROI', - 'CircleROI', - 'PlanarFreehandROI', - 'SplineROI', - 'LivewireContour', - ]); - - toolbarService.updateSection('MoreTools', [ - 'Reset', - 'rotate-right', - 'flipHorizontal', - 'ImageSliceSync', - 'ReferenceLines', - 'ImageOverlayViewer', - 'StackScroll', - 'invert', - 'Probe', - 'Cine', - 'Angle', - 'CobbAngle', - 'Magnify', - 'CalibrationLine', - 'TagBrowser', - 'AdvancedMagnify', - 'UltrasoundDirectionalTool', - 'WindowLevelRegion', - ]); - }, - onModeExit: ({ servicesManager }: withAppTypes) => { - const { - toolGroupService, - syncGroupService, - segmentationService, - cornerstoneViewportService, - uiDialogService, - uiModalService, - } = servicesManager.services; - - uiDialogService.hideAll(); - uiModalService.hide(); - toolGroupService.destroy(); - syncGroupService.destroy(); - segmentationService.destroy(); - cornerstoneViewportService.destroy(); - }, - /** */ - validationTags: { - study: [], - series: [], - }, - /** - * A boolean return value that indicates whether the mode is valid for the - * modalities of the selected studies. For instance a PET/CT mode should be - */ - isValidMode: ({ modalities }) => { - return { valid: true }; - }, - /** - * Mode Routes are used to define the mode's behavior. A list of Mode Route - * that includes the mode's path and the layout to be used. The layout will - * include the components that are used in the layout. For instance, if the - * default layoutTemplate is used (id: '@ohif/extension-default.layoutTemplateModule.viewerLayout') - * it will include the leftPanels, rightPanels, and viewports. However, if - * you define another layoutTemplate that includes a Footer for instance, - * you should provide the Footer component here too. Note: We use Strings - * to reference the component's ID as they are registered in the internal - * ExtensionManager. The template for the string is: - * `${extensionId}.{moduleType}.${componentId}`. - */ routes: [ - { - path: 'template', - layoutTemplate: ({ location, servicesManager }) => { - return { - id: ohif.layout, - props: { - leftPanels: [ohif.leftPanel], - rightPanels: [ohif.rightPanel], - viewports: [ - { - namespace: cornerstone.viewport, - displaySetsToDisplay: [ohif.sopClassHandler], - }, - ], - }, - }; - }, - }, + longitudinalRoute ], - /** List of extensions that are used by the mode */ - extensions: extensionDependencies, - /** HangingProtocol used by the mode */ - // hangingProtocol: [''], - /** SopClassHandlers used by the mode */ - sopClassHandlers: [ohif.sopClassHandler], - /** hotkeys for mode */ }; -} -const mode = { +export const mode = { + ...longitudinalMode, id, - modeFactory, - extensionDependencies, + modeInstance, }; export default mode; diff --git a/platform/core/src/services/ToolBarService/ToolbarService.ts b/platform/core/src/services/ToolBarService/ToolbarService.ts index 80343519c..873a886ca 100644 --- a/platform/core/src/services/ToolBarService/ToolbarService.ts +++ b/platform/core/src/services/ToolBarService/ToolbarService.ts @@ -63,6 +63,8 @@ export default class ToolbarService extends PubSubService { }, }; + public static TOOLBAR_SECTIONS = TOOLBAR_SECTIONS; + /** * Access to predefined toolbar sections for autocomplete support */ diff --git a/platform/core/src/utils/index.ts b/platform/core/src/utils/index.ts index 0955686ca..6b80a21ec 100644 --- a/platform/core/src/utils/index.ts +++ b/platform/core/src/utils/index.ts @@ -45,6 +45,7 @@ import * as MeasurementFilters from './measurementFilters'; import getClosestOrientationFromIOP from './getClosestOrientationFromIOP'; import calculateScanAxisNormal from './calculateScanAxisNormal'; import areAllImageOrientationsEqual from './areAllImageOrientationsEqual'; +import { structuredCloneWithFunctions } from './structuredCloneWithFunctions'; // Commented out unused functionality. // Need to implement new mechanism for derived displaySets using the displaySetManager. @@ -71,6 +72,7 @@ const utils = { //loadAndCacheDerivedDisplaySets, makeDeferred, makeCancelable, + structuredCloneWithFunctions, hotkeys, Queue, isDicomUid, @@ -109,6 +111,7 @@ export { //loadAndCacheDerivedDisplaySets, makeDeferred, makeCancelable, + structuredCloneWithFunctions, hotkeys, Queue, isDicomUid, diff --git a/platform/core/src/utils/structuredCloneWithFunctions.ts b/platform/core/src/utils/structuredCloneWithFunctions.ts new file mode 100644 index 000000000..e76698714 --- /dev/null +++ b/platform/core/src/utils/structuredCloneWithFunctions.ts @@ -0,0 +1,40 @@ +/** + * Clones the object, incorporating functions as functions in the result. + */ +export function structuredCloneWithFunctions(obj, seen = new WeakMap()) { + // Handle null, primitives, and functions + if (obj === null || typeof obj !== 'object') { + return obj; + } + if (typeof obj === 'function') { + return obj; // copy function by reference + } + + // Handle circular references + if (seen.has(obj)) { + return seen.get(obj); + } + + // Handle Date + if (obj instanceof Date) { + return new Date(obj.getTime()); + } + + // Handle Array + if (Array.isArray(obj)) { + const arrCopy = []; + seen.set(obj, arrCopy); + for (const item of obj) { + arrCopy.push(structuredCloneWithFunctions(item, seen)); + } + return arrCopy; + } + + // Handle Object + const copy = {}; + seen.set(obj, copy); + for (const key of Object.keys(obj)) { + copy[key] = structuredCloneWithFunctions(obj[key], seen); + } + return copy; +} diff --git a/platform/docs/docs/migration-guide/3p11-to-3p12/index.md b/platform/docs/docs/migration-guide/3p11-to-3p12/index.md index 24c79d596..d24ccf66a 100644 --- a/platform/docs/docs/migration-guide/3p11-to-3p12/index.md +++ b/platform/docs/docs/migration-guide/3p11-to-3p12/index.md @@ -6,3 +6,21 @@ sidebar_label: 3.11 -> 3.12 beta # Migration Guide This guide provides information about migrating from OHIF version 3.11 to version 3.12 beta + +## Optional: Migrate modes to extend `modes/basic` + +There is a lot of support for the basic mode definition contained in the +`modes/basic` module. Using this framework will allow your mode to avoid +creating a lot of boilerplate code that may not upgrade very well. + +This is an OPTIONAL change - your existing mode definitions will continue to work, +but using the new basic mode as a basis will reduce the amount of effort when +there are changes unrelated to your custom mode. + + +## ui button with text size + +Using the class text size with the ui-button is inconsistent as to whether +it will apply or not. Instead, create a new size value to assign the desired size. +To support this, a new size enum is created, smallTall, which is used in the worklist +for an over-ride. diff --git a/platform/docs/docs/platform/modes/index.md b/platform/docs/docs/platform/modes/index.md index 7fdd3e39a..a85900343 100644 --- a/platform/docs/docs/platform/modes/index.md +++ b/platform/docs/docs/platform/modes/index.md @@ -52,9 +52,12 @@ The mode configuration specifies which `extensions` the mode requires, which template this defines which `side panels` will be available, as well as what `viewports` and which `displaySets` they may hang. -Mode's config is composed of three elements: +Mode's config is composed of these elements: - `id`: the mode `id` - `modeFactory`: the function that returns the mode specific configuration +- `modeInstance`: An optional configuration used by the default modeFactory + exported by the basic mode. This allows specifying or updating the + default mode values. - `extensionDependencies`: the list of extensions that the mode requires @@ -62,10 +65,18 @@ that return a config object with certain properties, the high-level view of this config object is: ```js title="modes/example/src/index.js" -function modeFactory() { - return { +function modeFactory({modeConfiguration}) { + return { ...this.modeInstance, ...modeConfiguration }; + +} + +const mode = { + id, + modeFactory, + modeInstance: { id: '', version: '', + hide: true, displayName: '', onModeEnter: () => {}, onModeExit: () => {}, @@ -75,19 +86,27 @@ function modeFactory() { { path: '', init: () => {}, - layoutTemplate: () => {}, + layoutInstance: { + id, + props: { + leftPanels: [], + leftPanelResizable: true, + rightPanels: [], + rightPanelClosed: true, + rightPanelResizable: true, + viewports: [], + }, + }, + layoutTemplate: function() { return this.layoutInstance }, }, ], extensions: extensionDependencies, hangingProtocol: [], sopClassHandlers: [], - hotkeys: [] - }; -} - -const mode = { - id, - modeFactory, + hotkeys: [], + nonModeModalities: [], + modeModalities: [], + }, extensionDependencies, }; @@ -108,6 +127,12 @@ export default mode; unique mode id used to refer to the mode + + + hide + + Set to true to hide this mode on the worklist, but allow it in the path + displayName @@ -168,7 +193,7 @@ export default mode; hanging protocol - list of hanging protocols that the mode should have access to + list of hanging protocols that the mode applies initially, choosing the highest scoring match @@ -186,10 +211,44 @@ export default mode; hotkeys + + + modeModalities + + If non-empty, then the default isValidMode will only return true when the modalities list has all of the elements of one of the mode modalities. Eg `[` [CT,PT], [MR,PT] ]` would mean that the mode supports a CT AND a PT, OR an MR and a PT + + + + nonModeModalities + + Enable the mode if the modalities list contains a modality OTHER than those in the array + + + + enableSegmentationEdit + + Boolean to skip the segmentation edit capabilities + + + + toolbarSections + + An object containing toolbar section definitions to register + + +### Extending Modes + +The `basic` mode provides support for creating mode extensions without having +to redeclare the entire mode. See `longitudinal/src/index.ts` for an example +mode that builds on top of the basic mode. Also see `basic/src/index.tsx` for +some default functions which can be used to create your own modes. Doing a mode +this way makes the definition of new modes based on your existing mode much easier, +and the upgrade to new versions of modes tends to be more consistent. + ### Consuming Extensions As mentioned in the [Extensions](../extensions/index.md) section, in `OHIF-v3` @@ -345,7 +404,6 @@ const myHotkeys = [ function modeFactory() { return { - id: '', id: '', displayName: '', /* @@ -413,3 +471,50 @@ rightPanels: [[dicomSeg.panel, tracked.measurements], [dicomSeg.panel, tracked.m This will result in two panels, one with `dicomSeg.panel` and `tracked.measurements` and the other with `dicomSeg.panel` and `tracked.measurements` stacked on top of each other. ::: + +## APP Configuration of Modes + +Modes based on the `basic` mode allow for customization using the `immutability-helper` +api within the `app-config.js` file as specified by the build process. For example, +to list the `basic` mode by default, and hide the `longitudinal` mode, the following +configuration from `config/kheops.js` can be used: + +``` +... app config file + modesConfiguration: { + '@ohif/mode-basic': { + hide: { $set: false }, + displayName: { $set: 'Basic' }, + }, + '@ohif/mode-longitudinal': { + hide: { $set: true }, + }, + }, +``` + +## Default Modes + +There are a number of modes provided in a default OHIF installation. These +are described here, along with some amount of information about extending/configuration +of those modes. + +Modes which are loaded by default, but which are hidden can be activated by +using a direct URL launch. For example, to show a study in the `basic` mode, +use the URL for the `longitudinal` mode, and replace the `/viewer` with `/basic` + +### Basic (NOT `Basic Viewer`, which got assigned to `longitudinal`) + +The basic mode is a mode that demonstrates the base capabilities of the OHIF +system, without including features such as longitudinal tracking, segmentation editing +or other custom capabilities. The left hand panel uses the study browser thumbnails +without tracking, and the right hand panel uses the basic segmentation panel and the +measurements without tracking (longitudinal) layouts. This makes it a good overall +base for using when the tracking behaviour of longitudinal mode is not desired. + +It can be used in a default install by direct URL launch to the `/basic` endpoint +instead of the `/viewer` endpoint. + +### Longitudinal (The `Basic Viewer` label in OHIF) + +The longitudinal mode adds the tracking for measurements in the study browser +and in the measurements panel, and is otherwise identical to the `basic` mode. diff --git a/platform/docs/docs/platform/modes/validity.md b/platform/docs/docs/platform/modes/validity.md index f95421b80..3c5c65099 100644 --- a/platform/docs/docs/platform/modes/validity.md +++ b/platform/docs/docs/platform/modes/validity.md @@ -11,6 +11,8 @@ summary: Documentation for OHIF Mode validity checks, which determine when speci There are two mechanism for checking the validity of a mode for a study. - `isValidMode`: which is called on a selected study in the workList. + - The basic mode exports an `isValidMode` function which selects + validity based on the modalities in the study. - `validTags` @@ -22,15 +24,16 @@ validity of the mode based on `StudyInstanceUID` and `modalities` that are in th For instance, for pet-ct mode, both `PT` and 'CT' modalities should be available inside the study. ```js +import { isValidMode } from '@ohif/mode-basic'; + function modeFactory() { return { id: '', displayName: '', - isValidMode: ({ modalities, StudyInstanceUID }) => { - const modalities_list = modalities.split('\\'); - const validMode = ['CT', 'PT'].every(modality => modalities_list.includes(modality)); - return validMode; - }, + // Select either `CT & PT | MR & PT` + modeModalities: [ ['CT', 'PT'], ['MR', 'PT'] ], + // Just re-use the existing function + isValidMode, /* ... */ diff --git a/platform/ui/src/components/Button/Button.tsx b/platform/ui/src/components/Button/Button.tsx index f3ba159de..09425e310 100644 --- a/platform/ui/src/components/Button/Button.tsx +++ b/platform/ui/src/components/Button/Button.tsx @@ -6,6 +6,7 @@ import Tooltip from '../Tooltip/Tooltip'; const sizeClasses = { [ButtonEnums.size.small]: 'h-[26px] text-[13px]', + [ButtonEnums.size.smallTall]: 'h-[32px] text-[13px]', [ButtonEnums.size.medium]: 'h-[32px] text-[14px]', }; diff --git a/platform/ui/src/components/Button/ButtonEnums.ts b/platform/ui/src/components/Button/ButtonEnums.ts index 1fe82c014..bda981255 100644 --- a/platform/ui/src/components/Button/ButtonEnums.ts +++ b/platform/ui/src/components/Button/ButtonEnums.ts @@ -4,6 +4,7 @@ enum type { } enum size { medium = 'medium', + smallTall = 'smallTall', small = 'small', } diff --git a/yarn.lock b/yarn.lock index 4ba47f193..e28348bf5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6700,40 +6700,14 @@ create-require@^1.1.0: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== -cross-env@^5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-5.2.1.tgz#b2c76c1ca7add66dc874d11798466094f551b34d" - integrity sha512-1yHhtcfAd1r4nwQgknowuUNfIT9E8dOMMspC36g45dN+iD1blloi7xp8X/xAIDnjHWyt1uQ8PHk2fkNaym7soQ== - dependencies: - cross-spawn "^6.0.5" - -cross-env@^7.0.3: +cross-env@7.0.3, cross-env@^5.2.0, cross-env@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw== dependencies: cross-spawn "^7.0.1" -cross-spawn@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41" - integrity sha512-yAXz/pA1tD8Gtg2S98Ekf/sewp3Lcp3YoFKJ4Hkp5h5yLWnKVTDU0kwjKJ8NDCYcfTLfyGkzTikst+jWypT1iA== - dependencies: - lru-cache "^4.0.1" - which "^1.2.9" - -cross-spawn@^6.0.0, cross-spawn@^6.0.5: - version "6.0.6" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.6.tgz#30d0efa0712ddb7eb5a76e1e8721bffafa6b5d57" - integrity sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw== - dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" - -cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3, cross-spawn@^7.0.6: +cross-spawn@7.0.6, cross-spawn@^4.0.2, cross-spawn@^6.0.0, cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3, cross-spawn@^7.0.6: version "7.0.6" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== @@ -12444,14 +12418,6 @@ lru-cache@^10.2.0: resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== -lru-cache@^4.0.1: - version "4.1.5" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" - integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== - dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" - lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -13484,11 +13450,6 @@ next-themes@^0.3.0: resolved "https://registry.yarnpkg.com/next-themes/-/next-themes-0.3.0.tgz#b4d2a866137a67d42564b07f3a3e720e2ff3871a" integrity sha512-/QHIrsYpd6Kfk7xakK4svpDI5mmXP0gfvCoJdGpZQ2TOrQZmsW0QxjaiLn8wbIKjtm4BTSqLoix4lxYYOnLJ/w== -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== - no-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" @@ -14550,7 +14511,7 @@ path-is-inside@1.0.2, path-is-inside@^1.0.2: resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" integrity sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w== -path-key@^2.0.0, path-key@^2.0.1: +path-key@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== @@ -15524,11 +15485,6 @@ proxy-from-env@^1.1.0: resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== -pseudomap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== - psl@^1.1.33: version "1.15.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.15.0.tgz#bdace31896f1d97cec6a79e8224898ce93d974c6" @@ -16683,7 +16639,7 @@ semver-compare@^1.0.0: resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" integrity sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow== -"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0: +"semver@2 || 3 || 4 || 5", semver@^5.6.0: version "5.7.2" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== @@ -16865,13 +16821,6 @@ shallow-clone@^3.0.0: dependencies: kind-of "^6.0.2" -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== - dependencies: - shebang-regex "^1.0.0" - shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -16879,11 +16828,6 @@ shebang-command@^2.0.0: dependencies: shebang-regex "^3.0.0" -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== - shebang-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" @@ -17379,7 +17323,7 @@ string-natural-compare@^3.0.1: resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw== -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -17397,6 +17341,15 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" @@ -17505,7 +17458,7 @@ stringify-object@^3.3.0: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -17526,6 +17479,13 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -19060,7 +19020,7 @@ which-typed-array@^1.1.13, which-typed-array@^1.1.16, which-typed-array@^1.1.19, gopd "^1.2.0" has-tostringtag "^1.0.2" -which@^1.1.1, which@^1.2.9: +which@^1.1.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== @@ -19287,7 +19247,7 @@ worker-loader@3.0.8, worker-loader@^3.0.8: loader-utils "^2.0.0" schema-utils "^3.0.0" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -19313,6 +19273,15 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.0.1, wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" @@ -19444,11 +19413,6 @@ y18n@^5.0.5: resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A== - yallist@^3.0.2: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"