nuxt-devtools-observatory 0.1.26 → 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.
- package/README.md +50 -11
- package/client/dist/assets/index-BCaKoHBH.js +17 -0
- package/client/dist/assets/index-BmGW_M3W.css +1 -0
- package/client/dist/index.html +2 -2
- package/client/src/App.vue +2 -6
- package/client/src/composables/useResizablePane.ts +65 -0
- package/client/src/stores/observatory.ts +162 -218
- package/client/src/style.css +203 -28
- package/client/src/views/ComposableTracker.vue +327 -294
- package/client/src/views/FetchDashboard.vue +104 -132
- package/client/src/views/ProvideInjectGraph.vue +101 -118
- package/client/src/views/RenderHeatmap.vue +192 -157
- package/client/src/views/TransitionTimeline.vue +166 -130
- package/client/tsconfig.json +3 -1
- package/client/vite.config.ts +12 -1
- package/dist/module.d.mts +6 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +238 -186
- package/dist/runtime/composables/fetch-registry.js +3 -0
- package/dist/runtime/plugin.js +89 -66
- package/package.json +12 -3
- package/client/dist/assets/index-1-H6UMCK.css +0 -1
- package/client/dist/assets/index-eSUuhYQ0.js +0 -17
|
@@ -1,27 +1,24 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { ref, computed } from 'vue'
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
useObservatoryData,
|
|
5
|
+
setComposableMode,
|
|
6
|
+
editComposableValue,
|
|
7
|
+
openInEditor as openInEditorFromStore,
|
|
8
|
+
} from '@observatory-client/stores/observatory'
|
|
9
|
+
import type { ComposableEntry as RuntimeComposableEntry } from '@observatory/types/snapshot'
|
|
4
10
|
|
|
5
11
|
const { composables: rawEntries, connected, features, clearComposables } = useObservatoryData()
|
|
6
12
|
|
|
7
13
|
const composableMode = computed<'route' | 'session'>(() => (features.value?.composableNavigationMode === 'session' ? 'session' : 'route'))
|
|
8
14
|
|
|
9
15
|
function toggleComposableMode() {
|
|
10
|
-
const origin = getObservatoryOrigin()
|
|
11
|
-
|
|
12
|
-
if (!origin) {
|
|
13
|
-
return
|
|
14
|
-
}
|
|
15
|
-
|
|
16
16
|
const nextMode = composableMode.value === 'route' ? 'session' : 'route'
|
|
17
|
-
|
|
17
|
+
setComposableMode(nextMode)
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
function clearSession() {
|
|
21
|
-
const origin = getObservatoryOrigin()
|
|
22
|
-
if (!origin) return
|
|
23
21
|
clearComposables()
|
|
24
|
-
window.top?.postMessage({ type: 'observatory:clear-composables' }, origin)
|
|
25
22
|
}
|
|
26
23
|
|
|
27
24
|
// ── Flat per-instance display ─────────────────────────────────────────────
|
|
@@ -89,17 +86,7 @@ function basename(file: string) {
|
|
|
89
86
|
}
|
|
90
87
|
|
|
91
88
|
function openInEditor(file: string) {
|
|
92
|
-
|
|
93
|
-
return
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
const origin = getObservatoryOrigin()
|
|
97
|
-
|
|
98
|
-
if (!origin) {
|
|
99
|
-
return
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
window.top?.postMessage({ type: 'observatory:open-in-editor', file }, origin)
|
|
89
|
+
openInEditorFromStore(file)
|
|
103
90
|
}
|
|
104
91
|
|
|
105
92
|
const filter = ref('all')
|
|
@@ -302,40 +289,26 @@ function applyEdit() {
|
|
|
302
289
|
return
|
|
303
290
|
}
|
|
304
291
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
if (!origin) {
|
|
308
|
-
return
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
window.top?.postMessage(
|
|
312
|
-
{
|
|
313
|
-
type: 'observatory:edit-composable',
|
|
314
|
-
id: editTarget.value.id,
|
|
315
|
-
key: editTarget.value.key,
|
|
316
|
-
value: parsed,
|
|
317
|
-
},
|
|
318
|
-
origin
|
|
319
|
-
)
|
|
292
|
+
editComposableValue(editTarget.value.id, editTarget.value.key, parsed)
|
|
320
293
|
|
|
321
294
|
editTarget.value = null
|
|
322
295
|
}
|
|
323
296
|
</script>
|
|
324
297
|
|
|
325
298
|
<template>
|
|
326
|
-
<div class="view">
|
|
327
|
-
<div class="stats-row">
|
|
299
|
+
<div class="composable-tracker tracker-view">
|
|
300
|
+
<div class="composable-tracker__stats tracker-stats-row">
|
|
328
301
|
<div class="stat-card">
|
|
329
302
|
<div class="stat-label">total</div>
|
|
330
303
|
<div class="stat-val">{{ entries.length }}</div>
|
|
331
304
|
</div>
|
|
332
305
|
<div class="stat-card">
|
|
333
306
|
<div class="stat-label">mounted</div>
|
|
334
|
-
<div class="stat-val
|
|
307
|
+
<div class="stat-val stat-val--active">{{ counts.mounted }}</div>
|
|
335
308
|
</div>
|
|
336
309
|
<div class="stat-card">
|
|
337
310
|
<div class="stat-label">leaks</div>
|
|
338
|
-
<div class="stat-val
|
|
311
|
+
<div class="stat-val stat-val--error">{{ counts.leaks }}</div>
|
|
339
312
|
</div>
|
|
340
313
|
<div class="stat-card">
|
|
341
314
|
<div class="stat-label">instances</div>
|
|
@@ -343,38 +316,47 @@ function applyEdit() {
|
|
|
343
316
|
</div>
|
|
344
317
|
</div>
|
|
345
318
|
|
|
346
|
-
<div class="toolbar">
|
|
319
|
+
<div class="composable-tracker__toolbar tracker-toolbar">
|
|
347
320
|
<button :class="{ active: filter === 'all' }" @click="filter = 'all'">all</button>
|
|
348
321
|
<button :class="{ active: filter === 'mounted' }" @click="filter = 'mounted'">mounted</button>
|
|
349
322
|
<button :class="{ 'danger-active': filter === 'leak' }" @click="filter = 'leak'">leaks only</button>
|
|
350
323
|
<button :class="{ active: filter === 'unmounted' }" @click="filter = 'unmounted'">unmounted</button>
|
|
351
324
|
<button
|
|
352
|
-
class="
|
|
325
|
+
class="composable-tracker__mode-btn"
|
|
353
326
|
:title="`switch to ${composableMode === 'route' ? 'session' : 'route'} mode`"
|
|
354
327
|
@click="toggleComposableMode"
|
|
355
328
|
>
|
|
356
329
|
mode: {{ composableMode }}
|
|
357
330
|
</button>
|
|
358
|
-
<
|
|
359
|
-
<
|
|
331
|
+
<span class="tracker-toolbar__spacer"></span>
|
|
332
|
+
<input v-model="search" class="composable-tracker__search" type="search" placeholder="search name, file, or ref…" />
|
|
333
|
+
<button
|
|
334
|
+
v-if="composableMode === 'session'"
|
|
335
|
+
class="composable-tracker__clear-btn"
|
|
336
|
+
title="Clear session history"
|
|
337
|
+
@click="clearSession"
|
|
338
|
+
>
|
|
360
339
|
clear session
|
|
361
340
|
</button>
|
|
362
341
|
</div>
|
|
363
342
|
|
|
364
|
-
<div class="
|
|
343
|
+
<div class="composable-tracker__list">
|
|
365
344
|
<div
|
|
366
345
|
v-for="entry in filtered"
|
|
367
346
|
:key="entry.id"
|
|
368
|
-
class="
|
|
369
|
-
:class="{
|
|
347
|
+
class="composable-tracker__card"
|
|
348
|
+
:class="{
|
|
349
|
+
'composable-tracker__card--leak': entry.leak,
|
|
350
|
+
'composable-tracker__card--expanded': expanded === entry.id,
|
|
351
|
+
}"
|
|
370
352
|
@click="expanded = expanded === entry.id ? null : entry.id"
|
|
371
353
|
>
|
|
372
|
-
<div class="
|
|
373
|
-
<div class="
|
|
374
|
-
<span class="
|
|
375
|
-
<span class="
|
|
354
|
+
<div class="composable-tracker__card-header">
|
|
355
|
+
<div class="composable-tracker__identity">
|
|
356
|
+
<span class="composable-tracker__name mono">{{ entry.name }}</span>
|
|
357
|
+
<span class="composable-tracker__file muted mono">{{ basename(entry.componentFile) }}</span>
|
|
376
358
|
</div>
|
|
377
|
-
<div class="
|
|
359
|
+
<div class="composable-tracker__meta">
|
|
378
360
|
<span v-if="entry.watcherCount > 0 && !entry.leak" class="badge badge-warn">{{ entry.watcherCount }}w</span>
|
|
379
361
|
<span v-if="entry.intervalCount > 0 && !entry.leak" class="badge badge-warn">{{ entry.intervalCount }}t</span>
|
|
380
362
|
<span v-if="entry.leak" class="badge badge-err">leak</span>
|
|
@@ -384,33 +366,33 @@ function applyEdit() {
|
|
|
384
366
|
</div>
|
|
385
367
|
|
|
386
368
|
<!-- Inline ref preview — shows up to 3 refs without expanding -->
|
|
387
|
-
<div v-if="Object.keys(entry.refs).length" class="
|
|
369
|
+
<div v-if="Object.keys(entry.refs).length" class="composable-tracker__refs-preview">
|
|
388
370
|
<span
|
|
389
371
|
v-for="[k, v] in Object.entries(entry.refs).slice(0, 3)"
|
|
390
372
|
:key="k"
|
|
391
|
-
class="
|
|
373
|
+
class="composable-tracker__ref-chip"
|
|
392
374
|
:class="{
|
|
393
|
-
'
|
|
394
|
-
'
|
|
395
|
-
'
|
|
375
|
+
'composable-tracker__ref-chip--reactive': v.type === 'reactive',
|
|
376
|
+
'composable-tracker__ref-chip--computed': v.type === 'computed',
|
|
377
|
+
'composable-tracker__ref-chip--shared': entry.sharedKeys?.includes(k),
|
|
396
378
|
}"
|
|
397
379
|
:title="entry.sharedKeys?.includes(k) ? 'shared global state' : ''"
|
|
398
380
|
>
|
|
399
|
-
<span class="
|
|
400
|
-
<span class="
|
|
401
|
-
<span v-if="entry.sharedKeys?.includes(k)" class="
|
|
381
|
+
<span class="composable-tracker__ref-chip-key">{{ k }}</span>
|
|
382
|
+
<span class="composable-tracker__ref-chip-val">{{ formatVal(v.value) }}</span>
|
|
383
|
+
<span v-if="entry.sharedKeys?.includes(k)" class="composable-tracker__ref-chip-shared-dot" title="global"></span>
|
|
402
384
|
</span>
|
|
403
385
|
<span v-if="Object.keys(entry.refs).length > 3" class="muted text-sm">
|
|
404
386
|
+{{ Object.keys(entry.refs).length - 3 }} more
|
|
405
387
|
</span>
|
|
406
388
|
</div>
|
|
407
389
|
|
|
408
|
-
<div v-if="expanded === entry.id" class="
|
|
409
|
-
<div v-if="entry.leak" class="
|
|
390
|
+
<div v-if="expanded === entry.id" class="composable-tracker__detail" @click.stop>
|
|
391
|
+
<div v-if="entry.leak" class="composable-tracker__leak-banner">{{ entry.leakReason }}</div>
|
|
410
392
|
|
|
411
393
|
<!-- Global state warning -->
|
|
412
|
-
<div v-if="entry.sharedKeys?.length" class="
|
|
413
|
-
<span class="
|
|
394
|
+
<div v-if="entry.sharedKeys?.length" class="composable-tracker__global-banner">
|
|
395
|
+
<span class="composable-tracker__global-dot"></span>
|
|
414
396
|
<span>
|
|
415
397
|
<strong>global state</strong>
|
|
416
398
|
— {{ entry.sharedKeys.join(', ') }}
|
|
@@ -419,31 +401,31 @@ function applyEdit() {
|
|
|
419
401
|
</span>
|
|
420
402
|
</div>
|
|
421
403
|
|
|
422
|
-
<div class="section-label">reactive state</div>
|
|
423
|
-
<div v-if="!Object.keys(entry.refs).length" class="muted text-sm"
|
|
404
|
+
<div class="composable-tracker__section-label tracker-section-label">reactive state</div>
|
|
405
|
+
<div v-if="!Object.keys(entry.refs).length" class="composable-tracker__compact-muted muted text-sm">
|
|
424
406
|
no tracked state returned
|
|
425
407
|
</div>
|
|
426
|
-
<div v-for="[k, v] in Object.entries(entry.refs)" :key="k" class="
|
|
408
|
+
<div v-for="[k, v] in Object.entries(entry.refs)" :key="k" class="composable-tracker__ref-row">
|
|
427
409
|
<span
|
|
428
|
-
class="
|
|
410
|
+
class="composable-tracker__ref-key composable-tracker__ref-key--clickable mono text-sm"
|
|
429
411
|
:title="`click to see all instances exposing '${k}'`"
|
|
430
412
|
@click.stop="openLookup(k)"
|
|
431
413
|
>
|
|
432
414
|
{{ k }}
|
|
433
415
|
</span>
|
|
434
416
|
<span
|
|
435
|
-
class="mono text-sm
|
|
417
|
+
class="composable-tracker__ref-val mono text-sm"
|
|
436
418
|
:class="{
|
|
437
|
-
'
|
|
438
|
-
'
|
|
419
|
+
'composable-tracker__ref-val--full': isLongValue(v.value) && isRefExpanded(entry.id, k),
|
|
420
|
+
'composable-tracker__ref-val--collapsed': isLongValue(v.value) && !isRefExpanded(entry.id, k),
|
|
439
421
|
}"
|
|
440
422
|
>
|
|
441
423
|
{{ isLongValue(v.value) && !isRefExpanded(entry.id, k) ? formatVal(v.value) : formatValFull(v.value) }}
|
|
442
424
|
</span>
|
|
443
|
-
<div class="
|
|
425
|
+
<div class="composable-tracker__ref-row-actions">
|
|
444
426
|
<button
|
|
445
427
|
v-if="isLongValue(v.value)"
|
|
446
|
-
class="
|
|
428
|
+
class="composable-tracker__expand-btn"
|
|
447
429
|
:title="isRefExpanded(entry.id, k) ? 'Collapse' : 'Expand'"
|
|
448
430
|
@click.stop="toggleRefExpand(entry.id, k)"
|
|
449
431
|
>
|
|
@@ -453,7 +435,7 @@ function applyEdit() {
|
|
|
453
435
|
<span v-if="entry.sharedKeys?.includes(k)" class="badge badge-amber text-xs">global</span>
|
|
454
436
|
<button
|
|
455
437
|
v-if="v.type === 'ref'"
|
|
456
|
-
class="
|
|
438
|
+
class="composable-tracker__edit-btn"
|
|
457
439
|
title="Edit value"
|
|
458
440
|
@click.stop="openEdit(entry.id, k, v.value)"
|
|
459
441
|
>
|
|
@@ -463,103 +445,127 @@ function applyEdit() {
|
|
|
463
445
|
</div>
|
|
464
446
|
|
|
465
447
|
<template v-if="entry.history && entry.history.length">
|
|
466
|
-
<div class="
|
|
448
|
+
<div class="composable-tracker__section-label composable-tracker__section-label--spaced tracker-section-label">
|
|
467
449
|
change history
|
|
468
|
-
<span class="
|
|
469
|
-
({{ entry.history.length }} events)
|
|
470
|
-
</span>
|
|
450
|
+
<span class="composable-tracker__section-label-meta muted">({{ entry.history.length }} events)</span>
|
|
471
451
|
</div>
|
|
472
|
-
<div class="
|
|
473
|
-
<div
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
452
|
+
<div class="composable-tracker__history-list">
|
|
453
|
+
<div
|
|
454
|
+
v-for="(evt, idx) in [...entry.history].reverse().slice(0, 20)"
|
|
455
|
+
:key="idx"
|
|
456
|
+
class="composable-tracker__history-row"
|
|
457
|
+
>
|
|
458
|
+
<span class="composable-tracker__history-time mono muted">+{{ (evt.t / 1000).toFixed(2) }}s</span>
|
|
459
|
+
<span class="composable-tracker__history-key mono">{{ evt.key }}</span>
|
|
460
|
+
<span class="composable-tracker__history-val mono">{{ formatVal(evt.value) }}</span>
|
|
477
461
|
</div>
|
|
478
|
-
<div v-if="entry.history.length > 20" class="muted text-sm"
|
|
462
|
+
<div v-if="entry.history.length > 20" class="composable-tracker__compact-muted muted text-sm">
|
|
479
463
|
… {{ entry.history.length - 20 }} earlier events
|
|
480
464
|
</div>
|
|
481
465
|
</div>
|
|
482
466
|
</template>
|
|
483
467
|
|
|
484
|
-
<div class="
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
<span
|
|
468
|
+
<div class="composable-tracker__section-label composable-tracker__section-label--spaced tracker-section-label">
|
|
469
|
+
lifecycle
|
|
470
|
+
</div>
|
|
471
|
+
<div v-for="row in lifecycleRows(entry)" :key="row.label" class="composable-tracker__lifecycle-row">
|
|
472
|
+
<span
|
|
473
|
+
class="composable-tracker__lifecycle-dot"
|
|
474
|
+
:class="row.ok ? 'composable-tracker__lifecycle-dot--ok' : 'composable-tracker__lifecycle-dot--error'"
|
|
475
|
+
></span>
|
|
476
|
+
<span class="composable-tracker__context-label muted text-sm">{{ row.label }}</span>
|
|
477
|
+
<span
|
|
478
|
+
class="composable-tracker__lifecycle-status text-sm"
|
|
479
|
+
:class="row.ok ? 'composable-tracker__lifecycle-status--ok' : 'composable-tracker__lifecycle-status--error'"
|
|
480
|
+
>
|
|
481
|
+
{{ row.status }}
|
|
482
|
+
</span>
|
|
489
483
|
</div>
|
|
490
484
|
|
|
491
|
-
<div class="
|
|
492
|
-
|
|
493
|
-
<span class="muted text-sm" style="min-width: 120px">component</span>
|
|
494
|
-
<span class="mono text-sm">{{ basename(entry.componentFile) }}</span>
|
|
485
|
+
<div class="composable-tracker__section-label composable-tracker__section-label--spaced tracker-section-label">
|
|
486
|
+
context
|
|
495
487
|
</div>
|
|
496
|
-
<div class="
|
|
497
|
-
<span class="muted text-sm"
|
|
498
|
-
<span class="mono text-sm
|
|
488
|
+
<div class="composable-tracker__lifecycle-row">
|
|
489
|
+
<span class="composable-tracker__context-label muted text-sm">component</span>
|
|
490
|
+
<span class="composable-tracker__context-value mono text-sm">{{ basename(entry.componentFile) }}</span>
|
|
499
491
|
</div>
|
|
500
|
-
<div class="
|
|
501
|
-
<span class="muted text-sm"
|
|
502
|
-
<span class="mono text-sm muted"
|
|
492
|
+
<div class="composable-tracker__lifecycle-row">
|
|
493
|
+
<span class="composable-tracker__context-label muted text-sm">uid</span>
|
|
494
|
+
<span class="composable-tracker__context-value composable-tracker__context-value--muted mono text-sm muted">
|
|
495
|
+
{{ entry.componentUid }}
|
|
496
|
+
</span>
|
|
497
|
+
</div>
|
|
498
|
+
<div class="composable-tracker__lifecycle-row">
|
|
499
|
+
<span class="composable-tracker__context-label muted text-sm">defined in</span>
|
|
500
|
+
<span
|
|
501
|
+
class="composable-tracker__context-value composable-tracker__context-value--row composable-tracker__context-value--muted mono text-sm muted"
|
|
502
|
+
>
|
|
503
503
|
{{ entry.file }}:{{ entry.line }}
|
|
504
|
-
<button class="
|
|
504
|
+
<button class="composable-tracker__jump-btn" title="Open in editor" @click.stop="openInEditor(entry.file)">
|
|
505
|
+
open ↗
|
|
506
|
+
</button>
|
|
505
507
|
</span>
|
|
506
508
|
</div>
|
|
507
|
-
<div class="
|
|
508
|
-
<span class="muted text-sm"
|
|
509
|
-
<span class="mono text-sm muted">
|
|
509
|
+
<div class="composable-tracker__lifecycle-row">
|
|
510
|
+
<span class="composable-tracker__context-label muted text-sm">route</span>
|
|
511
|
+
<span class="composable-tracker__context-value composable-tracker__context-value--muted mono text-sm muted">
|
|
512
|
+
{{ entry.route }}
|
|
513
|
+
</span>
|
|
510
514
|
</div>
|
|
511
|
-
<div class="
|
|
512
|
-
<span class="muted text-sm"
|
|
513
|
-
<span class="mono text-sm">{{ entry.watcherCount }}</span>
|
|
515
|
+
<div class="composable-tracker__lifecycle-row">
|
|
516
|
+
<span class="composable-tracker__context-label muted text-sm">watchers</span>
|
|
517
|
+
<span class="composable-tracker__context-value mono text-sm">{{ entry.watcherCount }}</span>
|
|
514
518
|
</div>
|
|
515
|
-
<div class="
|
|
516
|
-
<span class="muted text-sm"
|
|
517
|
-
<span class="mono text-sm">{{ entry.intervalCount }}</span>
|
|
519
|
+
<div class="composable-tracker__lifecycle-row">
|
|
520
|
+
<span class="composable-tracker__context-label muted text-sm">intervals</span>
|
|
521
|
+
<span class="composable-tracker__context-value mono text-sm">{{ entry.intervalCount }}</span>
|
|
518
522
|
</div>
|
|
519
523
|
</div>
|
|
520
524
|
</div>
|
|
521
525
|
|
|
522
|
-
<div v-if="!filtered.length" class="muted text-sm"
|
|
526
|
+
<div v-if="!filtered.length" class="composable-tracker__empty muted text-sm">
|
|
523
527
|
{{ connected ? 'No composables recorded yet.' : 'Waiting for connection to the Nuxt app…' }}
|
|
524
528
|
</div>
|
|
525
529
|
</div>
|
|
526
530
|
|
|
527
531
|
<!-- ── Reverse lookup panel ──────────────────────────────────────── -->
|
|
528
532
|
<Transition name="slide">
|
|
529
|
-
<div v-if="lookupKey" class="
|
|
530
|
-
<div class="
|
|
533
|
+
<div v-if="lookupKey" class="composable-tracker__lookup-panel">
|
|
534
|
+
<div class="composable-tracker__lookup-header">
|
|
531
535
|
<span class="mono text-sm">{{ lookupKey }}</span>
|
|
532
536
|
<span class="muted text-sm">— {{ lookupResults.length }} instance{{ lookupResults.length !== 1 ? 's' : '' }}</span>
|
|
533
|
-
<button class="
|
|
537
|
+
<button class="composable-tracker__clear-btn composable-tracker__lookup-close" @click="lookupKey = null">✕</button>
|
|
538
|
+
</div>
|
|
539
|
+
<div v-if="!lookupResults.length" class="composable-tracker__lookup-empty muted text-sm">
|
|
540
|
+
No mounted instances expose this key.
|
|
534
541
|
</div>
|
|
535
|
-
<div v-
|
|
536
|
-
<div v-for="r in lookupResults" :key="r.id" class="lookup-row">
|
|
542
|
+
<div v-for="r in lookupResults" :key="r.id" class="composable-tracker__lookup-row">
|
|
537
543
|
<span class="mono text-sm">{{ r.name }}</span>
|
|
538
544
|
<span class="muted text-sm">{{ basename(r.componentFile) }}</span>
|
|
539
|
-
<span class="muted text-sm"
|
|
545
|
+
<span class="composable-tracker__lookup-route muted text-sm">{{ r.route }}</span>
|
|
540
546
|
</div>
|
|
541
547
|
</div>
|
|
542
548
|
</Transition>
|
|
543
549
|
|
|
544
550
|
<!-- ── Edit value dialog ─────────────────────────────────────────── -->
|
|
545
551
|
<Transition name="fade">
|
|
546
|
-
<div v-if="editTarget" class="
|
|
547
|
-
<div class="
|
|
548
|
-
<div class="
|
|
552
|
+
<div v-if="editTarget" class="composable-tracker__edit-overlay" @click.self="editTarget = null">
|
|
553
|
+
<div class="composable-tracker__edit-dialog">
|
|
554
|
+
<div class="composable-tracker__edit-dialog-header">
|
|
549
555
|
edit
|
|
550
556
|
<span class="mono">{{ editTarget.key }}</span>
|
|
551
|
-
<button class="
|
|
557
|
+
<button class="composable-tracker__clear-btn composable-tracker__dialog-close" @click="editTarget = null">✕</button>
|
|
552
558
|
</div>
|
|
553
|
-
<p class="muted text-sm"
|
|
559
|
+
<p class="composable-tracker__edit-help muted text-sm">
|
|
554
560
|
Value applied immediately to the live ref. Only
|
|
555
561
|
<span class="mono">ref</span>
|
|
556
562
|
values are writable.
|
|
557
563
|
</p>
|
|
558
|
-
<textarea v-model="editTarget.rawValue" class="
|
|
559
|
-
<div v-if="editError" class="
|
|
560
|
-
<div class="
|
|
564
|
+
<textarea v-model="editTarget.rawValue" class="composable-tracker__edit-textarea" rows="6" spellcheck="false" />
|
|
565
|
+
<div v-if="editError" class="composable-tracker__edit-error text-sm">{{ editError }}</div>
|
|
566
|
+
<div class="composable-tracker__edit-actions">
|
|
561
567
|
<button @click="applyEdit">apply</button>
|
|
562
|
-
<button class="
|
|
568
|
+
<button class="composable-tracker__clear-btn" @click="editTarget = null">cancel</button>
|
|
563
569
|
</div>
|
|
564
570
|
</div>
|
|
565
571
|
</div>
|
|
@@ -568,239 +574,222 @@ function applyEdit() {
|
|
|
568
574
|
</template>
|
|
569
575
|
|
|
570
576
|
<style scoped>
|
|
571
|
-
.
|
|
572
|
-
display: flex;
|
|
573
|
-
flex-direction: column;
|
|
574
|
-
height: 100%;
|
|
575
|
-
overflow: hidden;
|
|
576
|
-
padding: 12px;
|
|
577
|
-
gap: 10px;
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
.stats-row {
|
|
581
|
-
display: grid;
|
|
582
|
-
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
583
|
-
gap: 8px;
|
|
584
|
-
flex-shrink: 0;
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
.toolbar {
|
|
588
|
-
display: flex;
|
|
589
|
-
align-items: center;
|
|
590
|
-
gap: 6px;
|
|
591
|
-
flex-shrink: 0;
|
|
592
|
-
flex-wrap: wrap;
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
.clear-btn {
|
|
577
|
+
.composable-tracker__clear-btn {
|
|
596
578
|
color: var(--text3);
|
|
597
579
|
border-color: var(--border);
|
|
598
580
|
flex-shrink: 0;
|
|
599
581
|
}
|
|
600
582
|
|
|
601
|
-
.
|
|
583
|
+
.composable-tracker__clear-btn:hover {
|
|
602
584
|
color: var(--red);
|
|
603
585
|
border-color: var(--red);
|
|
604
586
|
background: transparent;
|
|
605
587
|
}
|
|
606
588
|
|
|
607
|
-
.
|
|
589
|
+
.composable-tracker__mode-btn {
|
|
608
590
|
border-color: color-mix(in srgb, var(--blue) 40%, var(--border));
|
|
609
591
|
color: var(--blue);
|
|
610
592
|
}
|
|
611
593
|
|
|
612
|
-
.
|
|
594
|
+
.composable-tracker__mode-btn:hover {
|
|
613
595
|
border-color: var(--blue);
|
|
614
596
|
background: color-mix(in srgb, var(--blue) 12%, transparent);
|
|
615
597
|
}
|
|
616
598
|
|
|
617
|
-
.
|
|
599
|
+
.composable-tracker__search {
|
|
600
|
+
max-width: 220px;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
.composable-tracker__list {
|
|
618
604
|
flex: 1;
|
|
619
605
|
overflow: auto;
|
|
620
606
|
display: flex;
|
|
621
607
|
flex-direction: column;
|
|
622
|
-
gap:
|
|
608
|
+
gap: var(--tracker-space-2);
|
|
623
609
|
min-height: 0;
|
|
624
610
|
}
|
|
625
611
|
|
|
626
|
-
.
|
|
612
|
+
.composable-tracker__card {
|
|
627
613
|
background: var(--bg3);
|
|
628
|
-
border:
|
|
614
|
+
border: var(--tracker-border-width) solid var(--border);
|
|
629
615
|
border-radius: var(--radius-lg);
|
|
630
616
|
overflow: hidden;
|
|
631
617
|
cursor: pointer;
|
|
632
618
|
flex-shrink: 0;
|
|
633
619
|
}
|
|
634
620
|
|
|
635
|
-
.
|
|
621
|
+
.composable-tracker__card:hover {
|
|
636
622
|
border-color: var(--text3);
|
|
637
623
|
}
|
|
638
624
|
|
|
639
|
-
.
|
|
625
|
+
.composable-tracker__card--leak {
|
|
640
626
|
border-left: 2px solid var(--red);
|
|
641
627
|
border-radius: 0 var(--radius-lg) var(--radius-lg) 0;
|
|
642
628
|
}
|
|
643
629
|
|
|
644
|
-
.
|
|
630
|
+
.composable-tracker__card--expanded {
|
|
645
631
|
border-color: var(--purple);
|
|
646
632
|
}
|
|
647
633
|
|
|
648
|
-
.
|
|
634
|
+
.composable-tracker__card-header {
|
|
649
635
|
display: flex;
|
|
650
636
|
align-items: center;
|
|
651
637
|
justify-content: space-between;
|
|
652
|
-
padding:
|
|
653
|
-
gap:
|
|
638
|
+
padding: var(--tracker-space-3) var(--tracker-space-4);
|
|
639
|
+
gap: var(--tracker-space-3);
|
|
654
640
|
}
|
|
655
641
|
|
|
656
|
-
.
|
|
642
|
+
.composable-tracker__identity {
|
|
657
643
|
display: flex;
|
|
658
644
|
align-items: baseline;
|
|
659
|
-
gap:
|
|
645
|
+
gap: var(--tracker-space-2);
|
|
660
646
|
min-width: 0;
|
|
661
647
|
flex: 1;
|
|
662
648
|
}
|
|
663
649
|
|
|
664
|
-
.
|
|
665
|
-
font-size:
|
|
650
|
+
.composable-tracker__name {
|
|
651
|
+
font-size: var(--tracker-font-size-md);
|
|
666
652
|
font-weight: 500;
|
|
667
653
|
color: var(--text);
|
|
668
654
|
flex-shrink: 0;
|
|
669
655
|
}
|
|
670
656
|
|
|
671
|
-
.
|
|
672
|
-
font-size:
|
|
657
|
+
.composable-tracker__file {
|
|
658
|
+
font-size: var(--tracker-font-size-sm);
|
|
673
659
|
color: var(--text3);
|
|
674
660
|
overflow: hidden;
|
|
675
661
|
text-overflow: ellipsis;
|
|
676
662
|
white-space: nowrap;
|
|
677
663
|
}
|
|
678
664
|
|
|
679
|
-
.
|
|
665
|
+
.composable-tracker__meta {
|
|
680
666
|
display: flex;
|
|
681
667
|
align-items: center;
|
|
682
|
-
gap:
|
|
668
|
+
gap: var(--tracker-space-2);
|
|
683
669
|
flex-shrink: 0;
|
|
684
670
|
}
|
|
685
671
|
|
|
686
|
-
|
|
687
|
-
.refs-preview {
|
|
672
|
+
.composable-tracker__refs-preview {
|
|
688
673
|
display: flex;
|
|
689
674
|
flex-wrap: wrap;
|
|
690
|
-
gap:
|
|
691
|
-
padding: 0
|
|
675
|
+
gap: var(--tracker-space-1);
|
|
676
|
+
padding: 0 var(--tracker-space-4) var(--tracker-space-3);
|
|
692
677
|
align-items: center;
|
|
693
678
|
}
|
|
694
679
|
|
|
695
|
-
.
|
|
680
|
+
.composable-tracker__ref-chip {
|
|
696
681
|
display: inline-flex;
|
|
697
682
|
align-items: center;
|
|
698
|
-
gap:
|
|
683
|
+
gap: var(--tracker-space-1);
|
|
699
684
|
padding: 2px 7px;
|
|
700
685
|
border-radius: 4px;
|
|
701
686
|
background: var(--bg2);
|
|
702
|
-
border:
|
|
703
|
-
font-size:
|
|
687
|
+
border: var(--tracker-border-width) solid var(--border);
|
|
688
|
+
font-size: var(--tracker-font-size-sm);
|
|
704
689
|
font-family: var(--mono);
|
|
705
690
|
max-width: 220px;
|
|
706
691
|
overflow: hidden;
|
|
707
692
|
}
|
|
708
693
|
|
|
709
|
-
.
|
|
694
|
+
.composable-tracker__ref-chip--reactive {
|
|
710
695
|
border-color: color-mix(in srgb, var(--purple) 40%, var(--border));
|
|
711
696
|
background: color-mix(in srgb, var(--purple) 8%, var(--bg2));
|
|
712
697
|
}
|
|
713
698
|
|
|
714
|
-
.
|
|
699
|
+
.composable-tracker__ref-chip--computed {
|
|
715
700
|
border-color: color-mix(in srgb, var(--blue) 40%, var(--border));
|
|
716
701
|
background: color-mix(in srgb, var(--blue) 8%, var(--bg2));
|
|
717
702
|
}
|
|
718
703
|
|
|
719
|
-
.
|
|
704
|
+
.composable-tracker__ref-chip-key {
|
|
720
705
|
color: var(--text2);
|
|
721
706
|
flex-shrink: 0;
|
|
722
707
|
}
|
|
723
708
|
|
|
724
|
-
.
|
|
709
|
+
.composable-tracker__ref-chip-val {
|
|
725
710
|
color: var(--teal);
|
|
726
711
|
overflow: hidden;
|
|
727
712
|
text-overflow: ellipsis;
|
|
728
713
|
white-space: nowrap;
|
|
729
714
|
}
|
|
730
715
|
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
border-top: 0.5px solid var(--border);
|
|
716
|
+
.composable-tracker__detail {
|
|
717
|
+
padding: var(--tracker-space-1) var(--tracker-space-4) var(--tracker-space-4);
|
|
718
|
+
border-top: var(--tracker-border-width) solid var(--border);
|
|
735
719
|
display: flex;
|
|
736
720
|
flex-direction: column;
|
|
737
|
-
gap:
|
|
721
|
+
gap: var(--tracker-space-1);
|
|
738
722
|
}
|
|
739
723
|
|
|
740
|
-
.
|
|
724
|
+
.composable-tracker__leak-banner {
|
|
741
725
|
background: color-mix(in srgb, var(--red) 12%, transparent);
|
|
742
|
-
border:
|
|
726
|
+
border: var(--tracker-border-width) solid color-mix(in srgb, var(--red) 40%, var(--border));
|
|
743
727
|
border-radius: var(--radius);
|
|
744
728
|
padding: 6px 10px;
|
|
745
|
-
font-size:
|
|
729
|
+
font-size: var(--tracker-font-size-sm);
|
|
746
730
|
color: var(--red);
|
|
747
|
-
margin-bottom:
|
|
731
|
+
margin-bottom: var(--tracker-space-2);
|
|
748
732
|
font-family: var(--mono);
|
|
749
733
|
}
|
|
750
734
|
|
|
751
|
-
.
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
margin-top:
|
|
758
|
-
|
|
735
|
+
.composable-tracker__section-label {
|
|
736
|
+
margin-top: var(--tracker-space-2);
|
|
737
|
+
margin-bottom: var(--tracker-space-1);
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
.composable-tracker__section-label--spaced {
|
|
741
|
+
margin-top: var(--tracker-space-4);
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
.composable-tracker__section-label-meta {
|
|
745
|
+
font-weight: 400;
|
|
746
|
+
text-transform: none;
|
|
747
|
+
letter-spacing: 0;
|
|
759
748
|
}
|
|
760
749
|
|
|
761
|
-
.
|
|
750
|
+
.composable-tracker__ref-row {
|
|
762
751
|
display: flex;
|
|
763
752
|
align-items: flex-start;
|
|
764
|
-
gap:
|
|
753
|
+
gap: var(--tracker-space-3);
|
|
765
754
|
padding: 3px 0;
|
|
766
755
|
}
|
|
767
756
|
|
|
768
|
-
.
|
|
757
|
+
.composable-tracker__ref-key {
|
|
769
758
|
min-width: 90px;
|
|
770
759
|
color: var(--text2);
|
|
771
760
|
flex-shrink: 0;
|
|
772
761
|
}
|
|
773
762
|
|
|
774
|
-
.
|
|
763
|
+
.composable-tracker__ref-val {
|
|
775
764
|
flex: 1;
|
|
776
765
|
color: var(--teal);
|
|
777
766
|
min-width: 0;
|
|
778
767
|
}
|
|
779
768
|
|
|
780
|
-
.
|
|
769
|
+
.composable-tracker__ref-val--collapsed {
|
|
781
770
|
overflow: hidden;
|
|
782
771
|
text-overflow: ellipsis;
|
|
783
772
|
white-space: nowrap;
|
|
784
773
|
}
|
|
785
774
|
|
|
786
|
-
.
|
|
775
|
+
.composable-tracker__ref-val--full {
|
|
787
776
|
white-space: pre-wrap;
|
|
788
777
|
word-break: break-all;
|
|
789
778
|
line-height: 1.5;
|
|
790
779
|
}
|
|
791
780
|
|
|
792
|
-
.
|
|
781
|
+
.composable-tracker__ref-row-actions {
|
|
793
782
|
display: flex;
|
|
794
783
|
align-items: center;
|
|
795
|
-
gap:
|
|
784
|
+
gap: var(--tracker-space-1);
|
|
796
785
|
flex-shrink: 0;
|
|
797
786
|
}
|
|
798
787
|
|
|
799
|
-
.
|
|
800
|
-
font-size:
|
|
788
|
+
.composable-tracker__expand-btn {
|
|
789
|
+
font-size: var(--tracker-font-size-xs);
|
|
801
790
|
padding: 1px 5px;
|
|
802
791
|
border-radius: 4px;
|
|
803
|
-
border:
|
|
792
|
+
border: var(--tracker-border-width) solid var(--border);
|
|
804
793
|
background: var(--bg2);
|
|
805
794
|
color: var(--text3);
|
|
806
795
|
cursor: pointer;
|
|
@@ -808,31 +797,66 @@ function applyEdit() {
|
|
|
808
797
|
flex-shrink: 0;
|
|
809
798
|
}
|
|
810
799
|
|
|
811
|
-
.
|
|
800
|
+
.composable-tracker__expand-btn:hover {
|
|
812
801
|
border-color: var(--text3);
|
|
813
802
|
color: var(--text);
|
|
814
803
|
}
|
|
815
804
|
|
|
816
|
-
.
|
|
805
|
+
.composable-tracker__lifecycle-row {
|
|
817
806
|
display: flex;
|
|
818
807
|
align-items: center;
|
|
819
|
-
gap:
|
|
808
|
+
gap: var(--tracker-space-3);
|
|
820
809
|
padding: 2px 0;
|
|
821
810
|
}
|
|
822
811
|
|
|
823
|
-
.
|
|
812
|
+
.composable-tracker__lifecycle-dot {
|
|
824
813
|
width: 6px;
|
|
825
814
|
height: 6px;
|
|
826
815
|
border-radius: 50%;
|
|
827
816
|
flex-shrink: 0;
|
|
828
817
|
}
|
|
829
818
|
|
|
830
|
-
.
|
|
819
|
+
.composable-tracker__lifecycle-dot--ok {
|
|
820
|
+
background: var(--teal);
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
.composable-tracker__lifecycle-dot--error {
|
|
824
|
+
background: var(--red);
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
.composable-tracker__lifecycle-status--ok {
|
|
828
|
+
color: var(--teal);
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
.composable-tracker__lifecycle-status--error {
|
|
832
|
+
color: var(--red);
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
.composable-tracker__context-label {
|
|
836
|
+
min-width: 120px;
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
.composable-tracker__context-value {
|
|
840
|
+
min-width: 0;
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
.composable-tracker__context-value--row {
|
|
844
|
+
display: flex;
|
|
845
|
+
align-items: center;
|
|
846
|
+
gap: var(--tracker-space-2);
|
|
847
|
+
flex-wrap: wrap;
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
.composable-tracker__context-value--muted {
|
|
851
|
+
color: var(--text3);
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
.composable-tracker__ref-chip--shared {
|
|
831
855
|
border-color: color-mix(in srgb, var(--amber) 50%, var(--border));
|
|
832
856
|
background: color-mix(in srgb, var(--amber) 10%, var(--bg2));
|
|
833
857
|
}
|
|
834
858
|
|
|
835
|
-
.
|
|
859
|
+
.composable-tracker__ref-chip-shared-dot {
|
|
836
860
|
display: inline-block;
|
|
837
861
|
width: 5px;
|
|
838
862
|
height: 5px;
|
|
@@ -842,20 +866,20 @@ function applyEdit() {
|
|
|
842
866
|
margin-left: 1px;
|
|
843
867
|
}
|
|
844
868
|
|
|
845
|
-
.
|
|
869
|
+
.composable-tracker__global-banner {
|
|
846
870
|
display: flex;
|
|
847
871
|
align-items: flex-start;
|
|
848
|
-
gap:
|
|
872
|
+
gap: var(--tracker-space-3);
|
|
849
873
|
background: color-mix(in srgb, var(--amber) 10%, transparent);
|
|
850
|
-
border:
|
|
874
|
+
border: var(--tracker-border-width) solid color-mix(in srgb, var(--amber) 40%, var(--border));
|
|
851
875
|
border-radius: var(--radius);
|
|
852
876
|
padding: 7px 10px;
|
|
853
|
-
font-size:
|
|
877
|
+
font-size: var(--tracker-font-size-sm);
|
|
854
878
|
color: var(--text2);
|
|
855
|
-
margin-bottom:
|
|
879
|
+
margin-bottom: var(--tracker-space-2);
|
|
856
880
|
}
|
|
857
881
|
|
|
858
|
-
.
|
|
882
|
+
.composable-tracker__global-dot {
|
|
859
883
|
display: inline-block;
|
|
860
884
|
width: 6px;
|
|
861
885
|
height: 6px;
|
|
@@ -871,7 +895,7 @@ function applyEdit() {
|
|
|
871
895
|
border: 0.5px solid color-mix(in srgb, var(--amber) 40%, var(--border));
|
|
872
896
|
}
|
|
873
897
|
|
|
874
|
-
.
|
|
898
|
+
.composable-tracker__history-list {
|
|
875
899
|
display: flex;
|
|
876
900
|
flex-direction: column;
|
|
877
901
|
gap: 1px;
|
|
@@ -882,33 +906,33 @@ function applyEdit() {
|
|
|
882
906
|
overflow-y: auto;
|
|
883
907
|
}
|
|
884
908
|
|
|
885
|
-
.
|
|
909
|
+
.composable-tracker__history-row {
|
|
886
910
|
display: flex;
|
|
887
911
|
align-items: center;
|
|
888
|
-
gap:
|
|
912
|
+
gap: var(--tracker-space-3);
|
|
889
913
|
padding: 2px 0;
|
|
890
|
-
font-size:
|
|
914
|
+
font-size: var(--tracker-font-size-sm);
|
|
891
915
|
font-family: var(--mono);
|
|
892
|
-
border-bottom:
|
|
916
|
+
border-bottom: var(--tracker-border-width) solid var(--border);
|
|
893
917
|
}
|
|
894
918
|
|
|
895
|
-
.
|
|
919
|
+
.composable-tracker__history-row:last-child {
|
|
896
920
|
border-bottom: none;
|
|
897
921
|
}
|
|
898
922
|
|
|
899
|
-
.
|
|
923
|
+
.composable-tracker__history-time {
|
|
900
924
|
min-width: 52px;
|
|
901
925
|
color: var(--text3);
|
|
902
926
|
flex-shrink: 0;
|
|
903
927
|
}
|
|
904
928
|
|
|
905
|
-
.
|
|
929
|
+
.composable-tracker__history-key {
|
|
906
930
|
min-width: 80px;
|
|
907
931
|
color: var(--text2);
|
|
908
932
|
flex-shrink: 0;
|
|
909
933
|
}
|
|
910
934
|
|
|
911
|
-
.
|
|
935
|
+
.composable-tracker__history-val {
|
|
912
936
|
color: var(--amber);
|
|
913
937
|
overflow: hidden;
|
|
914
938
|
text-overflow: ellipsis;
|
|
@@ -916,48 +940,22 @@ function applyEdit() {
|
|
|
916
940
|
flex: 1;
|
|
917
941
|
}
|
|
918
942
|
|
|
919
|
-
|
|
920
|
-
.stat-card {
|
|
921
|
-
background: var(--bg3);
|
|
922
|
-
border: 0.5px solid var(--border);
|
|
923
|
-
border-radius: var(--radius-lg);
|
|
924
|
-
padding: 10px 14px;
|
|
925
|
-
}
|
|
926
|
-
|
|
927
|
-
.stat-label {
|
|
928
|
-
font-size: 10px;
|
|
929
|
-
font-weight: 500;
|
|
930
|
-
text-transform: uppercase;
|
|
931
|
-
letter-spacing: 0.4px;
|
|
932
|
-
color: var(--text3);
|
|
933
|
-
margin-bottom: 4px;
|
|
934
|
-
}
|
|
935
|
-
|
|
936
|
-
.stat-val {
|
|
937
|
-
font-size: 22px;
|
|
938
|
-
font-weight: 500;
|
|
939
|
-
line-height: 1;
|
|
940
|
-
color: var(--text);
|
|
941
|
-
}
|
|
942
|
-
|
|
943
|
-
/* Clickable ref key */
|
|
944
|
-
.ref-key--clickable {
|
|
943
|
+
.composable-tracker__ref-key--clickable {
|
|
945
944
|
cursor: pointer;
|
|
946
945
|
text-decoration: underline dotted var(--text3);
|
|
947
946
|
text-underline-offset: 2px;
|
|
948
947
|
}
|
|
949
948
|
|
|
950
|
-
.
|
|
949
|
+
.composable-tracker__ref-key--clickable:hover {
|
|
951
950
|
color: var(--purple);
|
|
952
951
|
text-decoration-color: var(--purple);
|
|
953
952
|
}
|
|
954
953
|
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
font-size: 10px;
|
|
954
|
+
.composable-tracker__edit-btn {
|
|
955
|
+
font-size: var(--tracker-font-size-xs);
|
|
958
956
|
padding: 1px 6px;
|
|
959
957
|
border-radius: var(--radius);
|
|
960
|
-
border:
|
|
958
|
+
border: var(--tracker-border-width) solid var(--border);
|
|
961
959
|
background: transparent;
|
|
962
960
|
color: var(--text3);
|
|
963
961
|
cursor: pointer;
|
|
@@ -966,44 +964,60 @@ function applyEdit() {
|
|
|
966
964
|
font-family: var(--mono);
|
|
967
965
|
}
|
|
968
966
|
|
|
969
|
-
.
|
|
967
|
+
.composable-tracker__edit-btn:hover {
|
|
970
968
|
border-color: var(--purple);
|
|
971
969
|
color: var(--purple);
|
|
972
970
|
background: color-mix(in srgb, var(--purple) 8%, transparent);
|
|
973
971
|
}
|
|
974
972
|
|
|
975
|
-
|
|
976
|
-
|
|
973
|
+
.composable-tracker__empty {
|
|
974
|
+
padding: 16px 0;
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
.composable-tracker__compact-muted {
|
|
978
|
+
padding: 2px 0 6px;
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
.composable-tracker__lookup-panel {
|
|
977
982
|
flex-shrink: 0;
|
|
978
|
-
border:
|
|
983
|
+
border: var(--tracker-border-width) solid var(--border);
|
|
979
984
|
border-radius: var(--radius-lg);
|
|
980
985
|
background: var(--bg3);
|
|
981
986
|
overflow: hidden;
|
|
982
987
|
}
|
|
983
988
|
|
|
984
|
-
.
|
|
989
|
+
.composable-tracker__lookup-header {
|
|
985
990
|
display: flex;
|
|
986
991
|
align-items: center;
|
|
987
|
-
gap:
|
|
992
|
+
gap: var(--tracker-space-2);
|
|
988
993
|
padding: 7px 12px;
|
|
989
|
-
border-bottom:
|
|
994
|
+
border-bottom: var(--tracker-border-width) solid var(--border);
|
|
990
995
|
background: var(--bg2);
|
|
991
996
|
}
|
|
992
997
|
|
|
993
|
-
.
|
|
998
|
+
.composable-tracker__lookup-close,
|
|
999
|
+
.composable-tracker__dialog-close,
|
|
1000
|
+
.composable-tracker__lookup-route {
|
|
1001
|
+
margin-left: auto;
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
.composable-tracker__lookup-empty {
|
|
1005
|
+
padding: 6px 12px;
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
.composable-tracker__lookup-row {
|
|
994
1009
|
display: flex;
|
|
995
1010
|
align-items: center;
|
|
996
|
-
gap:
|
|
1011
|
+
gap: var(--tracker-space-3);
|
|
997
1012
|
padding: 5px 12px;
|
|
998
|
-
border-bottom:
|
|
1013
|
+
border-bottom: var(--tracker-border-width) solid var(--border);
|
|
999
1014
|
}
|
|
1000
1015
|
|
|
1001
|
-
.
|
|
1016
|
+
.composable-tracker__lookup-row:last-child {
|
|
1002
1017
|
border-bottom: none;
|
|
1003
1018
|
}
|
|
1004
1019
|
|
|
1005
|
-
|
|
1006
|
-
.edit-overlay {
|
|
1020
|
+
.composable-tracker__edit-overlay {
|
|
1007
1021
|
position: fixed;
|
|
1008
1022
|
inset: 0;
|
|
1009
1023
|
background: rgb(0 0 0 / 40%);
|
|
@@ -1013,9 +1027,9 @@ function applyEdit() {
|
|
|
1013
1027
|
justify-content: center;
|
|
1014
1028
|
}
|
|
1015
1029
|
|
|
1016
|
-
.
|
|
1030
|
+
.composable-tracker__edit-dialog {
|
|
1017
1031
|
background: var(--bg1, var(--bg2));
|
|
1018
|
-
border:
|
|
1032
|
+
border: var(--tracker-border-width) solid var(--border);
|
|
1019
1033
|
border-radius: var(--radius-lg);
|
|
1020
1034
|
padding: 14px 16px;
|
|
1021
1035
|
width: 380px;
|
|
@@ -1026,44 +1040,47 @@ function applyEdit() {
|
|
|
1026
1040
|
box-shadow: 0 8px 32px rgb(0 0 0 / 30%);
|
|
1027
1041
|
}
|
|
1028
1042
|
|
|
1029
|
-
.
|
|
1043
|
+
.composable-tracker__edit-dialog-header {
|
|
1030
1044
|
display: flex;
|
|
1031
1045
|
align-items: center;
|
|
1032
|
-
gap:
|
|
1033
|
-
font-size:
|
|
1046
|
+
gap: var(--tracker-space-2);
|
|
1047
|
+
font-size: var(--tracker-font-size-md);
|
|
1034
1048
|
color: var(--text2);
|
|
1035
1049
|
margin-bottom: 2px;
|
|
1036
1050
|
}
|
|
1037
1051
|
|
|
1038
|
-
.
|
|
1052
|
+
.composable-tracker__edit-help {
|
|
1053
|
+
padding: 4px 0 8px;
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
.composable-tracker__edit-textarea {
|
|
1039
1057
|
width: 100%;
|
|
1040
1058
|
font-family: var(--mono);
|
|
1041
|
-
font-size:
|
|
1059
|
+
font-size: var(--tracker-font-size-md);
|
|
1042
1060
|
padding: 8px 10px;
|
|
1043
1061
|
background: var(--bg2);
|
|
1044
|
-
border:
|
|
1062
|
+
border: var(--tracker-border-width) solid var(--border);
|
|
1045
1063
|
border-radius: var(--radius);
|
|
1046
1064
|
color: var(--text);
|
|
1047
1065
|
resize: vertical;
|
|
1048
1066
|
outline: none;
|
|
1049
1067
|
}
|
|
1050
1068
|
|
|
1051
|
-
.
|
|
1069
|
+
.composable-tracker__edit-textarea:focus {
|
|
1052
1070
|
border-color: var(--purple);
|
|
1053
1071
|
}
|
|
1054
1072
|
|
|
1055
|
-
.
|
|
1073
|
+
.composable-tracker__edit-error {
|
|
1056
1074
|
color: var(--red);
|
|
1057
1075
|
font-family: var(--mono);
|
|
1058
1076
|
}
|
|
1059
1077
|
|
|
1060
|
-
.
|
|
1078
|
+
.composable-tracker__edit-actions {
|
|
1061
1079
|
display: flex;
|
|
1062
|
-
gap:
|
|
1080
|
+
gap: var(--tracker-space-2);
|
|
1063
1081
|
padding-top: 4px;
|
|
1064
1082
|
}
|
|
1065
1083
|
|
|
1066
|
-
/* Slide / fade transitions for the panels */
|
|
1067
1084
|
.slide-enter-active,
|
|
1068
1085
|
.slide-leave-active {
|
|
1069
1086
|
transition:
|
|
@@ -1087,10 +1104,10 @@ function applyEdit() {
|
|
|
1087
1104
|
opacity: 0;
|
|
1088
1105
|
}
|
|
1089
1106
|
|
|
1090
|
-
.
|
|
1091
|
-
font-size:
|
|
1107
|
+
.composable-tracker__jump-btn {
|
|
1108
|
+
font-size: var(--tracker-font-size-xs);
|
|
1092
1109
|
padding: 1px 6px;
|
|
1093
|
-
border:
|
|
1110
|
+
border: var(--tracker-border-width) solid var(--border);
|
|
1094
1111
|
border-radius: var(--radius);
|
|
1095
1112
|
background: transparent;
|
|
1096
1113
|
color: var(--text3);
|
|
@@ -1099,9 +1116,25 @@ function applyEdit() {
|
|
|
1099
1116
|
font-family: var(--mono);
|
|
1100
1117
|
}
|
|
1101
1118
|
|
|
1102
|
-
.
|
|
1119
|
+
.composable-tracker__jump-btn:hover {
|
|
1103
1120
|
border-color: var(--teal);
|
|
1104
1121
|
color: var(--teal);
|
|
1105
1122
|
background: color-mix(in srgb, var(--teal) 8%, transparent);
|
|
1106
1123
|
}
|
|
1124
|
+
|
|
1125
|
+
@media (width <= 900px) {
|
|
1126
|
+
.composable-tracker__card-header,
|
|
1127
|
+
.composable-tracker__ref-row,
|
|
1128
|
+
.composable-tracker__lifecycle-row,
|
|
1129
|
+
.composable-tracker__lookup-row {
|
|
1130
|
+
flex-wrap: wrap;
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
.composable-tracker__identity,
|
|
1134
|
+
.composable-tracker__context-label,
|
|
1135
|
+
.composable-tracker__lookup-route {
|
|
1136
|
+
min-width: 100%;
|
|
1137
|
+
margin-left: 0;
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1107
1140
|
</style>
|