nuxt-devtools-observatory 0.1.28 → 0.1.31
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 +93 -11
- package/client/.env +2 -1
- package/client/.env.example +2 -1
- package/client/dist/assets/index-BuMXDBO9.js +17 -0
- package/client/dist/assets/index-CwcspZ6w.css +1 -0
- package/client/dist/index.html +2 -2
- package/client/src/App.vue +4 -0
- package/client/src/components/Flamegraph.vue +443 -0
- package/client/src/components/SpanInspector.vue +446 -0
- package/client/src/components/TraceFilter.vue +344 -0
- package/client/src/components/WaterfallView.vue +443 -0
- package/client/src/composables/useResizablePane.ts +65 -0
- package/client/src/composables/useTraceFilter.ts +164 -0
- package/client/src/stores/observatory.ts +16 -2
- package/client/src/style.css +203 -28
- package/client/src/views/ComposableTracker.vue +324 -259
- package/client/src/views/FetchDashboard.vue +104 -133
- package/client/src/views/ProvideInjectGraph.vue +99 -109
- package/client/src/views/RenderHeatmap.vue +191 -147
- package/client/src/views/TraceViewer.vue +599 -0
- package/client/src/views/TransitionTimeline.vue +167 -137
- package/client/tsconfig.json +3 -1
- package/client/vite.config.ts +8 -0
- package/dist/module.d.mts +5 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +186 -200
- package/dist/runtime/composables/render-registry.js +66 -110
- package/dist/runtime/composables/transition-registry.js +103 -28
- package/dist/runtime/instrumentation/asyncData.d.ts +9 -0
- package/dist/runtime/instrumentation/asyncData.js +49 -0
- package/dist/runtime/instrumentation/component.d.ts +2 -0
- package/dist/runtime/instrumentation/component.js +126 -0
- package/dist/runtime/instrumentation/fetch.d.ts +2 -0
- package/dist/runtime/instrumentation/fetch.js +89 -0
- package/dist/runtime/instrumentation/route.d.ts +6 -0
- package/dist/runtime/instrumentation/route.js +41 -0
- package/dist/runtime/plugin.js +39 -3
- package/dist/runtime/tracing/context.d.ts +9 -0
- package/dist/runtime/tracing/context.js +15 -0
- package/dist/runtime/tracing/trace.d.ts +25 -0
- package/dist/runtime/tracing/trace.js +0 -0
- package/dist/runtime/tracing/traceStore.d.ts +39 -0
- package/dist/runtime/tracing/traceStore.js +101 -0
- package/dist/runtime/tracing/tracing.d.ts +27 -0
- package/dist/runtime/tracing/tracing.js +48 -0
- package/package.json +9 -6
- package/client/dist/assets/index-DXCGQOSF.js +0 -17
- package/client/dist/assets/index-htI4WwBU.css +0 -1
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { ref, computed } from 'vue'
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
3
|
+
import { useResizablePane } from '@observatory-client/composables/useResizablePane'
|
|
4
|
+
import { useObservatoryData } from '@observatory-client/stores/observatory'
|
|
5
|
+
import type { TransitionEntry } from '@observatory/types/snapshot'
|
|
5
6
|
|
|
6
7
|
const { transitions: entries, connected } = useObservatoryData()
|
|
8
|
+
const { paneWidth: detailWidth, onHandleMouseDown } = useResizablePane(260, 'observatory:transitions:detailWidth')
|
|
7
9
|
|
|
8
10
|
type FilterMode = 'all' | 'cancelled' | 'active' | 'completed'
|
|
9
11
|
const filter = ref<FilterMode>('all')
|
|
@@ -26,12 +28,7 @@ const filtered = computed(() => {
|
|
|
26
28
|
list = list.filter((e) => e.phase === 'entered' || e.phase === 'left')
|
|
27
29
|
}
|
|
28
30
|
|
|
29
|
-
return list.sort((a, b) =>
|
|
30
|
-
const aTime = a.endTime ?? a.startTime
|
|
31
|
-
const bTime = b.endTime ?? b.startTime
|
|
32
|
-
|
|
33
|
-
return bTime - aTime
|
|
34
|
-
})
|
|
31
|
+
return list.sort((a, b) => a.startTime - b.startTime)
|
|
35
32
|
})
|
|
36
33
|
|
|
37
34
|
const stats = computed(() => ({
|
|
@@ -129,19 +126,19 @@ function directionColor(e: TransitionEntry): string {
|
|
|
129
126
|
</script>
|
|
130
127
|
|
|
131
128
|
<template>
|
|
132
|
-
<div class="timeline-
|
|
129
|
+
<div class="transition-timeline tracker-view">
|
|
133
130
|
<!-- Stats bar -->
|
|
134
|
-
<div class="stats-row">
|
|
131
|
+
<div class="transition-timeline__stats tracker-stats-row">
|
|
135
132
|
<div class="stat-card">
|
|
136
133
|
<div class="stat-val">{{ stats.total }}</div>
|
|
137
134
|
<div class="stat-label">total</div>
|
|
138
135
|
</div>
|
|
139
136
|
<div class="stat-card">
|
|
140
|
-
<div class="stat-val
|
|
137
|
+
<div class="stat-val stat-val--active">{{ stats.active }}</div>
|
|
141
138
|
<div class="stat-label">active</div>
|
|
142
139
|
</div>
|
|
143
140
|
<div class="stat-card">
|
|
144
|
-
<div class="stat-val
|
|
141
|
+
<div class="stat-val stat-val--error">{{ stats.cancelled }}</div>
|
|
145
142
|
<div class="stat-label">cancelled</div>
|
|
146
143
|
</div>
|
|
147
144
|
<div class="stat-card">
|
|
@@ -154,9 +151,9 @@ function directionColor(e: TransitionEntry): string {
|
|
|
154
151
|
</div>
|
|
155
152
|
|
|
156
153
|
<!-- Toolbar -->
|
|
157
|
-
<div class="toolbar">
|
|
158
|
-
<input v-model="search" type="search" placeholder="filter by name or component…" class="
|
|
159
|
-
<div class="
|
|
154
|
+
<div class="transition-timeline__toolbar tracker-toolbar">
|
|
155
|
+
<input v-model="search" type="search" placeholder="filter by name or component…" class="transition-timeline__search" />
|
|
156
|
+
<div class="transition-timeline__filters">
|
|
160
157
|
<button :class="{ active: filter === 'all' }" @click="filter = 'all'">All</button>
|
|
161
158
|
<button :class="{ active: filter === 'active' }" @click="filter = 'active'">Active</button>
|
|
162
159
|
<button :class="{ active: filter === 'completed' }" @click="filter = 'completed'">Completed</button>
|
|
@@ -167,16 +164,16 @@ function directionColor(e: TransitionEntry): string {
|
|
|
167
164
|
</div>
|
|
168
165
|
|
|
169
166
|
<!-- Main content -->
|
|
170
|
-
<div class="
|
|
167
|
+
<div class="transition-timeline__content tracker-split">
|
|
171
168
|
<!-- Timeline table -->
|
|
172
|
-
<div class="
|
|
169
|
+
<div class="transition-timeline__table tracker-table-wrap">
|
|
173
170
|
<table class="data-table">
|
|
174
171
|
<thead>
|
|
175
172
|
<tr>
|
|
176
|
-
<th
|
|
177
|
-
<th
|
|
178
|
-
<th
|
|
179
|
-
<th
|
|
173
|
+
<th class="transition-timeline__col-name">NAME</th>
|
|
174
|
+
<th class="transition-timeline__col-dir">DIR</th>
|
|
175
|
+
<th class="transition-timeline__col-phase">PHASE</th>
|
|
176
|
+
<th class="transition-timeline__col-duration">DURATION</th>
|
|
180
177
|
<th>COMPONENT</th>
|
|
181
178
|
<th>TIMELINE</th>
|
|
182
179
|
</tr>
|
|
@@ -189,24 +186,24 @@ function directionColor(e: TransitionEntry): string {
|
|
|
189
186
|
@click="selected = selected?.id === entry.id ? null : entry"
|
|
190
187
|
>
|
|
191
188
|
<td>
|
|
192
|
-
<span class="
|
|
189
|
+
<span class="transition-timeline__name mono">{{ entry.transitionName }}</span>
|
|
193
190
|
</td>
|
|
194
191
|
<td>
|
|
195
|
-
<span class="
|
|
192
|
+
<span class="transition-timeline__direction mono" :style="{ color: directionColor(entry) }">
|
|
196
193
|
{{ directionLabel(entry) }}
|
|
197
194
|
</span>
|
|
198
195
|
</td>
|
|
199
196
|
<td>
|
|
200
197
|
<span class="badge" :class="phaseBadgeClass(entry.phase)">{{ entry.phase }}</span>
|
|
201
198
|
</td>
|
|
202
|
-
<td class="
|
|
199
|
+
<td class="transition-timeline__duration mono">
|
|
203
200
|
{{ entry.durationMs !== undefined ? entry.durationMs + 'ms' : '—' }}
|
|
204
201
|
</td>
|
|
205
|
-
<td class="
|
|
206
|
-
<td class="
|
|
207
|
-
<div class="
|
|
202
|
+
<td class="transition-timeline__component muted">{{ entry.parentComponent }}</td>
|
|
203
|
+
<td class="transition-timeline__bar-cell">
|
|
204
|
+
<div class="transition-timeline__bar-track">
|
|
208
205
|
<div
|
|
209
|
-
class="
|
|
206
|
+
class="transition-timeline__bar-fill"
|
|
210
207
|
:style="{
|
|
211
208
|
left: timelineGeometry[i]?.left + '%',
|
|
212
209
|
width: Math.max(timelineGeometry[i]?.width ?? 1, 1) + '%',
|
|
@@ -219,7 +216,7 @@ function directionColor(e: TransitionEntry): string {
|
|
|
219
216
|
</tr>
|
|
220
217
|
|
|
221
218
|
<tr v-if="!filtered.length">
|
|
222
|
-
<td colspan="6"
|
|
219
|
+
<td colspan="6" class="tracker-empty-cell">
|
|
223
220
|
{{
|
|
224
221
|
connected
|
|
225
222
|
? 'No transitions recorded yet — trigger one on the page.'
|
|
@@ -233,46 +230,59 @@ function directionColor(e: TransitionEntry): string {
|
|
|
233
230
|
|
|
234
231
|
<!-- Detail panel -->
|
|
235
232
|
<transition name="panel-slide">
|
|
236
|
-
<
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
233
|
+
<div v-if="selected" class="tracker-resize-handle" @mousedown="onHandleMouseDown" />
|
|
234
|
+
</transition>
|
|
235
|
+
<transition name="panel-slide">
|
|
236
|
+
<aside v-if="selected" class="transition-timeline__detail" :style="{ width: detailWidth + 'px' }">
|
|
237
|
+
<div class="transition-timeline__detail-header">
|
|
238
|
+
<span class="transition-timeline__detail-title">{{ selected.transitionName }}</span>
|
|
239
|
+
<button class="transition-timeline__close-btn" @click="selected = null">✕</button>
|
|
240
240
|
</div>
|
|
241
241
|
|
|
242
|
-
<div class="
|
|
243
|
-
<div class="
|
|
244
|
-
<span class="
|
|
245
|
-
<span class="
|
|
242
|
+
<div class="transition-timeline__detail-section">
|
|
243
|
+
<div class="transition-timeline__detail-row">
|
|
244
|
+
<span class="transition-timeline__detail-key">Direction</span>
|
|
245
|
+
<span class="transition-timeline__detail-val" :style="{ color: directionColor(selected) }">
|
|
246
|
+
{{ directionLabel(selected) }}
|
|
247
|
+
</span>
|
|
246
248
|
</div>
|
|
247
|
-
<div class="
|
|
248
|
-
<span class="
|
|
249
|
+
<div class="transition-timeline__detail-row">
|
|
250
|
+
<span class="transition-timeline__detail-key">Phase</span>
|
|
249
251
|
<span class="badge" :class="phaseBadgeClass(selected.phase)">{{ selected.phase }}</span>
|
|
250
252
|
</div>
|
|
251
|
-
<div class="
|
|
252
|
-
<span class="
|
|
253
|
-
<span class="
|
|
253
|
+
<div class="transition-timeline__detail-row">
|
|
254
|
+
<span class="transition-timeline__detail-key">Component</span>
|
|
255
|
+
<span class="transition-timeline__detail-val transition-timeline__detail-val--mono mono">
|
|
256
|
+
{{ selected.parentComponent }}
|
|
257
|
+
</span>
|
|
254
258
|
</div>
|
|
255
|
-
<div v-if="selected.mode" class="
|
|
256
|
-
<span class="
|
|
257
|
-
<span class="
|
|
259
|
+
<div v-if="selected.mode" class="transition-timeline__detail-row">
|
|
260
|
+
<span class="transition-timeline__detail-key">Mode</span>
|
|
261
|
+
<span class="transition-timeline__detail-val transition-timeline__detail-val--mono mono">
|
|
262
|
+
{{ selected.mode }}
|
|
263
|
+
</span>
|
|
258
264
|
</div>
|
|
259
265
|
</div>
|
|
260
266
|
|
|
261
|
-
<div class="
|
|
262
|
-
<div class="
|
|
263
|
-
<div class="
|
|
264
|
-
<span class="
|
|
265
|
-
<span class="
|
|
267
|
+
<div class="transition-timeline__detail-section">
|
|
268
|
+
<div class="tracker-section-label transition-timeline__section-title">Timing</div>
|
|
269
|
+
<div class="transition-timeline__detail-row">
|
|
270
|
+
<span class="transition-timeline__detail-key">Start</span>
|
|
271
|
+
<span class="transition-timeline__detail-val transition-timeline__detail-val--mono mono">
|
|
272
|
+
{{ selected.startTime.toFixed(2) }}ms
|
|
273
|
+
</span>
|
|
266
274
|
</div>
|
|
267
|
-
<div class="
|
|
268
|
-
<span class="
|
|
269
|
-
<span class="
|
|
275
|
+
<div class="transition-timeline__detail-row">
|
|
276
|
+
<span class="transition-timeline__detail-key">End</span>
|
|
277
|
+
<span class="transition-timeline__detail-val transition-timeline__detail-val--mono mono">
|
|
270
278
|
{{ selected.endTime !== undefined ? selected.endTime.toFixed(2) + 'ms' : '—' }}
|
|
271
279
|
</span>
|
|
272
280
|
</div>
|
|
273
|
-
<div class="
|
|
274
|
-
<span class="
|
|
275
|
-
<span
|
|
281
|
+
<div class="transition-timeline__detail-row">
|
|
282
|
+
<span class="transition-timeline__detail-key">Duration</span>
|
|
283
|
+
<span
|
|
284
|
+
class="transition-timeline__detail-val transition-timeline__detail-val--mono transition-timeline__detail-val--strong mono"
|
|
285
|
+
>
|
|
276
286
|
{{
|
|
277
287
|
selected.durationMs !== undefined
|
|
278
288
|
? selected.durationMs + 'ms'
|
|
@@ -284,23 +294,29 @@ function directionColor(e: TransitionEntry): string {
|
|
|
284
294
|
</div>
|
|
285
295
|
</div>
|
|
286
296
|
|
|
287
|
-
<div class="
|
|
288
|
-
<div class="
|
|
289
|
-
<div class="
|
|
290
|
-
<span class="
|
|
291
|
-
<span
|
|
297
|
+
<div class="transition-timeline__detail-section">
|
|
298
|
+
<div class="tracker-section-label transition-timeline__section-title">Flags</div>
|
|
299
|
+
<div class="transition-timeline__detail-row">
|
|
300
|
+
<span class="transition-timeline__detail-key">Appear</span>
|
|
301
|
+
<span
|
|
302
|
+
class="transition-timeline__detail-val"
|
|
303
|
+
:style="{ color: selected.appear ? 'var(--amber)' : 'var(--text3)' }"
|
|
304
|
+
>
|
|
292
305
|
{{ selected.appear ? 'yes' : 'no' }}
|
|
293
306
|
</span>
|
|
294
307
|
</div>
|
|
295
|
-
<div class="
|
|
296
|
-
<span class="
|
|
297
|
-
<span
|
|
308
|
+
<div class="transition-timeline__detail-row">
|
|
309
|
+
<span class="transition-timeline__detail-key">Cancelled</span>
|
|
310
|
+
<span
|
|
311
|
+
class="transition-timeline__detail-val"
|
|
312
|
+
:style="{ color: selected.cancelled ? 'var(--red)' : 'var(--text3)' }"
|
|
313
|
+
>
|
|
298
314
|
{{ selected.cancelled ? 'yes' : 'no' }}
|
|
299
315
|
</span>
|
|
300
316
|
</div>
|
|
301
317
|
</div>
|
|
302
318
|
|
|
303
|
-
<div v-if="selected.cancelled" class="
|
|
319
|
+
<div v-if="selected.cancelled" class="transition-timeline__notice transition-timeline__notice--cancelled">
|
|
304
320
|
This transition was cancelled mid-flight. The element may be stuck in a partial animation state if the interruption
|
|
305
321
|
was not handled with
|
|
306
322
|
<code>onEnterCancelled</code>
|
|
@@ -309,7 +325,10 @@ function directionColor(e: TransitionEntry): string {
|
|
|
309
325
|
.
|
|
310
326
|
</div>
|
|
311
327
|
|
|
312
|
-
<div
|
|
328
|
+
<div
|
|
329
|
+
v-if="selected.phase === 'entering' || selected.phase === 'leaving'"
|
|
330
|
+
class="transition-timeline__notice transition-timeline__notice--active"
|
|
331
|
+
>
|
|
313
332
|
Transition is currently in progress. If it stays in this state longer than expected, the
|
|
314
333
|
<code>done()</code>
|
|
315
334
|
callback may not be getting called (JS-mode transition stall).
|
|
@@ -321,92 +340,65 @@ function directionColor(e: TransitionEntry): string {
|
|
|
321
340
|
</template>
|
|
322
341
|
|
|
323
342
|
<style scoped>
|
|
324
|
-
.
|
|
325
|
-
display: flex;
|
|
326
|
-
flex-direction: column;
|
|
327
|
-
height: 100%;
|
|
328
|
-
overflow: hidden;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
/* ── Stats ───────────────────────────────────────────────────────────────── */
|
|
332
|
-
.stats-row {
|
|
343
|
+
.transition-timeline__stats {
|
|
333
344
|
display: flex;
|
|
334
345
|
gap: 10px;
|
|
335
|
-
padding: 12px 14px 0;
|
|
336
|
-
flex-shrink: 0;
|
|
337
346
|
}
|
|
338
347
|
|
|
339
|
-
.stat-card {
|
|
340
|
-
background: var(--bg2);
|
|
341
|
-
border: 0.5px solid var(--border);
|
|
342
|
-
border-radius: var(--radius);
|
|
343
|
-
padding: 8px 14px;
|
|
348
|
+
.transition-timeline__stats :deep(.stat-card) {
|
|
344
349
|
min-width: 72px;
|
|
345
350
|
text-align: center;
|
|
351
|
+
padding: var(--tracker-space-2) 14px;
|
|
352
|
+
border: var(--tracker-border-width) solid var(--border);
|
|
346
353
|
}
|
|
347
354
|
|
|
348
|
-
.stat-val {
|
|
349
|
-
font-size: 20px;
|
|
355
|
+
.transition-timeline__stats :deep(.stat-val) {
|
|
350
356
|
font-weight: 600;
|
|
351
357
|
font-family: var(--mono);
|
|
352
358
|
line-height: 1.1;
|
|
353
359
|
}
|
|
354
360
|
|
|
355
361
|
.stat-unit {
|
|
356
|
-
font-size:
|
|
362
|
+
font-size: var(--tracker-font-size-md);
|
|
357
363
|
opacity: 0.6;
|
|
358
364
|
margin-left: 1px;
|
|
359
365
|
}
|
|
360
366
|
|
|
361
|
-
.stat-label {
|
|
362
|
-
font-size: 10px;
|
|
363
|
-
color: var(--text3);
|
|
364
|
-
margin-top: 2px;
|
|
365
|
-
text-transform: uppercase;
|
|
366
|
-
letter-spacing: 0.4px;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
367
|
/* ── Toolbar ─────────────────────────────────────────────────────────────── */
|
|
370
|
-
.
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
gap: 8px;
|
|
374
|
-
padding: 10px 14px;
|
|
375
|
-
flex-shrink: 0;
|
|
376
|
-
border-bottom: 0.5px solid var(--border);
|
|
368
|
+
.transition-timeline__toolbar {
|
|
369
|
+
border-bottom: var(--tracker-border-width) solid var(--border);
|
|
370
|
+
padding-bottom: 10px;
|
|
377
371
|
}
|
|
378
372
|
|
|
379
|
-
.
|
|
373
|
+
.transition-timeline__search {
|
|
380
374
|
flex: 1;
|
|
381
375
|
max-width: 260px;
|
|
382
376
|
}
|
|
383
377
|
|
|
384
|
-
.
|
|
378
|
+
.transition-timeline__filters {
|
|
385
379
|
display: flex;
|
|
386
380
|
gap: 4px;
|
|
387
381
|
}
|
|
388
382
|
|
|
389
383
|
/* ── Content ─────────────────────────────────────────────────────────────── */
|
|
390
|
-
.
|
|
391
|
-
|
|
392
|
-
flex: 1;
|
|
393
|
-
overflow: hidden;
|
|
394
|
-
min-height: 0;
|
|
384
|
+
.transition-timeline__content {
|
|
385
|
+
align-items: stretch;
|
|
395
386
|
}
|
|
396
387
|
|
|
397
|
-
.
|
|
398
|
-
flex: 1;
|
|
388
|
+
.transition-timeline__table {
|
|
399
389
|
overflow: hidden auto;
|
|
400
390
|
min-width: 0;
|
|
391
|
+
border: none;
|
|
392
|
+
border-radius: 0;
|
|
401
393
|
}
|
|
402
394
|
|
|
403
395
|
/* ── Timeline bar ────────────────────────────────────────────────────────── */
|
|
404
|
-
.
|
|
396
|
+
.transition-timeline__bar-cell {
|
|
405
397
|
width: 200px;
|
|
406
398
|
padding: 4px 8px;
|
|
407
399
|
}
|
|
408
400
|
|
|
409
|
-
.
|
|
401
|
+
.transition-timeline__bar-track {
|
|
410
402
|
position: relative;
|
|
411
403
|
height: 8px;
|
|
412
404
|
background: var(--bg2);
|
|
@@ -414,26 +406,62 @@ function directionColor(e: TransitionEntry): string {
|
|
|
414
406
|
overflow: hidden;
|
|
415
407
|
}
|
|
416
408
|
|
|
417
|
-
.
|
|
409
|
+
.transition-timeline__bar-fill {
|
|
418
410
|
position: absolute;
|
|
419
411
|
top: 0;
|
|
420
412
|
height: 100%;
|
|
421
413
|
min-width: 3px;
|
|
422
414
|
border-radius: 4px;
|
|
423
|
-
transition: width
|
|
415
|
+
transition: width var(--tracker-transition-ui);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
.transition-timeline__col-name {
|
|
419
|
+
width: 110px;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
.transition-timeline__col-dir {
|
|
423
|
+
width: 80px;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
.transition-timeline__col-phase {
|
|
427
|
+
width: 90px;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
.transition-timeline__col-duration {
|
|
431
|
+
width: 70px;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
.transition-timeline__name {
|
|
435
|
+
font-size: var(--tracker-font-size-sm);
|
|
436
|
+
font-weight: 500;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
.transition-timeline__direction {
|
|
440
|
+
font-size: var(--tracker-font-size-sm);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
.transition-timeline__duration {
|
|
444
|
+
font-size: var(--tracker-font-size-sm);
|
|
445
|
+
color: var(--text2);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
.transition-timeline__component {
|
|
449
|
+
font-size: var(--tracker-font-size-sm);
|
|
424
450
|
}
|
|
425
451
|
|
|
426
452
|
/* ── Detail panel ────────────────────────────────────────────────────────── */
|
|
427
|
-
.
|
|
428
|
-
|
|
453
|
+
.transition-timeline__detail {
|
|
454
|
+
display: flex;
|
|
455
|
+
flex-direction: column;
|
|
429
456
|
flex-shrink: 0;
|
|
430
|
-
border
|
|
457
|
+
border: var(--tracker-border-width) solid var(--border);
|
|
458
|
+
border-radius: var(--radius-lg);
|
|
431
459
|
overflow-y: auto;
|
|
432
460
|
background: var(--bg3);
|
|
433
461
|
padding: 0 0 16px;
|
|
434
462
|
}
|
|
435
463
|
|
|
436
|
-
.
|
|
464
|
+
.transition-timeline__detail-header {
|
|
437
465
|
display: flex;
|
|
438
466
|
align-items: center;
|
|
439
467
|
justify-content: space-between;
|
|
@@ -445,71 +473,73 @@ function directionColor(e: TransitionEntry): string {
|
|
|
445
473
|
z-index: 1;
|
|
446
474
|
}
|
|
447
475
|
|
|
448
|
-
.
|
|
476
|
+
.transition-timeline__detail-title {
|
|
449
477
|
font-family: var(--mono);
|
|
450
478
|
font-size: 13px;
|
|
451
479
|
font-weight: 500;
|
|
452
480
|
}
|
|
453
481
|
|
|
454
|
-
.
|
|
482
|
+
.transition-timeline__close-btn {
|
|
455
483
|
border: none;
|
|
456
484
|
background: transparent;
|
|
457
485
|
color: var(--text3);
|
|
458
|
-
font-size:
|
|
486
|
+
font-size: var(--tracker-font-size-sm);
|
|
459
487
|
padding: 2px 6px;
|
|
460
488
|
cursor: pointer;
|
|
461
489
|
}
|
|
462
490
|
|
|
463
|
-
.
|
|
491
|
+
.transition-timeline__detail-section {
|
|
464
492
|
padding: 10px 14px 6px;
|
|
465
|
-
border-bottom:
|
|
493
|
+
border-bottom: var(--tracker-border-width) solid var(--border);
|
|
466
494
|
}
|
|
467
495
|
|
|
468
|
-
.
|
|
469
|
-
font-size: 10px;
|
|
470
|
-
font-weight: 500;
|
|
471
|
-
color: var(--text3);
|
|
472
|
-
text-transform: uppercase;
|
|
473
|
-
letter-spacing: 0.4px;
|
|
496
|
+
.transition-timeline__section-title {
|
|
474
497
|
margin-bottom: 8px;
|
|
475
498
|
}
|
|
476
499
|
|
|
477
|
-
.
|
|
500
|
+
.transition-timeline__detail-row {
|
|
478
501
|
display: flex;
|
|
479
502
|
justify-content: space-between;
|
|
480
503
|
align-items: center;
|
|
481
504
|
gap: 8px;
|
|
482
505
|
padding: 3px 0;
|
|
483
|
-
font-size:
|
|
506
|
+
font-size: var(--tracker-font-size-md);
|
|
484
507
|
}
|
|
485
508
|
|
|
486
|
-
.
|
|
509
|
+
.transition-timeline__detail-key {
|
|
487
510
|
color: var(--text3);
|
|
488
511
|
flex-shrink: 0;
|
|
489
512
|
}
|
|
490
513
|
|
|
491
|
-
.
|
|
514
|
+
.transition-timeline__detail-val {
|
|
492
515
|
color: var(--text);
|
|
493
516
|
text-align: right;
|
|
494
517
|
word-break: break-all;
|
|
495
518
|
}
|
|
496
519
|
|
|
497
|
-
.
|
|
498
|
-
|
|
520
|
+
.transition-timeline__detail-val--mono {
|
|
521
|
+
font-family: var(--mono);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
.transition-timeline__detail-val--strong {
|
|
525
|
+
font-weight: 500;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
.transition-timeline__notice {
|
|
499
529
|
margin: 10px 14px 0;
|
|
500
|
-
font-size:
|
|
530
|
+
font-size: var(--tracker-font-size-sm);
|
|
501
531
|
line-height: 1.6;
|
|
502
532
|
padding: 8px 10px;
|
|
503
533
|
border-radius: var(--radius);
|
|
504
534
|
}
|
|
505
535
|
|
|
506
|
-
.
|
|
536
|
+
.transition-timeline__notice--cancelled {
|
|
507
537
|
background: rgb(226 75 74 / 10%);
|
|
508
538
|
color: var(--red);
|
|
509
539
|
border: 0.5px solid rgb(226 75 74 / 30%);
|
|
510
540
|
}
|
|
511
541
|
|
|
512
|
-
.active
|
|
542
|
+
.transition-timeline__notice--active {
|
|
513
543
|
background: rgb(127 119 221 / 10%);
|
|
514
544
|
color: var(--purple);
|
|
515
545
|
border: 0.5px solid rgb(127 119 221 / 30%);
|
package/client/tsconfig.json
CHANGED
|
@@ -6,9 +6,11 @@
|
|
|
6
6
|
"strict": true,
|
|
7
7
|
"jsx": "preserve",
|
|
8
8
|
"lib": ["ESNext", "DOM"],
|
|
9
|
-
"baseUrl": ".",
|
|
10
9
|
"forceConsistentCasingInFileNames": true,
|
|
11
10
|
"paths": {
|
|
11
|
+
"@observatory/*": ["../src/*"],
|
|
12
|
+
"@observatory-client/*": ["./src/*"],
|
|
13
|
+
"@observatory-tests/*": ["../tests/*"],
|
|
12
14
|
"*": ["../node_modules/*"]
|
|
13
15
|
}
|
|
14
16
|
},
|
package/client/vite.config.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import path from 'node:path'
|
|
1
2
|
import { defineConfig } from 'vite'
|
|
2
3
|
import vue from '@vitejs/plugin-vue'
|
|
3
4
|
|
|
@@ -8,6 +9,13 @@ export default defineConfig({
|
|
|
8
9
|
// the DevTools iframe without needing a separate dev server on a different port.
|
|
9
10
|
base: '/__observatory/',
|
|
10
11
|
plugins: [vue()],
|
|
12
|
+
resolve: {
|
|
13
|
+
alias: {
|
|
14
|
+
'@observatory': path.resolve(__dirname, '../src'),
|
|
15
|
+
'@observatory-client': path.resolve(__dirname, './src'),
|
|
16
|
+
'@observatory-tests': path.resolve(__dirname, '../tests'),
|
|
17
|
+
},
|
|
18
|
+
},
|
|
11
19
|
build: {
|
|
12
20
|
outDir: './dist',
|
|
13
21
|
emptyOutDir: true,
|
package/dist/module.d.mts
CHANGED
|
@@ -71,6 +71,11 @@ interface ModuleOptions {
|
|
|
71
71
|
* @default true
|
|
72
72
|
*/
|
|
73
73
|
transitionTracker?: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Enable the trace viewer tab (per-route component + fetch + composable + render spans)
|
|
76
|
+
* @default true
|
|
77
|
+
*/
|
|
78
|
+
traceViewer?: boolean;
|
|
74
79
|
/**
|
|
75
80
|
* Hide node_modules/internal components in the render heatmap
|
|
76
81
|
* @default false
|