@3cr/viewer-browser 0.0.200 → 0.0.246

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (383) hide show
  1. package/.circleci/config.yml +46 -22
  2. package/.prettierrc +6 -0
  3. package/components.d.ts +27 -10
  4. package/dist/Viewer3CR.js +36 -45
  5. package/dist/Viewer3CR.mjs +26893 -21667
  6. package/dist/Viewer3CR.umd.js +36 -45
  7. package/dist/android-chrome-192x192.png +0 -0
  8. package/dist/android-chrome-512x512.png +0 -0
  9. package/dist/apple-touch-icon.png +0 -0
  10. package/dist/browserconfig.xml +9 -0
  11. package/dist/favicon-16x16.png +0 -0
  12. package/dist/favicon-32x32.png +0 -0
  13. package/dist/favicon.ico +0 -0
  14. package/dist/mstile-144x144.png +0 -0
  15. package/dist/mstile-150x150.png +0 -0
  16. package/dist/mstile-310x150.png +0 -0
  17. package/dist/mstile-310x310.png +0 -0
  18. package/dist/mstile-70x70.png +0 -0
  19. package/dist/safari-pinned-tab.svg +50 -0
  20. package/dist/site.webmanifest +19 -0
  21. package/index.html +34 -41
  22. package/package.json +24 -20
  23. package/playground/android-chrome-192x192.png +0 -0
  24. package/playground/android-chrome-512x512.png +0 -0
  25. package/playground/apple-touch-icon.png +0 -0
  26. package/playground/browserconfig.xml +9 -0
  27. package/playground/favicon-16x16.png +0 -0
  28. package/playground/favicon-32x32.png +0 -0
  29. package/playground/favicon.ico +0 -0
  30. package/playground/index.html +30 -41
  31. package/playground/mstile-144x144.png +0 -0
  32. package/playground/mstile-150x150.png +0 -0
  33. package/playground/mstile-310x150.png +0 -0
  34. package/playground/mstile-310x310.png +0 -0
  35. package/playground/mstile-70x70.png +0 -0
  36. package/playground/safari-pinned-tab.svg +50 -0
  37. package/playground/site.webmanifest +19 -0
  38. package/playground/sw.js +15 -1
  39. package/public/android-chrome-192x192.png +0 -0
  40. package/public/android-chrome-512x512.png +0 -0
  41. package/public/apple-touch-icon.png +0 -0
  42. package/public/browserconfig.xml +9 -0
  43. package/public/favicon-16x16.png +0 -0
  44. package/public/favicon-32x32.png +0 -0
  45. package/public/favicon.ico +0 -0
  46. package/public/mstile-144x144.png +0 -0
  47. package/public/mstile-150x150.png +0 -0
  48. package/public/mstile-310x150.png +0 -0
  49. package/public/mstile-310x310.png +0 -0
  50. package/public/mstile-70x70.png +0 -0
  51. package/public/safari-pinned-tab.svg +50 -0
  52. package/public/site.webmanifest +19 -0
  53. package/src/App.vue +55 -50
  54. package/src/__tests__/app.spec.ts +7 -8
  55. package/{__tests__/index.spec.ts → src/__tests__/main.spec.ts} +5 -6
  56. package/src/assets/logos/3dicom/white-mini.svg +20 -0
  57. package/src/assets/logos/3dicom/white.svg +30 -0
  58. package/src/assets/styles.scss +18 -4
  59. package/src/components/demo/DemoPatientModal.vue +12 -22
  60. package/src/components/demo/__tests__/DemoModal.spec.ts +9 -8
  61. package/src/components/demo/__tests__/DemoPatientModal.spec.ts +11 -10
  62. package/src/components/demo/__tests__/options.spec.ts +1 -1
  63. package/src/components/demo/licence/DemoLicenceInfoModal.vue +11 -29
  64. package/src/components/demo/licence/__tests__/DemoLicenceEnableCloudStorageModal.spec.ts +11 -10
  65. package/src/components/demo/licence/__tests__/DemoLicenceInfoModal.spec.ts +21 -11
  66. package/src/components/demo/licence/__tests__/DemoLicenceSendToPartyModal.spec.ts +10 -10
  67. package/src/components/demo/licence/__tests__/DemoLicenceShareToMobileModal.spec.ts +14 -13
  68. package/src/components/demo/options.ts +74 -76
  69. package/src/components/demo/patient/DemoPatientInfoModal.vue +11 -29
  70. package/src/components/demo/patient/__tests__/DemoPatientEnableCloudStorageModal.spec.ts +11 -10
  71. package/src/components/demo/patient/__tests__/DemoPatientInfoModal.spec.ts +12 -11
  72. package/src/components/demo/patient/__tests__/DemoPatientSendToPartyModal.spec.ts +10 -10
  73. package/src/components/demo/patient/__tests__/DemoPatientShareToMobileModal.spec.ts +14 -13
  74. package/src/components/modal/ActionRail.vue +7 -11
  75. package/src/components/modal/AskAI.vue +35 -50
  76. package/src/components/modal/CloseViewerModal.vue +22 -57
  77. package/src/components/modal/MftpWebGL3DRModal.vue +230 -635
  78. package/src/components/modal/ViewerActionRail.vue +44 -39
  79. package/src/components/modal/ViewerNavigationDrawer.vue +10 -8
  80. package/src/components/modal/ViewerNavigationDrawerContent.vue +91 -49
  81. package/src/components/modal/ViewerNavigationDrawerFooter.vue +83 -63
  82. package/src/components/modal/ViewerNavigationDrawerHeader.vue +14 -44
  83. package/src/components/modal/ViewerScanView.vue +114 -0
  84. package/src/components/modal/WebGL3DR.vue +91 -0
  85. package/src/components/modal/__tests__/ActionRail.spec.ts +10 -0
  86. package/src/components/modal/__tests__/AskAI.spec.ts +33 -0
  87. package/src/components/modal/__tests__/CloseViewerModal.spec.ts +24 -14
  88. package/src/components/modal/__tests__/MftpWebGL3DRModal.spec.ts +147 -176
  89. package/src/components/modal/__tests__/ViewerActionRail.spec.ts +11 -0
  90. package/src/components/modal/__tests__/ViewerNavigationDrawer.spec.ts +10 -12
  91. package/src/components/modal/__tests__/ViewerNavigationDrawerContent.spec.ts +4 -22
  92. package/src/components/modal/__tests__/ViewerNavigationDrawerFooter.spec.ts +35 -32
  93. package/src/components/modal/__tests__/ViewerNavigationDrawerHeader.spec.ts +14 -11
  94. package/src/components/modal/__tests__/ViewerScanView.spec.ts +60 -0
  95. package/src/components/modal/__tests__/WebGL3DR.spec.ts +57 -0
  96. package/src/components/modal/actions/Flip3dAction.vue +1 -1
  97. package/src/components/modal/actions/FlipHorizontalAction.vue +5 -10
  98. package/src/components/modal/actions/FlipVerticalAction.vue +5 -10
  99. package/src/components/modal/actions/FullscreenAction.vue +6 -11
  100. package/src/components/modal/actions/NavigationCubeAction.vue +7 -14
  101. package/src/components/modal/actions/PanAction.vue +4 -4
  102. package/src/components/modal/actions/ResetViewAction.vue +1 -1
  103. package/src/components/modal/actions/Rotate2dAction.vue +8 -20
  104. package/src/components/modal/actions/Slice3dAction.vue +10 -32
  105. package/src/components/modal/actions/ZoomAction.vue +1 -1
  106. package/src/components/modal/actions/__tests__/Action.spec.ts +8 -9
  107. package/src/components/modal/actions/__tests__/Flip3dAction.spec.ts +6 -8
  108. package/src/components/modal/actions/__tests__/FlipHorizontalAction.spec.ts +6 -7
  109. package/src/components/modal/actions/__tests__/FlipVerticalAction.spec.ts +6 -7
  110. package/src/components/modal/actions/__tests__/FullscreenAction.spec.ts +9 -10
  111. package/src/components/modal/actions/__tests__/NavigationCubeAction.spec.ts +11 -11
  112. package/src/components/modal/actions/__tests__/PanAction.spec.ts +9 -10
  113. package/src/components/modal/actions/__tests__/ResetViewAction.spec.ts +7 -7
  114. package/src/components/modal/actions/__tests__/Rotate2dAction.spec.ts +6 -8
  115. package/src/components/modal/actions/__tests__/Slice3dAction.spec.ts +23 -5
  116. package/src/components/modal/actions/__tests__/ZoomAction.spec.ts +8 -10
  117. package/src/components/modal/buttons/AutoAnnotateBtn.vue +197 -0
  118. package/src/components/modal/buttons/__tests__/AutoAnnotateBtn.spec.ts +28 -0
  119. package/src/components/modal/menus/FileMenu.vue +73 -0
  120. package/src/components/modal/menus/SettingsMenu.vue +106 -0
  121. package/src/components/modal/menus/__tests__/FileMenu.spec.ts +110 -0
  122. package/src/components/modal/menus/__tests__/SettingsMenu.spec.ts +71 -0
  123. package/src/components/navigation/mcad/McadGlobalActions.vue +20 -0
  124. package/src/components/navigation/mcad/McadGlobalOpacitySlider.vue +103 -0
  125. package/src/components/navigation/mcad/McadGlobalScanViewBtn.vue +28 -0
  126. package/src/components/navigation/mcad/McadGlobalVisibilityBtn.vue +38 -0
  127. package/src/components/shared/DoubleSliderSelector.vue +142 -0
  128. package/src/components/{loading → shared}/LoadingSpinner.vue +27 -36
  129. package/src/components/shared/UpdateSnackbar.vue +72 -0
  130. package/src/components/{selectors → shared}/ValueSelector.vue +9 -12
  131. package/src/components/shared/__tests__/DoubleSliderSelector.spec.ts +83 -0
  132. package/src/components/shared/__tests__/LoadingSpinner.spec.ts +9 -0
  133. package/src/components/shared/__tests__/UpdateSnackbar.spec.ts +116 -0
  134. package/src/components/shared/__tests__/ValueSelector.spec.ts +39 -0
  135. package/src/components/shared/__tests__/VerticalSliderSelector.spec.ts +50 -0
  136. package/src/components/views/AnnotationTreeView.vue +236 -0
  137. package/src/components/{modal/ViewerDisplaySettings.vue → views/DisplaySettings.vue} +7 -15
  138. package/src/components/views/MarkupTreeView.vue +201 -0
  139. package/src/components/views/McadObjectTreeView.vue +129 -0
  140. package/src/components/views/__tests__/AnnotationTreeView.spec.ts +62 -0
  141. package/src/components/{modal/__tests__/ViewerDisplaySettings.spec.ts → views/__tests__/DisplaySettings.spec.ts} +24 -20
  142. package/src/components/views/__tests__/MarkupTreeView.spec.ts +41 -0
  143. package/src/components/views/__tests__/McadObjectTreeView.spec.ts +47 -0
  144. package/src/components/views/modals/DataOverlayGeneralModal.vue +71 -0
  145. package/src/components/views/modals/DataOverlayMarkupModal.vue +60 -0
  146. package/src/components/views/modals/DataOverlayModal.vue +88 -0
  147. package/src/components/views/shared/MaskIcon.vue +44 -0
  148. package/src/components/views/shared/ObjectColor.vue +31 -0
  149. package/src/components/views/shared/ObjectLabel.vue +30 -0
  150. package/src/components/views/shared/Opacity.vue +65 -0
  151. package/src/components/views/shared/VisibilityBtn.vue +25 -0
  152. package/src/components/views/shared/__tests__/MaskIcon.spec.ts +10 -0
  153. package/src/components/views/shared/__tests__/ObjectColor.spec.ts +10 -0
  154. package/src/components/views/shared/__tests__/ObjectLabel.spec.ts +10 -0
  155. package/src/components/views/shared/__tests__/Opacity.spec.ts +24 -0
  156. package/src/components/views/shared/__tests__/VisibilityBtn.spec.ts +11 -0
  157. package/src/components/views/types/annotation-tree-view-item-child-action.ts +6 -0
  158. package/src/components/views/types/annotation-tree-view-item-child.ts +9 -0
  159. package/src/components/views/types/annotation-tree-view-item.ts +13 -0
  160. package/src/components/views/types/markup-tree-view-item-child.ts +6 -0
  161. package/src/components/views/types/markup-tree-view-item.ts +14 -0
  162. package/src/components/views/types/mcad-object-tree-view-item.ts +13 -0
  163. package/src/composables/__tests__/useAnnotations.spec.ts +35 -0
  164. package/src/composables/__tests__/useEventListener.spec.ts +32 -0
  165. package/src/composables/__tests__/useIntroJs.spec.ts +51 -0
  166. package/src/composables/__tests__/useMarkups.spec.ts +39 -0
  167. package/src/composables/__tests__/useMcadObjects.spec.ts +36 -0
  168. package/src/composables/__tests__/useMouse.spec.ts +20 -0
  169. package/src/{components/modal/composables → composables}/__tests__/useNavigationCubeObserver.spec.ts +17 -12
  170. package/src/{dataLayer → composables}/__tests__/useViewer3cr.spec.ts +1 -2
  171. package/src/composables/useAnnotations.ts +37 -0
  172. package/src/composables/useDebounce.ts +11 -0
  173. package/src/composables/useEventListener.ts +25 -0
  174. package/src/composables/useIntroJs.ts +142 -0
  175. package/src/composables/useMarkups.ts +41 -0
  176. package/src/composables/useMcadObjects.ts +32 -0
  177. package/src/composables/useMouse.ts +14 -0
  178. package/src/{components/modal/composables → composables}/useNavigationCubeObserver.ts +35 -25
  179. package/src/composables/useScanMovement.ts +25 -0
  180. package/src/composables/useScanSliders.ts +36 -0
  181. package/src/composables/useVersion3cr.ts +7 -0
  182. package/src/composables/useViewer3cr.ts +7 -0
  183. package/src/composables/useViewerOptions.ts +36 -0
  184. package/src/{dataLayer → functions}/__tests__/clamp.spec.ts +1 -2
  185. package/src/functions/__tests__/layoutOverlayStyle.spec.ts +325 -0
  186. package/src/{helpers/__tests__/model-helper.spec.ts → functions/__tests__/modelHelper.spec.ts} +77 -40
  187. package/src/{notifications → functions}/__tests__/notification.spec.ts +19 -29
  188. package/src/functions/__tests__/parseAction.spec.ts +9 -0
  189. package/src/functions/__tests__/parseCallToAction.spec.ts +11 -0
  190. package/src/functions/__tests__/parseDataOverlay.spec.ts +15 -0
  191. package/src/functions/__tests__/parseDataOverlayData.spec.ts +9 -0
  192. package/src/functions/__tests__/parseDataOverlayEvent.spec.ts +10 -0
  193. package/src/functions/__tests__/parseMcadEvent.spec.ts +10 -0
  194. package/src/functions/guards/isDataOverlayAngle.ts +6 -0
  195. package/src/functions/guards/isDataOverlayLength.ts +6 -0
  196. package/src/functions/guards/isDataOverlayPolygon.ts +6 -0
  197. package/src/functions/layoutOverlayStyle.ts +84 -0
  198. package/src/{helpers → functions}/modelHelper.ts +81 -18
  199. package/src/functions/notification.ts +82 -0
  200. package/src/functions/parseAction.ts +9 -0
  201. package/src/functions/parseCallToAction.ts +9 -0
  202. package/src/functions/parseDataOverlay.ts +10 -0
  203. package/src/functions/parseDataOverlayData.ts +10 -0
  204. package/src/functions/parseDataOverlayEvent.ts +17 -0
  205. package/src/functions/parseMcadEvent.ts +10 -0
  206. package/src/functions/rgbaToCss.ts +13 -0
  207. package/src/main.ts +57 -9
  208. package/src/{dataLayer → models}/__tests__/eventHandlers.spec.ts +2 -3
  209. package/src/models/__tests__/loadViewerOptions.spec.ts +72 -0
  210. package/src/models/__tests__/loadViewerPayload.spec.ts +10 -0
  211. package/src/models/__tests__/scanState.spec.ts +190 -0
  212. package/src/models/callbacks.ts +4 -0
  213. package/src/models/loadViewerOptions.ts +79 -0
  214. package/src/models/loadViewerPayload.ts +17 -0
  215. package/src/{dataLayer → models}/scanState.ts +63 -74
  216. package/src/plugins/__tests__/usePlugins.spec.ts +12 -0
  217. package/src/plugins/__tests__/vuetify.spec.ts +3 -4
  218. package/src/plugins/usePlugins.ts +8 -0
  219. package/src/plugins/vuetify.ts +31 -65
  220. package/src/services/{gpt/__tests__ → __tests__}/gpt.service.spec.ts +2 -2
  221. package/src/services/__tests__/service-worker.service.spec.ts +32 -0
  222. package/src/{dataLayer/__tests__/viewer3cr.spec.ts → services/__tests__/viewer-3cr.service.spec.ts} +97 -36
  223. package/src/services/gpt.service.ts +17 -0
  224. package/src/services/service-worker.service.ts +16 -0
  225. package/src/{dataLayer/viewer3cr.ts → services/viewer-3cr.service.ts} +281 -150
  226. package/src/tools/data-overlay.tool.ts +71 -0
  227. package/src/types/action.ts +13 -0
  228. package/src/types/call-to-action.ts +9 -0
  229. package/src/types/colour.ts +6 -0
  230. package/src/types/data-overlay-angle.ts +16 -0
  231. package/src/types/data-overlay-annotation.ts +18 -0
  232. package/src/types/data-overlay-data.ts +15 -0
  233. package/src/types/data-overlay-event.ts +5 -0
  234. package/src/types/data-overlay-info.ts +18 -0
  235. package/src/types/data-overlay-interaction.ts +15 -0
  236. package/src/types/data-overlay-length.ts +16 -0
  237. package/src/types/data-overlay-markup.ts +7 -0
  238. package/src/types/data-overlay-mcad.ts +20 -0
  239. package/src/types/data-overlay-polygon.ts +18 -0
  240. package/src/types/data-overlay.ts +16 -0
  241. package/src/types/demo-type.ts +4 -0
  242. package/src/types/gpt-question.ts +4 -0
  243. package/src/types/gpt-response-payload.ts +6 -0
  244. package/src/types/mcad-object-interaction.ts +15 -0
  245. package/src/types/segment-angle.ts +5 -0
  246. package/src/types/vector2.ts +4 -0
  247. package/src/types/vector3.ts +5 -0
  248. package/test/fakers/action-data.faker.ts +11 -0
  249. package/test/fakers/action.faker.ts +19 -0
  250. package/test/fakers/call-to-action.faker.ts +17 -0
  251. package/test/fakers/colour.faker.ts +17 -0
  252. package/test/fakers/data-overlay-angle.faker.ts +37 -0
  253. package/test/fakers/data-overlay-annotation.faker.ts +41 -0
  254. package/test/fakers/data-overlay-data.faker.ts +97 -0
  255. package/test/fakers/data-overlay-info.faker.ts +29 -0
  256. package/test/fakers/data-overlay-interaction.faker.ts +62 -0
  257. package/test/fakers/data-overlay-length.faker.ts +37 -0
  258. package/test/fakers/data-overlay-mcad.faker.ts +40 -0
  259. package/test/fakers/data-overlay-polygon.faker.ts +39 -0
  260. package/test/fakers/gpt-question.faker.ts +11 -0
  261. package/test/fakers/gpt-response.faker.ts +12 -0
  262. package/test/fakers/invert-transform.faker.ts +16 -0
  263. package/test/fakers/mcad-object-interaction.faker.ts +22 -0
  264. package/test/fakers/orientation.faker.ts +17 -0
  265. package/test/fakers/segment-angle.faker.ts +12 -0
  266. package/test/fakers/vector2.faker.ts +12 -0
  267. package/test/fakers/vector3.faker.ts +16 -0
  268. package/test/plugins/findByTestId.ts +25 -0
  269. package/test/plugins/vuetify.ts +16 -0
  270. package/test/setup.ts +16 -5
  271. package/tsconfig.json +4 -15
  272. package/vite.config.mts +20 -46
  273. package/vitest.config.mts +24 -43
  274. package/index.ts +0 -72
  275. package/src/assets/images/dark/3DICOM.png +0 -0
  276. package/src/assets/images/dark/3dicom-logo.svg +0 -1
  277. package/src/assets/images/light/3DICOM.png +0 -0
  278. package/src/assets/images/light/3dicom-logo.svg +0 -1
  279. package/src/assets/logo.png +0 -0
  280. package/src/assets/logo.svg +0 -6
  281. package/src/components/WebGL3DR.vue +0 -102
  282. package/src/components/__tests__/webgl3dr.spec.ts +0 -37
  283. package/src/components/icons/liver.vue +0 -21
  284. package/src/components/loading/__tests__/loading-spinner.spec.ts +0 -11
  285. package/src/components/modal/ViewerAnnotationModal.vue +0 -111
  286. package/src/components/modal/ViewerAnnotations.vue +0 -289
  287. package/src/components/modal/__tests__/ViewerAnnotationModal.spec.ts +0 -79
  288. package/src/components/modal/composables/useEventListener.ts +0 -22
  289. package/src/components/selectors/__tests__/value-selector.spec.ts +0 -53
  290. package/src/components/sliders/DoubleSliderSelector.vue +0 -141
  291. package/src/components/sliders/__tests__/double-slider-selector.spec.ts +0 -104
  292. package/src/components/sliders/__tests__/vertical-slider-selector.spec.ts +0 -61
  293. package/src/dataLayer/__tests__/getIconForPreset.spec.ts +0 -40
  294. package/src/dataLayer/__tests__/patchDataOverlay.spec.ts +0 -88
  295. package/src/dataLayer/__tests__/scanState.spec.ts +0 -93
  296. package/src/dataLayer/getIconForPreset.ts +0 -11
  297. package/src/dataLayer/patchDataOverlay.ts +0 -101
  298. package/src/dataLayer/useViewer3cr.ts +0 -7
  299. package/src/helpers/__tests__/layout-overlay-style.spec.ts +0 -290
  300. package/src/helpers/__tests__/utils.spec.ts +0 -70
  301. package/src/helpers/layoutOverlayStyle.ts +0 -96
  302. package/src/helpers/utils.ts +0 -16
  303. package/src/models/Callbacks.ts +0 -2
  304. package/src/models/LoadViewerOptions.ts +0 -31
  305. package/src/models/LoadViewerPayload.ts +0 -9
  306. package/src/models/__tests__/load-viewer-options.spec.ts +0 -22
  307. package/src/notifications/notification.ts +0 -50
  308. package/src/plugins/__tests__/index.spec.ts +0 -19
  309. package/src/plugins/index.ts +0 -17
  310. package/src/services/gpt/gpt.service.ts +0 -35
  311. package/static/3cr-types-browser/index.ts +0 -74
  312. package/static/3cr-types-browser/types/Action.ts +0 -6
  313. package/static/3cr-types-browser/types/AlphaKeys.ts +0 -5
  314. package/static/3cr-types-browser/types/AnchorPoint.ts +0 -12
  315. package/static/3cr-types-browser/types/CallToAction.ts +0 -5
  316. package/static/3cr-types-browser/types/ColourData.ts +0 -7
  317. package/static/3cr-types-browser/types/ColourPresetData.ts +0 -9
  318. package/static/3cr-types-browser/types/CurrentDataOverlayState.ts +0 -6
  319. package/static/3cr-types-browser/types/CurrentScanState.ts +0 -22
  320. package/static/3cr-types-browser/types/DataOverlay.ts +0 -22
  321. package/static/3cr-types-browser/types/DataOverlayActions.ts +0 -14
  322. package/static/3cr-types-browser/types/DataOverlayData.ts +0 -8
  323. package/static/3cr-types-browser/types/DataOverlayEvent.ts +0 -8
  324. package/static/3cr-types-browser/types/DecryptionKey.ts +0 -4
  325. package/static/3cr-types-browser/types/DisplaySettings.ts +0 -10
  326. package/static/3cr-types-browser/types/EmptyPayload.ts +0 -3
  327. package/static/3cr-types-browser/types/EnumPayload.ts +0 -4
  328. package/static/3cr-types-browser/types/FileManagementActions.ts +0 -11
  329. package/static/3cr-types-browser/types/FlipValue.ts +0 -7
  330. package/static/3cr-types-browser/types/FrontEndInterfaces.ts +0 -14
  331. package/static/3cr-types-browser/types/GradientKeys.ts +0 -7
  332. package/static/3cr-types-browser/types/GreyscalePresetData.ts +0 -6
  333. package/static/3cr-types-browser/types/InitialDataOverlayState.ts +0 -6
  334. package/static/3cr-types-browser/types/InitialScanState.ts +0 -19
  335. package/static/3cr-types-browser/types/InteractionType.ts +0 -8
  336. package/static/3cr-types-browser/types/InteractivityActions.ts +0 -6
  337. package/static/3cr-types-browser/types/InteractivityState.ts +0 -4
  338. package/static/3cr-types-browser/types/InvertTransformData.ts +0 -6
  339. package/static/3cr-types-browser/types/LayoutActions.ts +0 -6
  340. package/static/3cr-types-browser/types/LayoutData.ts +0 -7
  341. package/static/3cr-types-browser/types/LoadDataSet.ts +0 -6
  342. package/static/3cr-types-browser/types/LoadSessionState.ts +0 -4
  343. package/static/3cr-types-browser/types/LocalLoadDataset.ts +0 -3
  344. package/static/3cr-types-browser/types/MovementData.ts +0 -7
  345. package/static/3cr-types-browser/types/NavigationCubeActions.ts +0 -8
  346. package/static/3cr-types-browser/types/NavigationCubeData.ts +0 -12
  347. package/static/3cr-types-browser/types/NavigationCubeTransform.ts +0 -9
  348. package/static/3cr-types-browser/types/NotificationPayload.ts +0 -7
  349. package/static/3cr-types-browser/types/NotificationsActions.ts +0 -6
  350. package/static/3cr-types-browser/types/Object.ts +0 -1
  351. package/static/3cr-types-browser/types/ObjectColour.ts +0 -7
  352. package/static/3cr-types-browser/types/ObjectIcon.ts +0 -5
  353. package/static/3cr-types-browser/types/ObjectInvert.ts +0 -7
  354. package/static/3cr-types-browser/types/ObjectSize.ts +0 -7
  355. package/static/3cr-types-browser/types/ObjectSize2D.ts +0 -7
  356. package/static/3cr-types-browser/types/ObjectVisible.ts +0 -5
  357. package/static/3cr-types-browser/types/PositionData.ts +0 -14
  358. package/static/3cr-types-browser/types/PresetsActions.ts +0 -4
  359. package/static/3cr-types-browser/types/RotationValue.ts +0 -7
  360. package/static/3cr-types-browser/types/ScanMovementActions.ts +0 -27
  361. package/static/3cr-types-browser/types/ScanMovementData.ts +0 -3
  362. package/static/3cr-types-browser/types/ScanOrientationActions.ts +0 -6
  363. package/static/3cr-types-browser/types/ScanStateActions.ts +0 -4
  364. package/static/3cr-types-browser/types/ScanView.ts +0 -6
  365. package/static/3cr-types-browser/types/SettingsData.ts +0 -12
  366. package/static/3cr-types-browser/types/SlicerData.ts +0 -9
  367. package/static/3cr-types-browser/types/SliderValue.ts +0 -4
  368. package/static/3cr-types-browser/types/SlidersActions.ts +0 -18
  369. package/static/3cr-types-browser/types/Vector2Data.ts +0 -5
  370. package/static/3cr-types-browser/types/Vector3Data.ts +0 -6
  371. package/static/3cr-types-browser/types/VectorMovementData.ts +0 -8
  372. package/static/3cr-types-browser/types/ViewInteractiveMode.ts +0 -5
  373. package/static/3cr-types-browser/types/ViewOrientation.ts +0 -8
  374. package/static/3cr-types-browser/types/ViewOrientations.ts +0 -10
  375. package/static/3cr-types-browser/types/ViewSelectionActions.ts +0 -9
  376. package/static/3cr-types-browser/types/ViewToggleData.ts +0 -7
  377. package/static/3cr-types-browser/types/VolumeOrientation.ts +0 -7
  378. package/test/helper.ts +0 -44
  379. /package/src/components/{sliders → shared}/VerticalSliderSelector.vue +0 -0
  380. /package/{config.ts → src/config.ts} +0 -0
  381. /package/src/{dataLayer → functions}/clamp.ts +0 -0
  382. /package/src/{dataLayer → models}/eventHandlers.ts +0 -0
  383. /package/{static/3cr-types-browser/types/ActionData.ts → src/types/action-data.ts} +0 -0
@@ -1,17 +1,16 @@
1
- import { describe, expect, it, vi } from "vitest";
2
- import { mountVuetify } from "~/helper";
3
- import { CurrentScanState, LayoutActions, ScanView } from "@3cr/types-ts";
4
- import { Viewer3cr } from "@/dataLayer/viewer3cr";
5
- import { previousLayout, scanState } from "@/dataLayer/scanState";
6
- import FullscreenAction from "../FullscreenAction.vue";
1
+ import { CurrentScanState, LayoutActions, ScanView } from '@3cr/types-ts';
2
+ import { Viewer3crService } from '@/services/viewer-3cr.service';
3
+ import { previousLayout, scanState } from '@/models/scanState';
4
+ import FullscreenAction from '../FullscreenAction.vue';
5
+ import { mount } from '@vue/test-utils';
7
6
 
8
7
  describe('FullscreenAction tests', () => {
9
8
  const props = { view: ScanView.Coronal };
10
- const layoutsSpy = vi.spyOn(Viewer3cr.prototype, 'layouts').mockResolvedValue();
11
- const viewSpy = vi.spyOn(Viewer3cr.prototype, 'viewSelection').mockResolvedValue();
9
+ const layoutsSpy = vi.spyOn(Viewer3crService.prototype, 'layouts').mockResolvedValue();
10
+ const viewSpy = vi.spyOn(Viewer3crService.prototype, 'viewSelection').mockResolvedValue();
12
11
 
13
12
  it('should fullscreen', async () => {
14
- const wrapper = mountVuetify(FullscreenAction, props);
13
+ const wrapper = mount(FullscreenAction, { props });
15
14
  const button = wrapper.find('[data-testid="button"]');
16
15
  await button.trigger('click');
17
16
  expect(layoutsSpy).toHaveBeenCalledWith(LayoutActions.lo01);
@@ -20,7 +19,7 @@ describe('FullscreenAction tests', () => {
20
19
 
21
20
  it('should exit fullscreen', async () => {
22
21
  scanState.value = { Layout: { PositionData: [{}] } } as CurrentScanState;
23
- const wrapper = mountVuetify(FullscreenAction, props);
22
+ const wrapper = mount(FullscreenAction, { props });
24
23
  const button = wrapper.find('[data-testid="button"]');
25
24
  await button.trigger('click');
26
25
  expect(layoutsSpy).toHaveBeenCalledWith(previousLayout.value);
@@ -1,24 +1,24 @@
1
- import { describe, expect, it, vi } from "vitest";
2
- import { Viewer3cr } from "@/dataLayer/viewer3cr";
3
- import { mountVuetify } from "~/helper";
4
- import { scanState } from "@/dataLayer/scanState";
5
- import { CurrentScanState } from "@3cr/types-ts";
6
- import NavigationCubeAction from "@/components/modal/actions/NavigationCubeAction.vue";
1
+ import { Viewer3crService } from '@/services/viewer-3cr.service';
2
+ import { scanState } from '@/models/scanState';
3
+ import { CurrentScanState } from '@3cr/types-ts';
4
+ import { VCheckbox } from 'vuetify/components';
5
+ import { mount } from '@vue/test-utils';
6
+ import NavigationCubeAction from '@/components/modal/actions/NavigationCubeAction.vue';
7
7
 
8
8
  describe('NavigationCubeAction tests', () => {
9
- const navCubeInteractivitySpy = vi.spyOn(Viewer3cr.prototype, 'setNavCubeInteractivity').mockResolvedValue();
9
+ const navCubeInteractivitySpy = vi.spyOn(Viewer3crService.prototype, 'setNavCubeInteractivity').mockResolvedValue();
10
10
 
11
11
  it('should show navigation cube', async () => {
12
- const wrapper = mountVuetify(NavigationCubeAction);
13
- const switchCmp = wrapper.findComponent('[data-testid="switch"]');
12
+ const wrapper = mount(NavigationCubeAction);
13
+ const switchCmp = wrapper.findComponent(VCheckbox);
14
14
  await switchCmp.trigger('click');
15
15
  expect(navCubeInteractivitySpy).toHaveBeenCalledWith(true);
16
16
  });
17
17
 
18
18
  it('should hide navigation cube', async () => {
19
19
  scanState.value = { NavigationCube: { Interactivity: { Value: true } } } as CurrentScanState;
20
- const wrapper = mountVuetify(NavigationCubeAction);
21
- const switchWrapper = wrapper.findComponent('[data-testid="switch"]');
20
+ const wrapper = mount(NavigationCubeAction);
21
+ const switchWrapper = wrapper.findComponent(VCheckbox);
22
22
  await switchWrapper.trigger('click');
23
23
  expect(navCubeInteractivitySpy).toHaveBeenCalledWith(false);
24
24
  });
@@ -1,18 +1,17 @@
1
- import { describe, expect, it, vi } from "vitest";
2
- import { mountVuetify } from "~/helper";
3
- import { ScanView } from "@3cr/types-ts";
4
- import { Viewer3cr } from "@/dataLayer/viewer3cr";
5
- import PanAction from "@/components/modal/actions/PanAction.vue";
1
+ import { ScanView } from '@3cr/types-ts';
2
+ import { Viewer3crService } from '@/services/viewer-3cr.service';
3
+ import { mount } from '@vue/test-utils';
4
+ import PanAction from '@/components/modal/actions/PanAction.vue';
6
5
 
7
6
  describe('PanAction tests', () => {
8
- const spy = vi.spyOn(Viewer3cr.prototype, 'hoverOverCanvas').mockResolvedValue();
9
- const element = { addEventListener: vi.fn(), removeEventListener: vi.fn() };
7
+ const spy = vi.spyOn(Viewer3crService.prototype, 'hoverOverCanvas').mockResolvedValue();
8
+ const element = { addEventListener: vi.fn(), removeEventListener: vi.fn() } as unknown as HTMLElement;
10
9
  const windowAddSpy = vi.spyOn(window, 'addEventListener');
11
10
  // const windowRemoveSpy = vi.spyOn(window, 'removeEventListener');
12
11
 
13
12
  it('should setup event listeners', async () => {
14
13
  const props = { view: ScanView.Volume, element };
15
- mountVuetify(PanAction, props);
14
+ mount(PanAction, { props });
16
15
  expect(element.addEventListener).toHaveBeenCalledWith('mousedown', expect.anything());
17
16
  expect(element.addEventListener).toHaveBeenCalledWith('mouseenter', expect.anything());
18
17
  expect(element.addEventListener).toHaveBeenCalledWith('mouseleave', expect.anything());
@@ -22,7 +21,7 @@ describe('PanAction tests', () => {
22
21
 
23
22
  it('should disable unity input while active', async () => {
24
23
  const props = { view: ScanView.Volume, element };
25
- const wrapper = mountVuetify(PanAction, props);
24
+ const wrapper = mount(PanAction, { props });
26
25
  const button = wrapper.findComponent('[data-testid="button"]');
27
26
  await button.trigger('click');
28
27
  expect(spy).toHaveBeenCalledWith(false);
@@ -32,7 +31,7 @@ describe('PanAction tests', () => {
32
31
  const element = document.createElement('div');
33
32
  document.body.appendChild(element);
34
33
  const props = { view: ScanView.Volume, element };
35
- const wrapper = mountVuetify(PanAction, props);
34
+ const wrapper = mount(PanAction, { props });
36
35
  const button = wrapper.findComponent('[data-testid="button"]');
37
36
  await button.trigger('click');
38
37
  element.dispatchEvent(new MouseEvent('mousedown', { clientX: 0, clientY: 0 }));
@@ -1,14 +1,14 @@
1
- import { describe, expect, it, vi } from "vitest";
2
- import { Viewer3cr } from "@/dataLayer/viewer3cr";
3
- import { mountVuetify } from "~/helper";
4
- import { ViewSelectionActions } from "@3cr/types-ts";
5
- import ResetViewAction from "@/components/modal/actions/ResetViewAction.vue";
1
+ import { Viewer3crService } from '@/services/viewer-3cr.service';
2
+ import { ScanView, ViewSelectionActions } from '@3cr/types-ts';
3
+ import { mount } from '@vue/test-utils';
4
+ import ResetViewAction from '@/components/modal/actions/ResetViewAction.vue';
6
5
 
7
6
  describe('ResetViewAction tests', () => {
8
- const viewSelectionSpy = vi.spyOn(Viewer3cr.prototype, 'viewSelection').mockResolvedValue();
7
+ const viewSelectionSpy = vi.spyOn(Viewer3crService.prototype, 'viewSelection').mockResolvedValue();
9
8
 
10
9
  it('should reset view', async () => {
11
- const wrapper = mountVuetify(ResetViewAction);
10
+ const props = { view: ScanView.Volume };
11
+ const wrapper = mount(ResetViewAction, { props });
12
12
  const button = wrapper.findComponent('[data-testid="button"]');
13
13
  await button.trigger('click');
14
14
  expect(viewSelectionSpy).toHaveBeenCalledWith(ViewSelectionActions.vs06);
@@ -1,15 +1,13 @@
1
- import { describe, expect, it, vi } from "vitest";
2
- import { mountVuetify } from "~/helper";
3
- import { ScanView } from "@3cr/types-ts";
4
- import { DOMWrapper } from "@vue/test-utils";
5
- import { Viewer3cr } from "@/dataLayer/viewer3cr";
6
- import Rotate2dAction from "@/components/modal/actions/Rotate2dAction.vue";
1
+ import { ScanView } from '@3cr/types-ts';
2
+ import { DOMWrapper, mount } from '@vue/test-utils';
3
+ import { Viewer3crService } from '@/services/viewer-3cr.service';
4
+ import Rotate2dAction from '@/components/modal/actions/Rotate2dAction.vue';
7
5
 
8
6
  describe('Rotate2dAction tests', () => {
9
7
  it('should apply rotation', async () => {
10
8
  const props = { view: ScanView.Sagittal };
11
- const spy = vi.spyOn(Viewer3cr.prototype, 'rotateByDeg').mockResolvedValue();
12
- const wrapper = mountVuetify(Rotate2dAction, props);
9
+ const spy = vi.spyOn(Viewer3crService.prototype, 'rotateByDeg').mockResolvedValue();
10
+ const wrapper = mount(Rotate2dAction, { props });
13
11
  const button = wrapper.findComponent('[data-testid="button"]');
14
12
  await button.trigger('click');
15
13
 
@@ -1,14 +1,32 @@
1
- import {describe, expect, it} from "vitest";
2
- import {mountVuetify} from "~/helper";
3
- import Slice3dAction from "@/components/modal/actions/Slice3dAction.vue";
4
- import {DOMWrapper} from "@vue/test-utils";
1
+ import { DOMWrapper, flushPromises, mount } from '@vue/test-utils';
2
+ import { ScanView } from '@3cr/types-ts';
3
+ import Slice3dAction from '@/components/modal/actions/Slice3dAction.vue';
4
+ import DoubleSliderSelector from '@/components/shared/DoubleSliderSelector.vue';
5
+ import { cSlider, sSlider, tSlider } from '@/models/scanState';
5
6
 
6
7
  describe('Slice3dAction tests', () => {
7
8
  it('should open slice menu', async () => {
8
- const wrapper = mountVuetify(Slice3dAction);
9
+ const props = { view: ScanView.Volume };
10
+ const wrapper = mount(Slice3dAction, { props });
9
11
  const button = wrapper.findComponent('[data-testid="button"]');
10
12
  await button.trigger('click');
11
13
  const menu = new DOMWrapper(document.querySelector('[data-testid="menu"]'));
12
14
  expect(menu.exists()).toBeTruthy();
13
15
  });
16
+
17
+ it('should set double-slider-selector model', async () => {
18
+ const props = { view: ScanView.Volume };
19
+ const wrapper = mount(Slice3dAction, { props });
20
+ await wrapper.findByTestId('button').trigger('click');
21
+
22
+ const sliders = wrapper.findAllComponents(DoubleSliderSelector);
23
+ for (const slider of sliders) {
24
+ await slider.setValue([40, 60]);
25
+ await flushPromises();
26
+ }
27
+
28
+ expect(tSlider.value).toEqual([40, 60]);
29
+ expect(sSlider.value).toEqual([40, 60]);
30
+ expect(cSlider.value).toEqual([40, 60]);
31
+ });
14
32
  });
@@ -1,17 +1,15 @@
1
- import {describe, expect, it, vi} from "vitest";
2
- import { ScanView } from "@3cr/types-ts";
3
- import { mountVuetify } from "~/helper";
4
- import { Viewer3cr } from "@/dataLayer/viewer3cr";
5
- import ZoomAction from "@/components/modal/actions/ZoomAction.vue";
6
- import {DOMWrapper} from "@vue/test-utils";
1
+ import { ScanView } from '@3cr/types-ts';
2
+ import { Viewer3crService } from '@/services/viewer-3cr.service';
3
+ import { DOMWrapper, mount } from '@vue/test-utils';
4
+ import ZoomAction from '@/components/modal/actions/ZoomAction.vue';
7
5
 
8
6
  describe('ZoomAction tests', () => {
9
7
  const props = { view: ScanView.Sagittal, percentage: 25 };
10
- const zoomInSpy = vi.spyOn(Viewer3cr.prototype, 'zoomIn');
11
- const zoomOutSpy = vi.spyOn(Viewer3cr.prototype, 'zoomOut');
8
+ const zoomInSpy = vi.spyOn(Viewer3crService.prototype, 'zoomIn');
9
+ const zoomOutSpy = vi.spyOn(Viewer3crService.prototype, 'zoomOut');
12
10
 
13
11
  it('should zoom in', async () => {
14
- const wrapper = mountVuetify(ZoomAction, props);
12
+ const wrapper = mount(ZoomAction, { props });
15
13
  const button = wrapper.findComponent('[data-testid="button"]');
16
14
  await button.trigger('click');
17
15
 
@@ -22,7 +20,7 @@ describe('ZoomAction tests', () => {
22
20
  });
23
21
 
24
22
  it('should zoom out', async () => {
25
- const wrapper = mountVuetify(ZoomAction, props);
23
+ const wrapper = mount(ZoomAction, { props });
26
24
  const button = wrapper.findComponent('[data-testid="button"]');
27
25
  await button.trigger('click');
28
26
 
@@ -0,0 +1,197 @@
1
+ <template>
2
+ <div>
3
+ <v-menu :close-on-content-click="false" v-if="opts.OnAutoAnnotate">
4
+ <template #activator="{ props }">
5
+ <v-btn v-bind="props" data-testid="menu" class="mx-2" color="primary" prepend-icon="psychology" variant="flat">
6
+ AI
7
+ </v-btn>
8
+ </template>
9
+ <v-list>
10
+ <v-list-item
11
+ data-testid="auto_annotate"
12
+ v-if="opts.OnAutoAnnotate"
13
+ @click="autoAnnotate()"
14
+ :disabled="done"
15
+ prepend-icon="flash_auto"
16
+ :append-icon="done ? 'check' : undefined"
17
+ >
18
+ <v-list-item-title>Auto Annotate</v-list-item-title>
19
+ </v-list-item>
20
+ </v-list>
21
+ </v-menu>
22
+ <v-dialog v-model:model-value="loading">
23
+ <template #default>
24
+ <v-card :title="`Annotiva AI: ${type}`" max-width="450" class="mx-auto">
25
+ <div class="prompt">
26
+ <div style="font-size: 6px; top: 30px; left: 40px">
27
+ <div class="cog" style="--cog-colour: #5a93ed"></div>
28
+ <div
29
+ class="cog anti-clockwise"
30
+ style="--cog-colour: #2955da; margin-top: 2.25em; margin-left: -3.375em"
31
+ ></div>
32
+ <div class="cog" style="--cog-colour: #bad3f8; margin-top: 5.625em; margin-left: -1.125em"></div>
33
+ </div>
34
+ <v-card-text class="ml-10" style="font-size: 16px">
35
+ {{ text }}
36
+ </v-card-text>
37
+ </div>
38
+ </v-card>
39
+ </template>
40
+ </v-dialog>
41
+ </div>
42
+ </template>
43
+
44
+ <script setup lang="ts">
45
+ import { useViewerOptions } from '@/composables/useViewerOptions';
46
+ import { ref } from 'vue';
47
+
48
+ const opts = useViewerOptions();
49
+ const loading = ref<boolean>(false);
50
+ const done = ref<boolean>(false);
51
+ const text = ref<string>('');
52
+ const type = ref<string>('');
53
+
54
+ async function autoAnnotate() {
55
+ type.value = 'Auto Annotate';
56
+ text.value = getRandomItemFromList(loaderTexts);
57
+ loading.value = true;
58
+ await opts.value!.OnAutoAnnotate!();
59
+ setTimeout(() => {
60
+ loading.value = false;
61
+ done.value = true;
62
+ }, 4000);
63
+ }
64
+
65
+ function getRandomItemFromList(list: Array<string>) {
66
+ const randomIndex = Math.floor(Math.random() * list.length);
67
+ return list[randomIndex];
68
+ }
69
+
70
+ const loaderTexts = [
71
+ "AI: Analyzing X-rays faster than you can say 'supercalifragilisticexpialidocious'!",
72
+ 'Just a moment, our AI is putting on its lab coat.',
73
+ 'Scanning pixels like Sherlock scans clues.',
74
+ 'Our AI is channeling its inner doctor.',
75
+ 'Hang tight, our AI is donning its stethoscope.',
76
+ "Analyzing with AI precision – because guessing isn't an option!",
77
+ 'Our AI is checking the scan like a detective at a crime scene.',
78
+ 'Crunching data like a pro! Results on the way.',
79
+ 'AI is on it, decoding your scan like a mystery novel.',
80
+ 'Our AI is in deep thought... about your health!',
81
+ 'Letting our AI take a close look at those pixels.',
82
+ 'Your scan is getting the AI treatment.',
83
+ 'Analyzing like a champ! Our AI is almost there.',
84
+ 'Hold tight! Our AI is putting on its thinking cap.',
85
+ 'AI is hard at work, diagnosing like a pro!',
86
+ 'Our AI is busy solving the puzzle of your scan.',
87
+ 'AI is processing... and sipping virtual coffee.',
88
+ "Your scan is in good hands – AI's hands.",
89
+ 'Just a sec, our AI is perfecting the diagnosis.',
90
+ 'Scanning... AI style.',
91
+ 'AI is reading your scan like an open book.',
92
+ 'Give us a moment, our AI is analyzing every detail.',
93
+ 'Our AI is double-checking for good measure.',
94
+ 'AI: Making sense of pixels and patterns.',
95
+ 'AI is decoding your scan, Sherlock style.',
96
+ 'Processing with precision – AI is on it.',
97
+ 'Our AI is diving deep into the data.',
98
+ 'AI is dissecting the details for an accurate diagnosis.',
99
+ 'Hold on, our AI is piecing together the puzzle.',
100
+ 'AI is at the helm, navigating your scan results.',
101
+ 'Analyzing with AI magic – results coming up!',
102
+ 'Our AI is untangling the mysteries of your scan.',
103
+ "Processing... AI's putting its brain to work.",
104
+ 'Your scan + our AI = accurate results.',
105
+ 'AI is fine-tuning the analysis for perfection.',
106
+ 'Letting our AI do the heavy lifting – almost done!',
107
+ 'AI is reading the scan like a pro.',
108
+ 'Our AI is on a mission – accurate results ahead.',
109
+ 'Analyzing with AI expertise – hang tight!',
110
+ 'AI is taking a closer look – results are on the way.'
111
+ ];
112
+ </script>
113
+ <style>
114
+ .prompt {
115
+ margin-left: 20px;
116
+ margin-right: 20px;
117
+ padding: 20px;
118
+ text-align: center;
119
+ color: black;
120
+ display: flex;
121
+ justify-content: space-between;
122
+ align-items: center;
123
+ margin-bottom: 15px;
124
+ z-index: 100;
125
+ position: relative;
126
+ }
127
+
128
+ .prompt::before {
129
+ content: '';
130
+ position: absolute;
131
+ inset: 0;
132
+ border-radius: 16px;
133
+ padding: 3px;
134
+ background: linear-gradient(to right, #6fb3f2, #4e51f5);
135
+
136
+ -webkit-mask:
137
+ linear-gradient(#fff 0 0) content-box,
138
+ linear-gradient(#fff 0 0);
139
+ -webkit-mask-composite: xor;
140
+ mask-composite: exclude;
141
+ }
142
+
143
+ div.cog {
144
+ nfont-size: 25px;
145
+ border-radius: 0.25em;
146
+ border: solid 0.55em var(--cog-colour, #eee);
147
+ display: inline-block;
148
+ padding: 1.125em;
149
+ position: absolute;
150
+ top: inherit;
151
+ left: inherit;
152
+ -webkit-animation: rotate var(--cog-speed, 3s) linear infinite;
153
+ -moz-animation: rotate var(--cog-speed, 3s) linear infinite;
154
+ animation: rotate var(--cog-speed, 3s) linear infinite;
155
+ }
156
+
157
+ div.cog.anti-clockwise {
158
+ -webkit-animation-direction: reverse;
159
+ -moz-animation-direction: reverse;
160
+ animation-direction: reverse;
161
+ }
162
+
163
+ div.cog::before {
164
+ border: solid 0.55em var(--cog-colour, #eee);
165
+ padding: 1.125em;
166
+ position: absolute;
167
+ content: '';
168
+ transform: translate(-1.675em, -1.675em) rotate(45deg);
169
+ border-radius: 0.25em;
170
+ }
171
+
172
+ div.cog::after {
173
+ content: '';
174
+ position: absolute;
175
+ border: solid 1em var(--cog-colour, #eee);
176
+ padding: 0.375em;
177
+ border-radius: 1.8125em;
178
+ transform: translate(-1.375em, -1.375em);
179
+ filter: brightness(87.5%);
180
+ }
181
+
182
+ @-moz-keyframes rotate {
183
+ 100% {
184
+ -moz-transform: rotate(360deg);
185
+ }
186
+ }
187
+ @-webkit-keyframes rotate {
188
+ 100% {
189
+ -webkit-transform: rotate(360deg);
190
+ }
191
+ }
192
+ @keyframes rotate {
193
+ 100% {
194
+ -webkit-transform: rotate(360deg);
195
+ }
196
+ }
197
+ </style>
@@ -0,0 +1,28 @@
1
+ import { describe } from 'vitest';
2
+ import { mount } from '@vue/test-utils';
3
+ import { useViewerOptions } from '@/composables/useViewerOptions';
4
+ import { VBtn } from 'vuetify/components';
5
+ import AutoAnnotateBtn from '@/components/modal/buttons/AutoAnnotateBtn.vue';
6
+
7
+ describe('AutoAnnotateBtn tests', () => {
8
+ const options = useViewerOptions();
9
+
10
+ it('should mount', () => {
11
+ const wrapper = mount(AutoAnnotateBtn);
12
+ expect(wrapper).toBeTruthy();
13
+ });
14
+
15
+ it('should call OnAutoAnnotate', async () => {
16
+ options.value.OnAutoAnnotate = vi.fn();
17
+ const wrapper = mount(AutoAnnotateBtn);
18
+ await wrapper.findComponent(VBtn).trigger('click');
19
+ expect(options.value.OnAutoAnnotate).toHaveBeenCalled();
20
+ });
21
+
22
+ it('should not call OnAutoAnnotate', () => {
23
+ options.value.OnAutoAnnotate = undefined;
24
+ const wrapper = mount(AutoAnnotateBtn);
25
+ const button = wrapper.findComponent(VBtn);
26
+ expect(button.exists()).toBeFalsy();
27
+ });
28
+ });
@@ -0,0 +1,73 @@
1
+ <template>
2
+ <v-menu :close-on-content-click="false">
3
+ <template #activator="{ props }">
4
+ <v-btn v-bind="props" data-testid="menu" class="mr-2" color="primary" prepend-icon="description" variant="flat">
5
+ File
6
+ </v-btn>
7
+ </template>
8
+ <v-list>
9
+ <v-list-item
10
+ data-testid="load-new-dicom-series"
11
+ v-if="opts.OnLoadNewDicomSeries"
12
+ @click="opts.OnLoadNewDicomSeries()"
13
+ prepend-icon="upload"
14
+ >
15
+ <v-list-item-title>Load New DICOM Series</v-list-item-title>
16
+ </v-list-item>
17
+ <v-list-item
18
+ data-testid="download-dicom-series"
19
+ v-if="opts.OnDownloadDicomSeries"
20
+ @click="opts.OnDownloadDicomSeries()"
21
+ prepend-icon="download"
22
+ >
23
+ <v-list-item-title>Download DICOM Series</v-list-item-title>
24
+ </v-list-item>
25
+ <v-list-item
26
+ data-testid="load-saved-session"
27
+ v-if="opts.OnLoadSavedSession"
28
+ @click="opts.OnLoadSavedSession()"
29
+ prepend-icon="sync"
30
+ >
31
+ <v-list-item-title>Load Saved Session</v-list-item-title>
32
+ </v-list-item>
33
+ <v-list-item
34
+ data-testid="send-to-3rd-party"
35
+ v-if="opts.OnSendTo3rdParty"
36
+ @click="opts.OnSendTo3rdParty()"
37
+ prepend-icon="send"
38
+ >
39
+ <v-list-item-title>Send to 3rd Party</v-list-item-title>
40
+ </v-list-item>
41
+ <v-list-item
42
+ data-testid="share-to-mobile"
43
+ v-if="opts.OnShareToMobile"
44
+ @click="opts.OnShareToMobile()"
45
+ prepend-icon="share"
46
+ >
47
+ <v-list-item-title>Share to Mobile / VR</v-list-item-title>
48
+ </v-list-item>
49
+ <v-list-item data-testid="close" @click="close" prepend-icon="close">
50
+ <v-list-item-title>Close Viewer</v-list-item-title>
51
+ </v-list-item>
52
+ </v-list>
53
+ </v-menu>
54
+ </template>
55
+
56
+ <script setup lang="ts">
57
+ import { useViewerOptions } from '@/composables/useViewerOptions';
58
+
59
+ type Emits = {
60
+ close: [void];
61
+ };
62
+
63
+ const emit = defineEmits<Emits>();
64
+
65
+ const opts = useViewerOptions();
66
+
67
+ async function close(): Promise<void> {
68
+ if (opts.value.OnClosePopup) {
69
+ await opts.value.OnClosePopup();
70
+ }
71
+ emit('close');
72
+ }
73
+ </script>
@@ -0,0 +1,106 @@
1
+ <template>
2
+ <v-menu v-model="menuState" :close-on-content-click="false">
3
+ <template #activator="{ props }">
4
+ <v-btn v-bind="mergeProps(props, activatorProps)" color="primary" prepend-icon="settings" variant="flat">
5
+ Settings
6
+ </v-btn>
7
+ </template>
8
+ <v-card id="settings-card" width="350" class="pa-4">
9
+ <ValueSelector
10
+ v-model:value="scanState.Display.Brightness"
11
+ data-testid="brightness"
12
+ label="Adjust Brightness"
13
+ prepend="percent"
14
+ />
15
+ <ValueSelector
16
+ v-model:value="scanState.Display.Contrast"
17
+ data-testid="contrast"
18
+ label="Adjust Contrast"
19
+ prepend="percent"
20
+ />
21
+ <ValueSelector
22
+ v-model:value="scanState.Display.Opacity"
23
+ data-testid="opacity"
24
+ label="Adjust Opacity"
25
+ prepend="percent"
26
+ />
27
+ <v-divider class="my-4" />
28
+ <ValueSelector
29
+ v-model:value="scanState.InteractionSettings.PanSensivitity"
30
+ data-testid="pan"
31
+ :min="0"
32
+ :max="100"
33
+ label="Pan Sensitivity"
34
+ prepend="percent"
35
+ />
36
+ <ValueSelector
37
+ v-model:value="scanState.InteractionSettings.ZoomSensitivity"
38
+ data-testid="zoom"
39
+ :min="0"
40
+ :max="100"
41
+ label="Zoom Sensitivity"
42
+ prepend="percent"
43
+ />
44
+ <ValueSelector
45
+ v-model:value="scanState.InteractionSettings.RotateSensitivity"
46
+ data-testid="rotate"
47
+ :min="0"
48
+ :max="100"
49
+ label="Rotate Sensitivity"
50
+ prepend="percent"
51
+ />
52
+ <ValueSelector
53
+ v-model:value="scanState.InteractionSettings.CameraRotateSensitivity"
54
+ data-testid="camera"
55
+ :min="0"
56
+ :max="100"
57
+ label="Camera Rotate Sensitivity"
58
+ prepend="percent"
59
+ />
60
+ <v-divider class="my-4" />
61
+ <NavigationCubeAction />
62
+ <v-divider class="my-4" v-if="isDemo" />
63
+ <ValueSelector
64
+ v-if="isDemo"
65
+ v-model:value="stlResolution"
66
+ data-testid="stl_resolution"
67
+ :min="1"
68
+ :max="25"
69
+ :step="1"
70
+ label="STL Resolution (max 25%)"
71
+ prepend="percent"
72
+ />
73
+ </v-card>
74
+ </v-menu>
75
+ </template>
76
+
77
+ <script setup lang="ts">
78
+ import { scanState, stlResolution } from '@/models/scanState';
79
+ import { computed, mergeProps } from 'vue';
80
+ import { isDemo } from '@/components/demo/options';
81
+
82
+ interface Props {
83
+ modelValue?: boolean;
84
+ activatorProps?: Record<string, unknown>;
85
+ }
86
+
87
+ type Emits = {
88
+ 'update:modelValue': [boolean];
89
+ };
90
+
91
+ const props = withDefaults(defineProps<Props>(), {
92
+ modelValue: false,
93
+ activatorProps: () => ({})
94
+ });
95
+
96
+ const emit = defineEmits<Emits>();
97
+
98
+ const menuState = computed({
99
+ get(): boolean {
100
+ return props.modelValue;
101
+ },
102
+ set(value: boolean): void {
103
+ emit('update:modelValue', value);
104
+ }
105
+ });
106
+ </script>