anywidget-vector 0.3.1__tar.gz → 0.3.2__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 (52) hide show
  1. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/CHANGELOG.md +18 -2
  2. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/PKG-INFO +1 -1
  3. anywidget_vector-0.3.2/assets/demo.png +0 -0
  4. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/examples/fashion-mnist-parallel-coords-6d.py +8 -11
  5. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/pyproject.toml +2 -1
  6. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/ui/__init__.py +26 -14
  7. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/ui/styles.css +1 -4
  8. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/uv.lock +1 -1
  9. anywidget_vector-0.3.1/assets/demo.png +0 -0
  10. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/.github/workflows/ci.yml +0 -0
  11. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/.github/workflows/pypi.yml +0 -0
  12. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/.gitignore +0 -0
  13. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/.python-version +0 -0
  14. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/LICENSE +0 -0
  15. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/README.md +0 -0
  16. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/examples/demo.py +0 -0
  17. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/examples/test_add_numpy.py +0 -0
  18. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/examples/test_projection.py +0 -0
  19. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/__init__.py +0 -0
  20. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/backends/__init__.py +0 -0
  21. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/backends/chroma/__init__.py +0 -0
  22. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/backends/chroma/client.py +0 -0
  23. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/backends/chroma/converter.py +0 -0
  24. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/backends/grafeo/__init__.py +0 -0
  25. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/backends/grafeo/browser.js +0 -0
  26. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/backends/grafeo/client.py +0 -0
  27. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/backends/grafeo/converter.py +0 -0
  28. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/backends/grafeo/embed.js +0 -0
  29. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/backends/lancedb/__init__.py +0 -0
  30. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/backends/lancedb/client.py +0 -0
  31. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/backends/lancedb/converter.py +0 -0
  32. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/backends/pinecone/__init__.py +0 -0
  33. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/backends/pinecone/client.js +0 -0
  34. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/backends/pinecone/converter.py +0 -0
  35. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/backends/qdrant/__init__.py +0 -0
  36. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/backends/qdrant/client.js +0 -0
  37. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/backends/qdrant/converter.py +0 -0
  38. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/backends/weaviate/__init__.py +0 -0
  39. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/backends/weaviate/client.js +0 -0
  40. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/backends/weaviate/converter.py +0 -0
  41. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/demo.py +0 -0
  42. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/py.typed +0 -0
  43. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/static/icons.js +0 -0
  44. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/ui/canvas.js +0 -0
  45. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/ui/constants.js +0 -0
  46. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/ui/properties.js +0 -0
  47. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/ui/settings.js +0 -0
  48. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/ui/sidebar.js +0 -0
  49. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/ui/toolbar.js +0 -0
  50. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/src/anywidget_vector/widget.py +0 -0
  51. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/tests/__init__.py +0 -0
  52. {anywidget_vector-0.3.1 → anywidget_vector-0.3.2}/tests/test_widget.py +0 -0
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.2 (2026-03-16)
4
+
5
+ ### Improvements
6
+
7
+ - **Marimo reactivity fix**: Removed camera and hover JS-to-Python sync to prevent continuous cell re-execution. Only user-initiated actions (selection, mode change) now trigger marimo reactive updates
8
+ - **Custom scroll zoom**: Replaced OrbitControls zoom with a custom wheel handler for much finer granularity
9
+ - **Selection hides completely**: Lasso/box selection now fully hides non-selected points (scale-to-zero for instanced meshes) instead of dimming
10
+ - **Auto zoom-to-fit on selection**: Camera automatically frames the selected points after lasso/box selection
11
+ - **Search filter modes**: Typing in the search bar dims non-matching points as a preview, pressing Run/Enter hides them completely
12
+ - **Hover via callback**: Properties panel hover now uses a direct JS callback instead of model sync, eliminating unnecessary Python round-trips
13
+
14
+ ### Bug Fixes
15
+
16
+ - **setSelection scoping**: Moved `setSelection` helper to `createCanvas` scope so lasso/box/click handlers can access it
17
+ - **Camera debounce variable**: Fixed `_cameraDebounce` lexical declaration error by moving it to the correct scope
18
+
3
19
  ## 0.3.1 (2026-03-16)
4
20
 
5
21
  ### New Features
@@ -24,7 +40,7 @@
24
40
 
25
41
  ### New Features
26
42
 
27
- - **Distance metrics sidebar**: Distance section with metric selector (euclidean, cosine, manhattan, dot product), configurable k-neighbors (0-50), and live nearest-neighbor display for the selected point
43
+ - **Distance metrics sidebar**: Distance section with metric selector (euclidean, cosine, manhattan, dot product), configurable k-neighbors (0-50) and live nearest-neighbor display for the selected point
28
44
  - **Dimension mapping display**: Sidebar now shows active visual mapping fields: color field, size range, shape field and unique shape count
29
45
 
30
46
  ### Improvements
@@ -35,7 +51,7 @@
35
51
 
36
52
  ### New Features
37
53
 
38
- - **6D parallel coordinates example**: Fashion-MNIST demo with PCA across 6+ dimensions, interactive axis mapping, and shape mapping to categorical labels
54
+ - **6D parallel coordinates example**: Fashion-MNIST demo with PCA across 6+ dimensions, interactive axis mapping and shape mapping to categorical labels
39
55
 
40
56
  ## 0.2.7 (2026-03-15)
41
57
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: anywidget-vector
3
- Version: 0.3.1
3
+ Version: 0.3.2
4
4
  Summary: Interactive 3D vector visualization with query UI for vector databases
5
5
  Project-URL: Homepage, https://grafeo.dev/
6
6
  Project-URL: Repository, https://github.com/GrafeoDB/anywidget-vector
Binary file
@@ -34,6 +34,7 @@ def _():
34
34
  from wigglystuff import ParallelCoordinates
35
35
 
36
36
  from anywidget_vector import VectorSpace
37
+
37
38
  return PCA, ParallelCoordinates, VectorSpace, fetch_openml, mo, np, pl, plt
38
39
 
39
40
 
@@ -244,10 +245,12 @@ def _(LABEL_COLORS, ParallelCoordinates, df, mo, vs):
244
245
  _indices = sorted(int(sid.split("_")[1]) for sid in _selected)
245
246
  _filtered_df = df[_indices]
246
247
  _par = ParallelCoordinates(_filtered_df, color_by="label", color_map=LABEL_COLORS)
247
- mo.vstack([
248
- mo.md(f"**{len(_indices)}** points selected in 3D view"),
249
- mo.ui.anywidget(_par),
250
- ])
248
+ mo.vstack(
249
+ [
250
+ mo.md(f"**{len(_indices)}** points selected in 3D view"),
251
+ mo.ui.anywidget(_par),
252
+ ]
253
+ )
251
254
  else:
252
255
  mo.md("*Lasso or box-select points in the 3D view to filter*")
253
256
  return
@@ -258,13 +261,7 @@ def _(LABEL_COLORS, idx, images, label_names, labels, np, plt, vs, widget):
258
261
  _selected_ids = set(vs.widget.selected_points or [])
259
262
  _filtered = widget.widget.filtered_indices
260
263
 
261
- if _selected_ids:
262
- _show = [
263
- _i for _i in range(len(idx))
264
- if f"p_{_i}" in _selected_ids
265
- ][:10]
266
- else:
267
- _show = list(_filtered[:10])
264
+ _show = [_i for _i in range(len(idx)) if f"p_{_i}" in _selected_ids][:10] if _selected_ids else list(_filtered[:10])
268
265
 
269
266
  _sample_idx = np.array(_show) if len(_show) > 0 else np.array([0])
270
267
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "anywidget-vector"
3
- version = "0.3.1"
3
+ version = "0.3.2"
4
4
  description = "Interactive 3D vector visualization with query UI for vector databases"
5
5
  readme = "README.md"
6
6
  license = "Apache-2.0"
@@ -73,6 +73,7 @@ select = ["E", "F", "W", "I", "UP", "B", "SIM", "RUF"]
73
73
 
74
74
  [tool.ruff.lint.per-file-ignores]
75
75
  "src/anywidget_vector/widget.py" = ["E501"] # Long lines in embedded JS
76
+ "src/anywidget_vector/ui/__init__.py" = ["E501"] # Long lines in embedded JS
76
77
  "examples/**" = ["B007", "B018"] # Marimo cells use bare expressions for output
77
78
 
78
79
  [tool.ty.environment]
@@ -134,11 +134,13 @@ function render({{ model, el }}) {{
134
134
 
135
135
  el.appendChild(wrapper);
136
136
 
137
- // Auto-detect host theme (marimo uses Tailwind class="dark" on <html>)
137
+ // Auto-detect host theme (Tailwind dark/dark-theme class, data-theme, or prefers-color-scheme)
138
138
  function detectHostDark() {{
139
139
  const html = document.documentElement;
140
- if (html.classList.contains("dark")) return true;
140
+ if (html.classList.contains("dark") || html.classList.contains("dark-theme")) return true;
141
141
  if (html.dataset.theme === "dark") return true;
142
+ if (document.body?.classList.contains("dark") || document.body?.classList.contains("dark-theme")) return true;
143
+ if (document.body?.dataset.theme === "dark") return true;
142
144
  if (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) return true;
143
145
  return false;
144
146
  }}
@@ -149,27 +151,37 @@ function render({{ model, el }}) {{
149
151
  model.save_changes();
150
152
  }}
151
153
 
152
- // Detect if we're inside a themed host (marimo, jupyter, etc.)
153
- const hasHostTheme = !!el.getRootNode()?.host?.tagName?.startsWith("MARIMO-");
154
- if (hasHostTheme) {{
155
- wrapper.classList.add("avs-auto-theme");
156
- model.set("dark_mode", detectHostDark());
157
- applyTheme(detectHostDark());
158
- // Watch host for live theme changes
159
- const themeObserver = new MutationObserver(() => {{
154
+ // Always auto-detect and observe theme changes
155
+ let autoTheme = true;
156
+ model.set("dark_mode", detectHostDark());
157
+ applyTheme(detectHostDark());
158
+
159
+ const themeObserver = new MutationObserver(() => {{
160
+ if (!autoTheme) return;
161
+ const dark = detectHostDark();
162
+ if (model.get("dark_mode") !== dark) {{
163
+ model.set("dark_mode", dark);
164
+ applyTheme(dark);
165
+ }}
166
+ }});
167
+ themeObserver.observe(document.documentElement, {{ attributes: true, attributeFilter: ["class", "data-theme", "style"] }});
168
+ if (document.body) {{
169
+ themeObserver.observe(document.body, {{ attributes: true, attributeFilter: ["class", "data-theme", "style"] }});
170
+ }}
171
+ if (window.matchMedia) {{
172
+ window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", () => {{
173
+ if (!autoTheme) return;
160
174
  const dark = detectHostDark();
161
175
  if (model.get("dark_mode") !== dark) {{
162
176
  model.set("dark_mode", dark);
163
177
  applyTheme(dark);
164
178
  }}
165
179
  }});
166
- themeObserver.observe(document.documentElement, {{ attributes: true, attributeFilter: ["class", "data-theme"] }});
167
- }} else {{
168
- applyTheme(model.get("dark_mode"));
169
180
  }}
170
181
 
171
- // Manual toggle from settings panel still works
182
+ // Manual toggle from settings panel disables auto-theme
172
183
  model.on("change:dark_mode", () => {{
184
+ autoTheme = false;
173
185
  applyTheme(model.get("dark_mode"));
174
186
  }});
175
187
 
@@ -602,7 +602,4 @@
602
602
  color: var(--avs-text);
603
603
  }
604
604
 
605
- /* Hide dark mode toggle when host provides theme */
606
- .avs-wrapper.avs-auto-theme .avs-theme-toggle {
607
- display: none;
608
- }
605
+ /* Dark mode toggle always visible — manual toggle disables auto-theme */
@@ -50,7 +50,7 @@ wheels = [
50
50
 
51
51
  [[package]]
52
52
  name = "anywidget-vector"
53
- version = "0.3.1"
53
+ version = "0.3.2"
54
54
  source = { editable = "." }
55
55
  dependencies = [
56
56
  { name = "anywidget" },
Binary file