@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
@@ -0,0 +1,51 @@
1
+ import { describe } from 'vitest';
2
+ import { mount } from '@vue/test-utils';
3
+ import { defineComponent } from 'vue';
4
+ import { useIntroJs } from '@/composables/useIntroJs';
5
+ import { Viewer3crService } from '@/services/viewer-3cr.service';
6
+ import { Tour } from 'intro.js/src/packages/tour';
7
+ import { scanState } from '@/models/scanState';
8
+ import { inflateScanState } from '@/functions/modelHelper';
9
+
10
+ describe('useIntroJs tests', () => {
11
+ vi.spyOn(Viewer3crService.prototype, 'layouts').mockResolvedValue();
12
+
13
+ beforeEach(() => {
14
+ vi.useFakeTimers();
15
+ });
16
+
17
+ afterEach(() => {
18
+ vi.useRealTimers();
19
+ });
20
+
21
+ it('should start introjs', async () => {
22
+ const component = defineComponent({
23
+ template: `
24
+ <div>
25
+ <div id="skin-to-bone"></div>
26
+ <div id="view-0"></div>
27
+ <div id="view-1"></div>
28
+ <div id="view-2"></div>
29
+ <div id="view-3"></div>
30
+ <div id="settings-card"></div>
31
+ </div>`,
32
+ setup(_, context) {
33
+ const { intro } = useIntroJs();
34
+ context.expose({ intro });
35
+ }
36
+ });
37
+
38
+ const wrapper = mount(component);
39
+ const intro = (wrapper.vm as any).intro as Tour;
40
+
41
+ await intro.start();
42
+ scanState.value = inflateScanState();
43
+ vi.advanceTimersByTime(1000);
44
+ for (let i = 0; i < 5; ++i) {
45
+ await intro.nextStep();
46
+ vi.advanceTimersByTime(1000);
47
+ }
48
+
49
+ expect(wrapper).toBeTruthy();
50
+ });
51
+ });
@@ -0,0 +1,39 @@
1
+ import { inflateInitialDataOverlayState } from '@/functions/modelHelper';
2
+ import { DataOverlayDataFaker } from '@test/fakers/data-overlay-data.faker';
3
+ import { dataOverlayEvent, dataOverlayState } from '@/models/scanState';
4
+ import { Interactiontype } from '@3cr/types-ts';
5
+ import { useMarkups } from '@/composables/useMarkups';
6
+
7
+ describe('useMarkups tests', () => {
8
+ it('should have no markups', () => {
9
+ const { markups, hasMarkups } = useMarkups();
10
+ expect(markups.value.length).toBe(0);
11
+ expect(hasMarkups.value).toBeFalsy();
12
+ });
13
+
14
+ it('should have markups', () => {
15
+ const dataOverlay = inflateInitialDataOverlayState();
16
+ dataOverlay.DataOverlay.DataOverlay.push(
17
+ DataOverlayDataFaker.lengthRaw(),
18
+ DataOverlayDataFaker.polygonRaw(),
19
+ DataOverlayDataFaker.angleRaw()
20
+ );
21
+ dataOverlayState.value = dataOverlay;
22
+
23
+ const { markups } = useMarkups();
24
+ expect(markups.value.length).toBe(3);
25
+ expect(typeof markups.value[0].Data).not.toBe('string');
26
+ });
27
+
28
+ it('should have null event', () => {
29
+ const { markupEvent } = useMarkups();
30
+ expect(markupEvent.value).toBeNull();
31
+ });
32
+
33
+ it('should have non-null event', () => {
34
+ dataOverlayEvent.value = DataOverlayDataFaker.polygonEventRaw(Interactiontype.HOVER_START);
35
+ const { markupEvent } = useMarkups();
36
+ expect(markupEvent.value).not.toBeNull();
37
+ expect(typeof markupEvent.value?.DataOverlay).not.toBe('string');
38
+ });
39
+ });
@@ -0,0 +1,36 @@
1
+ import { inflateInitialMcadObjectState } from '@/functions/modelHelper';
2
+ import { mcadObjectEvent, mcadObjectState } from '@/models/scanState';
3
+ import { Interactiontype } from '@3cr/types-ts';
4
+ import { useMcadObjects } from '@/composables/useMcadObjects';
5
+ import { DataOverlayMcadFaker } from '@test/fakers/data-overlay-mcad.faker';
6
+ import { McadObjectInteractionFaker } from '@test/fakers/mcad-object-interaction.faker';
7
+
8
+ describe('useMcadObjects tests', () => {
9
+ it('should have no mcad objects', () => {
10
+ const { mcadObjects, hasMcadObjects } = useMcadObjects();
11
+ expect(mcadObjects.value.length).toBe(0);
12
+ expect(hasMcadObjects.value).toBeFalsy();
13
+ });
14
+
15
+ it('should have mcad objects', () => {
16
+ const mcad = inflateInitialMcadObjectState();
17
+ mcad.Models.Models.push(DataOverlayMcadFaker.randomRaw() as any);
18
+ mcadObjectState.value = mcad;
19
+
20
+ const { mcadObjects } = useMcadObjects();
21
+ expect(mcadObjects.value.length).toBe(1);
22
+ expect(typeof mcadObjects.value[0].CallToAction).not.toBe('string');
23
+ });
24
+
25
+ it('should have null event', () => {
26
+ const { mcadObjectEvent } = useMcadObjects();
27
+ expect(mcadObjectEvent.value).toBeNull();
28
+ });
29
+
30
+ it('should have non-null event', () => {
31
+ mcadObjectEvent.value = McadObjectInteractionFaker.randomRaw(Interactiontype.HOVER_START) as any;
32
+ const { mcadObjectEvent: event } = useMcadObjects();
33
+ expect(event.value).not.toBeNull();
34
+ expect(typeof event.value?.Mcad).not.toBe('string');
35
+ });
36
+ });
@@ -0,0 +1,20 @@
1
+ import { useMouse } from '@/composables/useMouse';
2
+ import { defineComponent, onMounted } from 'vue';
3
+ import { mount } from '@vue/test-utils';
4
+
5
+ describe('useMouse tests', () => {
6
+ it('should set mouse position', () => {
7
+ const component = defineComponent({
8
+ template: '<div></div>',
9
+ setup() {
10
+ const { x, y } = useMouse(document);
11
+ onMounted(() => {
12
+ document.dispatchEvent(new MouseEvent('mousemove', { clientX: 100, clientY: 100 }));
13
+ expect(x.value).toBe(100);
14
+ expect(y.value).toBe(100);
15
+ });
16
+ }
17
+ });
18
+ mount(component);
19
+ });
20
+ });
@@ -1,9 +1,8 @@
1
- import { describe, expect, it, vi } from 'vitest';
2
- import { useNavigationCubeObserver } from "@/components/modal/composables/useNavigationCubeObserver";
3
- import { isFullscreen, isLayout1x3, isLayout2x2, scanState } from "@/dataLayer/scanState";
4
- import { Viewer3cr } from "@/dataLayer/viewer3cr";
5
- import { AnchorPoint, CurrentScanState, ScanView } from "@3cr/types-ts";
6
- import { flushPromises } from "@vue/test-utils";
1
+ import { useNavigationCubeObserver } from '@/composables/useNavigationCubeObserver';
2
+ import { isFullscreen, isLayout1x3, isLayout2x2, scanState } from '@/models/scanState';
3
+ import { Viewer3crService } from '@/services/viewer-3cr.service';
4
+ import { AnchorPoint, CurrentScanState, ScanView } from '@3cr/types-ts';
5
+ import { flushPromises } from '@vue/test-utils';
7
6
 
8
7
  function setupMocks(state: CurrentScanState, fullscreen: boolean, layout1x3: boolean, layout2x2: boolean): void {
9
8
  vi.spyOn(scanState, 'value', 'get').mockReturnValue(state);
@@ -13,15 +12,21 @@ function setupMocks(state: CurrentScanState, fullscreen: boolean, layout1x3: boo
13
12
  }
14
13
 
15
14
  describe('useNavigationCubeObserver tests', () => {
16
- vi.spyOn(ResizeObserver.prototype, 'observe').mockReturnValue()
15
+ vi.spyOn(ResizeObserver.prototype, 'observe').mockReturnValue();
17
16
  vi.spyOn(ResizeObserver.prototype, 'unobserve').mockReturnValue();
18
17
 
19
18
  const canvas = { clientWidth: 100, clientHeight: 100 } as HTMLCanvasElement;
20
- const fullscreen2d = { CurrentView: ScanView.Sagittal, NavigationCube: { Interactivity: { Value: true } } } as CurrentScanState;
21
- const fullscreen3d = { CurrentView: ScanView.Volume, NavigationCube: { Interactivity: { Value: true } } } as CurrentScanState;
22
-
23
- const visibilitySpy = vi.spyOn(Viewer3cr.prototype, 'setNavCubeVisibility');
24
- const positionSizeSpy = vi.spyOn(Viewer3cr.prototype, 'setNavCubePositionSize');
19
+ const fullscreen2d = {
20
+ CurrentView: ScanView.Sagittal,
21
+ NavigationCube: { Interactivity: { Value: true } }
22
+ } as CurrentScanState;
23
+ const fullscreen3d = {
24
+ CurrentView: ScanView.Volume,
25
+ NavigationCube: { Interactivity: { Value: true } }
26
+ } as CurrentScanState;
27
+
28
+ const visibilitySpy = vi.spyOn(Viewer3crService.prototype, 'setNavCubeVisibility');
29
+ const positionSizeSpy = vi.spyOn(Viewer3crService.prototype, 'setNavCubePositionSize');
25
30
 
26
31
  it('should update on 3d fullscreen changes', async () => {
27
32
  setupMocks(fullscreen3d, true, false, false);
@@ -1,5 +1,4 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { useViewer3cr } from '@/dataLayer/useViewer3cr';
1
+ import { useViewer3cr } from '@/composables/useViewer3cr';
3
2
 
4
3
  describe('useViewer3cr tests', () => {
5
4
  it('should return same service instance', () => {
@@ -0,0 +1,37 @@
1
+ import { computed } from 'vue';
2
+ import { dataOverlayEvent, dataOverlayState } from '@/models/scanState';
3
+ import { parseDataOverlayData } from '@/functions/parseDataOverlayData';
4
+ import { DataOverlayDataRaw, DataOverlayData } from '@/types/data-overlay-data';
5
+ import { DataOverlayAnnotation } from '@/types/data-overlay-annotation';
6
+ import { DataOverlayType } from '@3cr/types-ts';
7
+ import { DataOverlayInteraction } from '@/types/data-overlay-interaction';
8
+ import { parseDataOverlayEvent } from '@/functions/parseDataOverlayEvent';
9
+
10
+ function isAnnotation(data: DataOverlayDataRaw): boolean {
11
+ return data.DataType === DataOverlayType.Annotation;
12
+ }
13
+
14
+ function toAnnotation(data: DataOverlayDataRaw): DataOverlayData<DataOverlayAnnotation> {
15
+ return parseDataOverlayData<DataOverlayAnnotation>(data);
16
+ }
17
+
18
+ function toAnnotationEvent(data: DataOverlayDataRaw): DataOverlayInteraction<DataOverlayAnnotation> {
19
+ return parseDataOverlayEvent<DataOverlayAnnotation>(data).Data;
20
+ }
21
+
22
+ const annotations = computed(() => {
23
+ return dataOverlayState.value.DataOverlay.DataOverlay.filter(isAnnotation).map(toAnnotation);
24
+ });
25
+
26
+ const hasAnnotations = computed(() => {
27
+ return annotations.value.length > 0;
28
+ });
29
+
30
+ const annotationEvent = computed(() => {
31
+ const value = dataOverlayEvent.value;
32
+ return value && isAnnotation(value) ? toAnnotationEvent(value) : null;
33
+ });
34
+
35
+ export function useAnnotations() {
36
+ return { annotations, hasAnnotations, annotationEvent };
37
+ }
@@ -0,0 +1,11 @@
1
+ export type Debouncable<Args extends unknown[]> = (...args: Args) => any;
2
+
3
+ export type Debounced<Args extends unknown[]> = (...args: Args) => void;
4
+
5
+ export function useDebounce<Args extends unknown[]>(callback: Debouncable<Args>, delay: number): Debounced<Args> {
6
+ let timeout: NodeJS.Timeout;
7
+ return function (...args: Args): void {
8
+ clearTimeout(timeout);
9
+ timeout = setTimeout(callback, delay, ...args);
10
+ };
11
+ }
@@ -0,0 +1,25 @@
1
+ import { onBeforeUnmount, onMounted, Ref, unref, watch } from 'vue';
2
+
3
+ type Target = Ref<EventTarget> | EventTarget;
4
+ type EventType = keyof HTMLElementEventMap;
5
+ type Handler<T extends Event> = (event: T) => void | Promise<void>;
6
+
7
+ export function useEventListener<T extends Event>(target: Target, event: EventType, handler: Handler<T>) {
8
+ const wrapper = (e: Event) => handler(e as T);
9
+
10
+ onMounted(() => {
11
+ unref(target).addEventListener(event, wrapper);
12
+ });
13
+
14
+ watch(
15
+ () => unref(target),
16
+ (next, prev) => {
17
+ prev.removeEventListener(event, wrapper);
18
+ next.addEventListener(event, wrapper);
19
+ }
20
+ );
21
+
22
+ onBeforeUnmount(() => {
23
+ unref(target).removeEventListener(event, wrapper);
24
+ });
25
+ }
@@ -0,0 +1,142 @@
1
+ import { TourOptions } from 'intro.js/src/packages/tour/option';
2
+ import { Tour } from 'intro.js/src/packages/tour';
3
+ import { demoType } from '@/components/demo/options';
4
+ import { computed, nextTick, ref, watch, WatchStopHandle } from 'vue';
5
+ import { ScanView } from '@3cr/types-ts';
6
+ import { useViewer3cr } from '@/composables/useViewer3cr';
7
+ import { isFullscreen, previousLayout, scanState } from '@/models/scanState';
8
+ import { DemoType } from '@/types/demo-type';
9
+ import introJs from 'intro.js';
10
+ import { useViewerOptions } from '@/composables/useViewerOptions';
11
+
12
+ const demo = computed<string>(() => {
13
+ switch (demoType.value) {
14
+ case DemoType.Licence:
15
+ return 'Licence';
16
+ default:
17
+ return 'Patient';
18
+ }
19
+ });
20
+
21
+ const options = computed<Partial<TourOptions>>(() => ({
22
+ exitOnOverlayClick: false,
23
+ keyboardNavigation: false,
24
+ dontShowAgain: true,
25
+ steps: [
26
+ {
27
+ title: 'Take the Viewer Tour',
28
+ intro:
29
+ `Welcome to the ${demo.value} Online DICOM Viewer.` +
30
+ '<br/><br/>Take the short interative tour to better visualize your medical images in 2D and 3D.',
31
+ position: 'floating'
32
+ },
33
+ {
34
+ title: 'Density Slider',
35
+ intro:
36
+ 'Move the <em>lower density slider</em> to the right to hide softer tissue like skin and view internal organs.' +
37
+ '<br/><br/>For more precise control, change the numbers in the boxes above or use the <em>Fine Adjustment</em> slider below.',
38
+ element: '#skin-to-bone',
39
+ position: 'right'
40
+ },
41
+ {
42
+ title: '3D Viewing Controls',
43
+ intro:
44
+ 'With your cursor placed in the 3D view, <b>scroll to zoom</b> & <b>click and drag to rotate</b>.' +
45
+ '<br/><br/>You can also view the 3D view in full screen, reset the view, and cut into the 3D model from each side using the <em>3D slicing tool</em>.',
46
+ element: `#view-${ScanView.Volume}`
47
+ },
48
+ {
49
+ title: '2D Viewing Controls',
50
+ intro:
51
+ 'With your mouse in the 2D views, <b>scroll to navigate through the 2D images</b>, and use <b>Shift + Arrows to Pan and Zoom</b>.' +
52
+ '<br/><br/>Use the icons to <em>Fullscreen</em>, <em>Reset</em>, <em>Rotate</em>, and <em>Flip</em> each individual 2D view.',
53
+ element: `#view-${ScanView.Sagittal}`
54
+ },
55
+ {
56
+ title: 'Global settings',
57
+ intro:
58
+ 'Accurately change the <b>brightness</b>, <b>contrast</b>, and <b>opacity</b> to enhance the appearance of your medical images.' +
59
+ '<br/><br/>Adjust the sensitivity of mouse and keyboard inputs to suit your preferences.',
60
+ element: '#settings-card',
61
+ position: 'right'
62
+ },
63
+ {
64
+ title: 'Stay Tuned for Updates',
65
+ intro:
66
+ '<img src="https://c.tenor.com/S4Sz_yvlLn4AAAAC/cats-cat.gif" alt="cat" width="260" height="260">' +
67
+ '<br/>Us working hard on new features',
68
+ position: 'floating'
69
+ }
70
+ ]
71
+ }));
72
+
73
+ function blurActiveElement(): void {
74
+ (document.activeElement as HTMLElement | null)?.blur();
75
+ }
76
+
77
+ export function useIntroJs() {
78
+ const viewer3cr = useViewer3cr();
79
+ const viewerOptions = useViewerOptions();
80
+
81
+ let scanStateHandle: WatchStopHandle;
82
+
83
+ function onStart(this: Tour): void {
84
+ scanStateHandle = watch(scanState, () => {
85
+ if (this.isActive()) {
86
+ this.refresh(true);
87
+ }
88
+ });
89
+ }
90
+
91
+ function onBeforeChange(this: Tour, el: HTMLElement, step: number, direction: 'forward' | 'backward'): boolean {
92
+ // If the user has enabled full-screen, turn it off for steps 2 and 3
93
+ /* istanbul ignore next: does not work with jsdom -- @preserve */
94
+ if (isFullscreen.value && (step === 2 || step === 3)) {
95
+ viewer3cr
96
+ .layouts(previousLayout.value)
97
+ .then(() => nextTick())
98
+ .then(() => this.refresh(true))
99
+ .then(() => (direction === 'forward' ? this.nextStep() : this.previousStep()));
100
+ return false;
101
+ }
102
+
103
+ // Only show Don't Show Again on last step
104
+ const introjsDontShowAgain = document.querySelector('.introjs-dontShowAgain') as HTMLElement | null;
105
+ if (introjsDontShowAgain) {
106
+ const lastStep = this.getSteps().length - 1;
107
+ introjsDontShowAgain.style.display = step !== lastStep ? 'none' : 'block';
108
+ }
109
+
110
+ return true;
111
+ }
112
+
113
+ function onChange(): void {
114
+ setTimeout(() => blurActiveElement(), 500);
115
+ }
116
+
117
+ /* istanbul ignore next: does not work with jsdom -- @preserve */
118
+ function onBeforeExit(this: Tour): boolean {
119
+ scanStateHandle();
120
+ setTimeout(() => blurActiveElement(), 500);
121
+ return true;
122
+ }
123
+
124
+ async function onExit(this: Tour): Promise<void> {
125
+ if (viewerOptions.value.OnInteractionReady) {
126
+ await viewerOptions.value.OnInteractionReady();
127
+ }
128
+ }
129
+
130
+ const tour = introJs
131
+ .tour()
132
+ .setOptions(options.value)
133
+ .onStart(onStart)
134
+ .onBeforeChange(onBeforeChange)
135
+ .onChange(onChange)
136
+ .onBeforeExit(onBeforeExit)
137
+ .onExit(onExit);
138
+
139
+ const intro = ref<Tour>(tour);
140
+
141
+ return { intro };
142
+ }
@@ -0,0 +1,41 @@
1
+ import { DataOverlayType } from '@3cr/types-ts';
2
+ import { parseDataOverlayData } from '@/functions/parseDataOverlayData';
3
+ import { computed } from 'vue';
4
+ import { dataOverlayEvent, dataOverlayState } from '@/models/scanState';
5
+ import { DataOverlayData, DataOverlayDataRaw } from '@/types/data-overlay-data';
6
+ import { DataOverlayMarkup } from '@/types/data-overlay-markup';
7
+ import { DataOverlayInteraction } from '@/types/data-overlay-interaction';
8
+ import { parseDataOverlayEvent } from '@/functions/parseDataOverlayEvent';
9
+
10
+ function isMarkup(data: DataOverlayDataRaw): boolean {
11
+ return (
12
+ data.DataType === DataOverlayType.Length ||
13
+ data.DataType === DataOverlayType.Polygon ||
14
+ data.DataType === DataOverlayType.Angle
15
+ );
16
+ }
17
+
18
+ function toMarkup(data: DataOverlayDataRaw): DataOverlayData<DataOverlayMarkup> {
19
+ return parseDataOverlayData<DataOverlayMarkup>(data);
20
+ }
21
+
22
+ function toMarkupEvent(data: DataOverlayDataRaw): DataOverlayInteraction<DataOverlayMarkup> {
23
+ return parseDataOverlayEvent<DataOverlayMarkup>(data).Data;
24
+ }
25
+
26
+ const markups = computed(() => {
27
+ return dataOverlayState.value.DataOverlay.DataOverlay.filter(isMarkup).map(toMarkup);
28
+ });
29
+
30
+ const hasMarkups = computed(() => {
31
+ return markups.value.length > 0;
32
+ });
33
+
34
+ const markupEvent = computed(() => {
35
+ const value = dataOverlayEvent.value;
36
+ return value && isMarkup(value) ? toMarkupEvent(value) : null;
37
+ });
38
+
39
+ export function useMarkups() {
40
+ return { markups, hasMarkups, markupEvent };
41
+ }
@@ -0,0 +1,32 @@
1
+ import { computed } from 'vue';
2
+ import { mcadObjectState } from '@/models/scanState';
3
+ import { mcadObjectEvent as mcadEvent } from '@/models/scanState';
4
+ import { McadObjectInteraction, McadObjectInteractionRaw } from '@/types/mcad-object-interaction';
5
+ import { parseMcadEvent } from '@/functions/parseMcadEvent';
6
+ import { DataOverlayMcad, DataOverlayMcadRaw } from '@/types/data-overlay-mcad';
7
+ import { parseDataOverlay } from '@/functions/parseDataOverlay';
8
+
9
+ function toMcadObject(data: DataOverlayMcadRaw): DataOverlayMcad {
10
+ return parseDataOverlay(data) as DataOverlayMcad;
11
+ }
12
+
13
+ function toMcadObjectEvent(data: McadObjectInteractionRaw): McadObjectInteraction {
14
+ return parseMcadEvent(data);
15
+ }
16
+
17
+ const mcadObjects = computed(() => {
18
+ return mcadObjectState.value.Models.Models.map(toMcadObject);
19
+ });
20
+
21
+ const hasMcadObjects = computed(() => {
22
+ return mcadObjects.value.length > 0;
23
+ });
24
+
25
+ const mcadObjectEvent = computed(() => {
26
+ const value = mcadEvent.value;
27
+ return value ? toMcadObjectEvent(value) : null;
28
+ });
29
+
30
+ export function useMcadObjects() {
31
+ return { mcadObjects, hasMcadObjects, mcadObjectEvent };
32
+ }
@@ -0,0 +1,14 @@
1
+ import { ref } from 'vue';
2
+ import { useEventListener } from '@/composables/useEventListener';
3
+
4
+ export function useMouse(target: EventTarget) {
5
+ const x = ref<number>(0);
6
+ const y = ref<number>(0);
7
+
8
+ useEventListener(target, 'mousemove', (e: MouseEvent) => {
9
+ x.value = e.x;
10
+ y.value = e.y;
11
+ });
12
+
13
+ return { x, y };
14
+ }
@@ -1,7 +1,7 @@
1
- import { isFullscreen, isLayout1x3, isLayout2x2, scanState } from "@/dataLayer/scanState";
2
- import { AnchorPoint, ScanView } from "@3cr/types-ts";
3
- import { useViewer3cr } from "@/dataLayer/useViewer3cr";
4
- import { ComputedRef, WatchStopHandle, computed, watch } from "vue";
1
+ import { isFullscreen, isLayout1x3, isLayout2x2, scanState } from '@/models/scanState';
2
+ import { AnchorPoint, ScanView } from '@3cr/types-ts';
3
+ import { useViewer3cr } from '@/composables/useViewer3cr';
4
+ import { ComputedRef, WatchStopHandle, computed, watch } from 'vue';
5
5
 
6
6
  const isNavigationCubeEnabled = computed(() => {
7
7
  return scanState.value.NavigationCube.Interactivity.Value;
@@ -40,7 +40,7 @@ export function useNavigationCubeObserver(canvas: HTMLCanvasElement): ResizeObse
40
40
  async function onLayout1x3(): Promise<void> {
41
41
  const [width, height] = getCanvasDimensions(canvas);
42
42
  const navCubeSize = getNavigationCubeSize(canvas);
43
- const xOffset = Math.floor(width - (height / 3) - navCubeSize);
43
+ const xOffset = Math.floor(width - height / 3 - navCubeSize);
44
44
  const yOffset = height - navCubeSize;
45
45
  await viewer3cr.setNavCubeVisibility(true);
46
46
  await viewer3cr.setNavCubePositionSize(AnchorPoint.TOP_LEFT, xOffset, yOffset, navCubeSize, navCubeSize);
@@ -49,19 +49,23 @@ export function useNavigationCubeObserver(canvas: HTMLCanvasElement): ResizeObse
49
49
  async function onLayout2x2(): Promise<void> {
50
50
  const [width, height] = getCanvasDimensions(canvas);
51
51
  const navCubeSize = getNavigationCubeSize(canvas);
52
- const xOffset = Math.floor((width / 2) - navCubeSize);
53
- const yOffset = Math.floor((height / 2) - navCubeSize);
52
+ const xOffset = Math.floor(width / 2 - navCubeSize);
53
+ const yOffset = Math.floor(height / 2 - navCubeSize);
54
54
  await viewer3cr.setNavCubeVisibility(true);
55
55
  await viewer3cr.setNavCubePositionSize(AnchorPoint.TOP_LEFT, xOffset, yOffset, navCubeSize, navCubeSize);
56
56
  }
57
57
 
58
58
  function createWatch(ref: ComputedRef<boolean>, callback: () => Promise<void>): WatchStopHandle {
59
- return watch(ref, async (value: boolean) => {
60
- if (value) {
61
- refresh = callback;
62
- await refresh();
63
- }
64
- }, { immediate: true });
59
+ return watch(
60
+ ref,
61
+ async (value: boolean) => {
62
+ if (value) {
63
+ refresh = callback;
64
+ await refresh();
65
+ }
66
+ },
67
+ { immediate: true }
68
+ );
65
69
  }
66
70
 
67
71
  function enable(): void {
@@ -69,21 +73,23 @@ export function useNavigationCubeObserver(canvas: HTMLCanvasElement): ResizeObse
69
73
  handles.push(createWatch(isFullscreen, onFullscreen));
70
74
  handles.push(createWatch(isLayout1x3, onLayout1x3));
71
75
  handles.push(createWatch(isLayout2x2, onLayout2x2));
72
- handles.push(watch([
73
- () => scanState.value.CurrentView,
74
- () => scanState.value.NavigationCube.Interactivity.Value
75
- ], async () => {
76
- if (refresh) {
77
- await refresh();
78
- }
79
- }));
76
+ handles.push(
77
+ watch(
78
+ [() => scanState.value.CurrentView, () => scanState.value.NavigationCube.Interactivity.Value],
79
+ async () => {
80
+ if (refresh) {
81
+ await refresh();
82
+ }
83
+ }
84
+ )
85
+ );
80
86
  observer.observe(canvas);
81
87
  }
82
88
  }
83
89
 
84
90
  async function disable(): Promise<void> {
85
91
  if (handles.length > 0) {
86
- handles.forEach(handle => handle());
92
+ handles.forEach((handle) => handle());
87
93
  handles = [];
88
94
  observer.unobserve(canvas);
89
95
  await viewer3cr.setNavCubeVisibility(false);
@@ -96,9 +102,13 @@ export function useNavigationCubeObserver(canvas: HTMLCanvasElement): ResizeObse
96
102
  }
97
103
  });
98
104
 
99
- watch(isNavigationCubeEnabled, (value: boolean) => {
100
- value ? enable() : disable();
101
- }, { immediate: true });
105
+ watch(
106
+ isNavigationCubeEnabled,
107
+ (value: boolean) => {
108
+ value ? enable() : disable();
109
+ },
110
+ { immediate: true }
111
+ );
102
112
 
103
113
  return observer;
104
114
  }
@@ -0,0 +1,25 @@
1
+ import { ScanMovementActions } from '@3cr/types-ts';
2
+ import { watch, WatchSource } from 'vue';
3
+ import { scanState } from '@/models/scanState';
4
+ import { useViewer3cr } from '@/composables/useViewer3cr';
5
+
6
+ type WatchScanMovement = {
7
+ [key in ScanMovementActions]: WatchSource<number>;
8
+ };
9
+
10
+ // @ts-ignore
11
+ const movements: WatchScanMovement = {
12
+ [ScanMovementActions.sm05]: () => scanState.value.InteractionSettings.PanSensivitity,
13
+ [ScanMovementActions.sm08]: () => scanState.value.InteractionSettings.ZoomSensitivity,
14
+ [ScanMovementActions.sm10]: () => scanState.value.InteractionSettings.RotateSensitivity,
15
+ [ScanMovementActions.sm12]: () => scanState.value.InteractionSettings.CameraRotateSensitivity
16
+ };
17
+
18
+ export function useScanMovement(): void {
19
+ const viewer3cr = useViewer3cr();
20
+ for (const movement of Object.keys(movements) as (keyof WatchScanMovement)[]) {
21
+ watch(movements[movement], async (value: number) => {
22
+ await viewer3cr.scanMovementHandler(movement, value);
23
+ });
24
+ }
25
+ }