anywidget-vector 0.1.0__py3-none-any.whl → 0.2.1__py3-none-any.whl

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 (34) hide show
  1. anywidget_vector/__init__.py +1 -1
  2. anywidget_vector/backends/__init__.py +103 -0
  3. anywidget_vector/backends/chroma/__init__.py +27 -0
  4. anywidget_vector/backends/chroma/client.py +60 -0
  5. anywidget_vector/backends/chroma/converter.py +86 -0
  6. anywidget_vector/backends/grafeo/__init__.py +20 -0
  7. anywidget_vector/backends/grafeo/client.py +33 -0
  8. anywidget_vector/backends/grafeo/converter.py +46 -0
  9. anywidget_vector/backends/lancedb/__init__.py +22 -0
  10. anywidget_vector/backends/lancedb/client.py +56 -0
  11. anywidget_vector/backends/lancedb/converter.py +71 -0
  12. anywidget_vector/backends/pinecone/__init__.py +21 -0
  13. anywidget_vector/backends/pinecone/client.js +45 -0
  14. anywidget_vector/backends/pinecone/converter.py +62 -0
  15. anywidget_vector/backends/qdrant/__init__.py +26 -0
  16. anywidget_vector/backends/qdrant/client.js +61 -0
  17. anywidget_vector/backends/qdrant/converter.py +83 -0
  18. anywidget_vector/backends/weaviate/__init__.py +33 -0
  19. anywidget_vector/backends/weaviate/client.js +50 -0
  20. anywidget_vector/backends/weaviate/converter.py +81 -0
  21. anywidget_vector/static/icons.js +14 -0
  22. anywidget_vector/traitlets.py +84 -0
  23. anywidget_vector/ui/__init__.py +206 -0
  24. anywidget_vector/ui/canvas.js +521 -0
  25. anywidget_vector/ui/constants.js +64 -0
  26. anywidget_vector/ui/properties.js +158 -0
  27. anywidget_vector/ui/settings.js +265 -0
  28. anywidget_vector/ui/styles.css +348 -0
  29. anywidget_vector/ui/toolbar.js +117 -0
  30. anywidget_vector/widget.py +187 -850
  31. {anywidget_vector-0.1.0.dist-info → anywidget_vector-0.2.1.dist-info}/METADATA +70 -3
  32. anywidget_vector-0.2.1.dist-info/RECORD +34 -0
  33. anywidget_vector-0.1.0.dist-info/RECORD +0 -6
  34. {anywidget_vector-0.1.0.dist-info → anywidget_vector-0.2.1.dist-info}/WHEEL +0 -0
@@ -0,0 +1,348 @@
1
+ /* === CSS Variables === */
2
+ .avs-wrapper {
3
+ --avs-bg: #1a1a2e;
4
+ --avs-surface: #252542;
5
+ --avs-border: #3a3a5c;
6
+ --avs-text: #e0e0e0;
7
+ --avs-text-muted: #888;
8
+ --avs-primary: #6366f1;
9
+ --avs-primary-hover: #818cf8;
10
+ --avs-success: #10b981;
11
+ --avs-warning: #f59e0b;
12
+ --avs-error: #ef4444;
13
+ --avs-radius: 6px;
14
+
15
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
16
+ background: var(--avs-bg);
17
+ border-radius: 8px;
18
+ overflow: hidden;
19
+ position: relative;
20
+ display: flex;
21
+ flex-direction: column;
22
+ }
23
+
24
+ /* === Main Layout === */
25
+ .avs-main {
26
+ display: flex;
27
+ flex: 1;
28
+ min-height: 0;
29
+ position: relative;
30
+ }
31
+
32
+ .avs-canvas-container {
33
+ flex: 1;
34
+ position: relative;
35
+ min-width: 0;
36
+ }
37
+
38
+ .avs-canvas-container canvas {
39
+ display: block;
40
+ }
41
+
42
+ /* === Toolbar === */
43
+ .avs-toolbar {
44
+ display: flex;
45
+ align-items: center;
46
+ gap: 8px;
47
+ padding: 8px 12px;
48
+ background: var(--avs-surface);
49
+ border-bottom: 1px solid var(--avs-border);
50
+ flex-shrink: 0;
51
+ }
52
+
53
+ .avs-backend-label {
54
+ padding: 6px 10px;
55
+ background: var(--avs-primary);
56
+ color: white;
57
+ border-radius: var(--avs-radius);
58
+ font-size: 12px;
59
+ font-weight: 600;
60
+ flex-shrink: 0;
61
+ }
62
+
63
+ .avs-query-input {
64
+ flex: 1;
65
+ min-width: 200px;
66
+ padding: 8px 12px;
67
+ background: var(--avs-bg);
68
+ border: 1px solid var(--avs-border);
69
+ border-radius: var(--avs-radius);
70
+ color: var(--avs-text);
71
+ font-size: 13px;
72
+ font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
73
+ }
74
+
75
+ .avs-query-input:focus {
76
+ outline: none;
77
+ border-color: var(--avs-primary);
78
+ box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.2);
79
+ }
80
+
81
+ .avs-query-input::placeholder {
82
+ color: var(--avs-text-muted);
83
+ }
84
+
85
+ /* === Buttons === */
86
+ .avs-btn {
87
+ display: flex;
88
+ align-items: center;
89
+ justify-content: center;
90
+ padding: 8px;
91
+ background: var(--avs-surface);
92
+ border: 1px solid var(--avs-border);
93
+ border-radius: var(--avs-radius);
94
+ color: var(--avs-text);
95
+ cursor: pointer;
96
+ transition: all 0.15s ease;
97
+ }
98
+
99
+ .avs-btn:hover {
100
+ background: var(--avs-border);
101
+ }
102
+
103
+ .avs-btn:disabled {
104
+ opacity: 0.5;
105
+ cursor: not-allowed;
106
+ }
107
+
108
+ .avs-btn svg {
109
+ width: 16px;
110
+ height: 16px;
111
+ }
112
+
113
+ .avs-btn-primary {
114
+ background: var(--avs-primary);
115
+ border-color: var(--avs-primary);
116
+ color: white;
117
+ }
118
+
119
+ .avs-btn-primary:hover {
120
+ background: var(--avs-primary-hover);
121
+ border-color: var(--avs-primary-hover);
122
+ }
123
+
124
+ .avs-btn-icon {
125
+ padding: 4px;
126
+ background: transparent;
127
+ border: none;
128
+ }
129
+
130
+ .avs-loading svg {
131
+ animation: avs-spin 1s linear infinite;
132
+ }
133
+
134
+ @keyframes avs-spin {
135
+ from { transform: rotate(0deg); }
136
+ to { transform: rotate(360deg); }
137
+ }
138
+
139
+ /* === Select === */
140
+ .avs-select {
141
+ padding: 8px 12px;
142
+ background: var(--avs-bg);
143
+ border: 1px solid var(--avs-border);
144
+ border-radius: var(--avs-radius);
145
+ color: var(--avs-text);
146
+ font-size: 13px;
147
+ cursor: pointer;
148
+ }
149
+
150
+ .avs-select:focus {
151
+ outline: none;
152
+ border-color: var(--avs-primary);
153
+ }
154
+
155
+ /* === Status Dot === */
156
+ .avs-settings-btn {
157
+ position: relative;
158
+ }
159
+
160
+ .avs-status-dot {
161
+ position: absolute;
162
+ top: 2px;
163
+ right: 2px;
164
+ width: 8px;
165
+ height: 8px;
166
+ border-radius: 50%;
167
+ background: var(--avs-text-muted);
168
+ }
169
+
170
+ .avs-status-connected {
171
+ background: var(--avs-success);
172
+ }
173
+
174
+ .avs-status-connecting {
175
+ background: var(--avs-warning);
176
+ animation: avs-pulse 1s ease-in-out infinite;
177
+ }
178
+
179
+ .avs-status-error {
180
+ background: var(--avs-error);
181
+ }
182
+
183
+ .avs-status-disconnected {
184
+ background: var(--avs-text-muted);
185
+ }
186
+
187
+ @keyframes avs-pulse {
188
+ 0%, 100% { opacity: 1; }
189
+ 50% { opacity: 0.4; }
190
+ }
191
+
192
+ /* === Side Panels (shared) === */
193
+ .avs-panel {
194
+ width: 0;
195
+ background: var(--avs-surface);
196
+ border-color: var(--avs-border);
197
+ overflow: hidden;
198
+ transition: width 0.2s ease;
199
+ flex-shrink: 0;
200
+ }
201
+
202
+ .avs-panel.avs-open {
203
+ width: 280px;
204
+ }
205
+
206
+ .avs-panel-left {
207
+ border-right: 1px solid var(--avs-border);
208
+ }
209
+
210
+ .avs-panel-right {
211
+ border-left: 1px solid var(--avs-border);
212
+ }
213
+
214
+ .avs-panel-inner {
215
+ width: 280px;
216
+ height: 100%;
217
+ overflow-y: auto;
218
+ }
219
+
220
+ .avs-panel-header {
221
+ display: flex;
222
+ align-items: center;
223
+ justify-content: space-between;
224
+ padding: 12px 16px;
225
+ border-bottom: 1px solid var(--avs-border);
226
+ font-weight: 600;
227
+ color: var(--avs-text);
228
+ }
229
+
230
+ .avs-section-header {
231
+ padding: 12px 16px 8px;
232
+ font-size: 11px;
233
+ font-weight: 600;
234
+ text-transform: uppercase;
235
+ letter-spacing: 0.5px;
236
+ color: var(--avs-text-muted);
237
+ border-top: 1px solid var(--avs-border);
238
+ margin-top: 8px;
239
+ }
240
+
241
+ /* === Form Elements === */
242
+ .avs-form-group {
243
+ padding: 8px 16px;
244
+ }
245
+
246
+ .avs-label {
247
+ display: block;
248
+ font-size: 12px;
249
+ color: var(--avs-text-muted);
250
+ margin-bottom: 4px;
251
+ }
252
+
253
+ .avs-input {
254
+ width: 100%;
255
+ padding: 8px 10px;
256
+ background: var(--avs-bg);
257
+ border: 1px solid var(--avs-border);
258
+ border-radius: var(--avs-radius);
259
+ color: var(--avs-text);
260
+ font-size: 13px;
261
+ box-sizing: border-box;
262
+ }
263
+
264
+ .avs-input:focus {
265
+ outline: none;
266
+ border-color: var(--avs-primary);
267
+ }
268
+
269
+ .avs-note {
270
+ padding: 12px 16px;
271
+ font-size: 12px;
272
+ color: var(--avs-text-muted);
273
+ font-style: italic;
274
+ }
275
+
276
+ .avs-error {
277
+ margin: 8px 16px;
278
+ padding: 8px 12px;
279
+ background: rgba(239, 68, 68, 0.1);
280
+ border: 1px solid var(--avs-error);
281
+ border-radius: var(--avs-radius);
282
+ color: var(--avs-error);
283
+ font-size: 12px;
284
+ }
285
+
286
+ .avs-connection-fields {
287
+ border-top: 1px solid var(--avs-border);
288
+ margin-top: 8px;
289
+ padding-top: 8px;
290
+ }
291
+
292
+ /* === Properties Panel === */
293
+ .avs-properties-empty {
294
+ padding: 24px 16px;
295
+ text-align: center;
296
+ color: var(--avs-text-muted);
297
+ font-size: 13px;
298
+ }
299
+
300
+ .avs-property-row {
301
+ display: flex;
302
+ justify-content: space-between;
303
+ padding: 6px 16px;
304
+ font-size: 13px;
305
+ }
306
+
307
+ .avs-property-key {
308
+ color: var(--avs-text-muted);
309
+ }
310
+
311
+ .avs-property-value {
312
+ color: var(--avs-text);
313
+ font-family: ui-monospace, SFMono-Regular, monospace;
314
+ max-width: 150px;
315
+ overflow: hidden;
316
+ text-overflow: ellipsis;
317
+ white-space: nowrap;
318
+ }
319
+
320
+ /* === Tooltip === */
321
+ .avs-tooltip {
322
+ position: absolute;
323
+ display: none;
324
+ background: rgba(0, 0, 0, 0.85);
325
+ color: white;
326
+ padding: 8px 12px;
327
+ border-radius: 4px;
328
+ font-size: 12px;
329
+ pointer-events: none;
330
+ z-index: 1000;
331
+ max-width: 250px;
332
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
333
+ }
334
+
335
+ .avs-tooltip-label {
336
+ font-weight: 600;
337
+ margin-bottom: 4px;
338
+ }
339
+
340
+ .avs-tooltip-row {
341
+ display: flex;
342
+ justify-content: space-between;
343
+ gap: 12px;
344
+ }
345
+
346
+ .avs-tooltip-key {
347
+ color: #999;
348
+ }
@@ -0,0 +1,117 @@
1
+ // Toolbar component for VectorSpace widget
2
+ import { ICONS } from "../static/icons.js";
3
+ import { BACKENDS } from "./constants.js";
4
+
5
+ export function createToolbar(model, callbacks) {
6
+ const toolbar = document.createElement("div");
7
+ toolbar.className = "avs-toolbar";
8
+
9
+ // Backend indicator (shows current backend name)
10
+ const backendLabel = document.createElement("span");
11
+ backendLabel.className = "avs-backend-label";
12
+ backendLabel.textContent = BACKENDS[model.get("backend")]?.name || "Qdrant";
13
+ toolbar.appendChild(backendLabel);
14
+
15
+ // Query input (native format for selected backend)
16
+ const queryInput = document.createElement("input");
17
+ queryInput.type = "text";
18
+ queryInput.className = "avs-query-input";
19
+ queryInput.placeholder = getPlaceholder(model.get("backend"));
20
+ queryInput.value = model.get("query_input") || "";
21
+ queryInput.title = getHelp(model.get("backend"));
22
+ queryInput.addEventListener("input", () => {
23
+ model.set("query_input", queryInput.value);
24
+ model.save_changes();
25
+ });
26
+ queryInput.addEventListener("keydown", (e) => {
27
+ if (e.key === "Enter" && !e.shiftKey) {
28
+ e.preventDefault();
29
+ callbacks.onRunQuery?.();
30
+ }
31
+ });
32
+ toolbar.appendChild(queryInput);
33
+
34
+ // Run button
35
+ const runBtn = document.createElement("button");
36
+ runBtn.className = "avs-btn avs-btn-primary";
37
+ runBtn.innerHTML = ICONS.play;
38
+ runBtn.title = "Run Query";
39
+ runBtn.addEventListener("click", () => callbacks.onRunQuery?.());
40
+ toolbar.appendChild(runBtn);
41
+
42
+ // Settings button with status dot
43
+ const settingsBtn = document.createElement("button");
44
+ settingsBtn.className = "avs-btn avs-settings-btn";
45
+ const statusDot = document.createElement("span");
46
+ statusDot.className = "avs-status-dot";
47
+ updateStatusDot(statusDot, model.get("connection_status") || "disconnected");
48
+ settingsBtn.innerHTML = ICONS.settings;
49
+ settingsBtn.appendChild(statusDot);
50
+ settingsBtn.title = "Settings";
51
+ settingsBtn.addEventListener("click", () => callbacks.onToggleSettings?.());
52
+ toolbar.appendChild(settingsBtn);
53
+
54
+ // Properties toggle button
55
+ const propsBtn = document.createElement("button");
56
+ propsBtn.className = "avs-btn";
57
+ propsBtn.innerHTML = ICONS.cube;
58
+ propsBtn.title = "Properties";
59
+ propsBtn.addEventListener("click", () => callbacks.onToggleProperties?.());
60
+ toolbar.appendChild(propsBtn);
61
+
62
+ // Model change listeners
63
+ model.on("change:connection_status", () => {
64
+ updateStatusDot(statusDot, model.get("connection_status"));
65
+ });
66
+
67
+ model.on("change:backend", () => {
68
+ const backend = model.get("backend");
69
+ backendLabel.textContent = BACKENDS[backend]?.name || backend;
70
+ queryInput.placeholder = getPlaceholder(backend);
71
+ queryInput.title = getHelp(backend);
72
+ });
73
+
74
+ return {
75
+ element: toolbar,
76
+ runBtn,
77
+ setLoading: (loading) => {
78
+ if (loading) {
79
+ runBtn.innerHTML = ICONS.loader;
80
+ runBtn.classList.add("avs-loading");
81
+ runBtn.disabled = true;
82
+ } else {
83
+ runBtn.innerHTML = ICONS.play;
84
+ runBtn.classList.remove("avs-loading");
85
+ runBtn.disabled = false;
86
+ }
87
+ },
88
+ };
89
+ }
90
+
91
+ function updateStatusDot(dot, status) {
92
+ dot.className = `avs-status-dot avs-status-${status}`;
93
+ }
94
+
95
+ function getPlaceholder(backend) {
96
+ const placeholders = {
97
+ qdrant: '{"vector": [...], "limit": 10}',
98
+ pinecone: '{"vector": [...], "topK": 10}',
99
+ weaviate: '{ Get { Class(limit: 10) { ... } } }',
100
+ chroma: '{"query_embeddings": [...], "n_results": 10}',
101
+ lancedb: 'category = "tech" AND year > 2020',
102
+ grafeo: 'MATCH (n:Vector) RETURN n LIMIT 10',
103
+ };
104
+ return placeholders[backend] || "Enter query...";
105
+ }
106
+
107
+ function getHelp(backend) {
108
+ const help = {
109
+ qdrant: "JSON: vector, filter, limit, recommend, ids",
110
+ pinecone: "JSON: vector, filter, topK, namespace",
111
+ weaviate: "GraphQL: nearVector, nearText, where",
112
+ chroma: "Dict: query_embeddings, where, n_results",
113
+ lancedb: "SQL WHERE clause for filtering",
114
+ grafeo: "Grafeo query language",
115
+ };
116
+ return help[backend] || "";
117
+ }