arrayview 0.28.0__tar.gz → 0.28.1__tar.gz

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 (214) hide show
  1. {arrayview-0.28.0 → arrayview-0.28.1}/PKG-INFO +1 -1
  2. {arrayview-0.28.0 → arrayview-0.28.1}/pyproject.toml +1 -1
  3. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_viewer.html +38 -14
  4. {arrayview-0.28.0 → arrayview-0.28.1}/uv.lock +1 -1
  5. {arrayview-0.28.0 → arrayview-0.28.1}/vscode-extension/extension.js +80 -41
  6. {arrayview-0.28.0 → arrayview-0.28.1}/.agents/skills/frontend-designer/SKILL.md +0 -0
  7. {arrayview-0.28.0 → arrayview-0.28.1}/.agents/skills/invocation-consistency/SKILL.md +0 -0
  8. {arrayview-0.28.0 → arrayview-0.28.1}/.agents/skills/modes-consistency/SKILL.md +0 -0
  9. {arrayview-0.28.0 → arrayview-0.28.1}/.agents/skills/playwright-cli/SKILL.md +0 -0
  10. {arrayview-0.28.0 → arrayview-0.28.1}/.agents/skills/playwright-cli/references/element-attributes.md +0 -0
  11. {arrayview-0.28.0 → arrayview-0.28.1}/.agents/skills/playwright-cli/references/playwright-tests.md +0 -0
  12. {arrayview-0.28.0 → arrayview-0.28.1}/.agents/skills/playwright-cli/references/request-mocking.md +0 -0
  13. {arrayview-0.28.0 → arrayview-0.28.1}/.agents/skills/playwright-cli/references/running-code.md +0 -0
  14. {arrayview-0.28.0 → arrayview-0.28.1}/.agents/skills/playwright-cli/references/session-management.md +0 -0
  15. {arrayview-0.28.0 → arrayview-0.28.1}/.agents/skills/playwright-cli/references/storage-state.md +0 -0
  16. {arrayview-0.28.0 → arrayview-0.28.1}/.agents/skills/playwright-cli/references/test-generation.md +0 -0
  17. {arrayview-0.28.0 → arrayview-0.28.1}/.agents/skills/playwright-cli/references/tracing.md +0 -0
  18. {arrayview-0.28.0 → arrayview-0.28.1}/.agents/skills/playwright-cli/references/video-recording.md +0 -0
  19. {arrayview-0.28.0 → arrayview-0.28.1}/.agents/skills/todo-workflow/SKILL.md +0 -0
  20. {arrayview-0.28.0 → arrayview-0.28.1}/.agents/skills/ui-consistency-audit/SKILL.md +0 -0
  21. {arrayview-0.28.0 → arrayview-0.28.1}/.agents/skills/viewer-ui-checklist/SKILL.md +0 -0
  22. {arrayview-0.28.0 → arrayview-0.28.1}/.agents/skills/visual-bug-fixing/SKILL.md +0 -0
  23. {arrayview-0.28.0 → arrayview-0.28.1}/.github/copilot-instructions.md +0 -0
  24. {arrayview-0.28.0 → arrayview-0.28.1}/.github/workflows/docs.yml +0 -0
  25. {arrayview-0.28.0 → arrayview-0.28.1}/.github/workflows/python-publish.yml +0 -0
  26. {arrayview-0.28.0 → arrayview-0.28.1}/.gitignore +0 -0
  27. {arrayview-0.28.0 → arrayview-0.28.1}/.ignore +0 -0
  28. {arrayview-0.28.0 → arrayview-0.28.1}/.mex/AGENTS.md +0 -0
  29. {arrayview-0.28.0 → arrayview-0.28.1}/.mex/ROUTER.md +0 -0
  30. {arrayview-0.28.0 → arrayview-0.28.1}/.mex/SETUP.md +0 -0
  31. {arrayview-0.28.0 → arrayview-0.28.1}/.mex/SYNC.md +0 -0
  32. {arrayview-0.28.0 → arrayview-0.28.1}/.mex/context/architecture.md +0 -0
  33. {arrayview-0.28.0 → arrayview-0.28.1}/.mex/context/conventions.md +0 -0
  34. {arrayview-0.28.0 → arrayview-0.28.1}/.mex/context/decisions.md +0 -0
  35. {arrayview-0.28.0 → arrayview-0.28.1}/.mex/context/frontend.md +0 -0
  36. {arrayview-0.28.0 → arrayview-0.28.1}/.mex/context/lifecycle.md +0 -0
  37. {arrayview-0.28.0 → arrayview-0.28.1}/.mex/context/project-state.md +0 -0
  38. {arrayview-0.28.0 → arrayview-0.28.1}/.mex/context/render-pipeline.md +0 -0
  39. {arrayview-0.28.0 → arrayview-0.28.1}/.mex/context/setup.md +0 -0
  40. {arrayview-0.28.0 → arrayview-0.28.1}/.mex/context/stack.md +0 -0
  41. {arrayview-0.28.0 → arrayview-0.28.1}/.mex/patterns/INDEX.md +0 -0
  42. {arrayview-0.28.0 → arrayview-0.28.1}/.mex/patterns/README.md +0 -0
  43. {arrayview-0.28.0 → arrayview-0.28.1}/.mex/patterns/add-file-format.md +0 -0
  44. {arrayview-0.28.0 → arrayview-0.28.1}/.mex/patterns/add-server-endpoint.md +0 -0
  45. {arrayview-0.28.0 → arrayview-0.28.1}/.mex/patterns/animation-verify.md +0 -0
  46. {arrayview-0.28.0 → arrayview-0.28.1}/.mex/patterns/debug-render.md +0 -0
  47. {arrayview-0.28.0 → arrayview-0.28.1}/.mex/patterns/debug-vscode-extension-python.md +0 -0
  48. {arrayview-0.28.0 → arrayview-0.28.1}/.mex/patterns/extend-compare-mode.md +0 -0
  49. {arrayview-0.28.0 → arrayview-0.28.1}/.mex/patterns/extract-server-route-module.md +0 -0
  50. {arrayview-0.28.0 → arrayview-0.28.1}/.mex/patterns/frontend-change.md +0 -0
  51. {arrayview-0.28.0 → arrayview-0.28.1}/.mex/setup.sh +0 -0
  52. {arrayview-0.28.0 → arrayview-0.28.1}/.mex/sync.sh +0 -0
  53. {arrayview-0.28.0 → arrayview-0.28.1}/.opencode/opencode.json +0 -0
  54. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-06T18-46-49-737Z.yml +0 -0
  55. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-06T18-48-21-979Z.yml +0 -0
  56. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-06T18-51-35-665Z.yml +0 -0
  57. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-06T19-07-01-393Z.yml +0 -0
  58. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-06T19-14-37-969Z.yml +0 -0
  59. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-06T19-21-30-940Z.yml +0 -0
  60. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-06T19-23-08-126Z.yml +0 -0
  61. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-06T19-29-33-155Z.yml +0 -0
  62. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-06T19-31-25-336Z.yml +0 -0
  63. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-06T19-31-53-789Z.yml +0 -0
  64. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-06T19-39-12-257Z.yml +0 -0
  65. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-06T19-39-16-449Z.yml +0 -0
  66. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-06T20-15-25-513Z.yml +0 -0
  67. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-06T20-25-13-179Z.yml +0 -0
  68. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-06T20-39-01-435Z.yml +0 -0
  69. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-06T21-01-27-659Z.yml +0 -0
  70. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-06T21-01-41-283Z.yml +0 -0
  71. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-06T21-03-00-625Z.yml +0 -0
  72. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-06T21-04-12-887Z.yml +0 -0
  73. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-06T21-33-39-044Z.yml +0 -0
  74. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-06T21-38-01-530Z.yml +0 -0
  75. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-06T21-45-20-383Z.yml +0 -0
  76. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-06T21-55-11-545Z.yml +0 -0
  77. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-06T21-56-03-307Z.yml +0 -0
  78. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-06T21-56-35-733Z.yml +0 -0
  79. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-06T21-57-12-181Z.yml +0 -0
  80. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-06T21-57-37-748Z.yml +0 -0
  81. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-06T21-58-13-679Z.yml +0 -0
  82. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-06T22-37-23-895Z.yml +0 -0
  83. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-07T00-39-18-637Z.yml +0 -0
  84. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-07T01-41-46-243Z.yml +0 -0
  85. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-07T04-31-48-472Z.yml +0 -0
  86. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-07T12-14-15-632Z.yml +0 -0
  87. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-07T12-14-47-582Z.yml +0 -0
  88. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-07T12-16-23-471Z.yml +0 -0
  89. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-07T12-17-10-247Z.yml +0 -0
  90. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-07T12-18-24-707Z.yml +0 -0
  91. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-07T12-20-06-164Z.yml +0 -0
  92. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-07T12-20-28-342Z.yml +0 -0
  93. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-07T12-21-54-962Z.yml +0 -0
  94. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-07T12-22-34-666Z.yml +0 -0
  95. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-07T12-23-11-336Z.yml +0 -0
  96. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-07T12-23-36-260Z.yml +0 -0
  97. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-07T12-24-09-267Z.yml +0 -0
  98. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-07T12-24-35-434Z.yml +0 -0
  99. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-07T12-25-57-010Z.yml +0 -0
  100. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-07T12-34-48-823Z.yml +0 -0
  101. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-07T12-46-46-468Z.yml +0 -0
  102. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-07T12-48-17-930Z.yml +0 -0
  103. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-07T12-49-26-400Z.yml +0 -0
  104. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-07T12-50-31-563Z.yml +0 -0
  105. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/page-2026-05-07T12-56-45-568Z.yml +0 -0
  106. {arrayview-0.28.0 → arrayview-0.28.1}/.playwright-cli/theme-dark.yml +0 -0
  107. {arrayview-0.28.0 → arrayview-0.28.1}/.python-version +0 -0
  108. {arrayview-0.28.0 → arrayview-0.28.1}/.vscode/settings.json +0 -0
  109. {arrayview-0.28.0 → arrayview-0.28.1}/AGENTS.md +0 -0
  110. {arrayview-0.28.0 → arrayview-0.28.1}/CONTRIBUTING.md +0 -0
  111. {arrayview-0.28.0 → arrayview-0.28.1}/DESIGN.md +0 -0
  112. {arrayview-0.28.0 → arrayview-0.28.1}/LICENSE +0 -0
  113. {arrayview-0.28.0 → arrayview-0.28.1}/README.md +0 -0
  114. {arrayview-0.28.0 → arrayview-0.28.1}/docs/comparing.md +0 -0
  115. {arrayview-0.28.0 → arrayview-0.28.1}/docs/configuration.md +0 -0
  116. {arrayview-0.28.0 → arrayview-0.28.1}/docs/display.md +0 -0
  117. {arrayview-0.28.0 → arrayview-0.28.1}/docs/index.md +0 -0
  118. {arrayview-0.28.0 → arrayview-0.28.1}/docs/launch-routing-refactor.md +0 -0
  119. {arrayview-0.28.0 → arrayview-0.28.1}/docs/lifecycle.md +0 -0
  120. {arrayview-0.28.0 → arrayview-0.28.1}/docs/loading.md +0 -0
  121. {arrayview-0.28.0 → arrayview-0.28.1}/docs/logo.png +0 -0
  122. {arrayview-0.28.0 → arrayview-0.28.1}/docs/measurement.md +0 -0
  123. {arrayview-0.28.0 → arrayview-0.28.1}/docs/remote.md +0 -0
  124. {arrayview-0.28.0 → arrayview-0.28.1}/docs/stylesheets/extra.css +0 -0
  125. {arrayview-0.28.0 → arrayview-0.28.1}/docs/viewing.md +0 -0
  126. {arrayview-0.28.0 → arrayview-0.28.1}/experiments/ws_tunnel_diag/ws_tunnel_diag.py +0 -0
  127. {arrayview-0.28.0 → arrayview-0.28.1}/matlab/arrayview.m +0 -0
  128. {arrayview-0.28.0 → arrayview-0.28.1}/mkdocs.yml +0 -0
  129. {arrayview-0.28.0 → arrayview-0.28.1}/plans/2026-04-14-immersive-animation.md +0 -0
  130. {arrayview-0.28.0 → arrayview-0.28.1}/plans/2026-05-07-unified-colormap-picker.md +0 -0
  131. {arrayview-0.28.0 → arrayview-0.28.1}/plans/arrayview_tool_menu_fix_prompt.md +0 -0
  132. {arrayview-0.28.0 → arrayview-0.28.1}/plans/arrayview_tool_menu_implementation_plan.md +0 -0
  133. {arrayview-0.28.0 → arrayview-0.28.1}/plans/egg-placement-mockup.html +0 -0
  134. {arrayview-0.28.0 → arrayview-0.28.1}/plans/refactoring_plan.md +0 -0
  135. {arrayview-0.28.0 → arrayview-0.28.1}/plans/roi-analysis-requirements.md +0 -0
  136. {arrayview-0.28.0 → arrayview-0.28.1}/plans/webview/LOG.md +0 -0
  137. {arrayview-0.28.0 → arrayview-0.28.1}/scripts/demo.py +0 -0
  138. {arrayview-0.28.0 → arrayview-0.28.1}/scripts/release.sh +0 -0
  139. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/ARCHITECTURE.md +0 -0
  140. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/__init__.py +0 -0
  141. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/__main__.py +0 -0
  142. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_analysis.py +0 -0
  143. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_app.py +0 -0
  144. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_codex_open.py +0 -0
  145. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_config.py +0 -0
  146. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_diff.py +0 -0
  147. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_icon.png +0 -0
  148. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_imaging.py +0 -0
  149. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_io.py +0 -0
  150. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_launch_plan.py +0 -0
  151. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_launcher.py +0 -0
  152. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_lifecycle.py +0 -0
  153. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_overlays.py +0 -0
  154. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_platform.py +0 -0
  155. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_render.py +0 -0
  156. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_routes_analysis.py +0 -0
  157. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_routes_export.py +0 -0
  158. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_routes_loading.py +0 -0
  159. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_routes_persistence.py +0 -0
  160. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_routes_preload.py +0 -0
  161. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_routes_query.py +0 -0
  162. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_routes_rendering.py +0 -0
  163. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_routes_segmentation.py +0 -0
  164. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_routes_state.py +0 -0
  165. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_routes_vectorfield.py +0 -0
  166. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_routes_websocket.py +0 -0
  167. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_segmentation.py +0 -0
  168. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_server.py +0 -0
  169. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_session.py +0 -0
  170. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_shell.html +0 -0
  171. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_synthetic_mri.py +0 -0
  172. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_torch.py +0 -0
  173. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_vectorfield.py +0 -0
  174. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_vscode.py +0 -0
  175. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_vscode_browser.py +0 -0
  176. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_vscode_extension.py +0 -0
  177. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/_vscode_signal.py +0 -0
  178. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/arrayview-opener.vsix +0 -0
  179. {arrayview-0.28.0 → arrayview-0.28.1}/src/arrayview/gsap.min.js +0 -0
  180. {arrayview-0.28.0 → arrayview-0.28.1}/tests/capture_v_animation.py +0 -0
  181. {arrayview-0.28.0 → arrayview-0.28.1}/tests/conftest.py +0 -0
  182. {arrayview-0.28.0 → arrayview-0.28.1}/tests/lifecycle_matrix.py +0 -0
  183. {arrayview-0.28.0 → arrayview-0.28.1}/tests/make_vectorfield_test_arrays.py +0 -0
  184. {arrayview-0.28.0 → arrayview-0.28.1}/tests/test_api.py +0 -0
  185. {arrayview-0.28.0 → arrayview-0.28.1}/tests/test_backend_shared.py +0 -0
  186. {arrayview-0.28.0 → arrayview-0.28.1}/tests/test_browser.py +0 -0
  187. {arrayview-0.28.0 → arrayview-0.28.1}/tests/test_cli.py +0 -0
  188. {arrayview-0.28.0 → arrayview-0.28.1}/tests/test_colorbar_hover_highlight.py +0 -0
  189. {arrayview-0.28.0 → arrayview-0.28.1}/tests/test_command_reachability.py +0 -0
  190. {arrayview-0.28.0 → arrayview-0.28.1}/tests/test_config.py +0 -0
  191. {arrayview-0.28.0 → arrayview-0.28.1}/tests/test_cross_mode_parametrized.py +0 -0
  192. {arrayview-0.28.0 → arrayview-0.28.1}/tests/test_interactions.py +0 -0
  193. {arrayview-0.28.0 → arrayview-0.28.1}/tests/test_io.py +0 -0
  194. {arrayview-0.28.0 → arrayview-0.28.1}/tests/test_large_arrays.py +0 -0
  195. {arrayview-0.28.0 → arrayview-0.28.1}/tests/test_launch_plan.py +0 -0
  196. {arrayview-0.28.0 → arrayview-0.28.1}/tests/test_lifecycle_contract.py +0 -0
  197. {arrayview-0.28.0 → arrayview-0.28.1}/tests/test_loading_server.py +0 -0
  198. {arrayview-0.28.0 → arrayview-0.28.1}/tests/test_mode_consistency.py +0 -0
  199. {arrayview-0.28.0 → arrayview-0.28.1}/tests/test_mode_matrix.py +0 -0
  200. {arrayview-0.28.0 → arrayview-0.28.1}/tests/test_mode_roundtrip.py +0 -0
  201. {arrayview-0.28.0 → arrayview-0.28.1}/tests/test_nifti_meta.py +0 -0
  202. {arrayview-0.28.0 → arrayview-0.28.1}/tests/test_nifti_series.py +0 -0
  203. {arrayview-0.28.0 → arrayview-0.28.1}/tests/test_rgb_pixel_art.py +0 -0
  204. {arrayview-0.28.0 → arrayview-0.28.1}/tests/test_torch.py +0 -0
  205. {arrayview-0.28.0 → arrayview-0.28.1}/tests/test_view_component_integration.py +0 -0
  206. {arrayview-0.28.0 → arrayview-0.28.1}/tests/test_view_component_unit.py +0 -0
  207. {arrayview-0.28.0 → arrayview-0.28.1}/tests/ui_audit.py +0 -0
  208. {arrayview-0.28.0 → arrayview-0.28.1}/tests/v_anim_frames/.gitkeep +0 -0
  209. {arrayview-0.28.0 → arrayview-0.28.1}/tests/visual_smoke.py +0 -0
  210. {arrayview-0.28.0 → arrayview-0.28.1}/vscode-extension/AGENTS.md +0 -0
  211. {arrayview-0.28.0 → arrayview-0.28.1}/vscode-extension/LICENSE +0 -0
  212. {arrayview-0.28.0 → arrayview-0.28.1}/vscode-extension/lifecycle_helpers.js +0 -0
  213. {arrayview-0.28.0 → arrayview-0.28.1}/vscode-extension/package.json +0 -0
  214. {arrayview-0.28.0 → arrayview-0.28.1}/vscode-extension/test_lifecycle_helpers.js +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arrayview
3
- Version: 0.28.0
3
+ Version: 0.28.1
4
4
  Summary: Fast multi-dimensional array viewer
5
5
  Project-URL: Home, https://github.com/oscarvanderheide/arrayview
6
6
  Project-URL: Source, https://github.com/oscarvanderheide/arrayview
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "arrayview"
7
- version = "0.28.0"
7
+ version = "0.28.1"
8
8
  description = "Fast multi-dimensional array viewer"
9
9
  readme = { file = "README.md", content-type = "text/markdown" }
10
10
  requires-python = ">=3.12"
@@ -702,6 +702,10 @@
702
702
  opacity: 1;
703
703
  transform: translateY(0);
704
704
  }
705
+ #info.dimbar-expanded .spatial-dim.dim-label {
706
+ color: var(--spatial-dim);
707
+ -webkit-text-fill-color: var(--spatial-dim);
708
+ }
705
709
  #info .active-dim.dim-label .dim-idx,
706
710
  #info .active-dim.dim-label .dim-slash,
707
711
  #info .active-dim.dim-label .dim-size {
@@ -15800,7 +15804,7 @@
15800
15804
  }
15801
15805
  _placeDimUnderline(marker, toRect, !_dimUnderlinePlaced);
15802
15806
  const infoVisible = _dimUnderlineInfoVisible(info);
15803
- const hidden = _crossfading || !_dimUnderlineStartupReady || !infoVisible || !info.classList.contains('dimbar-expanded');
15807
+ const hidden = true;
15804
15808
  marker.style.opacity = hidden ? '0' : '';
15805
15809
  if (!infoVisible) _dimUnderlineTrackUntil = Math.max(_dimUnderlineTrackUntil, performance.now() + 180);
15806
15810
  _dimUnderlinePlaced = true;
@@ -15881,7 +15885,7 @@
15881
15885
  if (_isQmriControlDim(i)) return '';
15882
15886
  const active = (i === activeDim);
15883
15887
  const playing = (playingDim >= 0 && i === playingDim);
15884
- const dimCls = playing ? 'playing-dim' : 'active-dim';
15888
+ const dimCls = playing ? 'playing-dim active-dim' : 'active-dim';
15885
15889
  const d = `data-dim="${i}"`;
15886
15890
  if (detachedDimMode && i === detachedDim) {
15887
15891
  const cls = (active || playing) ? `${dimCls} dim-label` : 'dim-label';
@@ -17506,7 +17510,8 @@
17506
17510
  function stopPlay() {
17507
17511
  if (_playRafId) { cancelAnimationFrame(_playRafId); _playRafId = null; }
17508
17512
  if (playInterval) { clearTimeout(playInterval); playInterval = null; }
17509
- isPlaying = false; playingVfieldT = false; playingDim = -1; setStatus('');
17513
+ isPlaying = false; playingVfieldT = false; playingDim = -1;
17514
+ setStatus('');
17510
17515
  renderInfo();
17511
17516
  }
17512
17517
 
@@ -17541,7 +17546,6 @@
17541
17546
  function togglePlay() {
17542
17547
  if (isPlaying) { stopPlay(); return; }
17543
17548
  isPlaying = true;
17544
- setStatus(`▶ playing (Space to stop · < / > fps: ${playFps})`);
17545
17549
  if (activeDim === VFIELD_T_DIM) {
17546
17550
  playingVfieldT = true;
17547
17551
  playingDim = -1; // vfield-T playback uses vfieldT, not indices[]
@@ -17549,6 +17553,10 @@
17549
17553
  playNextVfieldT();
17550
17554
  } else {
17551
17555
  playingDim = current_slice_dim;
17556
+ const sz = shape[playingDim];
17557
+ playFps = Math.max(3, Math.min(30, Math.round(Math.log2(Math.max(1, sz)) * 6)));
17558
+ setStatus(`▶ playing (Space to stop · < / > fps: ${playFps})`);
17559
+ playLastFrameTime = performance.now();
17552
17560
  playNext();
17553
17561
  }
17554
17562
  }
@@ -21577,11 +21585,19 @@
21577
21585
  vfieldT = Math.min(vfieldNTimes - 1, vfieldT + 1);
21578
21586
  drawVectorOverlay(); renderInfo(); saveState();
21579
21587
  } else if (multiViewActive) {
21580
- flipDims[activeDim] = !flipDims[activeDim];
21581
- renderInfo();
21582
- _mvRenderAllWithRois();
21583
- _debouncedHoverPrefetch();
21584
- saveState();
21588
+ if (mvDims.includes(activeDim)) {
21589
+ flipDims[activeDim] = !flipDims[activeDim];
21590
+ renderInfo();
21591
+ _mvRenderAllWithRois();
21592
+ _debouncedHoverPrefetch();
21593
+ saveState();
21594
+ } else {
21595
+ lastDirection = 1;
21596
+ indices[activeDim] = Math.min(shape[activeDim] - 1, indices[activeDim] + 1);
21597
+ _pendingNavDim = activeDim;
21598
+ updateView();
21599
+ saveState();
21600
+ }
21585
21601
  } else if (activeDim === dim_x) {
21586
21602
  flip_x = !flip_x;
21587
21603
  if (lastImageData) canvas.getContext('2d').putImageData(applyFlips(lastImageData, lastImgW, lastImgH), 0, 0);
@@ -21609,11 +21625,19 @@
21609
21625
  vfieldT = Math.max(0, vfieldT - 1);
21610
21626
  drawVectorOverlay(); renderInfo(); saveState();
21611
21627
  } else if (multiViewActive) {
21612
- flipDims[activeDim] = !flipDims[activeDim];
21613
- renderInfo();
21614
- _mvRenderAllWithRois();
21615
- _debouncedHoverPrefetch();
21616
- saveState();
21628
+ if (mvDims.includes(activeDim)) {
21629
+ flipDims[activeDim] = !flipDims[activeDim];
21630
+ renderInfo();
21631
+ _mvRenderAllWithRois();
21632
+ _debouncedHoverPrefetch();
21633
+ saveState();
21634
+ } else {
21635
+ lastDirection = -1;
21636
+ indices[activeDim] = Math.max(0, indices[activeDim] - 1);
21637
+ _pendingNavDim = activeDim;
21638
+ updateView();
21639
+ saveState();
21640
+ }
21617
21641
  } else if (activeDim === dim_x) {
21618
21642
  flip_x = !flip_x;
21619
21643
  if (lastImageData) canvas.getContext('2d').putImageData(applyFlips(lastImageData, lastImgW, lastImgH), 0, 0);
@@ -198,7 +198,7 @@ wheels = [
198
198
 
199
199
  [[package]]
200
200
  name = "arrayview"
201
- version = "0.28.0"
201
+ version = "0.28.1"
202
202
  source = { editable = "." }
203
203
  dependencies = [
204
204
  { name = "fastapi" },
@@ -103,6 +103,11 @@ let lastHandledAt = 0;
103
103
  // Track open webview panels by URL so we can reveal instead of re-creating.
104
104
  const _openPanels = new Map(); // url -> vscode.WebviewPanel
105
105
 
106
+ // Pending placeholder tabs from resolveCustomEditor, keyed by filePath.
107
+ // When a signal file arrives, we navigate the placeholder instead of
108
+ // creating a second panel, avoiding a visible flicker.
109
+ const _pendingPlaceholders = new Map(); // filePath -> { panel, basename }
110
+
106
111
  function log(message) {
107
112
  const prefix = logWindowId ? `[${logWindowId.slice(0, 8)}] ` : '';
108
113
  const line = `[${new Date().toISOString()}] ${prefix}${message}\n`;
@@ -157,6 +162,7 @@ function launchArrayViewFile(filePath, title) {
157
162
  cwd: vscode.workspace.workspaceFolders?.[0]?.uri.fsPath || path.dirname(filePath),
158
163
  detached: true,
159
164
  stdio: ['ignore', 'pipe', 'pipe'],
165
+ env: { ...process.env, TERM_PROGRAM: 'vscode' },
160
166
  });
161
167
  } catch (error) {
162
168
  log(`PYTHON: launch failed for ${candidate.command}: ${error.message}`);
@@ -264,16 +270,30 @@ class ArrayViewEditorProvider {
264
270
  const filePath = document.uri.fsPath;
265
271
  const title = path.basename(filePath);
266
272
  log(`CUSTOM-EDITOR: resolveCustomEditor for ${filePath}`);
267
- // This custom editor is only a VS Code file-association handoff. It
268
- // starts ArrayView normally, then the signal-file path opens the
269
- // URL-backed HTTP/WebSocket viewer and this placeholder closes.
273
+ // This custom editor is a handoff placeholder. We keep it open and
274
+ // navigate its webview when the signal-file URL arrives — no flicker.
270
275
  webviewPanel.webview.options = { enableScripts: true };
271
276
  webviewPanel.webview.html = `<html><body style="background:#1e1e1e;color:#ccc;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;font-family:ui-monospace,monospace">
272
277
  <div>Opening ${title} in ArrayView...</div></body></html>`;
273
278
  try {
274
279
  await launchArrayViewFile(filePath, title);
275
280
  log(`CUSTOM-EDITOR: launched network viewer for ${filePath}`);
276
- await closeActiveArrayViewCustomEditor(document.uri, 'handoff');
281
+ _pendingPlaceholders.set(filePath, { panel: webviewPanel, basename: title });
282
+ webviewPanel.onDidDispose(() => {
283
+ _pendingPlaceholders.delete(filePath);
284
+ log(`CUSTOM-EDITOR: placeholder disposed for ${title}`);
285
+ });
286
+ // Safety timeout: if no signal arrives within 30 s, show an error.
287
+ setTimeout(() => {
288
+ if (_pendingPlaceholders.has(filePath)) {
289
+ _pendingPlaceholders.delete(filePath);
290
+ try {
291
+ webviewPanel.webview.html = `<html><body style="color:#c00;padding:2em;font-family:monospace;background:#1e1e1e">
292
+ <h2>ArrayView failed to start</h2>
293
+ <p>The Python server did not respond. Check ~/.arrayview/extension.log for details.</p></body></html>`;
294
+ } catch (_) { /* panel already disposed */ }
295
+ }
296
+ }, 30000);
277
297
  } catch (e) {
278
298
  log(`CUSTOM-EDITOR: error: ${e.message}\n${e.stack || ''}`);
279
299
  webviewPanel.webview.html = `<html><body style="color:#c00;padding:2em;font-family:monospace">
@@ -555,44 +575,10 @@ async function tryOpenSignalFile() {
555
575
  // Open or reveal a VS Code WebviewPanel for the given server URL.
556
576
  // The panel is only a URL wrapper: ArrayView data and controls still flow
557
577
  // through the FastAPI/WebSocket backend, never direct Python/webview IPC.
558
- async function openInWebviewPanel(url, title, floating = false) {
559
- const label = title || 'ArrayView';
560
-
561
- // Reveal existing panel for this URL if still open.
562
- const existing = _openPanels.get(url);
563
- if (existing) {
564
- try {
565
- existing.reveal(undefined, false);
566
- log(`PANEL: revealed existing panel for ${url}`);
567
- return;
568
- } catch (_) {
569
- _openPanels.delete(url);
570
- }
571
- }
572
-
573
- const viewColumn = vscode.window.activeTextEditor
574
- ? vscode.ViewColumn.Beside
575
- : vscode.ViewColumn.Active;
576
-
577
- const panel = vscode.window.createWebviewPanel(
578
- 'arrayview.preview',
579
- label,
580
- { viewColumn, preserveFocus: false },
581
- {
582
- enableScripts: true,
583
- enableForms: true,
584
- retainContextWhenHidden: true,
585
- }
586
- );
587
-
588
- // Use a nonce so the CSP allows exactly our inline script and nothing else.
589
- // The iframe src is set via JS (not as an HTML attribute) to avoid any
590
- // attribute-encoding issues.
578
+ function _viewerPanelHtml(url) {
591
579
  const nonce = crypto.randomBytes(16).toString('hex');
592
- const jsonUrl = JSON.stringify(url); // safe JS string literal embedding
593
- const pingUrl = pingUrlFromViewerUrl(url);
594
-
595
- panel.webview.html = `<!DOCTYPE html>
580
+ const jsonUrl = JSON.stringify(url);
581
+ return `<!DOCTYPE html>
596
582
  <html>
597
583
  <head>
598
584
  <meta http-equiv="Content-Security-Policy"
@@ -657,6 +643,39 @@ frame.src = arrayviewUrl;
657
643
  </script>
658
644
  </body>
659
645
  </html>`;
646
+ }
647
+
648
+ async function openInWebviewPanel(url, title, floating = false) {
649
+ const label = title || 'ArrayView';
650
+
651
+ // Reveal existing panel for this URL if still open.
652
+ const existing = _openPanels.get(url);
653
+ if (existing) {
654
+ try {
655
+ existing.reveal(undefined, false);
656
+ log(`PANEL: revealed existing panel for ${url}`);
657
+ return;
658
+ } catch (_) {
659
+ _openPanels.delete(url);
660
+ }
661
+ }
662
+
663
+ const viewColumn = vscode.window.activeTextEditor
664
+ ? vscode.ViewColumn.Beside
665
+ : vscode.ViewColumn.Active;
666
+
667
+ const panel = vscode.window.createWebviewPanel(
668
+ 'arrayview.preview',
669
+ label,
670
+ { viewColumn, preserveFocus: false },
671
+ {
672
+ enableScripts: true,
673
+ enableForms: true,
674
+ retainContextWhenHidden: true,
675
+ }
676
+ );
677
+
678
+ panel.webview.html = _viewerPanelHtml(url);
660
679
 
661
680
  _openPanels.set(url, panel);
662
681
  let panelDisposed = false;
@@ -920,6 +939,26 @@ async function _processSignalDataBody(data) {
920
939
  openUrl = remoteUrl;
921
940
  }
922
941
 
942
+ // Check for a pending placeholder (resolveCustomEditor handoff).
943
+ // If one matches this signal, navigate the existing placeholder tab
944
+ // instead of creating a second panel — eliminates the flicker.
945
+ let handedOff = false;
946
+ for (const [filePath, placeholder] of _pendingPlaceholders) {
947
+ if (data.title && data.title.includes(placeholder.basename)) {
948
+ _pendingPlaceholders.delete(filePath);
949
+ try {
950
+ placeholder.panel.webview.html = _viewerPanelHtml(openUrl);
951
+ placeholder.panel.title = data.title || placeholder.title;
952
+ log(`HANDOFF: navigated placeholder for ${placeholder.basename} to ${openUrl}`);
953
+ handedOff = true;
954
+ } catch (_) {
955
+ log(`HANDOFF: placeholder panel disposed for ${placeholder.basename}`);
956
+ }
957
+ break;
958
+ }
959
+ }
960
+ if (handedOff) return;
961
+
923
962
  log(`openInWebviewPanel(${openUrl})`);
924
963
  await openInWebviewPanel(openUrl, data.title, !!data.floating);
925
964
  log('openInWebviewPanel done');
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes