nuxt-devtools-observatory 0.1.28 → 0.1.30

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,65 @@
1
+ import { ref, onBeforeUnmount } from 'vue'
2
+
3
+ /**
4
+ * Adds drag-to-resize behaviour for a right-side detail panel.
5
+ * The handle sits between the main area and the panel; dragging it
6
+ * left/right adjusts the panel width.
7
+ * @param {number} defaultWidth Initial panel width in px.
8
+ * @param {string} [storageKey] Optional localStorage key to persist the width.
9
+ * @returns {{ paneWidth: import('vue').Ref<number>, onHandleMouseDown: (e: MouseEvent) => void }} `paneWidth` ref (in px) and `onHandleMouseDown` event handler to attach to the resize handle element.
10
+ */
11
+ export function useResizablePane(defaultWidth: number, storageKey?: string) {
12
+ const stored = storageKey ? Number(localStorage.getItem(storageKey)) || defaultWidth : defaultWidth
13
+ const paneWidth = ref(Math.max(160, Math.min(600, stored)))
14
+
15
+ let dragging = false
16
+ let startX = 0
17
+ let startWidth = 0
18
+
19
+ function onMouseMove(e: MouseEvent) {
20
+ if (!dragging) {
21
+ return
22
+ }
23
+
24
+ // Handle is on the LEFT edge of the panel → moving left increases width
25
+ const delta = startX - e.clientX
26
+ paneWidth.value = Math.max(160, Math.min(600, startWidth + delta))
27
+
28
+ if (storageKey) {
29
+ // eslint-disable-next-line
30
+ localStorage.setItem(storageKey, String(paneWidth.value))
31
+ }
32
+ }
33
+
34
+ function onMouseUp() {
35
+ if (!dragging) {
36
+ return
37
+ }
38
+
39
+ dragging = false
40
+ document.removeEventListener('mousemove', onMouseMove)
41
+ document.removeEventListener('mouseup', onMouseUp)
42
+ document.body.style.cursor = ''
43
+ document.body.style.userSelect = ''
44
+ }
45
+
46
+ function onHandleMouseDown(e: MouseEvent) {
47
+ e.preventDefault()
48
+ dragging = true
49
+ startX = e.clientX
50
+ startWidth = paneWidth.value
51
+ document.addEventListener('mousemove', onMouseMove)
52
+ document.addEventListener('mouseup', onMouseUp)
53
+ document.body.style.cursor = 'col-resize'
54
+ document.body.style.userSelect = 'none'
55
+ }
56
+
57
+ onBeforeUnmount(() => {
58
+ document.removeEventListener('mousemove', onMouseMove)
59
+ document.removeEventListener('mouseup', onMouseUp)
60
+ document.body.style.cursor = ''
61
+ document.body.style.userSelect = ''
62
+ })
63
+
64
+ return { paneWidth, onHandleMouseDown }
65
+ }
@@ -1,7 +1,7 @@
1
1
  import { ref } from 'vue'
2
2
  import { useDevtoolsClient, onDevtoolsClientConnected } from '@nuxt/devtools-kit/iframe-client'
3
- import type { ObservatorySnapshot, ObservatoryServerFunctions, ObservatoryClientFunctions } from '../../../src/types/rpc'
4
- import type { FetchEntry, ProvideEntry, InjectEntry, ComposableEntry, RenderEntry, TransitionEntry } from '../../../src/types/snapshot'
3
+ import type { ObservatorySnapshot, ObservatoryServerFunctions, ObservatoryClientFunctions } from '@observatory/types/rpc'
4
+ import type { FetchEntry, ProvideEntry, InjectEntry, ComposableEntry, RenderEntry, TransitionEntry } from '@observatory/types/snapshot'
5
5
 
6
6
  type ProvideInjectSnapshot = { provides: ProvideEntry[]; injects: InjectEntry[] }
7
7
 
@@ -89,6 +89,16 @@ function ensureStarted() {
89
89
  }
90
90
 
91
91
  started = true
92
+
93
+ // Support mock data injection via postMessage (used by the screenshot capture script).
94
+ if (typeof window !== 'undefined') {
95
+ window.addEventListener('message', (event) => {
96
+ if (event.data && event.data.type === 'observatory:snapshot') {
97
+ applySnapshot(event.data.data)
98
+ }
99
+ })
100
+ }
101
+
92
102
  const client = useDevtoolsClient()
93
103
 
94
104
  const setupRpc = () => {
@@ -1,3 +1,32 @@
1
+ :root {
2
+ --tracker-space-1: 4px;
3
+ --tracker-space-2: 8px;
4
+ --tracker-space-3: 12px;
5
+ --tracker-space-4: 16px;
6
+ --tracker-space-5: 24px;
7
+ --tracker-gap-view: 10px;
8
+ --tracker-gap-toolbar: 6px;
9
+ --tracker-gap-grid: 8px;
10
+ --tracker-font-size-xs: 10px;
11
+ --tracker-font-size-sm: 11px;
12
+ --tracker-font-size-md: 12px;
13
+ --tracker-font-size-stat: 20px;
14
+ --tracker-border-width: 0.5px;
15
+ --tracker-resize-handle-width: 8px;
16
+ --tracker-resize-handle-gutter: 2px;
17
+ --tracker-panel-width: 280px;
18
+ --tracker-transition-fast: 0.12s;
19
+ --tracker-transition-ui: 0.15s;
20
+ --tracker-tint-purple: rgb(127 119 221 / 15%);
21
+ --tracker-tint-purple-strong: rgb(127 119 221 / 20%);
22
+ --tracker-tint-purple-soft: rgb(127 119 221 / 8%);
23
+ --tracker-tint-red: rgb(226 75 74 / 12%);
24
+ --tracker-tint-teal: rgb(29 158 117 / 12%);
25
+ --tracker-tint-teal-badge: rgb(29 158 117 / 15%);
26
+ --tracker-tint-amber: rgb(239 159 39 / 15%);
27
+ --tracker-tint-blue: rgb(55 138 221 / 12%);
28
+ }
29
+
1
30
  * {
2
31
  box-sizing: border-box;
3
32
  margin: 0;
@@ -30,14 +59,14 @@ body {
30
59
  /* ── Base elements ──────────────────────────────────────────────────────── */
31
60
  button {
32
61
  font-family: var(--font);
33
- font-size: 12px;
62
+ font-size: var(--tracker-font-size-md);
34
63
  cursor: pointer;
35
- border: 0.5px solid var(--border);
64
+ border: var(--tracker-border-width) solid var(--border);
36
65
  background: transparent;
37
66
  color: var(--text2);
38
- padding: 4px 10px;
67
+ padding: var(--tracker-space-1) 10px;
39
68
  border-radius: var(--radius);
40
- transition: background 0.12s;
69
+ transition: background var(--tracker-transition-fast);
41
70
  }
42
71
 
43
72
  button:hover {
@@ -49,19 +78,19 @@ button:active {
49
78
  }
50
79
 
51
80
  button.active {
52
- background: rgb(127 119 221 / 15%);
81
+ background: var(--tracker-tint-purple);
53
82
  color: var(--purple);
54
83
  border-color: var(--purple);
55
84
  }
56
85
 
57
86
  button.danger-active {
58
- background: rgb(226 75 74 / 12%);
87
+ background: var(--tracker-tint-red);
59
88
  color: var(--red);
60
89
  border-color: var(--red);
61
90
  }
62
91
 
63
92
  button.success-active {
64
- background: rgb(29 158 117 / 12%);
93
+ background: var(--tracker-tint-teal);
65
94
  color: var(--teal);
66
95
  border-color: var(--teal);
67
96
  }
@@ -69,8 +98,8 @@ button.success-active {
69
98
  input[type='text'],
70
99
  input[type='search'] {
71
100
  font-family: var(--font);
72
- font-size: 12px;
73
- border: 0.5px solid var(--border);
101
+ font-size: var(--tracker-font-size-md);
102
+ border: var(--tracker-border-width) solid var(--border);
74
103
  background: var(--bg2);
75
104
  color: var(--text);
76
105
  padding: 5px 10px;
@@ -82,7 +111,7 @@ input[type='search'] {
82
111
  input[type='text']:focus,
83
112
  input[type='search']:focus {
84
113
  border-color: var(--purple);
85
- box-shadow: 0 0 0 2px rgb(127 119 221 / 20%);
114
+ box-shadow: 0 0 0 2px var(--tracker-tint-purple-strong);
86
115
  }
87
116
 
88
117
  input[type='range'] {
@@ -100,11 +129,11 @@ input[type='range'] {
100
129
  }
101
130
 
102
131
  .text-sm {
103
- font-size: 11px;
132
+ font-size: var(--tracker-font-size-sm);
104
133
  }
105
134
 
106
135
  .text-xs {
107
- font-size: 10px;
136
+ font-size: var(--tracker-font-size-xs);
108
137
  }
109
138
 
110
139
  .bold {
@@ -114,7 +143,7 @@ input[type='range'] {
114
143
  /* ── Badge ──────────────────────────────────────────────────────────────── */
115
144
  .badge {
116
145
  display: inline-block;
117
- font-size: 10px;
146
+ font-size: var(--tracker-font-size-xs);
118
147
  font-weight: 500;
119
148
  padding: 2px 7px;
120
149
  border-radius: 99px;
@@ -122,42 +151,42 @@ input[type='range'] {
122
151
  }
123
152
 
124
153
  .badge-ok {
125
- background: rgb(29 158 117 / 15%);
154
+ background: var(--tracker-tint-teal-badge);
126
155
  color: var(--teal);
127
156
  }
128
157
 
129
158
  .badge-err {
130
- background: rgb(226 75 74 / 12%);
159
+ background: var(--tracker-tint-red);
131
160
  color: var(--red);
132
161
  }
133
162
 
134
163
  .badge-warn {
135
- background: rgb(239 159 39 / 15%);
164
+ background: var(--tracker-tint-amber);
136
165
  color: var(--amber);
137
166
  }
138
167
 
139
168
  .badge-info {
140
- background: rgb(55 138 221 / 12%);
169
+ background: var(--tracker-tint-blue);
141
170
  color: var(--blue);
142
171
  }
143
172
 
144
173
  .badge-gray {
145
174
  background: var(--bg2);
146
175
  color: var(--text3);
147
- border: 0.5px solid var(--border);
176
+ border: var(--tracker-border-width) solid var(--border);
148
177
  }
149
178
 
150
179
  .badge-purple {
151
- background: rgb(127 119 221 / 15%);
180
+ background: var(--tracker-tint-purple);
152
181
  color: var(--purple);
153
182
  }
154
183
 
155
184
  /* ── Card ───────────────────────────────────────────────────────────────── */
156
185
  .card {
157
186
  background: var(--bg3);
158
- border: 0.5px solid var(--border);
187
+ border: var(--tracker-border-width) solid var(--border);
159
188
  border-radius: var(--radius-lg);
160
- padding: 12px 14px;
189
+ padding: var(--tracker-space-3) 14px;
161
190
  }
162
191
 
163
192
  /* ── Table ──────────────────────────────────────────────────────────────── */
@@ -169,11 +198,11 @@ input[type='range'] {
169
198
 
170
199
  .data-table th {
171
200
  text-align: left;
172
- font-size: 10px;
201
+ font-size: var(--tracker-font-size-xs);
173
202
  font-weight: 500;
174
203
  color: var(--text3);
175
204
  padding: 6px 8px;
176
- border-bottom: 0.5px solid var(--border);
205
+ border-bottom: var(--tracker-border-width) solid var(--border);
177
206
  text-transform: uppercase;
178
207
  letter-spacing: 0.4px;
179
208
  white-space: nowrap;
@@ -181,7 +210,7 @@ input[type='range'] {
181
210
 
182
211
  .data-table td {
183
212
  padding: 8px;
184
- border-bottom: 0.5px solid var(--border);
213
+ border-bottom: var(--tracker-border-width) solid var(--border);
185
214
  color: var(--text);
186
215
  vertical-align: middle;
187
216
  }
@@ -192,18 +221,18 @@ input[type='range'] {
192
221
  }
193
222
 
194
223
  .data-table tr.selected td {
195
- background: rgb(127 119 221 / 8%);
224
+ background: var(--tracker-tint-purple-soft);
196
225
  }
197
226
 
198
227
  /* ── Stat card ──────────────────────────────────────────────────────────── */
199
228
  .stat-card {
200
229
  background: var(--bg2);
201
230
  border-radius: var(--radius);
202
- padding: 10px 12px;
231
+ padding: var(--tracker-space-2) var(--tracker-space-3);
203
232
  }
204
233
 
205
234
  .stat-label {
206
- font-size: 10px;
235
+ font-size: var(--tracker-font-size-xs);
207
236
  color: var(--text3);
208
237
  text-transform: uppercase;
209
238
  letter-spacing: 0.4px;
@@ -211,10 +240,156 @@ input[type='range'] {
211
240
  }
212
241
 
213
242
  .stat-val {
214
- font-size: 20px;
243
+ font-size: var(--tracker-font-size-stat);
215
244
  font-weight: 500;
216
245
  }
217
246
 
247
+ .stat-val--ok {
248
+ color: var(--teal);
249
+ }
250
+
251
+ .stat-val--pending {
252
+ color: var(--amber);
253
+ }
254
+
255
+ .stat-val--error {
256
+ color: var(--red);
257
+ }
258
+
259
+ .stat-val--active {
260
+ color: var(--purple);
261
+ }
262
+
263
+ /* ── Tracker primitives ─────────────────────────────────────────────────── */
264
+ .tracker-view {
265
+ display: flex;
266
+ flex-direction: column;
267
+ height: 100%;
268
+ overflow: hidden;
269
+ padding: var(--tracker-space-3);
270
+ gap: var(--tracker-gap-view);
271
+ }
272
+
273
+ .tracker-stats-row {
274
+ display: grid;
275
+ grid-template-columns: repeat(4, minmax(0, 1fr));
276
+ gap: var(--tracker-gap-grid);
277
+ flex-shrink: 0;
278
+ }
279
+
280
+ .tracker-toolbar {
281
+ display: flex;
282
+ align-items: center;
283
+ gap: var(--tracker-gap-toolbar);
284
+ flex-shrink: 0;
285
+ flex-wrap: wrap;
286
+ }
287
+
288
+ .tracker-toolbar__spacer {
289
+ margin-left: auto;
290
+ }
291
+
292
+ .tracker-split {
293
+ display: flex;
294
+ gap: 0;
295
+ flex: 1;
296
+ overflow: hidden;
297
+ min-height: 0;
298
+ }
299
+
300
+ .tracker-table-wrap {
301
+ flex: 1;
302
+ overflow: auto;
303
+ border: var(--tracker-border-width) solid var(--border);
304
+ border-radius: var(--radius-lg);
305
+ }
306
+
307
+ .tracker-resize-handle {
308
+ width: var(--tracker-resize-handle-width);
309
+ flex-shrink: 0;
310
+ cursor: col-resize;
311
+ background: transparent;
312
+ position: relative;
313
+ z-index: 1;
314
+ margin: 0 var(--tracker-resize-handle-gutter);
315
+ }
316
+
317
+ .tracker-resize-handle::after {
318
+ content: '';
319
+ position: absolute;
320
+ inset: 0 3px;
321
+ border-radius: 2px;
322
+ background: var(--border);
323
+ opacity: 0;
324
+ transition: opacity var(--tracker-transition-ui);
325
+ }
326
+
327
+ .tracker-resize-handle:hover::after {
328
+ opacity: 1;
329
+ }
330
+
331
+ .tracker-detail-panel {
332
+ flex-shrink: 0;
333
+ display: flex;
334
+ flex-direction: column;
335
+ gap: var(--tracker-space-2);
336
+ overflow: auto;
337
+ border: var(--tracker-border-width) solid var(--border);
338
+ border-radius: var(--radius-lg);
339
+ padding: var(--tracker-space-3);
340
+ background: var(--bg3);
341
+ }
342
+
343
+ .tracker-detail-empty {
344
+ width: var(--tracker-panel-width);
345
+ flex-shrink: 0;
346
+ display: flex;
347
+ align-items: center;
348
+ justify-content: center;
349
+ color: var(--text3);
350
+ font-size: var(--tracker-font-size-md);
351
+ border: var(--tracker-border-width) dashed var(--border);
352
+ border-radius: var(--radius-lg);
353
+ }
354
+
355
+ .tracker-section-label {
356
+ font-size: var(--tracker-font-size-xs);
357
+ font-weight: 500;
358
+ text-transform: uppercase;
359
+ letter-spacing: 0.4px;
360
+ color: var(--text3);
361
+ }
362
+
363
+ .tracker-empty-cell {
364
+ text-align: center;
365
+ color: var(--text3);
366
+ padding: var(--tracker-space-5);
367
+ }
368
+
369
+ .tracker-mono-secondary {
370
+ font-size: var(--tracker-font-size-sm);
371
+ color: var(--text2);
372
+ }
373
+
374
+ .tracker-truncate {
375
+ display: block;
376
+ overflow: hidden;
377
+ text-overflow: ellipsis;
378
+ white-space: nowrap;
379
+ }
380
+
381
+ .tracker-progress-bar {
382
+ height: 4px;
383
+ background: var(--bg2);
384
+ border-radius: 2px;
385
+ overflow: hidden;
386
+ }
387
+
388
+ .tracker-progress-bar__fill {
389
+ height: 100%;
390
+ border-radius: 2px;
391
+ }
392
+
218
393
  /* ── Layout helpers ─────────────────────────────────────────────────────── */
219
394
  .flex {
220
395
  display: flex;