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,7 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed, defineComponent, h, ref, watch, type VNode } from 'vue'
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
3
|
+
import { useResizablePane } from '@observatory-client/composables/useResizablePane'
|
|
4
|
+
import { useObservatoryData, openInEditor as openInEditorFromStore } from '@observatory-client/stores/observatory'
|
|
5
|
+
import type { RenderEntry, RenderEvent } from '@observatory/types/snapshot'
|
|
5
6
|
|
|
6
7
|
interface ComponentNode {
|
|
7
8
|
id: string
|
|
@@ -171,6 +172,7 @@ const TreeNode = defineComponent({
|
|
|
171
172
|
})
|
|
172
173
|
|
|
173
174
|
const { renders, connected } = useObservatoryData()
|
|
175
|
+
const { paneWidth: detailWidth, onHandleMouseDown: onDetailHandleMouseDown } = useResizablePane(280, 'observatory:heatmap:detailWidth')
|
|
174
176
|
|
|
175
177
|
const activeMode = ref<'count' | 'time'>('count')
|
|
176
178
|
// Route filter — '' means show all routes
|
|
@@ -706,13 +708,13 @@ function formatTimestamp(t: number): string {
|
|
|
706
708
|
</script>
|
|
707
709
|
|
|
708
710
|
<template>
|
|
709
|
-
<div class="view">
|
|
710
|
-
<div class="
|
|
711
|
-
<div class="
|
|
711
|
+
<div class="render-heatmap tracker-view">
|
|
712
|
+
<div class="render-heatmap__controls tracker-toolbar">
|
|
713
|
+
<div class="render-heatmap__mode-group">
|
|
712
714
|
<button :class="{ active: activeMode === 'count' }" @click="activeMode = 'count'">render count</button>
|
|
713
715
|
<button :class="{ active: activeMode === 'time' }" @click="activeMode = 'time'">render time</button>
|
|
714
716
|
</div>
|
|
715
|
-
<div class="
|
|
717
|
+
<div class="render-heatmap__threshold-group">
|
|
716
718
|
<span class="muted text-sm">threshold</span>
|
|
717
719
|
<input
|
|
718
720
|
v-model.number="activeThreshold"
|
|
@@ -720,7 +722,7 @@ function formatTimestamp(t: number): string {
|
|
|
720
722
|
:min="activeMode === 'count' ? 2 : 4"
|
|
721
723
|
:max="activeMode === 'count' ? 20 : 100"
|
|
722
724
|
:step="activeMode === 'count' ? 1 : 4"
|
|
723
|
-
|
|
725
|
+
class="render-heatmap__threshold-range"
|
|
724
726
|
/>
|
|
725
727
|
<span class="mono text-sm">{{ activeThreshold }}{{ activeMode === 'count' ? '+ renders' : 'ms+' }}</span>
|
|
726
728
|
</div>
|
|
@@ -729,12 +731,12 @@ function formatTimestamp(t: number): string {
|
|
|
729
731
|
<option value="">all routes</option>
|
|
730
732
|
<option v-for="r in knownRoutes" :key="r" :value="r">{{ r }}</option>
|
|
731
733
|
</select>
|
|
732
|
-
<button :class="{ active: frozen }"
|
|
734
|
+
<button :class="{ active: frozen }" class="render-heatmap__freeze tracker-toolbar__spacer" @click="toggleFreeze">
|
|
733
735
|
{{ frozen ? 'unfreeze' : 'freeze snapshot' }}
|
|
734
736
|
</button>
|
|
735
737
|
</div>
|
|
736
738
|
|
|
737
|
-
<div class="stats-row">
|
|
739
|
+
<div class="render-heatmap__stats tracker-stats-row">
|
|
738
740
|
<div class="stat-card">
|
|
739
741
|
<div class="stat-label">components</div>
|
|
740
742
|
<div class="stat-val">{{ allComponents.length }}</div>
|
|
@@ -745,7 +747,7 @@ function formatTimestamp(t: number): string {
|
|
|
745
747
|
</div>
|
|
746
748
|
<div class="stat-card">
|
|
747
749
|
<div class="stat-label">hot</div>
|
|
748
|
-
<div class="stat-val
|
|
750
|
+
<div class="stat-val stat-val--error">{{ hotCount }}</div>
|
|
749
751
|
</div>
|
|
750
752
|
<div class="stat-card">
|
|
751
753
|
<div class="stat-label">avg time</div>
|
|
@@ -753,32 +755,37 @@ function formatTimestamp(t: number): string {
|
|
|
753
755
|
</div>
|
|
754
756
|
</div>
|
|
755
757
|
|
|
756
|
-
<div class="
|
|
757
|
-
<aside class="
|
|
758
|
-
<div class="
|
|
758
|
+
<div class="render-heatmap__inspector">
|
|
759
|
+
<aside class="render-heatmap__roots-panel">
|
|
760
|
+
<div class="render-heatmap__panel-title tracker-section-label">apps</div>
|
|
759
761
|
<button
|
|
760
762
|
v-for="entry in appEntries"
|
|
761
763
|
:key="entry.id"
|
|
762
|
-
class="
|
|
764
|
+
class="render-heatmap__root-item"
|
|
763
765
|
:class="{ active: activeRootId === entry.id }"
|
|
764
766
|
@click="selectRoot(entry.root)"
|
|
765
767
|
>
|
|
766
|
-
<div class="
|
|
767
|
-
<span class="
|
|
768
|
-
<span class="
|
|
768
|
+
<div class="render-heatmap__root-copy">
|
|
769
|
+
<span class="render-heatmap__root-label mono">{{ entry.label }}</span>
|
|
770
|
+
<span class="render-heatmap__root-sub muted mono">{{ entry.root.label }}</span>
|
|
769
771
|
</div>
|
|
770
|
-
<span class="
|
|
772
|
+
<span class="render-heatmap__root-meta mono">{{ entry.meta }}</span>
|
|
771
773
|
</button>
|
|
772
|
-
<div v-if="!appEntries.length" class="
|
|
774
|
+
<div v-if="!appEntries.length" class="render-heatmap__detail-empty">no apps match</div>
|
|
773
775
|
</aside>
|
|
774
776
|
|
|
775
|
-
<section class="
|
|
776
|
-
<div class="
|
|
777
|
-
<input
|
|
777
|
+
<section class="render-heatmap__tree-panel">
|
|
778
|
+
<div class="render-heatmap__tree-toolbar">
|
|
779
|
+
<input
|
|
780
|
+
:value="search"
|
|
781
|
+
class="render-heatmap__search-input mono"
|
|
782
|
+
placeholder="Find components..."
|
|
783
|
+
@input="updateSearch"
|
|
784
|
+
/>
|
|
778
785
|
</div>
|
|
779
786
|
|
|
780
|
-
<div class="
|
|
781
|
-
<div class="tree-canvas">
|
|
787
|
+
<div class="render-heatmap__tree-frame">
|
|
788
|
+
<div class="render-heatmap__tree-canvas tree-canvas">
|
|
782
789
|
<TreeNode
|
|
783
790
|
v-for="root in visibleTreeRoots"
|
|
784
791
|
:key="root.id"
|
|
@@ -791,47 +798,62 @@ function formatTimestamp(t: number): string {
|
|
|
791
798
|
@toggle="toggleNode"
|
|
792
799
|
/>
|
|
793
800
|
</div>
|
|
794
|
-
<div v-if="!visibleTreeRoots.length" class="
|
|
801
|
+
<div v-if="!visibleTreeRoots.length" class="render-heatmap__detail-empty">
|
|
795
802
|
{{ connected ? 'No render activity recorded yet.' : 'Waiting for connection to the Nuxt app…' }}
|
|
796
803
|
</div>
|
|
797
804
|
</div>
|
|
798
805
|
</section>
|
|
799
806
|
|
|
800
|
-
<
|
|
807
|
+
<div class="tracker-resize-handle" @mousedown="onDetailHandleMouseDown" />
|
|
808
|
+
|
|
809
|
+
<aside class="render-heatmap__detail-panel tracker-detail-panel" :style="{ width: detailWidth + 'px' }">
|
|
801
810
|
<template v-if="activeSelected">
|
|
802
|
-
<div class="
|
|
803
|
-
<span class="mono bold"
|
|
811
|
+
<div class="render-heatmap__detail-header">
|
|
812
|
+
<span class="render-heatmap__detail-title mono bold">{{ activeSelected.label }}</span>
|
|
804
813
|
<button @click="activeSelectedId = null">×</button>
|
|
805
814
|
</div>
|
|
806
815
|
|
|
807
|
-
<div class="
|
|
808
|
-
<span class="
|
|
816
|
+
<div class="render-heatmap__detail-pill-row">
|
|
817
|
+
<span class="render-heatmap__detail-pill mono">
|
|
809
818
|
{{ activeSelected.rerenders + activeSelected.mountCount }} render{{
|
|
810
819
|
activeSelected.rerenders + activeSelected.mountCount !== 1 ? 's' : ''
|
|
811
820
|
}}
|
|
812
821
|
</span>
|
|
813
|
-
<span class="
|
|
822
|
+
<span class="render-heatmap__detail-pill render-heatmap__detail-pill--muted mono muted">
|
|
814
823
|
{{ activeSelected.mountCount }} mount{{ activeSelected.mountCount !== 1 ? 's' : '' }}
|
|
815
824
|
</span>
|
|
816
|
-
<span v-if="activeSelected.rerenders" class="
|
|
825
|
+
<span v-if="activeSelected.rerenders" class="render-heatmap__detail-pill mono">
|
|
817
826
|
{{ activeSelected.rerenders }} re-render{{ activeSelected.rerenders !== 1 ? 's' : '' }}
|
|
818
827
|
</span>
|
|
819
|
-
<span
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
828
|
+
<span
|
|
829
|
+
v-if="activeSelected.isPersistent"
|
|
830
|
+
class="render-heatmap__detail-pill render-heatmap__detail-pill--persistent mono"
|
|
831
|
+
>
|
|
832
|
+
persistent
|
|
833
|
+
</span>
|
|
834
|
+
<span
|
|
835
|
+
v-if="activeSelected.isHydrationMount"
|
|
836
|
+
class="render-heatmap__detail-pill render-heatmap__detail-pill--hydrated mono"
|
|
837
|
+
>
|
|
838
|
+
hydrated
|
|
839
|
+
</span>
|
|
840
|
+
<span class="render-heatmap__detail-pill mono">{{ activeSelected.avgMs.toFixed(1) }}ms avg</span>
|
|
841
|
+
<span
|
|
842
|
+
class="render-heatmap__detail-pill mono"
|
|
843
|
+
:class="{ 'render-heatmap__detail-pill--hot': isHot(activeSelected) }"
|
|
844
|
+
>
|
|
823
845
|
{{ isHot(activeSelected) ? 'hot' : 'cool' }}
|
|
824
846
|
</span>
|
|
825
847
|
</div>
|
|
826
848
|
|
|
827
|
-
<div class="section-label">identity</div>
|
|
828
|
-
<div class="
|
|
849
|
+
<div class="tracker-section-label render-heatmap__section-label">identity</div>
|
|
850
|
+
<div class="render-heatmap__meta-grid">
|
|
829
851
|
<span class="muted text-sm">label</span>
|
|
830
852
|
<span class="mono text-sm">{{ activeSelected.label }}</span>
|
|
831
853
|
<span class="muted text-sm">path</span>
|
|
832
854
|
<span class="mono text-sm">{{ pathLabel(activeSelected) }}</span>
|
|
833
855
|
<span class="muted text-sm">file</span>
|
|
834
|
-
<span class="mono text-sm muted"
|
|
856
|
+
<span class="render-heatmap__file-row mono text-sm muted">
|
|
835
857
|
{{ activeSelected.file }}
|
|
836
858
|
<button
|
|
837
859
|
v-if="activeSelected.file && activeSelected.file !== 'unknown'"
|
|
@@ -850,8 +872,8 @@ function formatTimestamp(t: number): string {
|
|
|
850
872
|
<span class="mono text-sm">{{ activeSelected.children.length }}</span>
|
|
851
873
|
</div>
|
|
852
874
|
|
|
853
|
-
<div class="section-label">rendering</div>
|
|
854
|
-
<div class="
|
|
875
|
+
<div class="tracker-section-label render-heatmap__section-label">rendering</div>
|
|
876
|
+
<div class="render-heatmap__meta-grid">
|
|
855
877
|
<span class="muted text-sm">total renders</span>
|
|
856
878
|
<span class="mono text-sm">{{ activeSelected.rerenders + activeSelected.mountCount }}</span>
|
|
857
879
|
<span class="muted text-sm">re-renders</span>
|
|
@@ -859,7 +881,7 @@ function formatTimestamp(t: number): string {
|
|
|
859
881
|
<span class="muted text-sm">mounts</span>
|
|
860
882
|
<span class="mono text-sm">{{ activeSelected.mountCount }}</span>
|
|
861
883
|
<span class="muted text-sm">persistent</span>
|
|
862
|
-
<span class="mono text-sm" :
|
|
884
|
+
<span class="mono text-sm" :class="{ 'render-heatmap__persistent-value': activeSelected.isPersistent }">
|
|
863
885
|
{{ activeSelected.isPersistent ? 'yes — survives navigation' : 'no' }}
|
|
864
886
|
</span>
|
|
865
887
|
<span class="muted text-sm">hydration mount</span>
|
|
@@ -872,47 +894,42 @@ function formatTimestamp(t: number): string {
|
|
|
872
894
|
<span class="mono text-sm">{{ activeMode === 'count' ? 're-render count' : 'render time' }}</span>
|
|
873
895
|
</div>
|
|
874
896
|
|
|
875
|
-
<div class="section-label">triggers</div>
|
|
876
|
-
<div v-for="trigger in activeSelected.triggers" :key="trigger" class="
|
|
897
|
+
<div class="tracker-section-label render-heatmap__section-label">triggers</div>
|
|
898
|
+
<div v-for="trigger in activeSelected.triggers" :key="trigger" class="render-heatmap__trigger-item mono text-sm">
|
|
899
|
+
{{ trigger }}
|
|
900
|
+
</div>
|
|
877
901
|
<div v-if="!activeSelected.triggers.length" class="muted text-sm">no triggers recorded</div>
|
|
878
902
|
|
|
879
|
-
<div class="section-label
|
|
903
|
+
<div class="tracker-section-label render-heatmap__section-label render-heatmap__section-label--timeline">
|
|
880
904
|
render timeline
|
|
881
|
-
<span class="
|
|
882
|
-
({{ activeSelected.timeline.length }})
|
|
883
|
-
</span>
|
|
905
|
+
<span class="render-heatmap__section-label-meta muted">({{ activeSelected.timeline.length }})</span>
|
|
884
906
|
</div>
|
|
885
907
|
<div v-if="!activeSelected.timeline.length" class="muted text-sm">no timeline events yet</div>
|
|
886
|
-
<div v-else class="
|
|
887
|
-
<div
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
<span class="
|
|
908
|
+
<div v-else class="render-heatmap__timeline-list">
|
|
909
|
+
<div
|
|
910
|
+
v-for="(event, idx) in [...activeSelected.timeline].reverse().slice(0, 30)"
|
|
911
|
+
:key="idx"
|
|
912
|
+
class="render-heatmap__timeline-row"
|
|
913
|
+
>
|
|
914
|
+
<span class="render-heatmap__timeline-kind mono" :class="event.kind">{{ event.kind }}</span>
|
|
915
|
+
<span class="render-heatmap__timeline-time mono muted">{{ formatTimestamp(event.t) }}</span>
|
|
916
|
+
<span class="render-heatmap__timeline-dur mono">{{ formatMs(event.durationMs) }}</span>
|
|
917
|
+
<span v-if="event.triggerKey" class="render-heatmap__timeline-trigger mono muted">{{ event.triggerKey }}</span>
|
|
918
|
+
<span class="render-heatmap__timeline-route mono muted">{{ event.route }}</span>
|
|
893
919
|
</div>
|
|
894
|
-
<div v-if="activeSelected.timeline.length > 30" class="muted text-sm"
|
|
920
|
+
<div v-if="activeSelected.timeline.length > 30" class="render-heatmap__compact-muted muted text-sm">
|
|
895
921
|
… {{ activeSelected.timeline.length - 30 }} earlier events
|
|
896
922
|
</div>
|
|
897
923
|
</div>
|
|
898
924
|
</template>
|
|
899
|
-
<div v-else class="
|
|
925
|
+
<div v-else class="render-heatmap__detail-empty">click a component to inspect</div>
|
|
900
926
|
</aside>
|
|
901
927
|
</div>
|
|
902
928
|
</div>
|
|
903
929
|
</template>
|
|
904
930
|
|
|
905
931
|
<style scoped>
|
|
906
|
-
.
|
|
907
|
-
display: flex;
|
|
908
|
-
flex-direction: column;
|
|
909
|
-
height: 100%;
|
|
910
|
-
overflow: hidden;
|
|
911
|
-
padding: 12px;
|
|
912
|
-
gap: 10px;
|
|
913
|
-
}
|
|
914
|
-
|
|
915
|
-
.controls {
|
|
932
|
+
.render-heatmap__controls {
|
|
916
933
|
display: flex;
|
|
917
934
|
align-items: center;
|
|
918
935
|
gap: 8px;
|
|
@@ -920,65 +937,67 @@ function formatTimestamp(t: number): string {
|
|
|
920
937
|
flex-wrap: wrap;
|
|
921
938
|
}
|
|
922
939
|
|
|
923
|
-
.
|
|
940
|
+
.render-heatmap__mode-group {
|
|
924
941
|
display: flex;
|
|
925
942
|
gap: 2px;
|
|
926
943
|
}
|
|
927
944
|
|
|
928
|
-
.
|
|
945
|
+
.render-heatmap__threshold-group {
|
|
929
946
|
display: flex;
|
|
930
947
|
align-items: center;
|
|
931
948
|
gap: 6px;
|
|
932
949
|
}
|
|
933
950
|
|
|
934
|
-
.
|
|
935
|
-
|
|
936
|
-
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
937
|
-
gap: 8px;
|
|
938
|
-
flex-shrink: 0;
|
|
951
|
+
.render-heatmap__threshold-range {
|
|
952
|
+
width: 90px;
|
|
939
953
|
}
|
|
940
954
|
|
|
941
955
|
.stat-sub {
|
|
942
|
-
margin-top:
|
|
943
|
-
font-size:
|
|
956
|
+
margin-top: var(--tracker-space-1);
|
|
957
|
+
font-size: var(--tracker-font-size-sm);
|
|
944
958
|
color: var(--text3);
|
|
945
959
|
}
|
|
946
960
|
|
|
947
|
-
.
|
|
948
|
-
display:
|
|
949
|
-
|
|
950
|
-
gap: 12px;
|
|
961
|
+
.render-heatmap__inspector {
|
|
962
|
+
display: flex;
|
|
963
|
+
gap: 0;
|
|
951
964
|
flex: 1;
|
|
952
965
|
min-height: 0;
|
|
953
966
|
}
|
|
954
967
|
|
|
955
|
-
.
|
|
956
|
-
.
|
|
957
|
-
|
|
958
|
-
|
|
968
|
+
.render-heatmap__roots-panel,
|
|
969
|
+
.render-heatmap__detail-panel {
|
|
970
|
+
flex-shrink: 0;
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
.render-heatmap__roots-panel {
|
|
974
|
+
width: 240px;
|
|
975
|
+
margin-right: 12px;
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
.render-heatmap__roots-panel,
|
|
979
|
+
.render-heatmap__tree-panel,
|
|
980
|
+
.render-heatmap__detail-panel {
|
|
981
|
+
border: var(--tracker-border-width) solid var(--border);
|
|
959
982
|
border-radius: var(--radius-lg);
|
|
960
983
|
background: var(--bg3);
|
|
961
984
|
min-height: 0;
|
|
962
985
|
}
|
|
963
986
|
|
|
964
|
-
.
|
|
965
|
-
.
|
|
987
|
+
.render-heatmap__roots-panel,
|
|
988
|
+
.render-heatmap__detail-panel {
|
|
966
989
|
display: flex;
|
|
967
990
|
flex-direction: column;
|
|
968
991
|
overflow: auto;
|
|
969
|
-
padding:
|
|
970
|
-
gap:
|
|
992
|
+
padding: var(--tracker-space-3);
|
|
993
|
+
gap: var(--tracker-space-2);
|
|
971
994
|
}
|
|
972
995
|
|
|
973
|
-
.
|
|
974
|
-
|
|
975
|
-
font-weight: 500;
|
|
976
|
-
text-transform: uppercase;
|
|
977
|
-
letter-spacing: 0.4px;
|
|
978
|
-
color: var(--text3);
|
|
996
|
+
.render-heatmap__panel-title {
|
|
997
|
+
margin: 0;
|
|
979
998
|
}
|
|
980
999
|
|
|
981
|
-
.
|
|
1000
|
+
.render-heatmap__root-item {
|
|
982
1001
|
display: flex;
|
|
983
1002
|
align-items: center;
|
|
984
1003
|
justify-content: space-between;
|
|
@@ -992,44 +1011,46 @@ function formatTimestamp(t: number): string {
|
|
|
992
1011
|
text-align: left;
|
|
993
1012
|
}
|
|
994
1013
|
|
|
995
|
-
.
|
|
1014
|
+
.render-heatmap__root-item.active {
|
|
996
1015
|
border-color: var(--teal);
|
|
997
1016
|
background: color-mix(in srgb, var(--teal) 16%, var(--bg2));
|
|
998
1017
|
}
|
|
999
1018
|
|
|
1000
|
-
.
|
|
1019
|
+
.render-heatmap__root-label {
|
|
1001
1020
|
overflow: hidden;
|
|
1002
1021
|
text-overflow: ellipsis;
|
|
1003
1022
|
white-space: nowrap;
|
|
1004
1023
|
}
|
|
1005
1024
|
|
|
1006
|
-
.
|
|
1025
|
+
.render-heatmap__root-copy {
|
|
1007
1026
|
display: flex;
|
|
1008
1027
|
flex-direction: column;
|
|
1009
1028
|
min-width: 0;
|
|
1010
1029
|
}
|
|
1011
1030
|
|
|
1012
|
-
.
|
|
1013
|
-
font-size:
|
|
1031
|
+
.render-heatmap__root-sub {
|
|
1032
|
+
font-size: var(--tracker-font-size-sm);
|
|
1014
1033
|
}
|
|
1015
1034
|
|
|
1016
|
-
.
|
|
1035
|
+
.render-heatmap__root-meta {
|
|
1017
1036
|
color: var(--text3);
|
|
1018
|
-
font-size:
|
|
1037
|
+
font-size: var(--tracker-font-size-sm);
|
|
1019
1038
|
}
|
|
1020
1039
|
|
|
1021
|
-
.
|
|
1040
|
+
.render-heatmap__tree-panel {
|
|
1022
1041
|
display: flex;
|
|
1023
1042
|
flex-direction: column;
|
|
1024
1043
|
overflow: hidden;
|
|
1044
|
+
flex: 1;
|
|
1045
|
+
min-width: 0;
|
|
1025
1046
|
}
|
|
1026
1047
|
|
|
1027
|
-
.
|
|
1028
|
-
padding:
|
|
1029
|
-
border-bottom:
|
|
1048
|
+
.render-heatmap__tree-toolbar {
|
|
1049
|
+
padding: var(--tracker-space-3);
|
|
1050
|
+
border-bottom: var(--tracker-border-width) solid var(--border);
|
|
1030
1051
|
}
|
|
1031
1052
|
|
|
1032
|
-
.
|
|
1053
|
+
.render-heatmap__search-input {
|
|
1033
1054
|
width: 100%;
|
|
1034
1055
|
padding: 10px 12px;
|
|
1035
1056
|
border: 1px solid var(--border);
|
|
@@ -1038,14 +1059,14 @@ function formatTimestamp(t: number): string {
|
|
|
1038
1059
|
color: var(--text);
|
|
1039
1060
|
}
|
|
1040
1061
|
|
|
1041
|
-
.
|
|
1062
|
+
.render-heatmap__tree-frame {
|
|
1042
1063
|
flex: 1;
|
|
1043
1064
|
min-height: 0;
|
|
1044
1065
|
overflow: auto;
|
|
1045
|
-
padding:
|
|
1066
|
+
padding: var(--tracker-space-3);
|
|
1046
1067
|
}
|
|
1047
1068
|
|
|
1048
|
-
|
|
1069
|
+
.render-heatmap__tree-canvas {
|
|
1049
1070
|
display: inline-block;
|
|
1050
1071
|
min-width: 100%;
|
|
1051
1072
|
width: max-content;
|
|
@@ -1197,72 +1218,77 @@ function formatTimestamp(t: number): string {
|
|
|
1197
1218
|
border-left: 1px solid color-mix(in srgb, var(--border) 72%, transparent);
|
|
1198
1219
|
}
|
|
1199
1220
|
|
|
1200
|
-
.
|
|
1221
|
+
.render-heatmap__detail-empty {
|
|
1201
1222
|
display: flex;
|
|
1202
1223
|
align-items: center;
|
|
1203
1224
|
justify-content: center;
|
|
1204
1225
|
height: 100%;
|
|
1205
1226
|
color: var(--text3);
|
|
1206
|
-
font-size:
|
|
1227
|
+
font-size: var(--tracker-font-size-md);
|
|
1207
1228
|
}
|
|
1208
1229
|
|
|
1209
|
-
.
|
|
1230
|
+
.render-heatmap__detail-header {
|
|
1210
1231
|
display: flex;
|
|
1211
1232
|
align-items: center;
|
|
1212
1233
|
justify-content: space-between;
|
|
1213
1234
|
}
|
|
1214
1235
|
|
|
1215
|
-
.
|
|
1236
|
+
.render-heatmap__detail-title {
|
|
1237
|
+
font-size: var(--tracker-font-size-md);
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
.render-heatmap__meta-grid {
|
|
1216
1241
|
display: grid;
|
|
1217
1242
|
grid-template-columns: auto 1fr;
|
|
1218
|
-
gap:
|
|
1243
|
+
gap: var(--tracker-space-1) var(--tracker-space-3);
|
|
1219
1244
|
}
|
|
1220
1245
|
|
|
1221
|
-
.
|
|
1246
|
+
.render-heatmap__detail-pill-row {
|
|
1222
1247
|
display: flex;
|
|
1223
1248
|
flex-wrap: wrap;
|
|
1224
1249
|
gap: 6px;
|
|
1225
1250
|
}
|
|
1226
1251
|
|
|
1227
|
-
.
|
|
1252
|
+
.render-heatmap__detail-pill {
|
|
1228
1253
|
border: 1px solid var(--border);
|
|
1229
1254
|
border-radius: 999px;
|
|
1230
1255
|
padding: 4px 8px;
|
|
1231
1256
|
background: var(--bg2);
|
|
1232
|
-
font-size:
|
|
1257
|
+
font-size: var(--tracker-font-size-sm);
|
|
1233
1258
|
}
|
|
1234
1259
|
|
|
1235
|
-
.
|
|
1260
|
+
.render-heatmap__detail-pill--hot {
|
|
1236
1261
|
border-color: color-mix(in srgb, var(--red) 50%, var(--border));
|
|
1237
1262
|
color: var(--red);
|
|
1238
1263
|
}
|
|
1239
1264
|
|
|
1240
|
-
.
|
|
1265
|
+
.render-heatmap__detail-pill--persistent {
|
|
1241
1266
|
border-color: color-mix(in srgb, var(--amber) 55%, var(--border));
|
|
1242
1267
|
color: color-mix(in srgb, var(--amber) 80%, var(--text));
|
|
1243
1268
|
}
|
|
1244
1269
|
|
|
1245
|
-
.
|
|
1270
|
+
.render-heatmap__detail-pill--hydrated {
|
|
1246
1271
|
border-color: color-mix(in srgb, var(--teal) 55%, var(--border));
|
|
1247
1272
|
color: color-mix(in srgb, var(--teal) 80%, var(--text));
|
|
1248
1273
|
}
|
|
1249
1274
|
|
|
1250
|
-
.
|
|
1275
|
+
.render-heatmap__detail-pill--muted {
|
|
1251
1276
|
color: var(--text3);
|
|
1252
1277
|
border-color: var(--border);
|
|
1253
1278
|
}
|
|
1254
1279
|
|
|
1255
|
-
.
|
|
1256
|
-
font-size: 10px;
|
|
1257
|
-
font-weight: 500;
|
|
1258
|
-
text-transform: uppercase;
|
|
1259
|
-
letter-spacing: 0.4px;
|
|
1260
|
-
color: var(--text3);
|
|
1280
|
+
.render-heatmap__section-label {
|
|
1261
1281
|
margin-top: 8px;
|
|
1262
1282
|
margin-bottom: 4px;
|
|
1263
1283
|
}
|
|
1264
1284
|
|
|
1265
|
-
.
|
|
1285
|
+
.render-heatmap__file-row {
|
|
1286
|
+
display: flex;
|
|
1287
|
+
align-items: center;
|
|
1288
|
+
gap: 6px;
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
.render-heatmap__trigger-item {
|
|
1266
1292
|
background: var(--bg2);
|
|
1267
1293
|
border-radius: var(--radius);
|
|
1268
1294
|
padding: 4px 8px;
|
|
@@ -1270,6 +1296,20 @@ function formatTimestamp(t: number): string {
|
|
|
1270
1296
|
color: var(--text2);
|
|
1271
1297
|
}
|
|
1272
1298
|
|
|
1299
|
+
.render-heatmap__persistent-value {
|
|
1300
|
+
color: color-mix(in srgb, var(--amber) 80%, var(--text));
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1303
|
+
.render-heatmap__section-label--timeline {
|
|
1304
|
+
margin-top: var(--tracker-space-2);
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
.render-heatmap__section-label-meta {
|
|
1308
|
+
font-weight: 400;
|
|
1309
|
+
text-transform: none;
|
|
1310
|
+
letter-spacing: 0;
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1273
1313
|
:deep(.tree-jump-btn) {
|
|
1274
1314
|
display: none;
|
|
1275
1315
|
padding: 0 4px;
|
|
@@ -1320,7 +1360,7 @@ function formatTimestamp(t: number): string {
|
|
|
1320
1360
|
max-width: 140px;
|
|
1321
1361
|
}
|
|
1322
1362
|
|
|
1323
|
-
.
|
|
1363
|
+
.render-heatmap__timeline-list {
|
|
1324
1364
|
display: flex;
|
|
1325
1365
|
flex-direction: column;
|
|
1326
1366
|
gap: 1px;
|
|
@@ -1332,49 +1372,49 @@ function formatTimestamp(t: number): string {
|
|
|
1332
1372
|
min-height: fit-content;
|
|
1333
1373
|
}
|
|
1334
1374
|
|
|
1335
|
-
.
|
|
1375
|
+
.render-heatmap__timeline-row {
|
|
1336
1376
|
display: flex;
|
|
1337
1377
|
align-items: center;
|
|
1338
1378
|
gap: 6px;
|
|
1339
1379
|
padding: 2px 0;
|
|
1340
|
-
font-size:
|
|
1341
|
-
border-bottom:
|
|
1380
|
+
font-size: var(--tracker-font-size-sm);
|
|
1381
|
+
border-bottom: var(--tracker-border-width) solid var(--border);
|
|
1342
1382
|
min-width: 0;
|
|
1343
1383
|
min-height: fit-content;
|
|
1344
1384
|
}
|
|
1345
1385
|
|
|
1346
|
-
.
|
|
1386
|
+
.render-heatmap__timeline-row:last-child {
|
|
1347
1387
|
border-bottom: none;
|
|
1348
1388
|
}
|
|
1349
1389
|
|
|
1350
|
-
.
|
|
1390
|
+
.render-heatmap__timeline-kind {
|
|
1351
1391
|
flex-shrink: 0;
|
|
1352
|
-
font-size:
|
|
1392
|
+
font-size: var(--tracker-font-size-xs);
|
|
1353
1393
|
font-weight: 500;
|
|
1354
1394
|
min-width: 40px;
|
|
1355
1395
|
}
|
|
1356
1396
|
|
|
1357
|
-
.
|
|
1397
|
+
.render-heatmap__timeline-kind.mount {
|
|
1358
1398
|
color: var(--teal);
|
|
1359
1399
|
}
|
|
1360
1400
|
|
|
1361
|
-
.
|
|
1401
|
+
.render-heatmap__timeline-kind.update {
|
|
1362
1402
|
color: var(--amber);
|
|
1363
1403
|
}
|
|
1364
1404
|
|
|
1365
|
-
.
|
|
1405
|
+
.render-heatmap__timeline-time {
|
|
1366
1406
|
flex-shrink: 0;
|
|
1367
1407
|
min-width: 52px;
|
|
1368
1408
|
color: var(--text3);
|
|
1369
1409
|
}
|
|
1370
1410
|
|
|
1371
|
-
.
|
|
1411
|
+
.render-heatmap__timeline-dur {
|
|
1372
1412
|
flex-shrink: 0;
|
|
1373
1413
|
min-width: 38px;
|
|
1374
1414
|
color: var(--text2);
|
|
1375
1415
|
}
|
|
1376
1416
|
|
|
1377
|
-
.
|
|
1417
|
+
.render-heatmap__timeline-trigger {
|
|
1378
1418
|
overflow: hidden;
|
|
1379
1419
|
text-overflow: ellipsis;
|
|
1380
1420
|
white-space: nowrap;
|
|
@@ -1383,19 +1423,23 @@ function formatTimestamp(t: number): string {
|
|
|
1383
1423
|
min-width: 0;
|
|
1384
1424
|
}
|
|
1385
1425
|
|
|
1386
|
-
.
|
|
1426
|
+
.render-heatmap__timeline-route {
|
|
1387
1427
|
flex-shrink: 0;
|
|
1428
|
+
margin-left: auto;
|
|
1388
1429
|
color: var(--text3);
|
|
1389
|
-
font-size:
|
|
1430
|
+
font-size: var(--tracker-font-size-xs);
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
.render-heatmap__compact-muted {
|
|
1434
|
+
padding: 2px 0;
|
|
1390
1435
|
}
|
|
1391
1436
|
|
|
1392
1437
|
@media (width <= 1180px) {
|
|
1393
|
-
.
|
|
1394
|
-
|
|
1438
|
+
.render-heatmap__roots-panel {
|
|
1439
|
+
display: none;
|
|
1395
1440
|
}
|
|
1396
1441
|
|
|
1397
|
-
.
|
|
1398
|
-
grid-column: 1 / -1;
|
|
1442
|
+
.render-heatmap__detail-panel {
|
|
1399
1443
|
max-height: 220px;
|
|
1400
1444
|
}
|
|
1401
1445
|
}
|