@ogygia/devtools 0.0.0-stage → 0.11.0
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/LICENSE +21 -0
- package/README.md +25 -2
- package/dist/client.d.ts +3 -0
- package/dist/client.js +24 -0
- package/dist/devtools/BoundaryOverlay.svelte +396 -0
- package/dist/devtools/BoundaryOverlay.svelte.d.ts +19 -0
- package/dist/devtools/Devtools.svelte +663 -0
- package/dist/devtools/Devtools.svelte.d.ts +15 -0
- package/dist/devtools/HubTab.svelte +206 -0
- package/dist/devtools/HubTab.svelte.d.ts +11 -0
- package/dist/devtools/HydrationTab.svelte +237 -0
- package/dist/devtools/HydrationTab.svelte.d.ts +13 -0
- package/dist/devtools/IslandDetail.svelte +615 -0
- package/dist/devtools/IslandDetail.svelte.d.ts +15 -0
- package/dist/devtools/LedgerTab.svelte +287 -0
- package/dist/devtools/LedgerTab.svelte.d.ts +11 -0
- package/dist/devtools/LensTab.svelte +290 -0
- package/dist/devtools/LensTab.svelte.d.ts +19 -0
- package/dist/devtools/NavTab.svelte +229 -0
- package/dist/devtools/NavTab.svelte.d.ts +11 -0
- package/dist/devtools/PageTab.svelte +1122 -0
- package/dist/devtools/PageTab.svelte.d.ts +15 -0
- package/dist/devtools/ProfilerTab.svelte +755 -0
- package/dist/devtools/ProfilerTab.svelte.d.ts +15 -0
- package/dist/devtools/PropsTree.svelte +155 -0
- package/dist/devtools/PropsTree.svelte.d.ts +15 -0
- package/dist/devtools/SessionTab.svelte +796 -0
- package/dist/devtools/SessionTab.svelte.d.ts +11 -0
- package/dist/devtools/TimelineTab.svelte +267 -0
- package/dist/devtools/TimelineTab.svelte.d.ts +11 -0
- package/dist/devtools/WireTab.svelte +149 -0
- package/dist/devtools/WireTab.svelte.d.ts +11 -0
- package/dist/devtools/bytes.d.ts +70 -0
- package/dist/devtools/bytes.js +82 -0
- package/dist/devtools/cache-headers.d.ts +20 -0
- package/dist/devtools/cache-headers.js +81 -0
- package/dist/devtools/highlight.d.ts +7 -0
- package/dist/devtools/highlight.js +83 -0
- package/dist/devtools/hydration.d.ts +48 -0
- package/dist/devtools/hydration.js +93 -0
- package/dist/devtools/index.d.ts +3 -0
- package/dist/devtools/index.js +3 -0
- package/dist/devtools/ledger-dom.d.ts +7 -0
- package/dist/devtools/ledger-dom.js +151 -0
- package/dist/devtools/leftovers.d.ts +77 -0
- package/dist/devtools/leftovers.js +319 -0
- package/dist/devtools/names.d.ts +1 -0
- package/dist/devtools/names.js +34 -0
- package/dist/devtools/page.d.ts +96 -0
- package/dist/devtools/page.js +957 -0
- package/dist/devtools/profile-anchors.d.ts +22 -0
- package/dist/devtools/profile-anchors.js +135 -0
- package/dist/devtools/profile-store.d.ts +175 -0
- package/dist/devtools/profile-store.js +239 -0
- package/dist/devtools/regions.d.ts +77 -0
- package/dist/devtools/regions.js +132 -0
- package/dist/devtools/session.d.ts +31 -0
- package/dist/devtools/session.js +455 -0
- package/dist/devtools/since-load.d.ts +50 -0
- package/dist/devtools/since-load.js +89 -0
- package/dist/devtools/source-lines.d.ts +24 -0
- package/dist/devtools/source-lines.js +106 -0
- package/dist/devtools/styles.d.ts +52 -0
- package/dist/devtools/styles.js +248 -0
- package/dist/devtools/testing-engine.d.ts +83 -0
- package/dist/devtools/testing-engine.js +220 -0
- package/dist/devtools/ui-app.d.ts +5 -0
- package/dist/devtools/ui-app.js +69 -0
- package/dist/devtools/ui.d.ts +50 -0
- package/dist/devtools/ui.js +175 -0
- package/dist/profiler/alloc.d.ts +75 -0
- package/dist/profiler/alloc.js +76 -0
- package/dist/profiler/analyze.d.ts +437 -0
- package/dist/profiler/analyze.js +1941 -0
- package/dist/profiler/app-path.d.ts +7 -0
- package/dist/profiler/app-path.js +26 -0
- package/dist/profiler/async-io.d.ts +58 -0
- package/dist/profiler/async-io.js +187 -0
- package/dist/profiler/beacon-standalone.d.ts +4 -0
- package/dist/profiler/beacon-standalone.js +409 -0
- package/dist/profiler/browser-findings.d.ts +25 -0
- package/dist/profiler/browser-findings.js +260 -0
- package/dist/profiler/byte-strip.d.ts +58 -0
- package/dist/profiler/byte-strip.js +228 -0
- package/dist/profiler/client-files.d.ts +16 -0
- package/dist/profiler/client-files.js +60 -0
- package/dist/profiler/client-windows.d.ts +49 -0
- package/dist/profiler/client-windows.js +95 -0
- package/dist/profiler/client.d.ts +40 -0
- package/dist/profiler/client.js +82 -0
- package/dist/profiler/compare.d.ts +308 -0
- package/dist/profiler/compare.js +733 -0
- package/dist/profiler/compress.d.ts +10 -0
- package/dist/profiler/compress.js +36 -0
- package/dist/profiler/contention.d.ts +60 -0
- package/dist/profiler/contention.js +86 -0
- package/dist/profiler/crypto.d.ts +19 -0
- package/dist/profiler/crypto.js +101 -0
- package/dist/profiler/doc-diff.d.ts +47 -0
- package/dist/profiler/doc-diff.js +214 -0
- package/dist/profiler/dom-diff.d.ts +43 -0
- package/dist/profiler/dom-diff.js +121 -0
- package/dist/profiler/drill.d.ts +89 -0
- package/dist/profiler/drill.js +553 -0
- package/dist/profiler/embedded-maps.d.ts +37 -0
- package/dist/profiler/embedded-maps.js +135 -0
- package/dist/profiler/env.d.ts +6 -0
- package/dist/profiler/env.js +10 -0
- package/dist/profiler/forecast.d.ts +76 -0
- package/dist/profiler/forecast.js +225 -0
- package/dist/profiler/frames.d.ts +11 -0
- package/dist/profiler/frames.js +42 -0
- package/dist/profiler/gc.d.ts +144 -0
- package/dist/profiler/gc.js +271 -0
- package/dist/profiler/hole-slots.d.ts +31 -0
- package/dist/profiler/hole-slots.js +90 -0
- package/dist/profiler/index.d.ts +288 -0
- package/dist/profiler/index.js +4921 -0
- package/dist/profiler/insights.d.ts +96 -0
- package/dist/profiler/insights.js +239 -0
- package/dist/profiler/ledger.d.ts +121 -0
- package/dist/profiler/ledger.js +440 -0
- package/dist/profiler/lineage.d.ts +81 -0
- package/dist/profiler/lineage.js +359 -0
- package/dist/profiler/module-map.d.ts +12 -0
- package/dist/profiler/module-map.js +94 -0
- package/dist/profiler/net.d.ts +169 -0
- package/dist/profiler/net.js +586 -0
- package/dist/profiler/on-demand.d.ts +11 -0
- package/dist/profiler/on-demand.js +15 -0
- package/dist/profiler/own-requests.d.ts +9 -0
- package/dist/profiler/own-requests.js +17 -0
- package/dist/profiler/patterns.d.ts +476 -0
- package/dist/profiler/patterns.js +2203 -0
- package/dist/profiler/profiler-router.d.ts +245 -0
- package/dist/profiler/profiler-router.js +113 -0
- package/dist/profiler/refresh-stub.d.ts +2 -0
- package/dist/profiler/refresh-stub.js +37 -0
- package/dist/profiler/report.d.ts +1404 -0
- package/dist/profiler/report.js +2638 -0
- package/dist/profiler/river.d.ts +65 -0
- package/dist/profiler/river.js +298 -0
- package/dist/profiler/route-files.d.ts +22 -0
- package/dist/profiler/route-files.js +55 -0
- package/dist/profiler/route-imports.d.ts +14 -0
- package/dist/profiler/route-imports.js +83 -0
- package/dist/profiler/saving.d.ts +22 -0
- package/dist/profiler/saving.js +42 -0
- package/dist/profiler/score.d.ts +109 -0
- package/dist/profiler/score.js +261 -0
- package/dist/profiler/session-cookie.d.ts +28 -0
- package/dist/profiler/session-cookie.js +45 -0
- package/dist/profiler/sink.d.ts +81 -0
- package/dist/profiler/sink.js +124 -0
- package/dist/profiler/site-fixes.d.ts +25 -0
- package/dist/profiler/site-fixes.js +62 -0
- package/dist/profiler/source-scan.d.ts +210 -0
- package/dist/profiler/source-scan.js +1724 -0
- package/dist/profiler/span.d.ts +90 -0
- package/dist/profiler/span.js +109 -0
- package/dist/profiler/stacks.d.ts +43 -0
- package/dist/profiler/stacks.js +107 -0
- package/dist/profiler/standalone.d.ts +27 -0
- package/dist/profiler/standalone.js +98 -0
- package/dist/profiler/steps.d.ts +39 -0
- package/dist/profiler/steps.js +74 -0
- package/dist/profiler/storage/index.d.ts +87 -0
- package/dist/profiler/storage/index.js +76 -0
- package/dist/profiler/storage/postgres.d.ts +12 -0
- package/dist/profiler/storage/postgres.js +94 -0
- package/dist/profiler/storage/redis.d.ts +19 -0
- package/dist/profiler/storage/redis.js +148 -0
- package/dist/profiler/storage/sqlite.d.ts +2 -0
- package/dist/profiler/storage/sqlite.js +85 -0
- package/dist/profiler/storage/visits.d.ts +4 -0
- package/dist/profiler/storage/visits.js +6 -0
- package/dist/profiler/stream-tail.d.ts +26 -0
- package/dist/profiler/stream-tail.js +74 -0
- package/dist/profiler/timeline.d.ts +279 -0
- package/dist/profiler/timeline.js +690 -0
- package/dist/profiler/ui/AllocStrip.svelte +146 -0
- package/dist/profiler/ui/AllocStrip.svelte.d.ts +17 -0
- package/dist/profiler/ui/Awaits.svelte +363 -0
- package/dist/profiler/ui/Awaits.svelte.d.ts +16 -0
- package/dist/profiler/ui/ByteStrip.svelte +182 -0
- package/dist/profiler/ui/ByteStrip.svelte.d.ts +18 -0
- package/dist/profiler/ui/Compare.svelte +24 -0
- package/dist/profiler/ui/Compare.svelte.d.ts +16 -0
- package/dist/profiler/ui/CompareBody.svelte +429 -0
- package/dist/profiler/ui/CompareBody.svelte.d.ts +8 -0
- package/dist/profiler/ui/ComponentsTable.svelte +265 -0
- package/dist/profiler/ui/ComponentsTable.svelte.d.ts +20 -0
- package/dist/profiler/ui/Dashboard.svelte +492 -0
- package/dist/profiler/ui/Dashboard.svelte.d.ts +31 -0
- package/dist/profiler/ui/DataRiver.svelte +206 -0
- package/dist/profiler/ui/DataRiver.svelte.d.ts +13 -0
- package/dist/profiler/ui/DomTravel.svelte +207 -0
- package/dist/profiler/ui/DomTravel.svelte.d.ts +9 -0
- package/dist/profiler/ui/DownloadHtml.svelte +52 -0
- package/dist/profiler/ui/DownloadHtml.svelte.d.ts +10 -0
- package/dist/profiler/ui/Drill.svelte +276 -0
- package/dist/profiler/ui/Drill.svelte.d.ts +12 -0
- package/dist/profiler/ui/ExportButton.svelte +59 -0
- package/dist/profiler/ui/ExportButton.svelte.d.ts +8 -0
- package/dist/profiler/ui/Flame.svelte +222 -0
- package/dist/profiler/ui/Flame.svelte.d.ts +12 -0
- package/dist/profiler/ui/FrameDetails.svelte +308 -0
- package/dist/profiler/ui/FrameDetails.svelte.d.ts +16 -0
- package/dist/profiler/ui/FunctionsTable.svelte +156 -0
- package/dist/profiler/ui/FunctionsTable.svelte.d.ts +17 -0
- package/dist/profiler/ui/IslandHeatmap.svelte +151 -0
- package/dist/profiler/ui/IslandHeatmap.svelte.d.ts +16 -0
- package/dist/profiler/ui/IslandsTable.svelte +448 -0
- package/dist/profiler/ui/IslandsTable.svelte.d.ts +16 -0
- package/dist/profiler/ui/KeepLocal.svelte +46 -0
- package/dist/profiler/ui/KeepLocal.svelte.d.ts +8 -0
- package/dist/profiler/ui/Ledger.svelte +196 -0
- package/dist/profiler/ui/Ledger.svelte.d.ts +18 -0
- package/dist/profiler/ui/LocalCompare.svelte +48 -0
- package/dist/profiler/ui/LocalCompare.svelte.d.ts +8 -0
- package/dist/profiler/ui/LocalReports.svelte +68 -0
- package/dist/profiler/ui/LocalReports.svelte.d.ts +7 -0
- package/dist/profiler/ui/Login.svelte +13 -0
- package/dist/profiler/ui/Login.svelte.d.ts +12 -0
- package/dist/profiler/ui/LoginForm.svelte +42 -0
- package/dist/profiler/ui/LoginForm.svelte.d.ts +7 -0
- package/dist/profiler/ui/Message.svelte +10 -0
- package/dist/profiler/ui/Message.svelte.d.ts +12 -0
- package/dist/profiler/ui/OnThisPage.svelte +137 -0
- package/dist/profiler/ui/OnThisPage.svelte.d.ts +3 -0
- package/dist/profiler/ui/OneClock.svelte +297 -0
- package/dist/profiler/ui/OneClock.svelte.d.ts +27 -0
- package/dist/profiler/ui/Panel.svelte +10 -0
- package/dist/profiler/ui/Panel.svelte.d.ts +16 -0
- package/dist/profiler/ui/Paths.svelte +269 -0
- package/dist/profiler/ui/Paths.svelte.d.ts +15 -0
- package/dist/profiler/ui/Patterns.svelte +364 -0
- package/dist/profiler/ui/Patterns.svelte.d.ts +15 -0
- package/dist/profiler/ui/PermalinkGate.svelte +143 -0
- package/dist/profiler/ui/PermalinkGate.svelte.d.ts +10 -0
- package/dist/profiler/ui/RenderSteps.svelte +218 -0
- package/dist/profiler/ui/RenderSteps.svelte.d.ts +13 -0
- package/dist/profiler/ui/Report.svelte +28 -0
- package/dist/profiler/ui/Report.svelte.d.ts +20 -0
- package/dist/profiler/ui/ReportBody.svelte +2592 -0
- package/dist/profiler/ui/ReportBody.svelte.d.ts +21 -0
- package/dist/profiler/ui/Run.svelte +17 -0
- package/dist/profiler/ui/Run.svelte.d.ts +14 -0
- package/dist/profiler/ui/RunView.svelte +146 -0
- package/dist/profiler/ui/RunView.svelte.d.ts +10 -0
- package/dist/profiler/ui/ScoreCard.svelte +197 -0
- package/dist/profiler/ui/ScoreCard.svelte.d.ts +7 -0
- package/dist/profiler/ui/Scrub.svelte +293 -0
- package/dist/profiler/ui/Scrub.svelte.d.ts +18 -0
- package/dist/profiler/ui/SeedExplainer.svelte +193 -0
- package/dist/profiler/ui/SeedExplainer.svelte.d.ts +16 -0
- package/dist/profiler/ui/ShareLink.svelte +148 -0
- package/dist/profiler/ui/ShareLink.svelte.d.ts +8 -0
- package/dist/profiler/ui/Shell.svelte +50 -0
- package/dist/profiler/ui/Shell.svelte.d.ts +27 -0
- package/dist/profiler/ui/Sidebar.svelte +312 -0
- package/dist/profiler/ui/Sidebar.svelte.d.ts +7 -0
- package/dist/profiler/ui/Site.svelte +20 -0
- package/dist/profiler/ui/Site.svelte.d.ts +23 -0
- package/dist/profiler/ui/SiteView.svelte +385 -0
- package/dist/profiler/ui/SiteView.svelte.d.ts +27 -0
- package/dist/profiler/ui/ThemeSwitch.svelte +78 -0
- package/dist/profiler/ui/ThemeSwitch.svelte.d.ts +3 -0
- package/dist/profiler/ui/Timeline.svelte +672 -0
- package/dist/profiler/ui/Timeline.svelte.d.ts +22 -0
- package/dist/profiler/ui/Treemap.svelte +278 -0
- package/dist/profiler/ui/Treemap.svelte.d.ts +20 -0
- package/dist/profiler/ui/Upload.svelte +19 -0
- package/dist/profiler/ui/Upload.svelte.d.ts +10 -0
- package/dist/profiler/ui/UploadForm.svelte +59 -0
- package/dist/profiler/ui/UploadForm.svelte.d.ts +6 -0
- package/dist/profiler/ui/WaitingTable.svelte +55 -0
- package/dist/profiler/ui/WaitingTable.svelte.d.ts +14 -0
- package/dist/profiler/ui/Waterfall.svelte +371 -0
- package/dist/profiler/ui/Waterfall.svelte.d.ts +7 -0
- package/dist/profiler/ui/WhatIf.svelte +87 -0
- package/dist/profiler/ui/WhatIf.svelte.d.ts +18 -0
- package/dist/profiler/ui/fake-progress.svelte.d.ts +15 -0
- package/dist/profiler/ui/fake-progress.svelte.js +38 -0
- package/dist/profiler/ui/format.d.ts +20 -0
- package/dist/profiler/ui/format.js +71 -0
- package/dist/profiler/ui/permalink.d.ts +9 -0
- package/dist/profiler/ui/permalink.js +108 -0
- package/dist/profiler/ui/press.d.ts +5 -0
- package/dist/profiler/ui/press.js +19 -0
- package/dist/profiler/ui/profiler.css +650 -0
- package/dist/profiler/ui/report-data.d.ts +189 -0
- package/dist/profiler/ui/report-data.js +393 -0
- package/dist/profiler/ui/report-request.d.ts +6 -0
- package/dist/profiler/ui/report-request.js +50 -0
- package/dist/profiler/ui/row-anchor.svelte.d.ts +12 -0
- package/dist/profiler/ui/row-anchor.svelte.js +44 -0
- package/dist/profiler/ui/sort.svelte.d.ts +14 -0
- package/dist/profiler/ui/sort.svelte.js +37 -0
- package/dist/profiler/ui/store.d.ts +45 -0
- package/dist/profiler/ui/store.js +92 -0
- package/dist/profiler/visit.d.ts +389 -0
- package/dist/profiler/visit.js +1002 -0
- package/dist/report.d.ts +5 -0
- package/dist/report.js +4 -0
- package/dist/server.d.ts +11 -0
- package/dist/server.js +38 -0
- package/dist/vite.d.ts +12 -0
- package/dist/vite.js +78 -0
- package/package.json +103 -3
|
@@ -0,0 +1,615 @@
|
|
|
1
|
+
<!-- (its CSS injected into the dock's shadow root: see Devtools.svelte) -->
|
|
2
|
+
<svelte:options css="injected" />
|
|
3
|
+
|
|
4
|
+
<script>
|
|
5
|
+
/**
|
|
6
|
+
* The per-island detail view — "inspect element" for an ogygia region. Selecting a region (a Lens
|
|
7
|
+
* roster row, or picking it on the page) opens this over the tab body: one focused card that pulls
|
|
8
|
+
* together what the separate tabs each show a slice of — the region's identity, its full cost
|
|
9
|
+
* breakdown (JS-with-deps / entry chunk / props / server HTML), and its client LIFECYCLE as a
|
|
10
|
+
* mini-timeline (connected → scheduled → woke → hydrate → done, with per-phase offsets). A pure
|
|
11
|
+
* consumer of the DOM + bus, keyed by the selected `<ogygia-region>` element.
|
|
12
|
+
*/
|
|
13
|
+
import { parse } from 'devalue';
|
|
14
|
+
import { onDestroy } from 'svelte';
|
|
15
|
+
import { highlight, clear_highlight } from './highlight.js';
|
|
16
|
+
import {
|
|
17
|
+
region_info,
|
|
18
|
+
region_name,
|
|
19
|
+
region_transitive,
|
|
20
|
+
chunk_bytes,
|
|
21
|
+
latest_event,
|
|
22
|
+
region_props_sidecar
|
|
23
|
+
} from './regions.js';
|
|
24
|
+
import { snapshot } from '@ogygia/core/events';
|
|
25
|
+
import { read_page } from './page.js';
|
|
26
|
+
import { profile_for, profiles_version, island_row } from './profile-store.js';
|
|
27
|
+
import { get_last_session, last_session_version } from './session.js';
|
|
28
|
+
import PropsTree from './PropsTree.svelte';
|
|
29
|
+
import { island_ledger } from './ledger-dom.js';
|
|
30
|
+
|
|
31
|
+
let { el, tick = 0, onclose } = $props();
|
|
32
|
+
|
|
33
|
+
const kb = (n) => (n < 1024 ? n + ' B' : (n / 1024).toFixed(1) + ' KB');
|
|
34
|
+
|
|
35
|
+
// Every transportable crosses under ONE devalue custom type ('OgygiaRef'). Decode it to a labelled
|
|
36
|
+
// placeholder — NOT the live instance (`wire.resolve` has side effects) — so the viewer stays inert.
|
|
37
|
+
const REVIVERS = {
|
|
38
|
+
OgygiaRef: (d) => ({ __ogRef: true, kind: d && d.k, id: d && d.i, tag: d && d.t }),
|
|
39
|
+
// A seed reference (seed-refs.ts): shown as the path it points at, not resolved — inert.
|
|
40
|
+
OgygiaSeedRef: (p) => ({ __ogSeedRef: true, path: Array.isArray(p) ? p.join('.') : String(p) })
|
|
41
|
+
};
|
|
42
|
+
function decode_props(text) {
|
|
43
|
+
if (!text || text.length < 3) return null;
|
|
44
|
+
try {
|
|
45
|
+
const v = parse(text, REVIVERS);
|
|
46
|
+
return v && typeof v === 'object' && Object.keys(v).length ? v : null;
|
|
47
|
+
} catch {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Client lifecycle phases, in order, with the Timeline's colours.
|
|
53
|
+
const PHASES = [
|
|
54
|
+
{ name: 'region.connected', label: 'connected', c: '#64748b' },
|
|
55
|
+
{ name: 'wake.scheduled', label: 'scheduled', c: '#38bdf8' },
|
|
56
|
+
{ name: 'wake.fired', label: 'woke', c: '#2dd4bf' },
|
|
57
|
+
{ name: 'region.hydrate.start', label: 'hydrate', c: '#f59e0b' },
|
|
58
|
+
{ name: 'region.hydrate.done', label: 'done', c: '#22c55e' },
|
|
59
|
+
{ name: 'interaction.replay', label: 'replay', c: '#8b5cf6' }
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
// its line of the exact byte ledger (a build: the page's island graph × the browser's sizes)
|
|
63
|
+
// the modules in this island's files that the page also loads in another file (the last profile's
|
|
64
|
+
// list, matched to its files by path): which copy is its, and what the second costs
|
|
65
|
+
const twice_here = $derived.by(() => {
|
|
66
|
+
profiles_version();
|
|
67
|
+
const urls = ledger?.row.urls ?? [];
|
|
68
|
+
const list = profile_for(location.pathname)?.assets?.twice ?? [];
|
|
69
|
+
if (!urls.length || !list.length) return [];
|
|
70
|
+
const paths = urls.map((u) => {
|
|
71
|
+
try {
|
|
72
|
+
return new URL(u).pathname;
|
|
73
|
+
} catch {
|
|
74
|
+
return u;
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
const out = [];
|
|
78
|
+
for (const d of list) {
|
|
79
|
+
const mine = d.copies.find((c) => paths.some((p) => p.endsWith(c.file)));
|
|
80
|
+
if (mine) out.push({ name: d.name, extra: d.extra, mine });
|
|
81
|
+
}
|
|
82
|
+
return out;
|
|
83
|
+
});
|
|
84
|
+
const ledger = $derived.by(() => {
|
|
85
|
+
void tick;
|
|
86
|
+
return island_ledger(el?.getAttribute('entry'));
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const model = $derived.by(() => {
|
|
90
|
+
void tick;
|
|
91
|
+
const info = region_info(el);
|
|
92
|
+
const t = region_transitive(info.entry);
|
|
93
|
+
const chunk = info.entry ? chunk_bytes(info.entry) : null;
|
|
94
|
+
const ev = snapshot();
|
|
95
|
+
const rendered = info.fp
|
|
96
|
+
? latest_event((e) => e.name === 'server.region.rendered' && e.fp === info.fp)
|
|
97
|
+
: null;
|
|
98
|
+
const marks = [];
|
|
99
|
+
for (const ph of PHASES) {
|
|
100
|
+
const e = ev.find((x) => x.name === ph.name && x.fp === info.fp);
|
|
101
|
+
if (e) marks.push({ ...ph, t: e.t });
|
|
102
|
+
}
|
|
103
|
+
marks.sort((a, b) => a.t - b.t);
|
|
104
|
+
const t0 = marks.length ? marks[0].t : 0;
|
|
105
|
+
const start = marks.find((m) => m.name === 'region.hydrate.start');
|
|
106
|
+
const done = marks.find((m) => m.name === 'region.hydrate.done');
|
|
107
|
+
const hydrateMs = start && done ? done.t - start.t : ((rendered && rendered.ms) ?? null);
|
|
108
|
+
// what the browser measured of this island (the Page tab's row + the findings that name it)
|
|
109
|
+
let browser = null;
|
|
110
|
+
try {
|
|
111
|
+
const view = info.fp ? read_page() : null;
|
|
112
|
+
if (view) {
|
|
113
|
+
const row = view.report.rows.find((r) => r.fp === info.fp) ?? null;
|
|
114
|
+
const findings = view.report.findings.filter((f) => f.fps.includes(info.fp));
|
|
115
|
+
if (row || findings.length) browser = { row, findings };
|
|
116
|
+
}
|
|
117
|
+
} catch {
|
|
118
|
+
browser = null;
|
|
119
|
+
}
|
|
120
|
+
// what happened to it in the last recorded session (the Record tab): clicks, slow handlers, the
|
|
121
|
+
// requests its clicks caused and the server's split of each
|
|
122
|
+
last_session_version();
|
|
123
|
+
const sess = get_last_session();
|
|
124
|
+
const in_session = info.fp && sess ? (sess.report?.by_island?.[info.fp] ?? null) : null;
|
|
125
|
+
// what the last SSR profile of this page measured for it (the Profiler tab's run)
|
|
126
|
+
profiles_version();
|
|
127
|
+
const prof = profile_for(location.pathname);
|
|
128
|
+
const server = island_row(prof, info.fp, info.entry);
|
|
129
|
+
return {
|
|
130
|
+
info,
|
|
131
|
+
name: region_name(info.entry),
|
|
132
|
+
t,
|
|
133
|
+
chunk,
|
|
134
|
+
rendered,
|
|
135
|
+
marks: marks.map((m) => ({ ...m, off: m.t - t0 })),
|
|
136
|
+
hydrateMs,
|
|
137
|
+
browser,
|
|
138
|
+
server: server ? { row: server, at: prof.at, same: server.fp === info.fp } : null,
|
|
139
|
+
session: in_session,
|
|
140
|
+
props: decode_props(region_props_sidecar(el))
|
|
141
|
+
};
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// scroll to it AND mark it for a moment: an island already on screen gave no sign at all
|
|
145
|
+
/** @type {ReturnType<typeof setTimeout> | undefined} */
|
|
146
|
+
let flash;
|
|
147
|
+
function locate() {
|
|
148
|
+
highlight([el], model.name, true);
|
|
149
|
+
clearTimeout(flash);
|
|
150
|
+
flash = setTimeout(clear_highlight, 1400);
|
|
151
|
+
}
|
|
152
|
+
onDestroy(() => clearTimeout(flash));
|
|
153
|
+
</script>
|
|
154
|
+
|
|
155
|
+
<div class="detail" data-og-detail>
|
|
156
|
+
<div class="bar">
|
|
157
|
+
<button class="back" onclick={onclose} title="back to the roster">‹ back</button>
|
|
158
|
+
<span class="dot og-{model.info.kind}"></span>
|
|
159
|
+
<b class="name">{model.name}</b>
|
|
160
|
+
<span class="k"
|
|
161
|
+
>{model.info.kind}{model.info.kind === 'island' ? ' · ' + model.info.wake : ''}</span
|
|
162
|
+
>
|
|
163
|
+
<button class="loc" onclick={locate}>scroll to it ›</button>
|
|
164
|
+
</div>
|
|
165
|
+
|
|
166
|
+
<div class="sec">lifecycle</div>
|
|
167
|
+
{#if model.marks.length}
|
|
168
|
+
<div class="life">
|
|
169
|
+
{#each model.marks as m, i}
|
|
170
|
+
{#if i > 0}<span class="arm"></span>{/if}
|
|
171
|
+
<div class="ph" title="{m.name} @ +{m.off.toFixed(1)}ms">
|
|
172
|
+
<span class="pd" style:background={m.c}></span><span class="pl">{m.label}</span>
|
|
173
|
+
<span class="off">+{m.off.toFixed(1)}ms</span>
|
|
174
|
+
</div>
|
|
175
|
+
{/each}
|
|
176
|
+
</div>
|
|
177
|
+
{#if model.hydrateMs != null}
|
|
178
|
+
<div class="hyd">hydrated in <b>{model.hydrateMs.toFixed(1)} ms</b></div>
|
|
179
|
+
{/if}
|
|
180
|
+
{:else}
|
|
181
|
+
<div class="muted">
|
|
182
|
+
{model.info.kind === 'island'
|
|
183
|
+
? model.info.hydrated
|
|
184
|
+
? 'hydrated (no timing captured this session)'
|
|
185
|
+
: 'cold — has not woken yet'
|
|
186
|
+
: 'no client lifecycle — pure server HTML'}
|
|
187
|
+
</div>
|
|
188
|
+
{/if}
|
|
189
|
+
|
|
190
|
+
{#if model.browser}
|
|
191
|
+
<div class="sec">in the browser <span class="secn">— measured on this visit</span></div>
|
|
192
|
+
<div class="rows" data-og-detail-browser>
|
|
193
|
+
{#if model.browser.row}
|
|
194
|
+
{@const r = model.browser.row}
|
|
195
|
+
<div class="row">
|
|
196
|
+
<span class="rk">module load</span><span class="v">{r.load_ms} ms</span>
|
|
197
|
+
</div>
|
|
198
|
+
{#if r.queue_ms !== null}<div class="row">
|
|
199
|
+
<span class="rk">waited for its turn</span><span class="v">{r.queue_ms} ms</span>
|
|
200
|
+
</div>{/if}
|
|
201
|
+
<div class="row">
|
|
202
|
+
<span class="rk">hydrate step</span><span class="v"
|
|
203
|
+
>{r.hydrate_ms} ms{#if r.longtask_ms}<span class="muted">
|
|
204
|
+
· {r.longtask_ms} ms in long tasks</span
|
|
205
|
+
>{/if}</span
|
|
206
|
+
>
|
|
207
|
+
</div>
|
|
208
|
+
<div class="row">
|
|
209
|
+
<span class="rk">awake at</span><span class="v"
|
|
210
|
+
>{Math.round(r.done)} ms<span class="muted"> after navigation</span></span
|
|
211
|
+
>
|
|
212
|
+
</div>
|
|
213
|
+
{#if r.shift}<div class="row">
|
|
214
|
+
<span class="rk">layout shift</span><span class="v">{r.shift}</span>
|
|
215
|
+
</div>{/if}
|
|
216
|
+
{/if}
|
|
217
|
+
{#each model.browser.findings as f, i (f.code + i)}
|
|
218
|
+
<div class="find {f.severity}">{f.message}</div>
|
|
219
|
+
{/each}
|
|
220
|
+
</div>
|
|
221
|
+
{/if}
|
|
222
|
+
|
|
223
|
+
{#if model.session}
|
|
224
|
+
{@const ss = model.session}
|
|
225
|
+
<div class="sec">
|
|
226
|
+
in the last session <span class="secn">— what using it did (Record tab)</span>
|
|
227
|
+
</div>
|
|
228
|
+
<div class="rows" data-og-detail-session>
|
|
229
|
+
<div class="row">
|
|
230
|
+
<span class="rk">clicks</span><span class="v"
|
|
231
|
+
>{ss.clicks}{#if ss.mutations}<span class="muted">
|
|
232
|
+
· {ss.mutations} DOM changes</span
|
|
233
|
+
>{/if}</span
|
|
234
|
+
>
|
|
235
|
+
</div>
|
|
236
|
+
{#each ss.slow as x, i (i)}
|
|
237
|
+
<div class="row">
|
|
238
|
+
<span class="rk">slow interaction</span><span class="v"
|
|
239
|
+
>{Math.round(x.duration)} ms<span class="muted">
|
|
240
|
+
· handlers {Math.round(x.processing)} ms · {x.target}</span
|
|
241
|
+
></span
|
|
242
|
+
>
|
|
243
|
+
</div>
|
|
244
|
+
{/each}
|
|
245
|
+
{#each ss.requests.slice(0, 5) as q, i (q.url + i)}
|
|
246
|
+
<div class="row">
|
|
247
|
+
<span class="rk">asked the server</span>
|
|
248
|
+
<span class="v"
|
|
249
|
+
>{q.url} <b>{Math.round(q.ms)} ms</b>{#if q.status && q.status >= 400}<span
|
|
250
|
+
class="muted"
|
|
251
|
+
>
|
|
252
|
+
· {q.status}</span
|
|
253
|
+
>{/if}{#if q.server_ms !== null}<span class="muted">
|
|
254
|
+
· {Math.round(q.server_ms)} ms on the server{q.net_ms
|
|
255
|
+
? `, ${Math.round(q.net_ms)} ms waiting`
|
|
256
|
+
: ''}{q.up ? ` (${q.up})` : ''}</span
|
|
257
|
+
>{/if}</span
|
|
258
|
+
>
|
|
259
|
+
</div>
|
|
260
|
+
{/each}
|
|
261
|
+
</div>
|
|
262
|
+
{/if}
|
|
263
|
+
|
|
264
|
+
{#if model.server}
|
|
265
|
+
{@const s = model.server.row}
|
|
266
|
+
<div class="sec">
|
|
267
|
+
on the server <span class="secn"
|
|
268
|
+
>— last profile, {new Date(model.server.at).toLocaleTimeString()}{model.server.same
|
|
269
|
+
? ''
|
|
270
|
+
: ' (same island, other props)'}</span
|
|
271
|
+
>
|
|
272
|
+
</div>
|
|
273
|
+
<div class="rows" data-og-detail-server>
|
|
274
|
+
<div class="row">
|
|
275
|
+
<span class="rk">render</span><span class="v"
|
|
276
|
+
>{s.ssr_ms !== null ? s.ssr_ms + ' ms' : 'not measured'}</span
|
|
277
|
+
>
|
|
278
|
+
</div>
|
|
279
|
+
{#if s.props_bytes !== null}<div class="row">
|
|
280
|
+
<span class="rk">props</span><span class="v"
|
|
281
|
+
>{kb(s.props_bytes)}{#if s.culprit}<span class="muted">
|
|
282
|
+
· not plain JSON: {s.culprit}</span
|
|
283
|
+
>{/if}</span
|
|
284
|
+
>
|
|
285
|
+
</div>{/if}
|
|
286
|
+
{#if s.seed_refs}<div class="row">
|
|
287
|
+
<span class="rk">seed references</span><span class="v">{s.seed_refs}</span>
|
|
288
|
+
</div>{/if}
|
|
289
|
+
{#if s.client_p50_ms !== null}<div class="row">
|
|
290
|
+
<span class="rk">hydrate (beacon)</span><span class="v"
|
|
291
|
+
>{s.client_p50_ms} ms{#if s.recovered}<span class="muted">
|
|
292
|
+
· recovered {s.recovered}×</span
|
|
293
|
+
>{/if}</span
|
|
294
|
+
>
|
|
295
|
+
</div>{/if}
|
|
296
|
+
{#if s.hazard && !model.t?.hazards?.length}
|
|
297
|
+
<!-- a build has no dev-server walk: the profiler's reading of its sources says it -->
|
|
298
|
+
<div class="row" data-og-detail-hazard>
|
|
299
|
+
<span class="rk">browser-only</span><span class="v"
|
|
300
|
+
>{s.hazard.file.split('/').pop()}:{s.hazard.line}
|
|
301
|
+
<span class="muted"
|
|
302
|
+
>· {s.hazard.kind === 'await'
|
|
303
|
+
? 'awaits at the top of its script'
|
|
304
|
+
: `reads ${s.hazard.reads ?? 'a browser-only value'} ${s.hazard.guard ? 'in a guard' : 'while rendering'}`}</span
|
|
305
|
+
></span
|
|
306
|
+
>
|
|
307
|
+
</div>
|
|
308
|
+
{/if}
|
|
309
|
+
</div>
|
|
310
|
+
{/if}
|
|
311
|
+
|
|
312
|
+
<div class="sec">cost</div>
|
|
313
|
+
<div class="rows">
|
|
314
|
+
{#if ledger}
|
|
315
|
+
<!-- a build: its files, weighed by the browser — what only it needs, and whom it shares with -->
|
|
316
|
+
<div class="row" data-og-detail-bytes>
|
|
317
|
+
<span class="rk">its code</span><span class="v"
|
|
318
|
+
>{kb(ledger.row.wire)} in {ledger.row.files} files{#if ledger.row.cold}<span
|
|
319
|
+
class="muted"
|
|
320
|
+
>
|
|
321
|
+
· {ledger.row.cold} not loaded yet</span
|
|
322
|
+
>{/if}</span
|
|
323
|
+
>
|
|
324
|
+
</div>
|
|
325
|
+
<div class="row">
|
|
326
|
+
<span class="rk">only it</span><span class="v"
|
|
327
|
+
>{kb(ledger.row.unique)}<span class="muted"> · what removing it would save</span></span
|
|
328
|
+
>
|
|
329
|
+
</div>
|
|
330
|
+
{#if ledger.row.shared}
|
|
331
|
+
<div class="row">
|
|
332
|
+
<span class="rk">shared</span><span class="v"
|
|
333
|
+
>{kb(ledger.row.shared)}{#if ledger.shares_with.length}<span class="muted">
|
|
334
|
+
· with {ledger.shares_with.slice(0, 4).join(', ')}{ledger.shares_with.length > 4
|
|
335
|
+
? ` and ${ledger.shares_with.length - 4} more`
|
|
336
|
+
: ''}</span
|
|
337
|
+
>{/if}</span
|
|
338
|
+
>
|
|
339
|
+
</div>
|
|
340
|
+
{/if}
|
|
341
|
+
{#if twice_here.length}
|
|
342
|
+
<!-- a module in its files that the page loads a second copy of, elsewhere (the last profile) -->
|
|
343
|
+
<div class="row" data-og-detail-twice>
|
|
344
|
+
<span class="rk">loaded twice</span><span class="v"
|
|
345
|
+
>{#each twice_here.slice(0, 3) as d, i (d.name)}{i ? ' · ' : ''}{d.name}
|
|
346
|
+
<span class="muted"
|
|
347
|
+
>{kb(d.extra)}{d.mine.from ? `, its copy from ${d.mine.from}` : ''}</span
|
|
348
|
+
>{/each}{#if twice_here.length > 3}<span class="muted">
|
|
349
|
+
and {twice_here.length - 3} more</span
|
|
350
|
+
>{/if}</span
|
|
351
|
+
>
|
|
352
|
+
</div>
|
|
353
|
+
{/if}
|
|
354
|
+
{/if}
|
|
355
|
+
{#if model.t}
|
|
356
|
+
<div class="row">
|
|
357
|
+
<span class="rk">js + deps</span><span class="v"
|
|
358
|
+
>{kb(model.t.bytes)}<span class="muted"> · {model.t.modules} mod</span></span
|
|
359
|
+
>
|
|
360
|
+
</div>
|
|
361
|
+
{#if model.t.top?.length}
|
|
362
|
+
<!-- where the island's weight is: its heaviest modules, as shares (dev code, unminified) -->
|
|
363
|
+
<div class="row" data-og-detail-top>
|
|
364
|
+
<span class="rk">heaviest</span><span class="v"
|
|
365
|
+
>{#each model.t.top.slice(0, 3) as m, i (m.file)}{i ? ' · ' : ''}{m.file
|
|
366
|
+
.split('/')
|
|
367
|
+
.pop()}
|
|
368
|
+
<span class="muted">{Math.round((m.bytes / model.t.bytes) * 100)}%</span>{/each}</span
|
|
369
|
+
>
|
|
370
|
+
</div>
|
|
371
|
+
{/if}
|
|
372
|
+
{#if model.t.barrels?.length}
|
|
373
|
+
<div class="row" data-og-detail-barrel>
|
|
374
|
+
<span class="rk">barrel</span><span class="v"
|
|
375
|
+
>{model.t.barrels[0].file}
|
|
376
|
+
<span class="muted">· {model.t.barrels[0].fanout} modules ride along</span></span
|
|
377
|
+
>
|
|
378
|
+
</div>
|
|
379
|
+
{/if}
|
|
380
|
+
{#if model.t.hazards?.length}
|
|
381
|
+
<!-- its lines that draw differently in the browser (the dev server read its sources): a
|
|
382
|
+
value only the browser has, read while rendering; an await at the top of its script -->
|
|
383
|
+
{@const h = model.t.hazards[0]}
|
|
384
|
+
<div class="row" data-og-detail-hazard>
|
|
385
|
+
<span class="rk">browser-only</span><span class="v"
|
|
386
|
+
>{h.file.split('/').pop()}:{h.line}
|
|
387
|
+
<span class="muted"
|
|
388
|
+
>· {h.kind === 'await'
|
|
389
|
+
? 'awaits at the top of its script'
|
|
390
|
+
: `reads ${h.reads ?? 'a browser-only value'} while rendering`}{model.t.hazards
|
|
391
|
+
.length > 1
|
|
392
|
+
? ` · ${model.t.hazards.length - 1} more`
|
|
393
|
+
: ''}</span
|
|
394
|
+
></span
|
|
395
|
+
>
|
|
396
|
+
</div>
|
|
397
|
+
{/if}
|
|
398
|
+
{/if}
|
|
399
|
+
{#if model.chunk?.loaded}
|
|
400
|
+
<div class="row">
|
|
401
|
+
<span class="rk">entry chunk</span><span class="v"
|
|
402
|
+
>{kb(model.chunk.wire)}<span class="muted"> wire · {kb(model.chunk.raw)} raw</span></span
|
|
403
|
+
>
|
|
404
|
+
</div>
|
|
405
|
+
{/if}
|
|
406
|
+
{#if model.rendered?.propsBytes != null}
|
|
407
|
+
<div class="row">
|
|
408
|
+
<span class="rk">props payload</span><span class="v">{model.rendered.propsBytes} B</span>
|
|
409
|
+
</div>
|
|
410
|
+
{/if}
|
|
411
|
+
{#if model.rendered?.htmlBytes != null}
|
|
412
|
+
<div class="row">
|
|
413
|
+
<span class="rk">server HTML</span><span class="v">{model.rendered.htmlBytes} B</span>
|
|
414
|
+
</div>
|
|
415
|
+
{/if}
|
|
416
|
+
</div>
|
|
417
|
+
|
|
418
|
+
{#if model.props}
|
|
419
|
+
<div class="sec">props <span class="secn">— the data that crossed the boundary</span></div>
|
|
420
|
+
<div class="props" data-og-props>
|
|
421
|
+
{#each Object.entries(model.props) as [k, v] (k)}
|
|
422
|
+
<PropsTree value={v} name={k} />
|
|
423
|
+
{/each}
|
|
424
|
+
</div>
|
|
425
|
+
{/if}
|
|
426
|
+
|
|
427
|
+
<div class="sec">identity</div>
|
|
428
|
+
<div class="rows">
|
|
429
|
+
<div class="row">
|
|
430
|
+
<span class="rk">mode</span><span class="v">{model.rendered?.mode ?? model.info.kind}</span>
|
|
431
|
+
</div>
|
|
432
|
+
<div class="row">
|
|
433
|
+
<span class="rk">state</span><span class="v"
|
|
434
|
+
>{model.info.kind === 'island'
|
|
435
|
+
? model.info.hydrated
|
|
436
|
+
? 'hydrated'
|
|
437
|
+
: 'cold'
|
|
438
|
+
: model.info.hydrated
|
|
439
|
+
? 'filled'
|
|
440
|
+
: 'pending'}</span
|
|
441
|
+
>
|
|
442
|
+
</div>
|
|
443
|
+
<div class="row">
|
|
444
|
+
<span class="rk">server-rendered</span><span class="v">{model.rendered ? 'yes' : 'no'}</span>
|
|
445
|
+
</div>
|
|
446
|
+
{#if model.info.fp}<div class="row">
|
|
447
|
+
<span class="rk">fingerprint</span><span class="v mono">{model.info.fp}</span>
|
|
448
|
+
</div>{/if}
|
|
449
|
+
{#if model.info.entry}<div class="row">
|
|
450
|
+
<span class="rk">entry</span><span class="v mono" title={model.info.entry}
|
|
451
|
+
>{model.info.entry.split('/').pop()}</span
|
|
452
|
+
>
|
|
453
|
+
</div>{/if}
|
|
454
|
+
</div>
|
|
455
|
+
</div>
|
|
456
|
+
|
|
457
|
+
<style>
|
|
458
|
+
.detail {
|
|
459
|
+
font:
|
|
460
|
+
11px/1.5 ui-monospace,
|
|
461
|
+
SFMono-Regular,
|
|
462
|
+
Menlo,
|
|
463
|
+
monospace;
|
|
464
|
+
}
|
|
465
|
+
.bar {
|
|
466
|
+
display: flex;
|
|
467
|
+
align-items: center;
|
|
468
|
+
gap: 8px;
|
|
469
|
+
padding-bottom: 10px;
|
|
470
|
+
margin-bottom: 4px;
|
|
471
|
+
border-bottom: 1px solid rgba(148, 163, 184, 0.18);
|
|
472
|
+
}
|
|
473
|
+
.back {
|
|
474
|
+
padding: 3px 9px;
|
|
475
|
+
border-radius: 6px;
|
|
476
|
+
border: 1px solid rgba(148, 163, 184, 0.3);
|
|
477
|
+
background: #0d1526;
|
|
478
|
+
color: #94a3b8;
|
|
479
|
+
cursor: pointer;
|
|
480
|
+
font: inherit;
|
|
481
|
+
}
|
|
482
|
+
.back:hover {
|
|
483
|
+
color: #e2e8f0;
|
|
484
|
+
}
|
|
485
|
+
.dot {
|
|
486
|
+
width: 9px;
|
|
487
|
+
height: 9px;
|
|
488
|
+
border-radius: 50%;
|
|
489
|
+
flex: none;
|
|
490
|
+
}
|
|
491
|
+
.dot.og-island {
|
|
492
|
+
background: #14b8a6;
|
|
493
|
+
}
|
|
494
|
+
.dot.og-lake {
|
|
495
|
+
background: #f59e0b;
|
|
496
|
+
}
|
|
497
|
+
.dot.og-hole {
|
|
498
|
+
background: #8b5cf6;
|
|
499
|
+
}
|
|
500
|
+
.name {
|
|
501
|
+
color: #e2e8f0;
|
|
502
|
+
font-size: 13px;
|
|
503
|
+
font-weight: 700;
|
|
504
|
+
}
|
|
505
|
+
.k {
|
|
506
|
+
color: #94a3b8;
|
|
507
|
+
}
|
|
508
|
+
.loc {
|
|
509
|
+
margin-left: auto;
|
|
510
|
+
padding: 3px 9px;
|
|
511
|
+
border-radius: 6px;
|
|
512
|
+
border: 1px solid rgba(94, 234, 212, 0.3);
|
|
513
|
+
background: rgba(20, 184, 166, 0.12);
|
|
514
|
+
color: #5eead4;
|
|
515
|
+
cursor: pointer;
|
|
516
|
+
font: inherit;
|
|
517
|
+
}
|
|
518
|
+
.sec {
|
|
519
|
+
margin: 12px 0 6px;
|
|
520
|
+
color: #94a3b8;
|
|
521
|
+
font-weight: 600;
|
|
522
|
+
text-transform: uppercase;
|
|
523
|
+
font-size: 10px;
|
|
524
|
+
letter-spacing: 0.04em;
|
|
525
|
+
}
|
|
526
|
+
.secn {
|
|
527
|
+
text-transform: none;
|
|
528
|
+
letter-spacing: 0;
|
|
529
|
+
color: #94a3b8;
|
|
530
|
+
font-weight: 400;
|
|
531
|
+
}
|
|
532
|
+
.props {
|
|
533
|
+
padding: 8px 10px;
|
|
534
|
+
border-radius: 8px;
|
|
535
|
+
background: rgba(148, 163, 184, 0.06);
|
|
536
|
+
border: 1px solid rgba(148, 163, 184, 0.14);
|
|
537
|
+
max-height: 240px;
|
|
538
|
+
overflow: auto;
|
|
539
|
+
}
|
|
540
|
+
.life {
|
|
541
|
+
display: flex;
|
|
542
|
+
align-items: center;
|
|
543
|
+
flex-wrap: wrap;
|
|
544
|
+
gap: 4px;
|
|
545
|
+
}
|
|
546
|
+
.ph {
|
|
547
|
+
display: inline-flex;
|
|
548
|
+
align-items: center;
|
|
549
|
+
gap: 5px;
|
|
550
|
+
padding: 3px 8px;
|
|
551
|
+
border-radius: 999px;
|
|
552
|
+
background: rgba(148, 163, 184, 0.1);
|
|
553
|
+
}
|
|
554
|
+
.pd {
|
|
555
|
+
width: 7px;
|
|
556
|
+
height: 7px;
|
|
557
|
+
border-radius: 50%;
|
|
558
|
+
}
|
|
559
|
+
.pl {
|
|
560
|
+
color: #e2e8f0;
|
|
561
|
+
}
|
|
562
|
+
.off {
|
|
563
|
+
color: #94a3b8;
|
|
564
|
+
font-size: 10px;
|
|
565
|
+
}
|
|
566
|
+
.arm {
|
|
567
|
+
width: 10px;
|
|
568
|
+
height: 1px;
|
|
569
|
+
background: rgba(148, 163, 184, 0.4);
|
|
570
|
+
}
|
|
571
|
+
.hyd {
|
|
572
|
+
margin-top: 8px;
|
|
573
|
+
color: #94a3b8;
|
|
574
|
+
}
|
|
575
|
+
.hyd b {
|
|
576
|
+
color: #5eead4;
|
|
577
|
+
}
|
|
578
|
+
.rows {
|
|
579
|
+
display: flex;
|
|
580
|
+
flex-direction: column;
|
|
581
|
+
gap: 3px;
|
|
582
|
+
}
|
|
583
|
+
.row {
|
|
584
|
+
display: flex;
|
|
585
|
+
justify-content: space-between;
|
|
586
|
+
gap: 14px;
|
|
587
|
+
padding: 2px 0;
|
|
588
|
+
}
|
|
589
|
+
.rk {
|
|
590
|
+
color: #94a3b8;
|
|
591
|
+
}
|
|
592
|
+
.v {
|
|
593
|
+
color: #e2e8f0;
|
|
594
|
+
}
|
|
595
|
+
.muted {
|
|
596
|
+
color: #94a3b8;
|
|
597
|
+
}
|
|
598
|
+
.mono {
|
|
599
|
+
color: #cbd5e1;
|
|
600
|
+
}
|
|
601
|
+
.find {
|
|
602
|
+
margin-top: 4px;
|
|
603
|
+
padding: 4px 8px;
|
|
604
|
+
border-left: 3px solid #38bdf8;
|
|
605
|
+
background: rgba(148, 163, 184, 0.07);
|
|
606
|
+
border-radius: 4px;
|
|
607
|
+
line-height: 1.5;
|
|
608
|
+
}
|
|
609
|
+
.find.warn {
|
|
610
|
+
border-left-color: #f59e0b;
|
|
611
|
+
}
|
|
612
|
+
.find.error {
|
|
613
|
+
border-left-color: #ef4444;
|
|
614
|
+
}
|
|
615
|
+
</style>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export default IslandDetail;
|
|
2
|
+
type IslandDetail = {
|
|
3
|
+
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
+
$set?(props: Partial<$$ComponentProps>): void;
|
|
5
|
+
};
|
|
6
|
+
declare const IslandDetail: import("svelte").Component<{
|
|
7
|
+
el: any;
|
|
8
|
+
tick?: number;
|
|
9
|
+
onclose: any;
|
|
10
|
+
}, {}, "">;
|
|
11
|
+
type $$ComponentProps = {
|
|
12
|
+
el: any;
|
|
13
|
+
tick?: number;
|
|
14
|
+
onclose: any;
|
|
15
|
+
};
|