anywidget-graph 0.2.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.
@@ -0,0 +1,584 @@
1
+ /**
2
+ * Styles for anywidget-graph UI components.
3
+ */
4
+
5
+ /* === CSS VARIABLES === */
6
+ .awg-wrapper {
7
+ --awg-bg: #ffffff;
8
+ --awg-bg-secondary: #f8f9fa;
9
+ --awg-bg-tertiary: #f3f4f6;
10
+ --awg-border: #e5e7eb;
11
+ --awg-text: #111827;
12
+ --awg-text-secondary: #6b7280;
13
+ --awg-text-muted: #9ca3af;
14
+ --awg-accent: #6366f1;
15
+ --awg-accent-hover: #4f46e5;
16
+ --awg-graph-bg: #fafafa;
17
+ --awg-input-bg: #ffffff;
18
+ --awg-input-border: #d1d5db;
19
+ }
20
+
21
+ .awg-wrapper.awg-dark {
22
+ --awg-bg: #1a1a2e;
23
+ --awg-bg-secondary: #16213e;
24
+ --awg-bg-tertiary: #0f3460;
25
+ --awg-border: #2d3748;
26
+ --awg-text: #e2e8f0;
27
+ --awg-text-secondary: #a0aec0;
28
+ --awg-text-muted: #718096;
29
+ --awg-accent: #818cf8;
30
+ --awg-accent-hover: #6366f1;
31
+ --awg-graph-bg: #0f0f1a;
32
+ --awg-input-bg: #1e1e32;
33
+ --awg-input-border: #3d4a5c;
34
+ }
35
+
36
+ /* === BASE === */
37
+ .awg-wrapper {
38
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
39
+ display: flex;
40
+ flex-direction: column;
41
+ border: 1px solid var(--awg-border);
42
+ border-radius: 8px;
43
+ overflow: hidden;
44
+ background: var(--awg-bg);
45
+ color: var(--awg-text);
46
+ }
47
+
48
+ .awg-content {
49
+ display: flex;
50
+ position: relative;
51
+ }
52
+
53
+ /* === TOOLBAR === */
54
+ .awg-toolbar {
55
+ display: flex;
56
+ align-items: center;
57
+ gap: 8px;
58
+ padding: 8px 12px;
59
+ background: var(--awg-bg-secondary);
60
+ border-bottom: 1px solid var(--awg-border);
61
+ min-height: 44px;
62
+ }
63
+
64
+ .awg-query-container {
65
+ flex: 1;
66
+ display: flex;
67
+ align-items: center;
68
+ gap: 8px;
69
+ }
70
+
71
+ .awg-query-input {
72
+ flex: 1;
73
+ padding: 8px 12px;
74
+ border: 1px solid var(--awg-input-border);
75
+ border-radius: 6px;
76
+ font-family: "Monaco", "Menlo", "Ubuntu Mono", "Consolas", monospace;
77
+ font-size: 13px;
78
+ background: var(--awg-input-bg);
79
+ color: var(--awg-text);
80
+ transition: border-color 0.15s, box-shadow 0.15s;
81
+ }
82
+
83
+ .awg-query-input:focus {
84
+ outline: none;
85
+ border-color: var(--awg-accent);
86
+ box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.2);
87
+ }
88
+
89
+ .awg-query-input::placeholder {
90
+ color: var(--awg-text-muted);
91
+ }
92
+
93
+ /* === BUTTONS === */
94
+ .awg-btn {
95
+ display: inline-flex;
96
+ align-items: center;
97
+ justify-content: center;
98
+ min-width: 36px;
99
+ height: 36px;
100
+ padding: 0 10px;
101
+ border: 1px solid var(--awg-input-border);
102
+ border-radius: 6px;
103
+ background: var(--awg-input-bg);
104
+ color: var(--awg-text);
105
+ cursor: pointer;
106
+ transition: all 0.15s;
107
+ position: relative;
108
+ font-size: 13px;
109
+ }
110
+
111
+ .awg-btn:hover {
112
+ background: var(--awg-bg-tertiary);
113
+ border-color: var(--awg-text-muted);
114
+ }
115
+
116
+ .awg-btn:disabled {
117
+ opacity: 0.5;
118
+ cursor: not-allowed;
119
+ }
120
+
121
+ .awg-btn-primary {
122
+ background: var(--awg-accent);
123
+ border-color: var(--awg-accent);
124
+ color: #fff;
125
+ }
126
+
127
+ .awg-btn-primary:hover {
128
+ background: var(--awg-accent-hover);
129
+ border-color: var(--awg-accent-hover);
130
+ }
131
+
132
+ .awg-btn-primary:disabled {
133
+ background: var(--awg-text-muted);
134
+ border-color: var(--awg-text-muted);
135
+ }
136
+
137
+ .awg-btn-full {
138
+ width: 100%;
139
+ }
140
+
141
+ .awg-btn-sm {
142
+ min-width: 24px;
143
+ height: 24px;
144
+ padding: 0 4px;
145
+ }
146
+
147
+ /* === STATUS DOTS === */
148
+ .awg-status-dot {
149
+ position: absolute;
150
+ top: 4px;
151
+ right: 4px;
152
+ width: 8px;
153
+ height: 8px;
154
+ border-radius: 50%;
155
+ border: 1.5px solid var(--awg-bg);
156
+ }
157
+
158
+ .awg-status-dot-inline {
159
+ display: inline-block;
160
+ width: 8px;
161
+ height: 8px;
162
+ border-radius: 50%;
163
+ margin-right: 6px;
164
+ }
165
+
166
+ .awg-status-disconnected {
167
+ background: #6b7280;
168
+ }
169
+ .awg-status-connecting {
170
+ background: #f59e0b;
171
+ animation: awg-pulse 1s infinite;
172
+ }
173
+ .awg-status-connected {
174
+ background: #22c55e;
175
+ }
176
+ .awg-status-error {
177
+ background: #ef4444;
178
+ }
179
+
180
+ @keyframes awg-pulse {
181
+ 0%,
182
+ 100% {
183
+ opacity: 1;
184
+ }
185
+ 50% {
186
+ opacity: 0.4;
187
+ }
188
+ }
189
+
190
+ /* === SPINNER === */
191
+ .awg-spinner {
192
+ width: 14px;
193
+ height: 14px;
194
+ border: 2px solid rgba(255, 255, 255, 0.3);
195
+ border-top-color: #fff;
196
+ border-radius: 50%;
197
+ animation: awg-spin 0.8s linear infinite;
198
+ }
199
+
200
+ @keyframes awg-spin {
201
+ to {
202
+ transform: rotate(360deg);
203
+ }
204
+ }
205
+
206
+ /* === GRAPH CONTAINER === */
207
+ .awg-graph-container {
208
+ flex: 1;
209
+ background: var(--awg-graph-bg);
210
+ }
211
+
212
+ /* === PANEL COMMON === */
213
+ .awg-panel-header {
214
+ padding: 12px 16px;
215
+ font-weight: 600;
216
+ font-size: 13px;
217
+ text-transform: uppercase;
218
+ letter-spacing: 0.5px;
219
+ color: var(--awg-text-secondary);
220
+ border-bottom: 1px solid var(--awg-border);
221
+ display: flex;
222
+ align-items: center;
223
+ justify-content: space-between;
224
+ }
225
+
226
+ .awg-panel-form {
227
+ padding: 16px;
228
+ display: flex;
229
+ flex-direction: column;
230
+ gap: 14px;
231
+ flex: 1;
232
+ overflow-y: auto;
233
+ }
234
+
235
+ .awg-panel-actions {
236
+ padding: 12px 16px;
237
+ border-top: 1px solid var(--awg-border);
238
+ display: flex;
239
+ flex-direction: column;
240
+ gap: 8px;
241
+ }
242
+
243
+ .awg-panel-error {
244
+ padding: 10px 16px;
245
+ background: rgba(239, 68, 68, 0.1);
246
+ color: #ef4444;
247
+ font-size: 12px;
248
+ border-top: 1px solid rgba(239, 68, 68, 0.2);
249
+ }
250
+
251
+ /* === SETTINGS PANEL === */
252
+ .awg-settings-panel {
253
+ width: 0;
254
+ overflow: hidden;
255
+ background: var(--awg-bg-secondary);
256
+ border-left: 1px solid var(--awg-border);
257
+ transition: width 0.2s ease;
258
+ display: flex;
259
+ flex-direction: column;
260
+ }
261
+
262
+ .awg-settings-panel.awg-panel-open {
263
+ width: 260px;
264
+ }
265
+
266
+ .awg-connection-status {
267
+ font-size: 12px;
268
+ color: var(--awg-text-secondary);
269
+ display: flex;
270
+ align-items: center;
271
+ }
272
+
273
+ /* === FORM ELEMENTS === */
274
+ .awg-form-group {
275
+ display: flex;
276
+ flex-direction: column;
277
+ gap: 5px;
278
+ }
279
+
280
+ .awg-label {
281
+ font-size: 11px;
282
+ font-weight: 600;
283
+ text-transform: uppercase;
284
+ letter-spacing: 0.3px;
285
+ color: var(--awg-text-secondary);
286
+ }
287
+
288
+ .awg-input,
289
+ .awg-select {
290
+ padding: 8px 10px;
291
+ border: 1px solid var(--awg-input-border);
292
+ border-radius: 5px;
293
+ font-size: 13px;
294
+ background: var(--awg-input-bg);
295
+ color: var(--awg-text);
296
+ transition: border-color 0.15s, box-shadow 0.15s;
297
+ }
298
+
299
+ .awg-input:focus,
300
+ .awg-select:focus {
301
+ outline: none;
302
+ border-color: var(--awg-accent);
303
+ box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.15);
304
+ }
305
+
306
+ .awg-select {
307
+ cursor: pointer;
308
+ }
309
+
310
+ .awg-select option:disabled {
311
+ color: var(--awg-text-muted);
312
+ }
313
+
314
+ /* === TOGGLE SWITCH === */
315
+ .awg-toggle {
316
+ display: flex;
317
+ align-items: center;
318
+ cursor: pointer;
319
+ gap: 10px;
320
+ }
321
+
322
+ .awg-toggle input {
323
+ display: none;
324
+ }
325
+
326
+ .awg-toggle-slider {
327
+ width: 36px;
328
+ height: 20px;
329
+ background: var(--awg-input-border);
330
+ border-radius: 10px;
331
+ position: relative;
332
+ transition: background 0.2s;
333
+ }
334
+
335
+ .awg-toggle-slider::after {
336
+ content: "";
337
+ position: absolute;
338
+ top: 2px;
339
+ left: 2px;
340
+ width: 16px;
341
+ height: 16px;
342
+ background: #fff;
343
+ border-radius: 50%;
344
+ transition: transform 0.2s;
345
+ }
346
+
347
+ .awg-toggle input:checked + .awg-toggle-slider {
348
+ background: var(--awg-accent);
349
+ }
350
+
351
+ .awg-toggle input:checked + .awg-toggle-slider::after {
352
+ transform: translateX(16px);
353
+ }
354
+
355
+ .awg-toggle-label {
356
+ font-size: 13px;
357
+ color: var(--awg-text);
358
+ }
359
+
360
+ /* === SCHEMA PANEL (LEFT) === */
361
+ .awg-schema-panel {
362
+ width: 0;
363
+ overflow: hidden;
364
+ background: var(--awg-bg-secondary);
365
+ border-right: 1px solid var(--awg-border);
366
+ transition: width 0.2s ease;
367
+ display: flex;
368
+ flex-direction: column;
369
+ }
370
+
371
+ .awg-schema-panel.awg-panel-open {
372
+ width: 220px;
373
+ }
374
+
375
+ .awg-schema-content {
376
+ flex: 1;
377
+ overflow-y: auto;
378
+ padding: 8px 0;
379
+ }
380
+
381
+ .awg-schema-empty {
382
+ padding: 20px 16px;
383
+ color: var(--awg-text-muted);
384
+ font-size: 12px;
385
+ text-align: center;
386
+ }
387
+
388
+ .awg-schema-section {
389
+ margin-bottom: 8px;
390
+ }
391
+
392
+ .awg-schema-section-header {
393
+ display: flex;
394
+ align-items: center;
395
+ gap: 8px;
396
+ padding: 8px 16px;
397
+ font-size: 11px;
398
+ font-weight: 600;
399
+ text-transform: uppercase;
400
+ letter-spacing: 0.3px;
401
+ color: var(--awg-text-secondary);
402
+ }
403
+
404
+ .awg-schema-item {
405
+ border-bottom: 1px solid var(--awg-border);
406
+ }
407
+
408
+ .awg-schema-item:last-child {
409
+ border-bottom: none;
410
+ }
411
+
412
+ .awg-schema-item-header {
413
+ display: flex;
414
+ align-items: center;
415
+ gap: 6px;
416
+ padding: 8px 16px;
417
+ cursor: pointer;
418
+ transition: background 0.1s;
419
+ }
420
+
421
+ .awg-schema-item-header:hover {
422
+ background: var(--awg-bg-tertiary);
423
+ }
424
+
425
+ .awg-schema-expand {
426
+ color: var(--awg-text-muted);
427
+ transition: transform 0.15s;
428
+ }
429
+
430
+ .awg-schema-item-expanded .awg-schema-expand {
431
+ transform: rotate(90deg);
432
+ }
433
+
434
+ .awg-schema-name {
435
+ font-size: 13px;
436
+ color: var(--awg-accent);
437
+ cursor: pointer;
438
+ flex: 1;
439
+ }
440
+
441
+ .awg-schema-name:hover {
442
+ text-decoration: underline;
443
+ }
444
+
445
+ .awg-schema-props {
446
+ display: none;
447
+ padding: 4px 16px 8px 32px;
448
+ }
449
+
450
+ .awg-schema-item-expanded .awg-schema-props {
451
+ display: block;
452
+ }
453
+
454
+ .awg-schema-prop {
455
+ display: flex;
456
+ align-items: center;
457
+ gap: 6px;
458
+ padding: 4px 8px;
459
+ font-size: 12px;
460
+ color: var(--awg-text-secondary);
461
+ cursor: pointer;
462
+ border-radius: 4px;
463
+ transition: background 0.1s;
464
+ }
465
+
466
+ .awg-schema-prop:hover {
467
+ background: var(--awg-bg-tertiary);
468
+ color: var(--awg-text);
469
+ }
470
+
471
+ .awg-schema-prop-empty {
472
+ color: var(--awg-text-muted);
473
+ font-style: italic;
474
+ cursor: default;
475
+ }
476
+
477
+ .awg-schema-prop-empty:hover {
478
+ background: transparent;
479
+ color: var(--awg-text-muted);
480
+ }
481
+
482
+ /* === PROPERTIES PANEL (RIGHT) === */
483
+ .awg-properties-panel {
484
+ width: 0;
485
+ overflow: hidden;
486
+ background: var(--awg-bg-secondary);
487
+ border-left: 1px solid var(--awg-border);
488
+ transition: width 0.2s ease;
489
+ display: flex;
490
+ flex-direction: column;
491
+ }
492
+
493
+ .awg-properties-panel.awg-panel-open {
494
+ width: 260px;
495
+ }
496
+
497
+ .awg-properties-content {
498
+ flex: 1;
499
+ overflow-y: auto;
500
+ padding: 8px 0;
501
+ }
502
+
503
+ .awg-properties-empty {
504
+ padding: 20px 16px;
505
+ color: var(--awg-text-muted);
506
+ font-size: 12px;
507
+ text-align: center;
508
+ }
509
+
510
+ .awg-properties-header {
511
+ display: flex;
512
+ align-items: center;
513
+ gap: 8px;
514
+ padding: 10px 16px;
515
+ font-size: 12px;
516
+ font-weight: 600;
517
+ color: var(--awg-text-secondary);
518
+ border-bottom: 1px solid var(--awg-border);
519
+ background: var(--awg-bg-tertiary);
520
+ }
521
+
522
+ .awg-properties-type {
523
+ text-transform: uppercase;
524
+ letter-spacing: 0.3px;
525
+ }
526
+
527
+ .awg-property-item {
528
+ display: flex;
529
+ flex-direction: column;
530
+ padding: 8px 16px;
531
+ border-bottom: 1px solid var(--awg-border);
532
+ }
533
+
534
+ .awg-property-item:last-child {
535
+ border-bottom: none;
536
+ }
537
+
538
+ .awg-property-key {
539
+ font-size: 10px;
540
+ font-weight: 600;
541
+ text-transform: uppercase;
542
+ letter-spacing: 0.3px;
543
+ color: var(--awg-text-muted);
544
+ margin-bottom: 2px;
545
+ }
546
+
547
+ .awg-property-value {
548
+ font-size: 13px;
549
+ color: var(--awg-text);
550
+ word-break: break-all;
551
+ }
552
+
553
+ .awg-property-truncate {
554
+ overflow: hidden;
555
+ text-overflow: ellipsis;
556
+ white-space: nowrap;
557
+ }
558
+
559
+ .awg-property-labels {
560
+ display: flex;
561
+ flex-wrap: wrap;
562
+ gap: 4px;
563
+ }
564
+
565
+ .awg-label-tag {
566
+ display: inline-block;
567
+ padding: 2px 8px;
568
+ font-size: 11px;
569
+ font-weight: 500;
570
+ background: var(--awg-accent);
571
+ color: #fff;
572
+ border-radius: 10px;
573
+ }
574
+
575
+ .awg-edge-tag {
576
+ display: inline-block;
577
+ padding: 2px 8px;
578
+ font-size: 11px;
579
+ font-weight: 500;
580
+ background: var(--awg-bg-tertiary);
581
+ color: var(--awg-text);
582
+ border-radius: 4px;
583
+ border: 1px solid var(--awg-border);
584
+ }
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Toolbar component with query input and action buttons.
3
+ */
4
+ import { ICONS } from "./icons.js";
5
+ import { toggleSchemaPanel } from "./schema.js";
6
+ import { toggleSettingsPanel, updateStatusDot } from "./settings.js";
7
+ import { togglePropertiesPanel } from "./properties.js";
8
+
9
+ /**
10
+ * Create the toolbar component.
11
+ */
12
+ export function createToolbar(model, wrapper, onExecuteQuery) {
13
+ const toolbar = document.createElement("div");
14
+ toolbar.className = "awg-toolbar";
15
+
16
+ // Schema sidebar toggle (left)
17
+ const schemaBtn = document.createElement("button");
18
+ schemaBtn.className = "awg-btn";
19
+ schemaBtn.innerHTML = ICONS.sidebar;
20
+ schemaBtn.title = "Toggle schema browser";
21
+ schemaBtn.addEventListener("click", () => toggleSchemaPanel(wrapper));
22
+ toolbar.appendChild(schemaBtn);
23
+
24
+ // Query container (collapsible input)
25
+ if (model.get("show_query_input")) {
26
+ const queryContainer = document.createElement("div");
27
+ queryContainer.className = "awg-query-container";
28
+
29
+ const queryInput = document.createElement("input");
30
+ queryInput.type = "text";
31
+ queryInput.className = "awg-query-input";
32
+ queryInput.placeholder = "Enter query (e.g., MATCH (n) RETURN n LIMIT 25)";
33
+ queryInput.value = model.get("query") || "";
34
+
35
+ queryInput.addEventListener("input", (e) => {
36
+ model.set("query", e.target.value);
37
+ model.save_changes();
38
+ });
39
+
40
+ queryInput.addEventListener("keydown", (e) => {
41
+ if (e.key === "Enter" && !e.shiftKey) {
42
+ e.preventDefault();
43
+ onExecuteQuery();
44
+ }
45
+ });
46
+
47
+ model.on("change:query", () => {
48
+ if (queryInput.value !== model.get("query")) {
49
+ queryInput.value = model.get("query") || "";
50
+ }
51
+ });
52
+
53
+ queryContainer.appendChild(queryInput);
54
+
55
+ // Play button
56
+ const playBtn = document.createElement("button");
57
+ playBtn.className = "awg-btn awg-btn-primary";
58
+ playBtn.innerHTML = ICONS.play;
59
+ playBtn.title = "Run query";
60
+ playBtn.addEventListener("click", () => onExecuteQuery());
61
+
62
+ model.on("change:query_running", () => {
63
+ playBtn.disabled = model.get("query_running");
64
+ playBtn.innerHTML = model.get("query_running")
65
+ ? '<span class="awg-spinner"></span>'
66
+ : ICONS.play;
67
+ });
68
+
69
+ queryContainer.appendChild(playBtn);
70
+ toolbar.appendChild(queryContainer);
71
+ }
72
+
73
+ // Settings button
74
+ if (model.get("show_settings")) {
75
+ const settingsBtn = document.createElement("button");
76
+ settingsBtn.className = "awg-btn";
77
+ settingsBtn.innerHTML = ICONS.settings;
78
+ settingsBtn.title = "Connection settings";
79
+
80
+ // Status dot
81
+ const statusDot = document.createElement("span");
82
+ statusDot.className = "awg-status-dot";
83
+ updateStatusDot(statusDot, model.get("connection_status"));
84
+ settingsBtn.appendChild(statusDot);
85
+
86
+ model.on("change:connection_status", () => {
87
+ updateStatusDot(statusDot, model.get("connection_status"));
88
+ });
89
+
90
+ settingsBtn.addEventListener("click", () => {
91
+ toggleSettingsPanel(wrapper);
92
+ });
93
+
94
+ toolbar.appendChild(settingsBtn);
95
+ }
96
+
97
+ // Properties panel toggle (right)
98
+ const propsBtn = document.createElement("button");
99
+ propsBtn.className = "awg-btn";
100
+ propsBtn.innerHTML = ICONS.property;
101
+ propsBtn.title = "Toggle properties panel";
102
+ propsBtn.addEventListener("click", () => togglePropertiesPanel(wrapper));
103
+ toolbar.appendChild(propsBtn);
104
+
105
+ return toolbar;
106
+ }