nuxt-devtools-observatory 0.1.32 → 0.1.33
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.
- package/README.md +5 -0
- package/client/.env.example +1 -0
- package/client/dist/assets/index-BqKYgjVB.js +20 -0
- package/client/dist/assets/index-bs1JBJ2u.css +1 -0
- package/client/dist/index.html +2 -2
- package/client/src/App.vue +4 -0
- package/client/src/components/Flamegraph.vue +4 -4
- package/client/src/components/SpanInspector.vue +1 -1
- package/client/src/composables/composable-search.ts +3 -0
- package/client/src/composables/trace-render-aggregation.ts +11 -2
- package/client/src/composables/useVirtualizationConfig.ts +40 -0
- package/client/src/composables/useVirtualizationFlags.ts +129 -0
- package/client/src/views/ComposableTracker.vue +212 -71
- package/client/src/views/FetchDashboard.vue +181 -16
- package/client/src/views/ProvideInjectGraph.vue +41 -18
- package/client/src/views/RenderHeatmap.vue +329 -75
- package/client/src/views/TraceViewer.vue +190 -20
- package/client/src/views/TransitionTimeline.vue +112 -19
- package/dist/module.d.mts +5 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +11 -22
- package/dist/runtime/composables/render-registry.js +6 -4
- package/dist/runtime/instrumentation/asyncData.d.ts +1 -1
- package/dist/runtime/instrumentation/fetch.d.ts +7 -1
- package/dist/runtime/instrumentation/fetch.js +22 -1
- package/dist/runtime/plugin.js +4 -1
- package/dist/runtime/test-bridge.d.ts +18 -0
- package/dist/runtime/test-bridge.js +86 -0
- package/package.json +14 -3
- package/client/dist/assets/index-5Wl1XYRH.js +0 -17
- package/client/dist/assets/index-DT_QUiIh.css +0 -1
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { ref, computed } from 'vue'
|
|
3
|
+
import { useVirtualizer } from '@tanstack/vue-virtual'
|
|
4
|
+
import { useVirtualizationConfig } from '@observatory-client/composables/useVirtualizationConfig'
|
|
5
|
+
import { useVirtualizationFlags } from '@observatory-client/composables/useVirtualizationFlags'
|
|
3
6
|
import {
|
|
4
7
|
useObservatoryData,
|
|
5
8
|
setComposableMode,
|
|
@@ -93,6 +96,10 @@ function openInEditor(file: string) {
|
|
|
93
96
|
const filter = ref('all')
|
|
94
97
|
const search = ref('')
|
|
95
98
|
const expanded = ref<string | null>(null)
|
|
99
|
+
const listScrollRef = ref<HTMLElement | null>(null)
|
|
100
|
+
|
|
101
|
+
const { effective: virtualizationFlags } = useVirtualizationFlags()
|
|
102
|
+
const { preset: virtualizationPreset } = useVirtualizationConfig({ rowHeight: 88, overscan: 6 })
|
|
96
103
|
|
|
97
104
|
const entries = computed<RuntimeComposableEntry[]>(() => rawEntries.value)
|
|
98
105
|
|
|
@@ -142,6 +149,99 @@ const filtered = computed(() => {
|
|
|
142
149
|
return [...layoutEntries, ...regularEntries]
|
|
143
150
|
})
|
|
144
151
|
|
|
152
|
+
const virtualizedCardsEnabled = computed(() => virtualizationFlags.value.composables && expanded.value === null)
|
|
153
|
+
|
|
154
|
+
const listVirtualizerOptions = computed(() => ({
|
|
155
|
+
count: filtered.value.length,
|
|
156
|
+
getScrollElement: () => listScrollRef.value,
|
|
157
|
+
estimateSize: () => virtualizationPreset.value.rowHeight,
|
|
158
|
+
overscan: virtualizationPreset.value.overscan,
|
|
159
|
+
}))
|
|
160
|
+
|
|
161
|
+
const listVirtualizer = useVirtualizer(listVirtualizerOptions)
|
|
162
|
+
|
|
163
|
+
const listVirtualItems = computed(() => {
|
|
164
|
+
if (!virtualizedCardsEnabled.value) {
|
|
165
|
+
return []
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return listVirtualizer.value.getVirtualItems()
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
const topListPadding = computed(() => {
|
|
172
|
+
if (!virtualizedCardsEnabled.value || listVirtualItems.value.length === 0) {
|
|
173
|
+
return 0
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return listVirtualItems.value[0].start
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
const bottomListPadding = computed(() => {
|
|
180
|
+
if (!virtualizedCardsEnabled.value || listVirtualItems.value.length === 0) {
|
|
181
|
+
return 0
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const total = listVirtualizer.value.getTotalSize()
|
|
185
|
+
const last = listVirtualItems.value[listVirtualItems.value.length - 1]
|
|
186
|
+
|
|
187
|
+
return Math.max(0, total - last.end)
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
const visibleEntries = computed(() => {
|
|
191
|
+
if (!virtualizedCardsEnabled.value) {
|
|
192
|
+
return filtered.value
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return listVirtualItems.value
|
|
196
|
+
.map((item) => filtered.value[item.index])
|
|
197
|
+
.filter((entry): entry is RuntimeComposableEntry => Boolean(entry))
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
const visibleEntryCards = computed<VisibleEntryCard[]>(() => {
|
|
201
|
+
return visibleEntries.value.map((entry) => {
|
|
202
|
+
const refEntries = Object.entries(entry.refs) as Array<[string, RuntimeComposableEntry['refs'][string]]>
|
|
203
|
+
const detailRefs: RefRowView[] = refEntries.map(([key, ref]) => {
|
|
204
|
+
const isLong = isLongValue(ref.value)
|
|
205
|
+
const expanded = isLong && isRefExpanded(entry.id, key)
|
|
206
|
+
const shared = Boolean(entry.sharedKeys?.includes(key))
|
|
207
|
+
|
|
208
|
+
return {
|
|
209
|
+
key,
|
|
210
|
+
ref,
|
|
211
|
+
isLong,
|
|
212
|
+
expanded,
|
|
213
|
+
displayValue: isLong && !expanded ? formatVal(ref.value) : formatValFull(ref.value),
|
|
214
|
+
typeClass: typeBadgeClass(ref.type),
|
|
215
|
+
shared,
|
|
216
|
+
}
|
|
217
|
+
})
|
|
218
|
+
|
|
219
|
+
const history = entry.history ?? []
|
|
220
|
+
const historyRows: HistoryRowView[] = []
|
|
221
|
+
const end = Math.max(history.length - 20, 0)
|
|
222
|
+
|
|
223
|
+
for (let i = history.length - 1; i >= end; i--) {
|
|
224
|
+
const evt = history[i]
|
|
225
|
+
historyRows.push({
|
|
226
|
+
id: `${entry.id}-${evt.key}-${evt.t}-${i}`,
|
|
227
|
+
timeLabel: `+${(evt.t / 1000).toFixed(2)}s`,
|
|
228
|
+
key: evt.key,
|
|
229
|
+
value: formatVal(evt.value),
|
|
230
|
+
})
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return {
|
|
234
|
+
entry,
|
|
235
|
+
refCount: refEntries.length,
|
|
236
|
+
previewRefs: detailRefs.slice(0, 3),
|
|
237
|
+
detailRefs,
|
|
238
|
+
historyRows,
|
|
239
|
+
historyHiddenCount: Math.max(0, history.length - 20),
|
|
240
|
+
lifecycle: lifecycleRows(entry),
|
|
241
|
+
}
|
|
242
|
+
})
|
|
243
|
+
})
|
|
244
|
+
|
|
145
245
|
function lifecycleRows(entry: RuntimeComposableEntry) {
|
|
146
246
|
return [
|
|
147
247
|
{
|
|
@@ -229,6 +329,33 @@ interface LookupTarget {
|
|
|
229
329
|
identityGroup?: string
|
|
230
330
|
}
|
|
231
331
|
|
|
332
|
+
interface RefRowView {
|
|
333
|
+
key: string
|
|
334
|
+
ref: RuntimeComposableEntry['refs'][string]
|
|
335
|
+
isLong: boolean
|
|
336
|
+
expanded: boolean
|
|
337
|
+
displayValue: string
|
|
338
|
+
typeClass: string
|
|
339
|
+
shared: boolean
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
interface HistoryRowView {
|
|
343
|
+
id: string
|
|
344
|
+
timeLabel: string
|
|
345
|
+
key: string
|
|
346
|
+
value: string
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
interface VisibleEntryCard {
|
|
350
|
+
entry: RuntimeComposableEntry
|
|
351
|
+
refCount: number
|
|
352
|
+
previewRefs: RefRowView[]
|
|
353
|
+
detailRefs: RefRowView[]
|
|
354
|
+
historyRows: HistoryRowView[]
|
|
355
|
+
historyHiddenCount: number
|
|
356
|
+
lifecycle: ReturnType<typeof lifecycleRows>
|
|
357
|
+
}
|
|
358
|
+
|
|
232
359
|
const lookupTarget = ref<LookupTarget | null>(null)
|
|
233
360
|
|
|
234
361
|
const lookupResults = computed(() => {
|
|
@@ -371,131 +498,133 @@ function applyEdit() {
|
|
|
371
498
|
</button>
|
|
372
499
|
</div>
|
|
373
500
|
|
|
374
|
-
<div class="composable-tracker__list">
|
|
501
|
+
<div ref="listScrollRef" class="composable-tracker__list">
|
|
375
502
|
<div
|
|
376
|
-
v-
|
|
377
|
-
|
|
503
|
+
v-if="virtualizedCardsEnabled && topListPadding > 0"
|
|
504
|
+
class="composable-tracker__virtual-spacer"
|
|
505
|
+
:style="{ height: `${topListPadding}px` }"
|
|
506
|
+
aria-hidden="true"
|
|
507
|
+
/>
|
|
508
|
+
<div
|
|
509
|
+
v-for="card in visibleEntryCards"
|
|
510
|
+
:key="card.entry.id"
|
|
378
511
|
class="composable-tracker__card"
|
|
379
512
|
:class="{
|
|
380
|
-
'composable-tracker__card--leak': entry.leak,
|
|
381
|
-
'composable-tracker__card--expanded': expanded === entry.id,
|
|
513
|
+
'composable-tracker__card--leak': card.entry.leak,
|
|
514
|
+
'composable-tracker__card--expanded': expanded === card.entry.id,
|
|
382
515
|
}"
|
|
383
|
-
@click="expanded = expanded === entry.id ? null : entry.id"
|
|
516
|
+
@click="expanded = expanded === card.entry.id ? null : card.entry.id"
|
|
384
517
|
>
|
|
385
518
|
<div class="composable-tracker__card-header">
|
|
386
519
|
<div class="composable-tracker__identity">
|
|
387
|
-
<span class="composable-tracker__name mono">{{ entry.name }}</span>
|
|
388
|
-
<span class="composable-tracker__file muted mono">{{ basename(entry.componentFile) }}</span>
|
|
520
|
+
<span class="composable-tracker__name mono">{{ card.entry.name }}</span>
|
|
521
|
+
<span class="composable-tracker__file muted mono">{{ basename(card.entry.componentFile) }}</span>
|
|
389
522
|
</div>
|
|
390
523
|
<div class="composable-tracker__meta">
|
|
391
|
-
<span v-if="entry.watcherCount > 0 && !entry.leak" class="badge badge-warn">
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
<span v-
|
|
524
|
+
<span v-if="card.entry.watcherCount > 0 && !card.entry.leak" class="badge badge-warn">
|
|
525
|
+
{{ card.entry.watcherCount }}w
|
|
526
|
+
</span>
|
|
527
|
+
<span v-if="card.entry.intervalCount > 0 && !card.entry.leak" class="badge badge-warn">
|
|
528
|
+
{{ card.entry.intervalCount }}t
|
|
529
|
+
</span>
|
|
530
|
+
<span v-if="card.entry.leak" class="badge badge-err">leak</span>
|
|
531
|
+
<span v-else-if="card.entry.status === 'mounted'" class="badge badge-ok">mounted</span>
|
|
395
532
|
<span v-else class="badge badge-gray">unmounted</span>
|
|
396
533
|
</div>
|
|
397
534
|
</div>
|
|
398
535
|
|
|
399
536
|
<!-- Inline ref preview — shows up to 3 refs without expanding -->
|
|
400
|
-
<div v-if="
|
|
537
|
+
<div v-if="card.refCount" class="composable-tracker__refs-preview">
|
|
401
538
|
<span
|
|
402
|
-
v-for="
|
|
403
|
-
:key="
|
|
539
|
+
v-for="row in card.previewRefs"
|
|
540
|
+
:key="row.key"
|
|
404
541
|
class="composable-tracker__ref-chip"
|
|
405
542
|
:class="{
|
|
406
|
-
'composable-tracker__ref-chip--reactive':
|
|
407
|
-
'composable-tracker__ref-chip--computed':
|
|
408
|
-
'composable-tracker__ref-chip--shared':
|
|
543
|
+
'composable-tracker__ref-chip--reactive': row.ref.type === 'reactive',
|
|
544
|
+
'composable-tracker__ref-chip--computed': row.ref.type === 'computed',
|
|
545
|
+
'composable-tracker__ref-chip--shared': row.shared,
|
|
409
546
|
}"
|
|
410
|
-
:title="
|
|
547
|
+
:title="row.shared ? 'shared global state' : ''"
|
|
411
548
|
>
|
|
412
|
-
<span class="composable-tracker__ref-chip-key">{{
|
|
413
|
-
<span class="composable-tracker__ref-chip-val">{{ formatVal(
|
|
414
|
-
<span v-if="
|
|
415
|
-
</span>
|
|
416
|
-
<span v-if="Object.keys(entry.refs).length > 3" class="muted text-sm">
|
|
417
|
-
+{{ Object.keys(entry.refs).length - 3 }} more
|
|
549
|
+
<span class="composable-tracker__ref-chip-key">{{ row.key }}</span>
|
|
550
|
+
<span class="composable-tracker__ref-chip-val">{{ formatVal(row.ref.value) }}</span>
|
|
551
|
+
<span v-if="row.shared" class="composable-tracker__ref-chip-shared-dot" title="global"></span>
|
|
418
552
|
</span>
|
|
553
|
+
<span v-if="card.refCount > 3" class="muted text-sm">+{{ card.refCount - 3 }} more</span>
|
|
419
554
|
</div>
|
|
420
555
|
|
|
421
|
-
<div v-if="expanded === entry.id" class="composable-tracker__detail" @click.stop>
|
|
422
|
-
<div v-if="entry.leak" class="composable-tracker__leak-banner">{{ entry.leakReason }}</div>
|
|
556
|
+
<div v-if="expanded === card.entry.id" class="composable-tracker__detail" @click.stop>
|
|
557
|
+
<div v-if="card.entry.leak" class="composable-tracker__leak-banner">{{ card.entry.leakReason }}</div>
|
|
423
558
|
|
|
424
559
|
<!-- Global state warning -->
|
|
425
|
-
<div v-if="entry.sharedKeys?.length" class="composable-tracker__global-banner">
|
|
560
|
+
<div v-if="card.entry.sharedKeys?.length" class="composable-tracker__global-banner">
|
|
426
561
|
<span class="composable-tracker__global-dot"></span>
|
|
427
562
|
<span>
|
|
428
563
|
<strong>global state</strong>
|
|
429
|
-
— {{ entry.sharedKeys.join(', ') }}
|
|
430
|
-
{{ entry.sharedKeys.length === 1 ? 'is' : 'are' }}
|
|
431
|
-
shared across all instances of {{ entry.name }}
|
|
564
|
+
— {{ card.entry.sharedKeys.join(', ') }}
|
|
565
|
+
{{ card.entry.sharedKeys.length === 1 ? 'is' : 'are' }}
|
|
566
|
+
shared across all instances of {{ card.entry.name }}
|
|
432
567
|
</span>
|
|
433
568
|
</div>
|
|
434
569
|
|
|
435
570
|
<div class="composable-tracker__section-label tracker-section-label">reactive state</div>
|
|
436
|
-
<div v-if="!
|
|
437
|
-
|
|
438
|
-
</div>
|
|
439
|
-
<div v-for="[k, v] in Object.entries(entry.refs)" :key="k" class="composable-tracker__ref-row">
|
|
571
|
+
<div v-if="!card.refCount" class="composable-tracker__compact-muted muted text-sm">no tracked state returned</div>
|
|
572
|
+
<div v-for="row in card.detailRefs" :key="row.key" class="composable-tracker__ref-row">
|
|
440
573
|
<span
|
|
441
574
|
class="composable-tracker__ref-key composable-tracker__ref-key--clickable mono text-sm"
|
|
442
575
|
:title="
|
|
443
|
-
entry.sharedKeyGroups?.[
|
|
444
|
-
? `click to see instances sharing this exact '${
|
|
445
|
-
: `click to see all instances exposing '${
|
|
576
|
+
card.entry.sharedKeyGroups?.[row.key]
|
|
577
|
+
? `click to see instances sharing this exact '${row.key}' state`
|
|
578
|
+
: `click to see all instances exposing '${row.key}'`
|
|
446
579
|
"
|
|
447
|
-
@click.stop="openLookup(entry,
|
|
580
|
+
@click.stop="openLookup(card.entry, row.key)"
|
|
448
581
|
>
|
|
449
|
-
{{
|
|
582
|
+
{{ row.key }}
|
|
450
583
|
</span>
|
|
451
584
|
<span
|
|
452
585
|
class="composable-tracker__ref-val mono text-sm"
|
|
453
586
|
:class="{
|
|
454
|
-
'composable-tracker__ref-val--full':
|
|
455
|
-
'composable-tracker__ref-val--collapsed':
|
|
587
|
+
'composable-tracker__ref-val--full': row.isLong && row.expanded,
|
|
588
|
+
'composable-tracker__ref-val--collapsed': row.isLong && !row.expanded,
|
|
456
589
|
}"
|
|
457
590
|
>
|
|
458
|
-
{{
|
|
591
|
+
{{ row.displayValue }}
|
|
459
592
|
</span>
|
|
460
593
|
<div class="composable-tracker__ref-row-actions">
|
|
461
594
|
<button
|
|
462
|
-
v-if="
|
|
595
|
+
v-if="row.isLong"
|
|
463
596
|
class="composable-tracker__expand-btn"
|
|
464
|
-
:title="
|
|
465
|
-
@click.stop="toggleRefExpand(entry.id,
|
|
597
|
+
:title="row.expanded ? 'Collapse' : 'Expand'"
|
|
598
|
+
@click.stop="toggleRefExpand(card.entry.id, row.key)"
|
|
466
599
|
>
|
|
467
|
-
{{
|
|
600
|
+
{{ row.expanded ? '▲' : '▼' }}
|
|
468
601
|
</button>
|
|
469
|
-
<span class="badge text-xs" :class="
|
|
470
|
-
<span v-if="
|
|
602
|
+
<span class="badge text-xs" :class="row.typeClass">{{ row.ref.type }}</span>
|
|
603
|
+
<span v-if="row.shared" class="badge badge-amber text-xs">global</span>
|
|
471
604
|
<button
|
|
472
|
-
v-if="
|
|
605
|
+
v-if="row.ref.type === 'ref'"
|
|
473
606
|
class="composable-tracker__edit-btn"
|
|
474
607
|
title="Edit value"
|
|
475
|
-
@click.stop="openEdit(entry.id,
|
|
608
|
+
@click.stop="openEdit(card.entry.id, row.key, row.ref.value)"
|
|
476
609
|
>
|
|
477
610
|
edit
|
|
478
611
|
</button>
|
|
479
612
|
</div>
|
|
480
613
|
</div>
|
|
481
614
|
|
|
482
|
-
<template v-if="
|
|
615
|
+
<template v-if="card.historyRows.length">
|
|
483
616
|
<div class="composable-tracker__section-label composable-tracker__section-label--spaced tracker-section-label">
|
|
484
617
|
change history
|
|
485
|
-
<span class="composable-tracker__section-label-meta muted">({{ entry.history.length }} events)</span>
|
|
618
|
+
<span class="composable-tracker__section-label-meta muted">({{ card.entry.history.length }} events)</span>
|
|
486
619
|
</div>
|
|
487
620
|
<div class="composable-tracker__history-list">
|
|
488
|
-
<div
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
class="composable-tracker__history-
|
|
492
|
-
>
|
|
493
|
-
<span class="composable-tracker__history-time mono muted">+{{ (evt.t / 1000).toFixed(2) }}s</span>
|
|
494
|
-
<span class="composable-tracker__history-key mono">{{ evt.key }}</span>
|
|
495
|
-
<span class="composable-tracker__history-val mono">{{ formatVal(evt.value) }}</span>
|
|
621
|
+
<div v-for="historyRow in card.historyRows" :key="historyRow.id" class="composable-tracker__history-row">
|
|
622
|
+
<span class="composable-tracker__history-time mono muted">{{ historyRow.timeLabel }}</span>
|
|
623
|
+
<span class="composable-tracker__history-key mono">{{ historyRow.key }}</span>
|
|
624
|
+
<span class="composable-tracker__history-val mono">{{ historyRow.value }}</span>
|
|
496
625
|
</div>
|
|
497
|
-
<div v-if="
|
|
498
|
-
… {{
|
|
626
|
+
<div v-if="card.historyHiddenCount > 0" class="composable-tracker__compact-muted muted text-sm">
|
|
627
|
+
… {{ card.historyHiddenCount }} earlier events
|
|
499
628
|
</div>
|
|
500
629
|
</div>
|
|
501
630
|
</template>
|
|
@@ -503,7 +632,7 @@ function applyEdit() {
|
|
|
503
632
|
<div class="composable-tracker__section-label composable-tracker__section-label--spaced tracker-section-label">
|
|
504
633
|
lifecycle
|
|
505
634
|
</div>
|
|
506
|
-
<div v-for="row in
|
|
635
|
+
<div v-for="row in card.lifecycle" :key="row.label" class="composable-tracker__lifecycle-row">
|
|
507
636
|
<span
|
|
508
637
|
class="composable-tracker__lifecycle-dot"
|
|
509
638
|
:class="row.ok ? 'composable-tracker__lifecycle-dot--ok' : 'composable-tracker__lifecycle-dot--error'"
|
|
@@ -522,12 +651,12 @@ function applyEdit() {
|
|
|
522
651
|
</div>
|
|
523
652
|
<div class="composable-tracker__lifecycle-row">
|
|
524
653
|
<span class="composable-tracker__context-label muted text-sm">component</span>
|
|
525
|
-
<span class="composable-tracker__context-value mono text-sm">{{ basename(entry.componentFile) }}</span>
|
|
654
|
+
<span class="composable-tracker__context-value mono text-sm">{{ basename(card.entry.componentFile) }}</span>
|
|
526
655
|
</div>
|
|
527
656
|
<div class="composable-tracker__lifecycle-row">
|
|
528
657
|
<span class="composable-tracker__context-label muted text-sm">uid</span>
|
|
529
658
|
<span class="composable-tracker__context-value composable-tracker__context-value--muted mono text-sm muted">
|
|
530
|
-
{{ entry.componentUid }}
|
|
659
|
+
{{ card.entry.componentUid }}
|
|
531
660
|
</span>
|
|
532
661
|
</div>
|
|
533
662
|
<div class="composable-tracker__lifecycle-row">
|
|
@@ -535,8 +664,8 @@ function applyEdit() {
|
|
|
535
664
|
<span
|
|
536
665
|
class="composable-tracker__context-value composable-tracker__context-value--row composable-tracker__context-value--muted mono text-sm muted"
|
|
537
666
|
>
|
|
538
|
-
{{ entry.file }}:{{ entry.line }}
|
|
539
|
-
<button class="composable-tracker__jump-btn" title="Open in editor" @click.stop="openInEditor(entry.file)">
|
|
667
|
+
{{ card.entry.file }}:{{ card.entry.line }}
|
|
668
|
+
<button class="composable-tracker__jump-btn" title="Open in editor" @click.stop="openInEditor(card.entry.file)">
|
|
540
669
|
open ↗
|
|
541
670
|
</button>
|
|
542
671
|
</span>
|
|
@@ -544,20 +673,27 @@ function applyEdit() {
|
|
|
544
673
|
<div class="composable-tracker__lifecycle-row">
|
|
545
674
|
<span class="composable-tracker__context-label muted text-sm">route</span>
|
|
546
675
|
<span class="composable-tracker__context-value composable-tracker__context-value--muted mono text-sm muted">
|
|
547
|
-
{{ entry.route }}
|
|
676
|
+
{{ card.entry.route }}
|
|
548
677
|
</span>
|
|
549
678
|
</div>
|
|
550
679
|
<div class="composable-tracker__lifecycle-row">
|
|
551
680
|
<span class="composable-tracker__context-label muted text-sm">watchers</span>
|
|
552
|
-
<span class="composable-tracker__context-value mono text-sm">{{ entry.watcherCount }}</span>
|
|
681
|
+
<span class="composable-tracker__context-value mono text-sm">{{ card.entry.watcherCount }}</span>
|
|
553
682
|
</div>
|
|
554
683
|
<div class="composable-tracker__lifecycle-row">
|
|
555
684
|
<span class="composable-tracker__context-label muted text-sm">intervals</span>
|
|
556
|
-
<span class="composable-tracker__context-value mono text-sm">{{ entry.intervalCount }}</span>
|
|
685
|
+
<span class="composable-tracker__context-value mono text-sm">{{ card.entry.intervalCount }}</span>
|
|
557
686
|
</div>
|
|
558
687
|
</div>
|
|
559
688
|
</div>
|
|
560
689
|
|
|
690
|
+
<div
|
|
691
|
+
v-if="virtualizedCardsEnabled && bottomListPadding > 0"
|
|
692
|
+
class="composable-tracker__virtual-spacer"
|
|
693
|
+
:style="{ height: `${bottomListPadding}px` }"
|
|
694
|
+
aria-hidden="true"
|
|
695
|
+
/>
|
|
696
|
+
|
|
561
697
|
<div v-if="!filtered.length" class="composable-tracker__empty muted text-sm">
|
|
562
698
|
{{ connected ? 'No composables recorded yet.' : 'Waiting for connection to the Nuxt app…' }}
|
|
563
699
|
</div>
|
|
@@ -644,6 +780,11 @@ function applyEdit() {
|
|
|
644
780
|
min-height: 0;
|
|
645
781
|
}
|
|
646
782
|
|
|
783
|
+
.composable-tracker__virtual-spacer {
|
|
784
|
+
width: 100%;
|
|
785
|
+
flex-shrink: 0;
|
|
786
|
+
}
|
|
787
|
+
|
|
647
788
|
.composable-tracker__card {
|
|
648
789
|
background: var(--bg3);
|
|
649
790
|
border: var(--tracker-border-width) solid var(--border);
|