miniledger 0.1.0 → 0.2.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.
@@ -12,7 +12,11 @@
12
12
  --green: #22c55e;
13
13
  --red: #ef4444;
14
14
  --yellow: #eab308;
15
+ --purple: #a855f7;
16
+ --orange: #f97316;
17
+ --cyan: #06b6d4;
15
18
  --mono: 'SF Mono', 'Fira Code', 'JetBrains Mono', monospace;
19
+ --sidebar-w: 220px;
16
20
  }
17
21
 
18
22
  body {
@@ -23,31 +27,88 @@ body {
23
27
  min-height: 100vh;
24
28
  }
25
29
 
26
- header {
30
+ /* ── Layout ──────────────────────────────────────────── */
31
+ .layout {
32
+ display: flex;
33
+ min-height: 100vh;
34
+ }
35
+
36
+ /* ── Sidebar ─────────────────────────────────────────── */
37
+ .sidebar {
38
+ width: var(--sidebar-w);
27
39
  background: var(--surface);
28
- border-bottom: 1px solid var(--border);
29
- padding: 12px 24px;
40
+ border-right: 1px solid var(--border);
30
41
  display: flex;
31
- align-items: center;
32
- justify-content: space-between;
42
+ flex-direction: column;
43
+ position: fixed;
44
+ top: 0;
45
+ left: 0;
46
+ bottom: 0;
47
+ z-index: 10;
48
+ overflow-y: auto;
33
49
  }
34
50
 
35
- header h1 {
51
+ .sidebar-logo {
52
+ padding: 16px 20px;
36
53
  font-size: 18px;
37
- font-weight: 600;
54
+ font-weight: 700;
38
55
  letter-spacing: -0.5px;
56
+ border-bottom: 1px solid var(--border);
57
+ }
58
+
59
+ .sidebar-logo span { color: var(--accent); }
60
+
61
+ .sidebar-nav {
62
+ flex: 1;
63
+ padding: 8px 0;
39
64
  }
40
65
 
41
- header h1 span { color: var(--accent); }
66
+ .nav-section {
67
+ padding: 12px 20px 4px;
68
+ font-size: 10px;
69
+ font-weight: 600;
70
+ text-transform: uppercase;
71
+ letter-spacing: 1px;
72
+ color: var(--text-dim);
73
+ }
42
74
 
43
- .status-bar {
75
+ .nav-link {
44
76
  display: flex;
45
- gap: 20px;
77
+ align-items: center;
78
+ gap: 10px;
79
+ padding: 8px 20px;
46
80
  font-size: 13px;
47
81
  color: var(--text-dim);
82
+ text-decoration: none;
83
+ cursor: pointer;
84
+ transition: background 0.15s, color 0.15s;
85
+ }
86
+
87
+ .nav-link:hover {
88
+ background: var(--surface2);
89
+ color: var(--text);
90
+ }
91
+
92
+ .nav-link.active {
93
+ background: var(--accent-dim);
94
+ color: var(--accent);
95
+ font-weight: 500;
96
+ }
97
+
98
+ .nav-link .nav-icon {
99
+ width: 16px;
100
+ text-align: center;
101
+ font-size: 14px;
102
+ }
103
+
104
+ .sidebar-footer {
105
+ padding: 12px 20px;
106
+ border-top: 1px solid var(--border);
107
+ font-size: 11px;
108
+ color: var(--text-dim);
48
109
  }
49
110
 
50
- .status-bar .dot {
111
+ .sidebar-footer .dot {
51
112
  display: inline-block;
52
113
  width: 8px;
53
114
  height: 8px;
@@ -56,14 +117,122 @@ header h1 span { color: var(--accent); }
56
117
  vertical-align: middle;
57
118
  }
58
119
 
59
- .dot.green { background: var(--green); }
60
- .dot.red { background: var(--red); }
120
+ /* ── Main content ────────────────────────────────────── */
121
+ .main {
122
+ flex: 1;
123
+ margin-left: var(--sidebar-w);
124
+ display: flex;
125
+ flex-direction: column;
126
+ min-height: 100vh;
127
+ }
128
+
129
+ /* ── Top bar ─────────────────────────────────────────── */
130
+ .topbar {
131
+ background: var(--surface);
132
+ border-bottom: 1px solid var(--border);
133
+ padding: 10px 24px;
134
+ display: flex;
135
+ align-items: center;
136
+ justify-content: space-between;
137
+ gap: 16px;
138
+ position: sticky;
139
+ top: 0;
140
+ z-index: 5;
141
+ }
142
+
143
+ .topbar-left {
144
+ display: flex;
145
+ align-items: center;
146
+ gap: 16px;
147
+ font-size: 13px;
148
+ color: var(--text-dim);
149
+ }
150
+
151
+ .topbar-left strong { color: var(--text); }
152
+
153
+ .search-box {
154
+ display: flex;
155
+ align-items: center;
156
+ gap: 8px;
157
+ background: var(--bg);
158
+ border: 1px solid var(--border);
159
+ border-radius: 6px;
160
+ padding: 6px 12px;
161
+ width: 360px;
162
+ transition: border-color 0.15s;
163
+ }
164
+
165
+ .search-box:focus-within { border-color: var(--accent); }
166
+
167
+ .search-box input {
168
+ flex: 1;
169
+ background: transparent;
170
+ border: none;
171
+ color: var(--text);
172
+ font-size: 13px;
173
+ outline: none;
174
+ font-family: var(--mono);
175
+ }
176
+
177
+ .search-box input::placeholder { color: var(--text-dim); }
178
+
179
+ .search-box .search-icon { color: var(--text-dim); font-size: 14px; }
61
180
 
181
+ /* ── Content area ────────────────────────────────────── */
182
+ .content {
183
+ flex: 1;
184
+ padding: 20px 24px;
185
+ }
186
+
187
+ .page-title {
188
+ font-size: 20px;
189
+ font-weight: 600;
190
+ margin-bottom: 16px;
191
+ }
192
+
193
+ .page-subtitle {
194
+ font-size: 13px;
195
+ color: var(--text-dim);
196
+ margin-top: -12px;
197
+ margin-bottom: 16px;
198
+ }
199
+
200
+ /* ── Stats row ───────────────────────────────────────── */
201
+ .stats {
202
+ display: grid;
203
+ grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
204
+ gap: 12px;
205
+ margin-bottom: 20px;
206
+ }
207
+
208
+ .stat {
209
+ background: var(--surface);
210
+ border: 1px solid var(--border);
211
+ border-radius: 8px;
212
+ padding: 14px 16px;
213
+ text-align: center;
214
+ }
215
+
216
+ .stat-value {
217
+ font-size: 24px;
218
+ font-weight: 700;
219
+ font-family: var(--mono);
220
+ color: var(--accent);
221
+ }
222
+
223
+ .stat-label {
224
+ font-size: 10px;
225
+ text-transform: uppercase;
226
+ letter-spacing: 0.5px;
227
+ color: var(--text-dim);
228
+ margin-top: 2px;
229
+ }
230
+
231
+ /* ── Cards ───────────────────────────────────────────── */
62
232
  .grid {
63
233
  display: grid;
64
234
  grid-template-columns: 1fr 1fr;
65
235
  gap: 16px;
66
- padding: 16px 24px;
67
236
  }
68
237
 
69
238
  .card {
@@ -76,7 +245,7 @@ header h1 span { color: var(--accent); }
76
245
  .card-header {
77
246
  padding: 12px 16px;
78
247
  border-bottom: 1px solid var(--border);
79
- font-size: 13px;
248
+ font-size: 12px;
80
249
  font-weight: 600;
81
250
  text-transform: uppercase;
82
251
  letter-spacing: 0.5px;
@@ -86,25 +255,82 @@ header h1 span { color: var(--accent); }
86
255
  align-items: center;
87
256
  }
88
257
 
89
- .card-header .badge {
90
- background: var(--accent-dim);
91
- color: var(--accent);
258
+ .card-body {
259
+ padding: 12px 16px;
260
+ max-height: 360px;
261
+ overflow-y: auto;
262
+ }
263
+
264
+ .full-width { grid-column: 1 / -1; }
265
+
266
+ /* ── Tables ──────────────────────────────────────────── */
267
+ .data-table {
268
+ width: 100%;
269
+ border-collapse: collapse;
270
+ font-size: 13px;
271
+ }
272
+
273
+ .data-table th {
274
+ text-align: left;
275
+ padding: 8px 12px;
276
+ background: var(--surface2);
277
+ color: var(--text-dim);
278
+ font-size: 11px;
279
+ font-weight: 600;
280
+ text-transform: uppercase;
281
+ letter-spacing: 0.5px;
282
+ border-bottom: 1px solid var(--border);
283
+ position: sticky;
284
+ top: 0;
285
+ }
286
+
287
+ .data-table td {
288
+ padding: 8px 12px;
289
+ border-bottom: 1px solid var(--border);
290
+ vertical-align: middle;
291
+ }
292
+
293
+ .data-table tr:hover td { background: var(--surface2); }
294
+
295
+ .data-table .clickable { cursor: pointer; }
296
+
297
+ .data-table .mono {
298
+ font-family: var(--mono);
299
+ font-size: 12px;
300
+ }
301
+
302
+ .data-table .dim { color: var(--text-dim); }
303
+
304
+ /* ── Badges ──────────────────────────────────────────── */
305
+ .badge {
306
+ display: inline-block;
92
307
  padding: 2px 8px;
93
308
  border-radius: 10px;
94
309
  font-size: 11px;
95
310
  font-weight: 500;
311
+ background: var(--accent-dim);
312
+ color: var(--accent);
313
+ white-space: nowrap;
96
314
  }
97
315
 
98
- .card-body {
99
- padding: 12px 16px;
100
- max-height: 360px;
101
- overflow-y: auto;
316
+ .badge-green { background: rgba(34,197,94,0.15); color: var(--green); }
317
+ .badge-red { background: rgba(239,68,68,0.15); color: var(--red); }
318
+ .badge-yellow { background: rgba(234,179,8,0.15); color: var(--yellow); }
319
+ .badge-purple { background: rgba(168,85,247,0.15); color: var(--purple); }
320
+ .badge-orange { background: rgba(249,115,22,0.15); color: var(--orange); }
321
+ .badge-cyan { background: rgba(6,182,212,0.15); color: var(--cyan); }
322
+
323
+ /* ── Links ───────────────────────────────────────────── */
324
+ .link {
325
+ color: var(--accent);
326
+ text-decoration: none;
327
+ cursor: pointer;
102
328
  }
103
329
 
104
- .full-width { grid-column: 1 / -1; }
330
+ .link:hover { text-decoration: underline; }
105
331
 
106
- /* Block list */
107
- .block-item {
332
+ /* ── Block / TX items (compact list) ─────────────────── */
333
+ .list-item {
108
334
  display: flex;
109
335
  align-items: center;
110
336
  gap: 12px;
@@ -113,9 +339,9 @@ header h1 span { color: var(--accent); }
113
339
  font-size: 13px;
114
340
  }
115
341
 
116
- .block-item:last-child { border-bottom: none; }
342
+ .list-item:last-child { border-bottom: none; }
117
343
 
118
- .block-num {
344
+ .list-item .num {
119
345
  background: var(--accent-dim);
120
346
  color: var(--accent);
121
347
  padding: 2px 10px;
@@ -126,63 +352,155 @@ header h1 span { color: var(--accent); }
126
352
  text-align: center;
127
353
  }
128
354
 
129
- .block-hash {
355
+ .list-item .hash {
130
356
  font-family: var(--mono);
131
357
  font-size: 12px;
132
358
  color: var(--text-dim);
133
359
  }
134
360
 
135
- .block-meta {
361
+ .list-item .meta {
136
362
  margin-left: auto;
137
363
  font-size: 12px;
138
364
  color: var(--text-dim);
365
+ white-space: nowrap;
139
366
  }
140
367
 
141
- /* TX list */
142
- .tx-item {
143
- padding: 8px 0;
368
+ /* ── Detail page ─────────────────────────────────────── */
369
+ .detail-grid {
370
+ display: grid;
371
+ grid-template-columns: 160px 1fr;
372
+ gap: 0;
373
+ background: var(--surface);
374
+ border: 1px solid var(--border);
375
+ border-radius: 8px;
376
+ overflow: hidden;
377
+ margin-bottom: 20px;
378
+ }
379
+
380
+ .detail-row {
381
+ display: contents;
382
+ }
383
+
384
+ .detail-label {
385
+ padding: 10px 16px;
386
+ font-size: 12px;
387
+ font-weight: 600;
388
+ color: var(--text-dim);
389
+ text-transform: uppercase;
390
+ letter-spacing: 0.5px;
391
+ background: var(--surface2);
144
392
  border-bottom: 1px solid var(--border);
393
+ }
394
+
395
+ .detail-value {
396
+ padding: 10px 16px;
145
397
  font-size: 13px;
398
+ border-bottom: 1px solid var(--border);
399
+ word-break: break-all;
400
+ font-family: var(--mono);
401
+ font-size: 12px;
146
402
  }
147
403
 
148
- .tx-item:last-child { border-bottom: none; }
404
+ .detail-value.text { font-family: inherit; font-size: 13px; }
149
405
 
150
- .tx-hash {
406
+ /* ── JSON viewer ─────────────────────────────────────── */
407
+ .json-viewer {
408
+ background: var(--bg);
409
+ border: 1px solid var(--border);
410
+ border-radius: 6px;
411
+ padding: 12px 16px;
151
412
  font-family: var(--mono);
152
413
  font-size: 12px;
153
- color: var(--accent);
414
+ line-height: 1.6;
415
+ overflow-x: auto;
416
+ white-space: pre-wrap;
417
+ word-break: break-word;
418
+ max-height: 400px;
419
+ overflow-y: auto;
154
420
  }
155
421
 
156
- .tx-type {
157
- display: inline-block;
158
- padding: 1px 6px;
159
- border-radius: 3px;
160
- font-size: 11px;
161
- font-weight: 500;
162
- background: var(--surface2);
422
+ /* ── Pagination ──────────────────────────────────────── */
423
+ .pagination {
424
+ display: flex;
425
+ align-items: center;
426
+ justify-content: center;
427
+ gap: 8px;
428
+ margin-top: 16px;
429
+ padding: 12px 0;
430
+ }
431
+
432
+ .pagination button {
433
+ background: var(--surface);
434
+ border: 1px solid var(--border);
435
+ color: var(--text);
436
+ padding: 6px 12px;
437
+ border-radius: 4px;
438
+ font-size: 13px;
439
+ cursor: pointer;
440
+ }
441
+
442
+ .pagination button:hover { background: var(--surface2); border-color: var(--accent); }
443
+ .pagination button:disabled { opacity: 0.4; cursor: not-allowed; }
444
+ .pagination button:disabled:hover { background: var(--surface); border-color: var(--border); }
445
+
446
+ .pagination .page-info {
447
+ font-size: 13px;
163
448
  color: var(--text-dim);
164
- margin-left: 8px;
449
+ padding: 0 8px;
165
450
  }
166
451
 
167
- /* Peers */
168
- .peer-item {
452
+ /* ── Block nav arrows ────────────────────────────────── */
453
+ .block-nav {
169
454
  display: flex;
170
455
  align-items: center;
171
- gap: 10px;
172
- padding: 8px 0;
456
+ gap: 12px;
457
+ margin-bottom: 16px;
458
+ }
459
+
460
+ .block-nav button {
461
+ background: var(--surface);
462
+ border: 1px solid var(--border);
463
+ color: var(--text);
464
+ padding: 6px 14px;
465
+ border-radius: 4px;
466
+ font-size: 13px;
467
+ cursor: pointer;
468
+ }
469
+
470
+ .block-nav button:hover { background: var(--surface2); border-color: var(--accent); }
471
+ .block-nav button:disabled { opacity: 0.4; cursor: not-allowed; }
472
+
473
+ .block-nav .block-nav-info {
474
+ font-size: 14px;
475
+ font-weight: 600;
476
+ }
477
+
478
+ /* ── Tabs ────────────────────────────────────────────── */
479
+ .tabs {
480
+ display: flex;
481
+ gap: 0;
173
482
  border-bottom: 1px solid var(--border);
483
+ margin-bottom: 16px;
484
+ }
485
+
486
+ .tab {
487
+ padding: 10px 20px;
174
488
  font-size: 13px;
489
+ color: var(--text-dim);
490
+ cursor: pointer;
491
+ border-bottom: 2px solid transparent;
492
+ transition: color 0.15s, border-color 0.15s;
175
493
  }
176
494
 
177
- .peer-item:last-child { border-bottom: none; }
495
+ .tab:hover { color: var(--text); }
178
496
 
179
- .peer-id {
180
- font-family: var(--mono);
181
- font-size: 12px;
497
+ .tab.active {
182
498
  color: var(--accent);
499
+ border-bottom-color: var(--accent);
500
+ font-weight: 500;
183
501
  }
184
502
 
185
- /* SQL Query */
503
+ /* ── SQL console ─────────────────────────────────────── */
186
504
  .query-area {
187
505
  display: flex;
188
506
  gap: 8px;
@@ -203,7 +521,7 @@ header h1 span { color: var(--accent); }
203
521
 
204
522
  .query-area input:focus { border-color: var(--accent); }
205
523
 
206
- .query-area button {
524
+ .query-area button, .btn {
207
525
  background: var(--accent);
208
526
  color: white;
209
527
  border: none;
@@ -214,9 +532,17 @@ header h1 span { color: var(--accent); }
214
532
  font-weight: 500;
215
533
  }
216
534
 
217
- .query-area button:hover { opacity: 0.9; }
535
+ .query-area button:hover, .btn:hover { opacity: 0.9; }
218
536
 
219
- /* Result table */
537
+ .btn-secondary {
538
+ background: var(--surface2);
539
+ border: 1px solid var(--border);
540
+ color: var(--text);
541
+ }
542
+
543
+ .btn-secondary:hover { border-color: var(--accent); }
544
+
545
+ /* ── Result table (SQL) ──────────────────────────────── */
220
546
  .result-table {
221
547
  width: 100%;
222
548
  border-collapse: collapse;
@@ -242,45 +568,144 @@ header h1 span { color: var(--accent); }
242
568
  white-space: nowrap;
243
569
  }
244
570
 
571
+ /* ── Dot indicator ───────────────────────────────────── */
572
+ .dot {
573
+ display: inline-block;
574
+ width: 8px;
575
+ height: 8px;
576
+ border-radius: 50%;
577
+ vertical-align: middle;
578
+ }
579
+
580
+ .dot.green { background: var(--green); }
581
+ .dot.red { background: var(--red); }
582
+ .dot.yellow { background: var(--yellow); }
583
+
584
+ /* ── Empty state ─────────────────────────────────────── */
245
585
  .empty-state {
246
586
  text-align: center;
247
587
  color: var(--text-dim);
248
- padding: 24px;
588
+ padding: 32px;
249
589
  font-size: 13px;
250
590
  }
251
591
 
252
- /* Stats row */
253
- .stats {
592
+ /* ── Mini chart ──────────────────────────────────────── */
593
+ .mini-chart {
594
+ background: var(--surface);
595
+ border: 1px solid var(--border);
596
+ border-radius: 8px;
597
+ padding: 16px;
598
+ margin-bottom: 20px;
599
+ }
600
+
601
+ .mini-chart-title {
602
+ font-size: 12px;
603
+ font-weight: 600;
604
+ text-transform: uppercase;
605
+ letter-spacing: 0.5px;
606
+ color: var(--text-dim);
607
+ margin-bottom: 12px;
608
+ }
609
+
610
+ .chart-bars {
254
611
  display: flex;
255
- gap: 16px;
256
- padding: 12px 24px;
612
+ align-items: flex-end;
613
+ gap: 3px;
614
+ height: 60px;
257
615
  }
258
616
 
259
- .stat {
617
+ .chart-bar {
618
+ flex: 1;
619
+ background: var(--accent);
620
+ border-radius: 2px 2px 0 0;
621
+ min-height: 2px;
622
+ opacity: 0.7;
623
+ transition: opacity 0.15s;
624
+ }
625
+
626
+ .chart-bar:hover { opacity: 1; }
627
+
628
+ /* ── Peer card ───────────────────────────────────────── */
629
+ .peer-card {
260
630
  background: var(--surface);
261
631
  border: 1px solid var(--border);
262
632
  border-radius: 8px;
263
- padding: 16px 20px;
264
- flex: 1;
265
- text-align: center;
633
+ padding: 12px 16px;
634
+ margin-bottom: 8px;
635
+ display: flex;
636
+ align-items: center;
637
+ gap: 12px;
266
638
  }
267
639
 
268
- .stat-value {
269
- font-size: 28px;
270
- font-weight: 700;
640
+ .peer-card .peer-info { flex: 1; }
641
+ .peer-card .peer-id { font-family: var(--mono); font-size: 12px; color: var(--accent); }
642
+ .peer-card .peer-meta { font-size: 12px; color: var(--text-dim); margin-top: 2px; }
643
+ .peer-card .peer-height { font-family: var(--mono); font-size: 12px; color: var(--text-dim); }
644
+
645
+ /* ── Code view ───────────────────────────────────────── */
646
+ .code-view {
647
+ background: var(--bg);
648
+ border: 1px solid var(--border);
649
+ border-radius: 6px;
650
+ padding: 16px;
271
651
  font-family: var(--mono);
272
- color: var(--accent);
652
+ font-size: 12px;
653
+ line-height: 1.6;
654
+ overflow-x: auto;
655
+ white-space: pre;
656
+ max-height: 500px;
657
+ overflow-y: auto;
273
658
  }
274
659
 
275
- .stat-label {
276
- font-size: 11px;
277
- text-transform: uppercase;
278
- letter-spacing: 0.5px;
660
+ /* ── Filter bar ──────────────────────────────────────── */
661
+ .filter-bar {
662
+ display: flex;
663
+ align-items: center;
664
+ gap: 12px;
665
+ margin-bottom: 16px;
666
+ }
667
+
668
+ .filter-bar select {
669
+ background: var(--surface);
670
+ border: 1px solid var(--border);
671
+ color: var(--text);
672
+ padding: 6px 12px;
673
+ border-radius: 4px;
674
+ font-size: 13px;
675
+ outline: none;
676
+ cursor: pointer;
677
+ }
678
+
679
+ .filter-bar select:focus { border-color: var(--accent); }
680
+
681
+ .filter-bar label {
682
+ font-size: 13px;
279
683
  color: var(--text-dim);
280
- margin-top: 4px;
281
684
  }
282
685
 
283
- /* Scrollbar */
284
- ::-webkit-scrollbar { width: 6px; }
686
+ /* ── Vote bar ────────────────────────────────────────── */
687
+ .vote-bar {
688
+ display: flex;
689
+ height: 8px;
690
+ border-radius: 4px;
691
+ overflow: hidden;
692
+ background: var(--surface2);
693
+ margin: 8px 0;
694
+ }
695
+
696
+ .vote-bar .yes { background: var(--green); }
697
+ .vote-bar .no { background: var(--red); }
698
+
699
+ /* ── Scrollbar ───────────────────────────────────────── */
700
+ ::-webkit-scrollbar { width: 6px; height: 6px; }
285
701
  ::-webkit-scrollbar-track { background: transparent; }
286
702
  ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
703
+
704
+ /* ── Responsive ──────────────────────────────────────── */
705
+ @media (max-width: 900px) {
706
+ .sidebar { display: none; }
707
+ .main { margin-left: 0; }
708
+ .grid { grid-template-columns: 1fr; }
709
+ .search-box { width: 200px; }
710
+ .detail-grid { grid-template-columns: 120px 1fr; }
711
+ }