@geode/opengeodeweb-front 10.34.0-rc.9 → 10.34.0

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 (282) hide show
  1. package/{server → .build/server}/utils/app_config.js +10 -9
  2. package/{server → .build/server}/utils/cleanup.js +31 -17
  3. package/{server → .build/server}/utils/cloud.js +1 -4
  4. package/{server → .build/server}/utils/microservices.js +21 -9
  5. package/{server → .build/server}/utils/path.js +4 -4
  6. package/{server → .build/server}/utils/scripts.js +9 -9
  7. package/.build/server/utils/server_config.js +51 -0
  8. package/.build/server/utils/stream.js +6 -0
  9. package/{server → .build/server}/utils/ws_client.js +18 -3
  10. package/{shared → .build/shared}/scripts.js +10 -10
  11. package/.build/shared/utils/call_raw.js +31 -0
  12. package/{shared → .build/shared}/utils/call_schema.js +2 -2
  13. package/.build/shared/utils/fetch_raw.js +52 -0
  14. package/{shared → .build/shared}/utils/fetch_schema.js +2 -2
  15. package/{shared → .build/shared}/utils/file.js +3 -1
  16. package/{shared → .build/shared}/utils/response_handlers/load.js +10 -7
  17. package/{shared → .build/shared}/utils/validate_schema.js +1 -1
  18. package/app/components/ActionButton.vue +6 -6
  19. package/app/components/CameraManager/List.vue +5 -5
  20. package/app/components/CameraManager/Saver.vue +3 -5
  21. package/app/components/CameraManager.vue +6 -4
  22. package/app/components/CameraOrientation.vue +12 -12
  23. package/app/components/ClippingPlaneCard.vue +4 -2
  24. package/app/components/ClippingPlanes.vue +8 -8
  25. package/app/components/CrsSelector.vue +9 -10
  26. package/app/components/DeleteDialog.vue +4 -2
  27. package/app/components/DragAndDrop.vue +10 -12
  28. package/app/components/DragAndDropInternal/DragAndDropInline.vue +4 -2
  29. package/app/components/ExtensionSelector.vue +4 -4
  30. package/app/components/FeedBack/ErrorBanner.vue +3 -1
  31. package/app/components/FeedBack/Snackers.vue +4 -3
  32. package/app/components/FileSelector.vue +10 -8
  33. package/app/components/FileUploader.vue +11 -11
  34. package/app/components/GlassCard.vue +1 -1
  35. package/app/components/HybridRenderingView.vue +7 -5
  36. package/app/components/HybridViewerTooltip.vue +7 -7
  37. package/app/components/Launcher.vue +1 -1
  38. package/app/components/Loading/EcoMessages.vue +9 -3
  39. package/app/components/Loading.vue +2 -2
  40. package/app/components/MissingFilesSelector.vue +12 -10
  41. package/app/components/ObjectSelector.vue +10 -9
  42. package/app/components/PackagesVersions.vue +6 -5
  43. package/app/components/Recaptcha.vue +3 -3
  44. package/app/components/RemoteRenderingView.vue +6 -7
  45. package/app/components/Ruler.vue +3 -3
  46. package/app/components/Screenshot.vue +6 -6
  47. package/app/components/SearchBar.vue +4 -2
  48. package/app/components/ShrinkFilter.vue +7 -7
  49. package/app/components/Step.vue +6 -5
  50. package/app/components/Stepper.vue +4 -3
  51. package/app/components/ToolPanel.vue +6 -3
  52. package/app/components/ViewToolbar.vue +25 -28
  53. package/app/components/Viewer/ContextMenu/CenterButton.vue +7 -5
  54. package/app/components/Viewer/ContextMenu/CircularItems.vue +3 -3
  55. package/app/components/Viewer/ContextMenu/ContextMenu.vue +22 -19
  56. package/app/components/Viewer/ContextMenu/ContextMenuItem.vue +10 -8
  57. package/app/components/Viewer/ContextMenu/InfoCard.vue +11 -12
  58. package/app/components/Viewer/EdgedCurve/SpecificEdgesOptions.vue +13 -17
  59. package/app/components/Viewer/Generic/Mesh/CellsOptions.vue +11 -15
  60. package/app/components/Viewer/Generic/Mesh/EdgesOptions.vue +12 -16
  61. package/app/components/Viewer/Generic/Mesh/PointsOptions.vue +8 -12
  62. package/app/components/Viewer/Generic/Mesh/PolygonsOptions.vue +11 -15
  63. package/app/components/Viewer/Generic/Mesh/PolyhedraOptions.vue +11 -15
  64. package/app/components/Viewer/Generic/Model/BlocksOptions.vue +67 -38
  65. package/app/components/Viewer/Generic/Model/CornersOptions.vue +53 -23
  66. package/app/components/Viewer/Generic/Model/EdgesOptions.vue +1 -3
  67. package/app/components/Viewer/Generic/Model/LinesOptions.vue +67 -38
  68. package/app/components/Viewer/Generic/Model/ModelStyleCard.vue +31 -15
  69. package/app/components/Viewer/Generic/Model/ModelStyleOptions.vue +2 -3
  70. package/app/components/Viewer/Generic/Model/PointsOptions.vue +6 -6
  71. package/app/components/Viewer/Generic/Model/SurfacesOptions.vue +69 -38
  72. package/app/components/Viewer/ObjectTree/Base/CommonTreeView.vue +64 -46
  73. package/app/components/Viewer/ObjectTree/Base/Controls.vue +5 -5
  74. package/app/components/Viewer/ObjectTree/Base/ItemLabel.vue +13 -9
  75. package/app/components/Viewer/ObjectTree/Base/StickyHeader.vue +5 -5
  76. package/app/components/Viewer/ObjectTree/Base/TreeRow.vue +10 -10
  77. package/app/components/Viewer/ObjectTree/Box.vue +6 -4
  78. package/app/components/Viewer/ObjectTree/Layout.vue +23 -21
  79. package/app/components/Viewer/ObjectTree/Views/GlobalObjects.vue +14 -14
  80. package/app/components/Viewer/ObjectTree/Views/{ModelCollections.vue → ModelTree.vue} +59 -24
  81. package/app/components/Viewer/Options/AttributeColorBar.vue +4 -2
  82. package/app/components/Viewer/Options/AttributeRangeSelector.vue +4 -2
  83. package/app/components/Viewer/Options/AttributeSelector.vue +7 -9
  84. package/app/components/Viewer/Options/ColorMapList.vue +15 -13
  85. package/app/components/Viewer/Options/ColorMapPicker.vue +4 -4
  86. package/app/components/Viewer/Options/ColorPicker.vue +223 -41
  87. package/app/components/Viewer/Options/ColoringTypeSelector.vue +16 -16
  88. package/app/components/Viewer/Options/ColormapQuickPicker.vue +7 -5
  89. package/app/components/Viewer/Options/OptionsSection.vue +1 -1
  90. package/app/components/Viewer/Options/TextureItem.vue +8 -6
  91. package/app/components/Viewer/Options/TexturesSelector.vue +1 -1
  92. package/app/components/Viewer/OverlappingObjectsPicker.vue +8 -9
  93. package/app/components/Viewer/PointSet/SpecificPointsOptions.vue +2 -6
  94. package/app/components/Viewer/Solid/SpecificPolyhedraOptions.vue +12 -16
  95. package/app/components/Viewer/Surface/PolygonsOptions.vue +12 -16
  96. package/app/components/Viewer/Ui.vue +2 -2
  97. package/app/components/Wrapper.vue +1 -4
  98. package/app/components/ZScaling.vue +5 -3
  99. package/app/components/csv-preview/CsvPreviewer.vue +38 -37
  100. package/app/components/csv-preview/CsvSettings.vue +6 -4
  101. package/app/components/csv-preview/CsvTable.vue +1 -1
  102. package/app/composables/batch_style.ts +5 -6
  103. package/app/composables/clipping_planes_widget.ts +73 -181
  104. package/app/composables/clipping_planes_widget_entries.ts +189 -0
  105. package/app/composables/copy_to_clipboard.ts +7 -0
  106. package/app/composables/global_attribute_style.ts +163 -83
  107. package/app/composables/hover_highlight.ts +46 -14
  108. package/app/composables/model_collections.ts +26 -13
  109. package/app/composables/model_components.ts +26 -13
  110. package/app/composables/project_manager.ts +76 -19
  111. package/app/composables/responsive_middle_truncate.ts +13 -13
  112. package/app/composables/stepper_tree.ts +34 -11
  113. package/app/composables/tree_filter.ts +66 -44
  114. package/app/composables/tree_keyboard_nav.ts +25 -11
  115. package/app/composables/tree_scroll.ts +44 -14
  116. package/app/composables/use_adaptive_styles.ts +66 -23
  117. package/app/composables/use_overlapping_picker.ts +66 -16
  118. package/app/composables/use_quick_colormap.ts +16 -5
  119. package/app/composables/virtual_tree.ts +75 -43
  120. package/app/composables/vtk_implicit_plane_widget.d.ts +2 -0
  121. package/app/plugins/auto_store_register.ts +2 -7
  122. package/app/plugins/click_outside_ignore_snackbars.client.ts +39 -0
  123. package/app/stores/app.ts +57 -192
  124. package/app/stores/app_helpers/extension.ts +179 -0
  125. package/app/stores/back.ts +37 -21
  126. package/app/stores/camera_manager.ts +22 -20
  127. package/app/stores/cloud.ts +17 -13
  128. package/app/stores/data.ts +88 -47
  129. package/app/stores/data_helpers/collections.ts +36 -38
  130. package/app/stores/data_helpers/mesh.ts +45 -36
  131. package/app/stores/data_style.ts +50 -28
  132. package/app/stores/feedback.ts +6 -6
  133. package/app/stores/hybrid_viewer.ts +41 -52
  134. package/app/stores/infra.ts +39 -37
  135. package/app/stores/menu.ts +23 -14
  136. package/app/stores/treeview.ts +72 -42
  137. package/app/stores/viewer.ts +39 -27
  138. package/app/utils/attributes.ts +3 -3
  139. package/app/utils/clipping_planes.ts +111 -14
  140. package/app/utils/color_picker.ts +57 -0
  141. package/app/utils/colormap.ts +58 -35
  142. package/app/utils/default_styles/index.ts +2 -2
  143. package/app/utils/default_styles/meshes.ts +107 -13
  144. package/app/utils/default_styles/models.ts +83 -14
  145. package/app/utils/extension.ts +47 -20
  146. package/app/utils/import_workflow.ts +21 -13
  147. package/app/utils/name_cleaner.ts +1 -1
  148. package/app/utils/string.ts +1 -1
  149. package/app/utils/treeview.ts +2 -2
  150. package/internal/database/base_database.ts +7 -3
  151. package/internal/database/database.ts +36 -26
  152. package/internal/database/extended_database.ts +1 -1
  153. package/internal/stores/data_style/mesh/cells/cell.ts +70 -34
  154. package/internal/stores/data_style/mesh/cells/color.ts +12 -6
  155. package/internal/stores/data_style/mesh/cells/common.ts +18 -8
  156. package/internal/stores/data_style/mesh/cells/index.ts +122 -42
  157. package/internal/stores/data_style/mesh/cells/textures.ts +12 -6
  158. package/internal/stores/data_style/mesh/cells/vertex.ts +75 -34
  159. package/internal/stores/data_style/mesh/cells/visibility.ts +15 -4
  160. package/internal/stores/data_style/mesh/edges/color.ts +12 -6
  161. package/internal/stores/data_style/mesh/edges/common.ts +14 -6
  162. package/internal/stores/data_style/mesh/edges/edge.ts +71 -39
  163. package/internal/stores/data_style/mesh/edges/index.ts +117 -42
  164. package/internal/stores/data_style/mesh/edges/vertex.ts +76 -39
  165. package/internal/stores/data_style/mesh/edges/visibility.ts +15 -4
  166. package/internal/stores/data_style/mesh/edges/width.ts +12 -4
  167. package/internal/stores/data_style/mesh/index.ts +30 -11
  168. package/internal/stores/data_style/mesh/points/color.ts +12 -6
  169. package/internal/stores/data_style/mesh/points/common.ts +21 -8
  170. package/internal/stores/data_style/mesh/points/index.ts +101 -50
  171. package/internal/stores/data_style/mesh/points/size.ts +12 -4
  172. package/internal/stores/data_style/mesh/points/vertex.ts +75 -34
  173. package/internal/stores/data_style/mesh/points/visibility.ts +17 -7
  174. package/internal/stores/data_style/mesh/polygons/color.ts +12 -6
  175. package/internal/stores/data_style/mesh/polygons/common.ts +23 -6
  176. package/internal/stores/data_style/mesh/polygons/index.ts +130 -70
  177. package/internal/stores/data_style/mesh/polygons/polygon.ts +77 -43
  178. package/internal/stores/data_style/mesh/polygons/textures.ts +12 -6
  179. package/internal/stores/data_style/mesh/polygons/vertex.ts +79 -39
  180. package/internal/stores/data_style/mesh/polygons/visibility.ts +16 -6
  181. package/internal/stores/data_style/mesh/polyhedra/color.ts +12 -6
  182. package/internal/stores/data_style/mesh/polyhedra/common.ts +14 -6
  183. package/internal/stores/data_style/mesh/polyhedra/index.ts +115 -56
  184. package/internal/stores/data_style/mesh/polyhedra/polyhedron.ts +80 -39
  185. package/internal/stores/data_style/mesh/polyhedra/vertex.ts +79 -39
  186. package/internal/stores/data_style/mesh/polyhedra/visibility.ts +16 -6
  187. package/internal/stores/data_style/model/blocks/color.ts +43 -13
  188. package/internal/stores/data_style/model/blocks/common.ts +21 -6
  189. package/internal/stores/data_style/model/blocks/index.ts +89 -59
  190. package/internal/stores/data_style/model/blocks/polyhedron.ts +101 -44
  191. package/internal/stores/data_style/model/blocks/vertex.ts +107 -42
  192. package/internal/stores/data_style/model/blocks/visibility.ts +17 -4
  193. package/internal/stores/data_style/model/color.ts +171 -83
  194. package/internal/stores/data_style/model/common.ts +70 -21
  195. package/internal/stores/data_style/model/corners/color.ts +43 -11
  196. package/internal/stores/data_style/model/corners/common.ts +25 -6
  197. package/internal/stores/data_style/model/corners/index.ts +66 -41
  198. package/internal/stores/data_style/model/corners/vertex.ts +105 -74
  199. package/internal/stores/data_style/model/corners/visibility.ts +19 -4
  200. package/internal/stores/data_style/model/edges/common.ts +12 -4
  201. package/internal/stores/data_style/model/edges/index.ts +2 -1
  202. package/internal/stores/data_style/model/edges/visibility.ts +24 -7
  203. package/internal/stores/data_style/model/index.ts +24 -11
  204. package/internal/stores/data_style/model/lines/color.ts +41 -11
  205. package/internal/stores/data_style/model/lines/common.ts +17 -6
  206. package/internal/stores/data_style/model/lines/edge.ts +105 -42
  207. package/internal/stores/data_style/model/lines/index.ts +86 -59
  208. package/internal/stores/data_style/model/lines/vertex.ts +105 -42
  209. package/internal/stores/data_style/model/lines/visibility.ts +17 -4
  210. package/internal/stores/data_style/model/points/common.ts +8 -4
  211. package/internal/stores/data_style/model/points/index.ts +10 -3
  212. package/internal/stores/data_style/model/points/size.ts +12 -4
  213. package/internal/stores/data_style/model/points/visibility.ts +16 -6
  214. package/internal/stores/data_style/model/selection.ts +80 -58
  215. package/internal/stores/data_style/model/surfaces/color.ts +41 -11
  216. package/internal/stores/data_style/model/surfaces/common.ts +23 -6
  217. package/internal/stores/data_style/model/surfaces/index.ts +89 -59
  218. package/internal/stores/data_style/model/surfaces/polygon.ts +107 -67
  219. package/internal/stores/data_style/model/surfaces/vertex.ts +111 -67
  220. package/internal/stores/data_style/model/surfaces/visibility.ts +18 -5
  221. package/internal/stores/data_style/model/visibility.ts +82 -20
  222. package/internal/stores/data_style/state.ts +77 -65
  223. package/internal/stores/hybrid_viewer/brightness.ts +49 -31
  224. package/internal/stores/hybrid_viewer/camera.ts +191 -177
  225. package/internal/stores/hybrid_viewer/camera_animation.ts +11 -10
  226. package/internal/stores/hybrid_viewer/core.ts +64 -0
  227. package/internal/stores/hybrid_viewer/filters.ts +10 -16
  228. package/internal/stores/hybrid_viewer/highlight.ts +91 -130
  229. package/internal/stores/hybrid_viewer/ruler.ts +24 -15
  230. package/internal/stores/hybrid_viewer/scene.ts +96 -117
  231. package/internal/stores/hybrid_viewer/viewport.ts +74 -65
  232. package/internal/stores/hybrid_viewer/vtk_types.ts +13 -29
  233. package/internal/utils/api_fetch.ts +54 -23
  234. package/internal/utils/upload_file.ts +74 -53
  235. package/internal/utils/viewer_call.ts +22 -13
  236. package/internal/utils/ws_client.ts +24 -13
  237. package/nuxt.config.ts +58 -1
  238. package/package.json +20 -8
  239. package/server/api/cloud/extensions/run.post.ts +6 -10
  240. package/server/api/local/app/project_folder_path.post.ts +4 -4
  241. package/server/api/local/app/run_back.post.ts +5 -7
  242. package/server/api/local/app/run_viewer.post.ts +5 -7
  243. package/server/api/local/extensions/kill.post.ts +4 -3
  244. package/server/api/local/extensions/run.post.ts +7 -10
  245. package/server/api/local/extensions/upload.put.ts +44 -54
  246. package/server/api/microservice/app/get_is_app_ready.get.ts +4 -5
  247. package/server/api/microservice/app/set_app_base_url.post.ts +5 -6
  248. package/server/api/microservice/app/set_back_base_url.post.ts +5 -6
  249. package/server/api/microservice/app/set_is_app_ready.post.ts +5 -6
  250. package/server/api/microservice/app/set_viewer_base_url.post.ts +5 -6
  251. package/server/api/microservice/extensions/download.post.ts +5 -4
  252. package/server/api/serverless/run_cloud.post.ts +53 -11
  253. package/server/utils/app_config.ts +29 -22
  254. package/server/utils/cleanup.ts +60 -30
  255. package/server/utils/cloud.ts +9 -8
  256. package/server/utils/extension.ts +23 -9
  257. package/server/utils/microservices.ts +33 -24
  258. package/server/utils/path.ts +4 -4
  259. package/server/utils/scripts.ts +26 -23
  260. package/server/utils/server.ts +2 -2
  261. package/server/utils/server_config.ts +41 -27
  262. package/server/utils/stream.ts +6 -0
  263. package/server/utils/ws_client.ts +42 -8
  264. package/shared/scripts.ts +15 -10
  265. package/shared/utils/call_raw.ts +23 -16
  266. package/shared/utils/call_schema.ts +5 -8
  267. package/shared/utils/fetch_raw.ts +87 -47
  268. package/shared/utils/fetch_schema.ts +6 -9
  269. package/shared/utils/file.ts +8 -2
  270. package/shared/utils/response_handlers/load.ts +26 -11
  271. package/shared/utils/types.ts +9 -9
  272. package/shared/utils/validate_schema.ts +1 -1
  273. package/app/components/Viewer/ObjectTree/Views/ModelComponents.vue +0 -276
  274. package/server/types/vendor.d.ts +0 -64
  275. package/server/utils/server_config.js +0 -43
  276. package/shared/utils/call_raw.js +0 -30
  277. package/shared/utils/fetch_raw.js +0 -40
  278. /package/{opengeodeweb_front_schemas.js → .build/opengeodeweb_front_schemas.js} +0 -0
  279. /package/{server → .build/server}/utils/server.js +0 -0
  280. /package/{shared → .build/shared}/app_mode.js +0 -0
  281. /package/{shared → .build/shared}/utils/parse_boolean.js +0 -0
  282. /package/{shared → .build/shared}/utils/types.js +0 -0
@@ -1,58 +1,38 @@
1
- // Not auto-fixable (eslint's sort-imports core rule has no autofixer) and this file's import order doesn't match its syntax-kind-then-alphabetical requirement - left as-is rather than manually reordered across the codebase for a purely cosmetic rule.
2
- // oxlint-disable eslint/sort-imports
3
1
  import {
4
- AXIS_SCALE,
5
2
  CHANGE_THRESHOLD,
6
- PLANE_COLORS,
7
- SIZE_RATIO,
3
+ type MainCameraOptions,
4
+ type SceneBoundsInfo,
5
+ alignCameraToMainCamera,
8
6
  computeSceneBoundsInfo,
9
- getPlaneStyle,
10
- hasPlaneChanged,
7
+ resolveActiveActors,
11
8
  } from "@ogw_front/utils/clipping_planes";
12
- import { newInstance as vtkGenericRenderWindow } from "@kitware/vtk.js/Rendering/Misc/GenericRenderWindow";
13
- // ImplicitPlaneWidget ships no type declarations at all (unlike most of vtk.js), unlike a module that simply doesn't exist, so it can't be given an ambient `declare module` shim either - suppress the resulting implicit-any error at the import site instead.
14
- // @ts-expect-error -- see comment above; newInstance() below is implicitly `any`.
15
- import { newInstance as vtkImplicitPlaneWidget } from "@kitware/vtk.js/Widgets/Widgets3D/ImplicitPlaneWidget";
16
- import { newInstance as vtkWidgetManager } from "@kitware/vtk.js/Widgets/Core/WidgetManager";
17
- // oxlint-disable-next-line eslint/no-duplicate-imports
18
- import type { vtkWidgetManager as WidgetManagerInstance } from "@kitware/vtk.js/Widgets/Core/WidgetManager";
19
- import type { Ref } from "vue";
20
- import type vtkActor from "@kitware/vtk.js/Rendering/Core/Actor";
21
- import type { vtkCamera } from "@kitware/vtk.js/Rendering/Core/Camera";
9
+ import {
10
+ type ClippingPlane,
11
+ useWidgetEntryManager,
12
+ } from "@ogw_front/composables/clipping_planes_widget_entries";
13
+ import {
14
+ type vtkWidgetManager as WidgetManagerInstance,
15
+ newInstance as vtkWidgetManager,
16
+ } from "@kitware/vtk.js/Widgets/Core/WidgetManager";
22
17
  import type { vtkGenericRenderWindow as GenericRenderWindowInstance } from "@ogw_internal/stores/hybrid_viewer/vtk_types";
23
18
  import type { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer";
24
-
25
- interface ClippingPlane {
26
- origin?: number[];
27
- normal: number[];
28
- }
19
+ import type { vtkCamera } from "@kitware/vtk.js/Rendering/Core/Camera";
20
+ import { newInstance as vtkGenericRenderWindow } from "@kitware/vtk.js/Rendering/Misc/GenericRenderWindow";
29
21
 
30
22
  interface DataItemLike {
31
23
  id: string;
32
24
  }
33
25
 
34
- // Vtk.js's plane-widget factory/handle/state objects (from ImplicitPlaneWidget, which ships no type declarations) are kept as `any` here - deep vtk.js widget internals with no typed surface to build on.
35
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
36
- type PlaneWidget = any;
37
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
38
- type WidgetHandle = any;
39
-
40
- interface WidgetEntry {
41
- planeWidget: PlaneWidget;
42
- widgetHandle: WidgetHandle;
43
- subscription: { unsubscribe: () => void };
44
- }
45
-
46
26
  interface ClippingPlanesWidgetParams {
47
27
  planes: Ref<ClippingPlane[]>;
48
28
  targetAllVisible: Ref<boolean>;
49
29
  selectedDatasetIds: Ref<string[]>;
50
30
  allItems: Ref<DataItemLike[]>;
51
31
  hybridViewerStore: ReturnType<typeof useHybridViewerStore>;
52
- debouncedApply: (...args: unknown[]) => void;
32
+ debouncedApply: (...args: readonly unknown[]) => void;
53
33
  }
54
34
 
55
- // oxlint-disable-next-line max-params max-lines-per-function
35
+ // oxlint-disable-next-line max-params max-lines-per-function typescript/prefer-readonly-parameter-types -- Ref-backed params are inherently mutable through .value.
56
36
  function useClippingPlanesWidget({
57
37
  planes,
58
38
  targetAllVisible,
@@ -60,118 +40,48 @@ function useClippingPlanesWidget({
60
40
  allItems,
61
41
  hybridViewerStore,
62
42
  debouncedApply,
63
- }: ClippingPlanesWidgetParams) {
43
+ }: ClippingPlanesWidgetParams): {
44
+ getSceneCenter: typeof getSceneCenter;
45
+ syncWidgets: typeof syncWidgets;
46
+ syncLocalCamera: typeof syncLocalCamera;
47
+ cleanupLocalWidget: typeof cleanupLocalWidget;
48
+ initLocalWidget: typeof initLocalWidget;
49
+ updateWidgetPlacement: typeof updateWidgetPlacement;
50
+ isFromWidget: typeof isFromWidget;
51
+ setFromWidget: typeof setFromWidget;
52
+ } {
64
53
  let localRenderWindow: GenericRenderWindowInstance | undefined = undefined;
65
54
  let widgetManager: WidgetManagerInstance | undefined = undefined;
66
- let widgetEntries: WidgetEntry[] = [];
67
- let fromWidget = false;
68
55
  let maxDistance = 0;
69
56
  let isLimitingCameraZoom = false;
70
- function resolveActiveActors(): vtkActor[] {
71
- const targetIds = targetAllVisible.value
72
- ? allItems.value.map((item) => item.id)
73
- : selectedDatasetIds.value;
74
- const targeted = targetIds
75
- .map((id) => {
76
- const item = hybridViewerStore.hybridDb[id];
77
- return item ? item.actor : undefined;
78
- })
79
- .filter((actor): actor is vtkActor => Boolean(actor));
80
- if (targeted.length > 0) {
81
- return targeted;
82
- }
83
- return Object.values(hybridViewerStore.hybridDb)
84
- .map((entry) => entry && entry.actor)
85
- .filter((actor): actor is vtkActor => Boolean(actor));
86
- }
87
- function getSceneBoundsInfo() {
88
- return computeSceneBoundsInfo(resolveActiveActors());
57
+ const widgetEntryManager = useWidgetEntryManager({ planes, debouncedApply });
58
+
59
+ function getSceneBoundsInfo(): SceneBoundsInfo {
60
+ return computeSceneBoundsInfo(
61
+ resolveActiveActors(
62
+ targetAllVisible.value,
63
+ allItems.value,
64
+ selectedDatasetIds.value,
65
+ hybridViewerStore.hybridDb,
66
+ ),
67
+ );
89
68
  }
90
- function getSceneCenter(): number[] {
69
+ function getSceneCenter(): readonly number[] {
91
70
  return getSceneBoundsInfo().center;
92
71
  }
93
- function createWidgetEntry(
94
- planeWidget: PlaneWidget,
95
- widgetHandle: WidgetHandle,
96
- planeIndex: number,
97
- ): WidgetEntry {
98
- const widgetState = planeWidget.getWidgetState();
99
- const plane = planes.value[planeIndex];
100
- if (plane?.origin) {
101
- widgetState.setOrigin(plane.origin);
102
- }
103
- if (plane) {
104
- widgetState.setNormal(plane.normal);
105
- }
106
- const subscription = widgetState.onModified(() => {
107
- if (fromWidget) {
108
- return;
109
- }
110
- const origin: number[] = widgetState.getOrigin().map((val: number) => Number(val.toFixed(4)));
111
- const normal: number[] = widgetState.getNormal().map((val: number) => Number(val.toFixed(4)));
112
- const currentPlane = planes.value[planeIndex];
113
- if (
114
- !currentPlane ||
115
- !hasPlaneChanged(origin, normal, currentPlane.origin, currentPlane.normal)
116
- ) {
117
- return;
118
- }
119
- fromWidget = true;
120
- currentPlane.origin = origin;
121
- currentPlane.normal = normal;
122
- nextTick(() => {
123
- fromWidget = false;
124
- });
125
- debouncedApply();
126
- });
127
- return {
128
- planeWidget,
129
- widgetHandle,
130
- subscription,
131
- };
132
- }
72
+
133
73
  function syncWidgets(): void {
134
74
  if (!widgetManager || !localRenderWindow) {
135
75
  return;
136
76
  }
137
- while (widgetEntries.length > planes.value.length) {
138
- const entry = widgetEntries.pop();
139
- if (!entry) {
140
- continue;
141
- }
142
- entry.subscription.unsubscribe();
143
- widgetManager.removeWidget(entry.planeWidget);
144
- entry.planeWidget.delete();
145
- }
77
+ widgetEntryManager.removeExtraWidgets(widgetManager);
146
78
  const { cubicBounds } = getSceneBoundsInfo();
147
79
  for (const [idx, plane] of planes.value.entries()) {
148
- // Modulo guarantees this index is within bounds of the non-empty PLANE_COLORS array.
149
- const rgb = PLANE_COLORS[idx % PLANE_COLORS.length]!;
150
- if (!widgetEntries[idx]) {
151
- const planeWidget = vtkImplicitPlaneWidget();
152
- const widgetHandle = widgetManager.addWidget(planeWidget);
153
- widgetHandle.setAxisScale(AXIS_SCALE);
154
- widgetHandle.setHandleSizeRatio(SIZE_RATIO);
155
- widgetEntries.push(createWidgetEntry(planeWidget, widgetHandle, idx));
156
- }
157
- const entry = widgetEntries[idx];
158
- if (!entry) {
159
- continue;
160
- }
161
- entry.widgetHandle.setRepresentationStyle(getPlaneStyle(rgb));
162
- fromWidget = true;
163
- entry.widgetHandle.placeWidget(cubicBounds);
164
- fromWidget = false;
165
- entry.widgetHandle.setAxisScale(AXIS_SCALE);
166
- entry.widgetHandle.setHandleSizeRatio(SIZE_RATIO);
167
- const widgetState = entry.planeWidget.getWidgetState();
168
- if (plane.origin) {
169
- widgetState.setOrigin(plane.origin);
170
- }
171
- widgetState.setNormal(plane.normal);
80
+ widgetEntryManager.updateWidgetEntry(idx, plane, cubicBounds, widgetManager);
172
81
  }
173
82
  localRenderWindow.getRenderWindow().render();
174
83
  }
84
+
175
85
  function limitCameraZoomOut(camera: vtkCamera): void {
176
86
  if (maxDistance <= 0 || isLimitingCameraZoom) {
177
87
  return;
@@ -192,65 +102,33 @@ function useClippingPlanesWidget({
192
102
  localRenderWindow?.getRenderWindow().render();
193
103
  isLimitingCameraZoom = false;
194
104
  }
195
- // The `noUncheckedIndexedAccess` compiler option (needed elsewhere in this migration) forces every `focal_point[i]`/`position[i]`/`view_up[i]` access below into its own `?? 0` fallback branch, which is what pushes this pre-existing function's cyclomatic complexity over the limit - the control flow itself is unchanged from the plain-JS version.
196
- // oxlint-disable-next-line complexity
105
+
197
106
  function syncLocalCamera(): void {
198
107
  if (!localRenderWindow) {
199
108
  return;
200
109
  }
201
110
  const renderer = localRenderWindow.getRenderer();
202
111
  const camera = renderer.getActiveCamera();
203
- const mainCam = hybridViewerStore.camera_options as {
204
- focal_point?: number[];
205
- position?: number[];
206
- view_up?: number[];
207
- };
112
+ const mainCam = hybridViewerStore.camera_options as MainCameraOptions;
208
113
  const { center, cubicBounds } = getSceneBoundsInfo();
114
+ // oxlint-disable-next-line no-unsafe-type-assertion -- cubicBounds is always a 6-element bounds tuple.
209
115
  renderer.resetCamera(cubicBounds as [number, number, number, number, number, number]);
210
- if (mainCam && mainCam.focal_point && mainCam.position) {
211
- const { focal_point, position } = mainCam;
212
- const dir = [
213
- (position[0] ?? 0) - (focal_point[0] ?? 0),
214
- (position[1] ?? 0) - (focal_point[1] ?? 0),
215
- (position[2] ?? 0) - (focal_point[2] ?? 0),
216
- ];
217
- const dirLen = Math.hypot(...dir);
218
- if (dirLen > 0) {
219
- const distance = camera.getDistance();
220
- const normDir = dir.map((component) => component / dirLen);
221
- camera.setFocalPoint(center[0] ?? 0, center[1] ?? 0, center[2] ?? 0);
222
- camera.setPosition(
223
- (center[0] ?? 0) + (normDir[0] ?? 0) * distance,
224
- (center[1] ?? 0) + (normDir[1] ?? 0) * distance,
225
- (center[2] ?? 0) + (normDir[2] ?? 0) * distance,
226
- );
227
- if (mainCam.view_up) {
228
- const [viewUpX = 0, viewUpY = 0, viewUpZ = 0] = mainCam.view_up;
229
- camera.setViewUp(viewUpX, viewUpY, viewUpZ);
230
- }
231
- }
232
- }
116
+ alignCameraToMainCamera(camera, mainCam, center);
233
117
  limitCameraZoomOut(camera);
234
118
  localRenderWindow.getRenderWindow().render();
235
119
  }
120
+
236
121
  function cleanupLocalWidget(): void {
237
122
  maxDistance = 0;
238
123
  isLimitingCameraZoom = false;
239
- for (const entry of widgetEntries) {
240
- entry.subscription.unsubscribe();
241
- if (widgetManager) {
242
- widgetManager.removeWidget(entry.planeWidget);
243
- }
244
- entry.planeWidget.delete();
245
- }
246
- widgetEntries = [];
124
+ widgetEntryManager.cleanupAll(widgetManager);
247
125
  if (localRenderWindow) {
248
126
  localRenderWindow.delete();
249
127
  localRenderWindow = undefined;
250
128
  widgetManager = undefined;
251
129
  }
252
130
  }
253
- function updateWidgetPlacement({ isReset = false } = {}): void {
131
+ function updateWidgetPlacement({ isReset = false }: { isReset?: boolean } = {}): void {
254
132
  if (!widgetManager || !localRenderWindow) {
255
133
  return;
256
134
  }
@@ -272,20 +150,32 @@ function useClippingPlanesWidget({
272
150
 
273
151
  function initLocalWidget(container: HTMLElement): void {
274
152
  cleanupLocalWidget();
275
- container.addEventListener("wheel", (event) => event.stopPropagation(), { passive: true });
153
+ container.addEventListener(
154
+ "wheel",
155
+ (event: WheelEvent) => {
156
+ event.stopPropagation();
157
+ },
158
+ { passive: true },
159
+ );
276
160
  localRenderWindow = vtkGenericRenderWindow({
277
161
  background: [0, 0, 0, 0],
278
162
  listenWindowResize: false,
279
163
  });
280
164
  localRenderWindow.setContainer(container);
281
165
  const camera = localRenderWindow.getRenderer().getActiveCamera();
282
- camera.onModified(() => limitCameraZoomOut(camera));
283
- const canvas = (
284
- localRenderWindow.getApiSpecificRenderWindow() as unknown as {
285
- getCanvas: () => HTMLCanvasElement;
286
- }
287
- ).getCanvas();
288
- Object.assign(canvas.style, { width: "100%", height: "100%", background: "transparent" });
166
+ camera.onModified(() => {
167
+ limitCameraZoomOut(camera);
168
+ });
169
+ // oxlint-disable-next-line no-unsafe-type-assertion -- trusted vtk.js OpenGL render window API boundary.
170
+ const openGLRenderWindow = localRenderWindow.getApiSpecificRenderWindow() as unknown as {
171
+ getCanvas: () => HTMLCanvasElement;
172
+ };
173
+ const canvas = openGLRenderWindow.getCanvas();
174
+ Object.assign(canvas.style, {
175
+ width: "100%",
176
+ height: "100%",
177
+ background: "transparent",
178
+ });
289
179
  localRenderWindow.resize();
290
180
  widgetManager = vtkWidgetManager();
291
181
  widgetManager.setRenderer(localRenderWindow.getRenderer());
@@ -293,11 +183,13 @@ function useClippingPlanesWidget({
293
183
  }
294
184
 
295
185
  function isFromWidget(): boolean {
296
- return fromWidget;
186
+ return widgetEntryManager.isFromWidget();
297
187
  }
188
+
298
189
  function setFromWidget(value: boolean): void {
299
- fromWidget = value;
190
+ widgetEntryManager.setFromWidget(value);
300
191
  }
192
+
301
193
  return {
302
194
  getSceneCenter,
303
195
  syncWidgets,
@@ -0,0 +1,189 @@
1
+ import {
2
+ AXIS_SCALE,
3
+ PLANE_COLORS,
4
+ SIZE_RATIO,
5
+ getPlaneStyle,
6
+ hasPlaneChanged,
7
+ } from "@ogw_front/utils/clipping_planes";
8
+ import type { vtkWidgetManager as WidgetManagerInstance } from "@kitware/vtk.js/Widgets/Core/WidgetManager";
9
+ import type vtkAbstractWidget from "@kitware/vtk.js/Widgets/Core/AbstractWidget";
10
+ import type vtkAbstractWidgetFactory from "@kitware/vtk.js/Widgets/Core/AbstractWidgetFactory";
11
+ import { newInstance as vtkImplicitPlaneWidget } from "@kitware/vtk.js/Widgets/Widgets3D/ImplicitPlaneWidget";
12
+
13
+ interface ClippingPlane {
14
+ origin?: number[];
15
+ normal: number[];
16
+ }
17
+
18
+ interface ClippingWidgetState {
19
+ getOrigin: () => number[];
20
+ setOrigin: (origin: readonly number[]) => void;
21
+ getNormal: () => number[];
22
+ setNormal: (normal: readonly number[]) => void;
23
+ onModified: (callback: () => void) => { unsubscribe: () => void };
24
+ }
25
+
26
+ interface PlaneWidget {
27
+ getWidgetState: () => ClippingWidgetState;
28
+ delete: () => void;
29
+ }
30
+
31
+ interface WidgetHandle {
32
+ setAxisScale: (scale: number) => void;
33
+ setHandleSizeRatio: (ratio: number) => void;
34
+ setRepresentationStyle: (style: unknown) => void;
35
+ placeWidget: (bounds: readonly number[]) => void;
36
+ }
37
+
38
+ interface WidgetEntry {
39
+ planeWidget: PlaneWidget;
40
+ widgetHandle: WidgetHandle;
41
+ subscription: { unsubscribe: () => void };
42
+ }
43
+
44
+ function asWidgetFactory(widget: PlaneWidget): vtkAbstractWidgetFactory<vtkAbstractWidget> {
45
+ // oxlint-disable-next-line no-unsafe-type-assertion -- vtk.js's WidgetManager APIs (addWidget/removeWidget) are untyped for our custom PlaneWidget shape; narrowed once here.
46
+ return widget as unknown as vtkAbstractWidgetFactory<vtkAbstractWidget>;
47
+ }
48
+
49
+ interface WidgetEntryManagerParams {
50
+ planes: Ref<ClippingPlane[]>;
51
+ debouncedApply: (...args: readonly unknown[]) => void;
52
+ }
53
+
54
+ // oxlint-disable-next-line max-lines-per-function typescript/prefer-readonly-parameter-types -- Ref-backed params are inherently mutable through .value.
55
+ function useWidgetEntryManager({ planes, debouncedApply }: WidgetEntryManagerParams): {
56
+ removeExtraWidgets: (widgetManager: WidgetManagerInstance | undefined) => void;
57
+ updateWidgetEntry: (
58
+ idx: number,
59
+ plane: ClippingPlane,
60
+ cubicBounds: readonly number[],
61
+ widgetManager: WidgetManagerInstance,
62
+ ) => void;
63
+ cleanupAll: (widgetManager: WidgetManagerInstance | undefined) => void;
64
+ isFromWidget: () => boolean;
65
+ setFromWidget: (value: boolean) => void;
66
+ } {
67
+ let widgetEntries: WidgetEntry[] = [];
68
+ let fromWidget = false;
69
+
70
+ function createWidgetEntry(
71
+ planeWidget: PlaneWidget,
72
+ widgetHandle: WidgetHandle,
73
+ planeIndex: number,
74
+ ): WidgetEntry {
75
+ const widgetState = planeWidget.getWidgetState();
76
+ const plane = planes.value[planeIndex];
77
+ if (plane?.origin) {
78
+ widgetState.setOrigin(plane.origin);
79
+ }
80
+ if (plane) {
81
+ widgetState.setNormal(plane.normal);
82
+ }
83
+ const subscription = widgetState.onModified(() => {
84
+ if (fromWidget) {
85
+ return;
86
+ }
87
+ const origin: number[] = widgetState.getOrigin().map((val: number) => Number(val.toFixed(4)));
88
+ const normal: number[] = widgetState.getNormal().map((val: number) => Number(val.toFixed(4)));
89
+ const currentPlane = planes.value[planeIndex];
90
+ if (
91
+ !currentPlane ||
92
+ !hasPlaneChanged(origin, normal, currentPlane.origin, currentPlane.normal)
93
+ ) {
94
+ return;
95
+ }
96
+ fromWidget = true;
97
+ currentPlane.origin = origin;
98
+ currentPlane.normal = normal;
99
+ nextTick(() => {
100
+ fromWidget = false;
101
+ // oxlint-disable-next-line promise/prefer-await-to-then -- fire-and-forget inside a sync widget callback; see codebase convention in global_attribute_style.ts.
102
+ }).catch(() => undefined);
103
+ debouncedApply();
104
+ });
105
+ return {
106
+ planeWidget,
107
+ widgetHandle,
108
+ subscription,
109
+ };
110
+ }
111
+
112
+ function removeExtraWidgets(widgetManager: WidgetManagerInstance | undefined): void {
113
+ while (widgetEntries.length > planes.value.length) {
114
+ const entry = widgetEntries.pop();
115
+ if (!entry) {
116
+ continue;
117
+ }
118
+ entry.subscription.unsubscribe();
119
+ widgetManager?.removeWidget(asWidgetFactory(entry.planeWidget));
120
+ entry.planeWidget.delete();
121
+ }
122
+ }
123
+
124
+ function updateWidgetEntry(
125
+ idx: number,
126
+ plane: ClippingPlane,
127
+ cubicBounds: readonly number[],
128
+ widgetManager: WidgetManagerInstance,
129
+ ): void {
130
+ // Modulo guarantees this index is within bounds of the non-empty PLANE_COLORS array.
131
+ const rgb = PLANE_COLORS[idx % PLANE_COLORS.length];
132
+ if (rgb === undefined) {
133
+ return;
134
+ }
135
+ if (!widgetEntries[idx]) {
136
+ // oxlint-disable-next-line no-unsafe-call no-unsafe-type-assertion -- vtk.js has no types for ImplicitPlaneWidget's factory; narrowed here.
137
+ const planeWidget = vtkImplicitPlaneWidget() as PlaneWidget;
138
+ const widgetHandle = widgetManager.addWidget(
139
+ asWidgetFactory(planeWidget),
140
+ // oxlint-disable-next-line no-unsafe-type-assertion -- vtk.js WidgetManager.addWidget is untyped for our custom WidgetHandle shape; narrowed here.
141
+ ) as unknown as WidgetHandle;
142
+ widgetEntries.push(createWidgetEntry(planeWidget, widgetHandle, idx));
143
+ }
144
+ const entry = widgetEntries[idx];
145
+ if (!entry) {
146
+ return;
147
+ }
148
+ entry.widgetHandle.setRepresentationStyle(getPlaneStyle(rgb));
149
+ fromWidget = true;
150
+ entry.widgetHandle.placeWidget(cubicBounds);
151
+ fromWidget = false;
152
+ entry.widgetHandle.setAxisScale(AXIS_SCALE);
153
+ entry.widgetHandle.setHandleSizeRatio(SIZE_RATIO);
154
+ const widgetState = entry.planeWidget.getWidgetState();
155
+ if (plane.origin) {
156
+ widgetState.setOrigin(plane.origin);
157
+ }
158
+ widgetState.setNormal(plane.normal);
159
+ }
160
+
161
+ function cleanupAll(widgetManager: WidgetManagerInstance | undefined): void {
162
+ for (const entry of widgetEntries) {
163
+ entry.subscription.unsubscribe();
164
+ if (widgetManager) {
165
+ widgetManager.removeWidget(asWidgetFactory(entry.planeWidget));
166
+ }
167
+ entry.planeWidget.delete();
168
+ }
169
+ widgetEntries = [];
170
+ }
171
+
172
+ function isFromWidget(): boolean {
173
+ return fromWidget;
174
+ }
175
+
176
+ function setFromWidget(value: boolean): void {
177
+ fromWidget = value;
178
+ }
179
+
180
+ return {
181
+ removeExtraWidgets,
182
+ updateWidgetEntry,
183
+ cleanupAll,
184
+ isFromWidget,
185
+ setFromWidget,
186
+ };
187
+ }
188
+
189
+ export { useWidgetEntryManager, type ClippingPlane };
@@ -0,0 +1,7 @@
1
+ import { type UseClipboardReturn, useClipboard } from "@vueuse/core";
2
+
3
+ const COPIED_FEEDBACK_TIMEOUT = 1500;
4
+
5
+ export function useCopyToClipboard(): UseClipboardReturn<false> {
6
+ return useClipboard({ copiedDuring: COPIED_FEEDBACK_TIMEOUT });
7
+ }