@reactra/devtools 0.1.0-alpha.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 +78 -0
- package/dist/ValueTree.d.ts +38 -0
- package/dist/ValueTree.d.ts.map +1 -0
- package/dist/ValueTree.js +178 -0
- package/dist/ValueTree.js.map +1 -0
- package/dist/helpers.d.ts +59 -0
- package/dist/helpers.d.ts.map +1 -0
- package/dist/helpers.js +110 -0
- package/dist/helpers.js.map +1 -0
- package/dist/hookRecorder.d.ts +72 -0
- package/dist/hookRecorder.d.ts.map +1 -0
- package/dist/hookRecorder.js +142 -0
- package/dist/hookRecorder.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/invoke.d.ts +35 -0
- package/dist/invoke.d.ts.map +1 -0
- package/dist/invoke.js +67 -0
- package/dist/invoke.js.map +1 -0
- package/dist/model.d.ts +99 -0
- package/dist/model.d.ts.map +1 -0
- package/dist/model.js +160 -0
- package/dist/model.js.map +1 -0
- package/dist/panel.d.ts +17 -0
- package/dist/panel.d.ts.map +1 -0
- package/dist/panel.js +438 -0
- package/dist/panel.js.map +1 -0
- package/dist/routerWatcher.d.ts +47 -0
- package/dist/routerWatcher.d.ts.map +1 -0
- package/dist/routerWatcher.js +51 -0
- package/dist/routerWatcher.js.map +1 -0
- package/dist/serialize.d.ts +38 -0
- package/dist/serialize.d.ts.map +1 -0
- package/dist/serialize.js +217 -0
- package/dist/serialize.js.map +1 -0
- package/dist/storeRecorder.d.ts +25 -0
- package/dist/storeRecorder.d.ts.map +1 -0
- package/dist/storeRecorder.js +94 -0
- package/dist/storeRecorder.js.map +1 -0
- package/dist/storeWatcher.d.ts +26 -0
- package/dist/storeWatcher.d.ts.map +1 -0
- package/dist/storeWatcher.js +24 -0
- package/dist/storeWatcher.js.map +1 -0
- package/dist/styles.d.ts +5 -0
- package/dist/styles.d.ts.map +1 -0
- package/dist/styles.js +288 -0
- package/dist/styles.js.map +1 -0
- package/dist/tabs/router.d.ts +10 -0
- package/dist/tabs/router.d.ts.map +1 -0
- package/dist/tabs/router.js +48 -0
- package/dist/tabs/router.js.map +1 -0
- package/dist/tabs/stores.d.ts +14 -0
- package/dist/tabs/stores.d.ts.map +1 -0
- package/dist/tabs/stores.js +167 -0
- package/dist/tabs/stores.js.map +1 -0
- package/dist/tabs/timeTravel.d.ts +46 -0
- package/dist/tabs/timeTravel.d.ts.map +1 -0
- package/dist/tabs/timeTravel.js +322 -0
- package/dist/tabs/timeTravel.js.map +1 -0
- package/package.json +43 -0
package/dist/panel.js
ADDED
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
// @reactra/devtools — the <ReactraDevtools> developer panel.
|
|
2
|
+
//
|
|
3
|
+
// Owner: reactra-devtools-spec.md §2 (mount/lifecycle, popup-out), §3 (data
|
|
4
|
+
// sources + DVT001 degradation), §4 (Components tab). Written with
|
|
5
|
+
// `createElement` (no JSX — Node type-stripping doesn't transform JSX;
|
|
6
|
+
// Runtime §2 tier rule) and injected stylesheets (no `.css` import).
|
|
7
|
+
// Browser globals appear only inside handlers/effects.
|
|
8
|
+
//
|
|
9
|
+
// Chrome mechanics (drag-resize, pop-out, theme, hotkey) delegate to the
|
|
10
|
+
// shared helpers in `@reactra/replay-devtools/chrome` (C1 — one impl, two
|
|
11
|
+
// consumers). `createPortal` stays here; no react-dom dep in chrome.ts (C2).
|
|
12
|
+
import { createElement as h, useEffect, useRef, useState, } from "react";
|
|
13
|
+
import { createPortal } from "react-dom";
|
|
14
|
+
import { openPanelWindow, usePanelHeight, usePanelTheme, useToggleHotkey } from "@reactra/replay-devtools/chrome";
|
|
15
|
+
import { diffKeys, ensureStyles as ensureTimelineStyles } from "@reactra/replay-devtools/timeline";
|
|
16
|
+
import { callableNames, dataBindings, groupBindings, isStale } from "./helpers.js";
|
|
17
|
+
import { runInvoke } from "./invoke.js";
|
|
18
|
+
import { createDevtoolsModel } from "./model.js";
|
|
19
|
+
import { createHookRecorder } from "./hookRecorder.js";
|
|
20
|
+
import { attachStoreRecorder } from "./storeRecorder.js";
|
|
21
|
+
import { createNavLog, routeSnapshot, subscribeRouter } from "./routerWatcher.js";
|
|
22
|
+
import { serializeBindings } from "./serialize.js";
|
|
23
|
+
import { ensureStyles } from "./styles.js";
|
|
24
|
+
import { ValueTree } from "./ValueTree.js";
|
|
25
|
+
import { StoresTab } from "./tabs/stores.js";
|
|
26
|
+
import { RouterTab } from "./tabs/router.js";
|
|
27
|
+
import { TimeTravelTab } from "./tabs/timeTravel.js";
|
|
28
|
+
const TABS = [
|
|
29
|
+
{ id: "components", label: "Components" },
|
|
30
|
+
{ id: "stores", label: "Stores" },
|
|
31
|
+
{ id: "router", label: "Router" },
|
|
32
|
+
{ id: "time", label: "Time Travel" },
|
|
33
|
+
];
|
|
34
|
+
/**
|
|
35
|
+
* The Reactra developer panel: Components / Stores / Router / Time Travel
|
|
36
|
+
* tabs over the shipped runtime surfaces (Devtools spec §3 — zero new
|
|
37
|
+
* compiler emission). Hand-mounted; the mount is the sole opt-in.
|
|
38
|
+
*/
|
|
39
|
+
export const ReactraDevtools = (props) => {
|
|
40
|
+
const [open, setOpen] = useState(props.defaultOpen ?? false);
|
|
41
|
+
// Latest-value ref for `open`, read by the Shift+Alt+D handler so it doesn't
|
|
42
|
+
// need a nested setState (which StrictMode double-invokes). Assigned every
|
|
43
|
+
// render — the recommended pattern for a "current value" ref.
|
|
44
|
+
const openRef = useRef(open);
|
|
45
|
+
openRef.current = open;
|
|
46
|
+
// Theme: System→Light→Dark, persisted. Shared chrome helper (C1).
|
|
47
|
+
const [theme, cycleTheme] = usePanelTheme("@reactra/devtools:theme");
|
|
48
|
+
// Minimized = docked but collapsed to the header bar only (the tab body is
|
|
49
|
+
// not rendered). Distinct from `open` (the corner pill) and `popup` (its own
|
|
50
|
+
// window). The passive recorder + nav log live on the panel, not the tabs, so
|
|
51
|
+
// recording continues while minimized.
|
|
52
|
+
const [minimized, setMinimized] = useState(false);
|
|
53
|
+
const [tab, setTab] = useState("components");
|
|
54
|
+
const [hookState, setHookState] = useState("pending");
|
|
55
|
+
const [popup, setPopup] = useState(null);
|
|
56
|
+
const [sel, setSel] = useState(null);
|
|
57
|
+
const [argText, setArgText] = useState({});
|
|
58
|
+
const [invokeErr, setInvokeErr] = useState({});
|
|
59
|
+
const [, setTick] = useState(0);
|
|
60
|
+
// T3.3: tracks whether the Time Travel tab is in replay mode so the panel
|
|
61
|
+
// can apply the rdt-panel--replaying class to the shell.
|
|
62
|
+
const [replaying, setReplaying] = useState(false);
|
|
63
|
+
// T2.2: stale display filter — names cleared by "Clear stale" remain hidden
|
|
64
|
+
// until they emit a new commit. Preserves the ring (recorder.events() is
|
|
65
|
+
// untouched); this is a pure display concern.
|
|
66
|
+
const [hiddenStale, setHiddenStale] = useState(new Set());
|
|
67
|
+
// T2.3: Components rail search — case-insensitive substring filter.
|
|
68
|
+
const [compSearch, setCompSearch] = useState("");
|
|
69
|
+
// Panel height: drag-to-resize + localStorage persistence. Shared chrome (C1).
|
|
70
|
+
const [panelHeight, resizeHandleProps] = usePanelHeight("@reactra/devtools:panel-height", { defaultHeight: 400 });
|
|
71
|
+
// One recorder per panel instance; survives re-renders, dies with unmount.
|
|
72
|
+
const recRef = useRef(null);
|
|
73
|
+
if (recRef.current === null) {
|
|
74
|
+
recRef.current = createHookRecorder({ historyLimit: props.historyLimit });
|
|
75
|
+
if (props.record === false)
|
|
76
|
+
recRef.current.setRecording(false);
|
|
77
|
+
}
|
|
78
|
+
const rec = recRef.current;
|
|
79
|
+
// Previous data-bindings per component — drives the changed-key flash.
|
|
80
|
+
const prevRef = useRef(new Map());
|
|
81
|
+
// One nav log per panel instance — records router transitions for the whole
|
|
82
|
+
// panel lifetime (not just while the Router tab is visible). The mount is
|
|
83
|
+
// the sole opt-in (Devtools §6).
|
|
84
|
+
const navRef = useRef(null);
|
|
85
|
+
if (navRef.current === null)
|
|
86
|
+
navRef.current = createNavLog();
|
|
87
|
+
const navLog = navRef.current;
|
|
88
|
+
// DevtoolsModel facade — owns the consolidated ticker (T2.1 / arch#2a).
|
|
89
|
+
// Created lazily in a ref so it persists across re-renders.
|
|
90
|
+
const modelRef = useRef(null);
|
|
91
|
+
if (modelRef.current === null) {
|
|
92
|
+
modelRef.current = createDevtoolsModel({ recorder: rec, navLog });
|
|
93
|
+
}
|
|
94
|
+
const model = modelRef.current;
|
|
95
|
+
ensureStyles();
|
|
96
|
+
// Shift+Alt+D: toggle open/minimized. Shared chrome hook (C1).
|
|
97
|
+
// Read open via openRef (not the state value) to avoid a nested setState
|
|
98
|
+
// inside a setOpen updater, which StrictMode double-invokes (2026-06-10 fix).
|
|
99
|
+
useToggleHotkey("D", { shift: true, alt: true }, () => {
|
|
100
|
+
if (!openRef.current)
|
|
101
|
+
setOpen(true);
|
|
102
|
+
else
|
|
103
|
+
setMinimized((wasMin) => !wasMin);
|
|
104
|
+
});
|
|
105
|
+
useEffect(() => {
|
|
106
|
+
// Install only into an empty slot — DVT001 degrades, never overwrites
|
|
107
|
+
// (Devtools §3; the recorder itself warns).
|
|
108
|
+
setHookState(rec.install());
|
|
109
|
+
// Subscribe via the facade: recorder commits + route changes + the
|
|
110
|
+
// consolidated store-poll ticker all funnel through one subscription.
|
|
111
|
+
const off = model.subscribe(() => setTick((t) => t + 1));
|
|
112
|
+
// The nav log + the route ring record only REAL navigations — never the
|
|
113
|
+
// route changes the Time Travel tab itself drives while scrubbing. Both
|
|
114
|
+
// gate on `rec.recording()`, which `freezeIfLive` flips to false
|
|
115
|
+
// SYNCHRONOUSLY before any scrub navigation (a `replaying` React-state gate
|
|
116
|
+
// would race the synchronous navigate() in the same click handler).
|
|
117
|
+
const stopNav = navLog.start(() => rec.recording());
|
|
118
|
+
// Navigation in the time-travel timeline: record the route at mount, then
|
|
119
|
+
// one synthetic `Route#1` snapshot per transition. recordSnapshot itself
|
|
120
|
+
// no-ops while the ring is frozen (traveling) or paused (Devtools §7).
|
|
121
|
+
rec.recordSnapshot("Route#1", routeSnapshot());
|
|
122
|
+
const offRoute = subscribeRouter(() => rec.recordSnapshot("Route#1", routeSnapshot()));
|
|
123
|
+
// Fold export/session store snapshots into the same passive ring so Time
|
|
124
|
+
// Travel can re-drive them (plan store-time-travel §3.2). recording()-gated;
|
|
125
|
+
// re-enumerates on its own interval to catch late-instantiated stores.
|
|
126
|
+
const storeRec = attachStoreRecorder(rec);
|
|
127
|
+
return () => {
|
|
128
|
+
off();
|
|
129
|
+
stopNav();
|
|
130
|
+
offRoute();
|
|
131
|
+
storeRec.dispose();
|
|
132
|
+
rec.uninstall();
|
|
133
|
+
// Fix 3: dispose the model on panel unmount to unsubscribe from the
|
|
134
|
+
// RouterRegistry singleton and prevent listener accumulation across
|
|
135
|
+
// panel mount/unmount cycles.
|
|
136
|
+
model.dispose();
|
|
137
|
+
};
|
|
138
|
+
}, [rec, navLog, model]);
|
|
139
|
+
// Popup-out (Devtools §2): the panel portals into its own window; closing
|
|
140
|
+
// the window returns it to the in-page drawer. The closed-poll now rides the
|
|
141
|
+
// consolidated ticker (T2.1) — no second setInterval here.
|
|
142
|
+
useEffect(() => {
|
|
143
|
+
if (!popup)
|
|
144
|
+
return;
|
|
145
|
+
// Use the model's ticker for popup-close detection rather than a separate
|
|
146
|
+
// interval. Subscribe to get periodic ticks; check popup.closed on each.
|
|
147
|
+
const off = model.subscribe(() => {
|
|
148
|
+
if (popup.closed)
|
|
149
|
+
setPopup(null);
|
|
150
|
+
});
|
|
151
|
+
return off;
|
|
152
|
+
}, [popup, model]);
|
|
153
|
+
const popOut = () => {
|
|
154
|
+
const w = openPanelWindow({
|
|
155
|
+
name: "reactra-devtools",
|
|
156
|
+
title: "Reactra Devtools",
|
|
157
|
+
injectStyles: [ensureStyles, ensureTimelineStyles],
|
|
158
|
+
});
|
|
159
|
+
if (w)
|
|
160
|
+
setPopup(w);
|
|
161
|
+
};
|
|
162
|
+
// ---- Components tab (Devtools §4) ---------------------------------------
|
|
163
|
+
// These values are computed unconditionally (before the !open early-return)
|
|
164
|
+
// because the prevRef-update useEffect below must be called on every render
|
|
165
|
+
// (Rules of Hooks — useEffect must not appear after a conditional return).
|
|
166
|
+
const components = rec.components();
|
|
167
|
+
const names = [...components.keys()];
|
|
168
|
+
// T2.2: latestWaveTime — the wave front: the most recent lastSeen across ALL
|
|
169
|
+
// tracked components. isStale is relative: a component is stale only if it
|
|
170
|
+
// missed this wave while others committed (prevents static pages from
|
|
171
|
+
// flagging everything stale).
|
|
172
|
+
const latestWaveTime = names.reduce((max, n) => {
|
|
173
|
+
const info = components.get(n);
|
|
174
|
+
return info ? Math.max(max, info.lastSeen) : max;
|
|
175
|
+
}, 0);
|
|
176
|
+
const selected = sel !== null && components.has(sel) ? sel : (names[0] ?? null);
|
|
177
|
+
// Fix 5: compute the set of hidden-stale names that have since recovered
|
|
178
|
+
// (they're no longer stale) during render — pure read, no setState here.
|
|
179
|
+
// The setState call is deferred to the useEffect below so it doesn't happen
|
|
180
|
+
// during the render phase (setState-during-render is fragile / warns in
|
|
181
|
+
// StrictMode).
|
|
182
|
+
const recoveredFromStale = names.filter((n) => hiddenStale.has(n) && !isStale(components.get(n).lastSeen, latestWaveTime));
|
|
183
|
+
// Remember the rendered data-bindings AFTER paint so the next commit's
|
|
184
|
+
// diff highlights exactly what that commit changed. Also reconciles the
|
|
185
|
+
// hidden-stale set (Fix 5). Must be before any conditional return (Rules
|
|
186
|
+
// of Hooks).
|
|
187
|
+
useEffect(() => {
|
|
188
|
+
if (open && selected) {
|
|
189
|
+
const info = components.get(selected);
|
|
190
|
+
if (info)
|
|
191
|
+
prevRef.current.set(selected, serializeBindings(info.bindings));
|
|
192
|
+
}
|
|
193
|
+
// Fix 5: remove recovered components from hiddenStale AFTER paint, not
|
|
194
|
+
// during render.
|
|
195
|
+
if (recoveredFromStale.length > 0) {
|
|
196
|
+
setHiddenStale((prev) => {
|
|
197
|
+
const next = new Set(prev);
|
|
198
|
+
for (const n of recoveredFromStale)
|
|
199
|
+
next.delete(n);
|
|
200
|
+
return next;
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
if (!open) {
|
|
205
|
+
return h("button", { className: "rdt-root rdt-pill", onClick: () => setOpen(true), title: "Open Reactra Devtools" }, h("span", { className: "rdt-logo" }, "⚛"), "reactra");
|
|
206
|
+
}
|
|
207
|
+
const invoke = (component, binding, fn) => {
|
|
208
|
+
const key = `${component}.${binding}`;
|
|
209
|
+
// Fix 6b: pass onAsyncError so a rejected async action surfaces inline
|
|
210
|
+
// as DVT004 rather than escaping to window.unhandledrejection.
|
|
211
|
+
const result = runInvoke(fn, argText[key], (msg) => setInvokeErr((cur) => ({ ...cur, [key]: msg })));
|
|
212
|
+
if (!result.ok) {
|
|
213
|
+
setInvokeErr((cur) => ({ ...cur, [key]: result.error }));
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
setInvokeErr((cur) => ({ ...cur, [key]: "" }));
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
const componentsTab = () => {
|
|
220
|
+
if (hookState === "occupied") {
|
|
221
|
+
return h("div", { className: "rdt-main" }, h("div", { className: "rdt-warn" }, "DVT001: __REACTRA_TEST__ is already installed by another consumer — the Components tab and passive time travel are disabled. Stores and Router still work."));
|
|
222
|
+
}
|
|
223
|
+
const info = selected ? components.get(selected) : undefined;
|
|
224
|
+
// Split bindings into data vs actions (T1.3 — grouping).
|
|
225
|
+
const { data: rawData, actions: rawActions } = info
|
|
226
|
+
? groupBindings(info.bindings)
|
|
227
|
+
: { data: {}, actions: {} };
|
|
228
|
+
const cur = serializeBindings(rawData);
|
|
229
|
+
const callables = Object.keys(rawActions);
|
|
230
|
+
// diffKeys compares Record<string,unknown>; cur is Record<string,Serialized>
|
|
231
|
+
// which extends it structurally.
|
|
232
|
+
const changed = new Set(selected ? diffKeys(prevRef.current.get(selected), cur) : []);
|
|
233
|
+
// T2.2: stale entries whose names appear in hiddenStale are filtered from
|
|
234
|
+
// the rail display. Components that recover (no longer stale) are un-hidden
|
|
235
|
+
// by the post-paint useEffect (Fix 5 — no setState during render).
|
|
236
|
+
// T2.3: additionally filtered by the search text (case-insensitive substring).
|
|
237
|
+
const searchLower = compSearch.toLowerCase();
|
|
238
|
+
const visibleNames = names.filter((n) => {
|
|
239
|
+
const c = components.get(n);
|
|
240
|
+
const stale = isStale(c.lastSeen, latestWaveTime);
|
|
241
|
+
if (stale && hiddenStale.has(n))
|
|
242
|
+
return false;
|
|
243
|
+
// T2.3 search filter — apply AFTER stale filter so we don't count
|
|
244
|
+
// hidden-stale entries in the search results.
|
|
245
|
+
if (searchLower && !n.toLowerCase().includes(searchLower))
|
|
246
|
+
return false;
|
|
247
|
+
return true;
|
|
248
|
+
});
|
|
249
|
+
const staleCount = names.filter((n) => isStale(components.get(n).lastSeen, latestWaveTime)).length;
|
|
250
|
+
return h("div", { className: "rdt-body" }, h("div", {
|
|
251
|
+
className: "rdt-rail",
|
|
252
|
+
// T3.1: ARIA listbox — the rail is a listbox of selectable components.
|
|
253
|
+
role: "listbox",
|
|
254
|
+
"aria-label": "Components",
|
|
255
|
+
"aria-orientation": "vertical",
|
|
256
|
+
// T3.1: arrow-key navigation in the rail listbox.
|
|
257
|
+
onKeyDown: (e) => {
|
|
258
|
+
const idx = visibleNames.indexOf(selected ?? "");
|
|
259
|
+
if (e.key === "ArrowDown" && idx < visibleNames.length - 1) {
|
|
260
|
+
setSel(visibleNames[idx + 1]);
|
|
261
|
+
e.preventDefault();
|
|
262
|
+
}
|
|
263
|
+
else if (e.key === "ArrowUp" && idx > 0) {
|
|
264
|
+
setSel(visibleNames[idx - 1]);
|
|
265
|
+
e.preventDefault();
|
|
266
|
+
}
|
|
267
|
+
},
|
|
268
|
+
}, h("div", { className: "rdt-rail-header" }, h("h4", null, "Components"),
|
|
269
|
+
// "Clear stale" button — hides stale entries from the display rail
|
|
270
|
+
// (recorder.events() is untouched; T2.2).
|
|
271
|
+
staleCount > 0 &&
|
|
272
|
+
h("button", {
|
|
273
|
+
className: "rdt-btn rdt-mini",
|
|
274
|
+
onClick: () => {
|
|
275
|
+
const toHide = new Set(names.filter((n) => isStale(components.get(n).lastSeen, latestWaveTime)));
|
|
276
|
+
setHiddenStale(toHide);
|
|
277
|
+
},
|
|
278
|
+
title: "Hide stale components from the rail (ring is preserved)",
|
|
279
|
+
}, "Clear stale")),
|
|
280
|
+
// T2.3: search input — shown once the rail has entries to filter.
|
|
281
|
+
names.length > 0 &&
|
|
282
|
+
h("input", {
|
|
283
|
+
className: "rdt-search",
|
|
284
|
+
type: "search",
|
|
285
|
+
placeholder: "Filter components…",
|
|
286
|
+
value: compSearch,
|
|
287
|
+
onChange: (e) => setCompSearch(e.target.value),
|
|
288
|
+
"aria-label": "Filter components by name",
|
|
289
|
+
}), visibleNames.length === 0 &&
|
|
290
|
+
names.length === 0 &&
|
|
291
|
+
h("div", { className: "rdt-hint" }, "Nothing reporting yet — interact with the app."), visibleNames.length === 0 &&
|
|
292
|
+
names.length > 0 &&
|
|
293
|
+
h("div", { className: "rdt-hint" }, compSearch
|
|
294
|
+
? `No components match "${compSearch}".`
|
|
295
|
+
: "All entries cleared. They reappear on next commit."), ...visibleNames.map((name) => {
|
|
296
|
+
const c = components.get(name);
|
|
297
|
+
const stale = isStale(c.lastSeen, latestWaveTime);
|
|
298
|
+
const isSelected = name === selected;
|
|
299
|
+
return h("button", {
|
|
300
|
+
key: name,
|
|
301
|
+
className: `rdt-item${isSelected ? " rdt-item--on" : ""}${stale ? " rdt-item--stale" : ""}`,
|
|
302
|
+
// T3.1: option role + aria-selected for screen reader support.
|
|
303
|
+
role: "option",
|
|
304
|
+
"aria-selected": isSelected,
|
|
305
|
+
tabIndex: isSelected ? 0 : -1,
|
|
306
|
+
onClick: () => setSel(name),
|
|
307
|
+
title: stale ? "stale (unmounted?) — DVT-LIM-01" : `${c.commits} commits`,
|
|
308
|
+
}, h("code", null, name), stale && h("span", { className: "rdt-badge rdt-badge--stale" }, "stale"), h("span", { className: "rdt-count" }, String(c.commits)));
|
|
309
|
+
})), h("div", { className: "rdt-main" }, selected === null
|
|
310
|
+
? h("div", { className: "rdt-hint" }, "No component selected.")
|
|
311
|
+
: h("div", { className: "rdt-card" }, h("div", { className: "rdt-card-id" }, selected, isStale(components.get(selected).lastSeen, latestWaveTime) &&
|
|
312
|
+
h("span", { className: "rdt-badge rdt-badge--stale" }, "stale (unmounted?)")),
|
|
313
|
+
// Data section (T1.3): props, state, derived, behaviour, resource.
|
|
314
|
+
Object.keys(cur).length > 0 &&
|
|
315
|
+
h("div", { className: "rdt-group" }, h("div", { className: "rdt-group-label" }, "State / Props"), h(ValueTree, { data: cur, changed })),
|
|
316
|
+
// Actions section (T1.3): callable bindings — the §4 invoke rows.
|
|
317
|
+
callables.length > 0 &&
|
|
318
|
+
h("div", { className: "rdt-group" }, h("div", { className: "rdt-group-label" }, "Actions"), ...callables.flatMap((k) => {
|
|
319
|
+
const key = `${selected}.${k}`;
|
|
320
|
+
return [
|
|
321
|
+
h("div", { key, className: "rdt-kv" }, h("span", { className: "rdt-k" }, `${k}()`), h("input", {
|
|
322
|
+
className: "rdt-args",
|
|
323
|
+
placeholder: 'args: ["x", 1]',
|
|
324
|
+
value: argText[key] ?? "",
|
|
325
|
+
onChange: (e) => setArgText((curText) => ({ ...curText, [key]: e.target.value })),
|
|
326
|
+
}), h("button", {
|
|
327
|
+
className: "rdt-btn rdt-mini rdt-run",
|
|
328
|
+
onClick: () => invoke(selected, k, components.get(selected).bindings[k]),
|
|
329
|
+
title: "Invoke — the exact callback the component's own UI calls",
|
|
330
|
+
}, "▶ run")),
|
|
331
|
+
invokeErr[key]
|
|
332
|
+
? h("div", { key: `${key}.err`, className: "rdt-invoke-err" }, invokeErr[key])
|
|
333
|
+
: null,
|
|
334
|
+
];
|
|
335
|
+
})))));
|
|
336
|
+
};
|
|
337
|
+
// While minimized the active tab component is not mounted (its effects/
|
|
338
|
+
// subscriptions pause) — only the header bar renders. A popup window is never
|
|
339
|
+
// minimized (it's already a separate, resizable window).
|
|
340
|
+
const showBody = !minimized || popup !== null;
|
|
341
|
+
const body = !showBody
|
|
342
|
+
? null
|
|
343
|
+
: tab === "components"
|
|
344
|
+
? componentsTab()
|
|
345
|
+
: tab === "stores"
|
|
346
|
+
? h(StoresTab, { model })
|
|
347
|
+
: tab === "router"
|
|
348
|
+
? h(RouterTab, { navLog })
|
|
349
|
+
: h(TimeTravelTab, { recorder: rec, hookState, onReplayingChange: setReplaying });
|
|
350
|
+
const isProd = typeof process !== "undefined" && process.env && process.env.NODE_ENV === "production";
|
|
351
|
+
// `.rdt-root` carries the CSS-variable token definitions (T0.3); all three
|
|
352
|
+
// panel variants include it so tokens are available in popup windows too.
|
|
353
|
+
// T3.3: add `rdt-panel--replaying` when the Time Travel tab is in replay mode.
|
|
354
|
+
const replayingSuffix = replaying ? " rdt-panel--replaying" : "";
|
|
355
|
+
const panelClass = popup
|
|
356
|
+
? `rdt-root rdt-panel rdt-panel--popup${replayingSuffix}`
|
|
357
|
+
: minimized
|
|
358
|
+
? `rdt-root rdt-panel rdt-panel--min${replayingSuffix}`
|
|
359
|
+
: `rdt-root rdt-panel${replayingSuffix}`;
|
|
360
|
+
// T2.4: apply persisted height only for the docked panel (not popup — the
|
|
361
|
+
// popup window is sized by the OS, not the CSS height property).
|
|
362
|
+
const panelStyle = popup || minimized ? undefined : { height: panelHeight };
|
|
363
|
+
const panel = h("section", {
|
|
364
|
+
className: panelClass,
|
|
365
|
+
tabIndex: 0,
|
|
366
|
+
style: panelStyle,
|
|
367
|
+
// Explicit theme override; "system" falls through to prefers-color-scheme.
|
|
368
|
+
"data-rdt-theme": theme,
|
|
369
|
+
},
|
|
370
|
+
// T2.4: resize handle — the 4px top-edge strip the user drags to resize.
|
|
371
|
+
// Only relevant for the docked panel (not popup, not minimized).
|
|
372
|
+
!popup && !minimized &&
|
|
373
|
+
h("div", {
|
|
374
|
+
className: "rdt-resize-handle",
|
|
375
|
+
onMouseDown: resizeHandleProps.onMouseDown,
|
|
376
|
+
title: "Drag to resize panel",
|
|
377
|
+
role: "separator",
|
|
378
|
+
"aria-orientation": "horizontal",
|
|
379
|
+
}), h("header", { className: "rdt-head" }, h("span", { className: "rdt-logo" }, "⚛"), h("span", { className: "rdt-title" }, "Reactra Devtools"), h("nav", {
|
|
380
|
+
className: "rdt-tabs",
|
|
381
|
+
// T3.1: ARIA tablist — screen readers navigate tabs by role.
|
|
382
|
+
role: "tablist",
|
|
383
|
+
"aria-label": "Reactra Devtools tabs",
|
|
384
|
+
// T3.1: arrow-key navigation within the tablist.
|
|
385
|
+
onKeyDown: (e) => {
|
|
386
|
+
const idx = TABS.findIndex((t) => t.id === tab);
|
|
387
|
+
if (e.key === "ArrowRight") {
|
|
388
|
+
const next = TABS[(idx + 1) % TABS.length];
|
|
389
|
+
setTab(next.id);
|
|
390
|
+
setMinimized(false);
|
|
391
|
+
}
|
|
392
|
+
else if (e.key === "ArrowLeft") {
|
|
393
|
+
const prev = TABS[(idx - 1 + TABS.length) % TABS.length];
|
|
394
|
+
setTab(prev.id);
|
|
395
|
+
setMinimized(false);
|
|
396
|
+
}
|
|
397
|
+
},
|
|
398
|
+
}, ...TABS.map((t) => h("button", {
|
|
399
|
+
key: t.id,
|
|
400
|
+
id: `rdt-tab-${t.id}`,
|
|
401
|
+
className: t.id === tab ? "rdt-tab rdt-tab--on" : "rdt-tab",
|
|
402
|
+
role: "tab",
|
|
403
|
+
"aria-selected": t.id === tab,
|
|
404
|
+
"aria-controls": `rdt-tabpanel-${t.id}`,
|
|
405
|
+
tabIndex: t.id === tab ? 0 : -1,
|
|
406
|
+
// Selecting a tab while minimized restores the body — you asked
|
|
407
|
+
// to see that tab, so show it.
|
|
408
|
+
onClick: () => {
|
|
409
|
+
setTab(t.id);
|
|
410
|
+
setMinimized(false);
|
|
411
|
+
},
|
|
412
|
+
}, t.label))), isProd && h("span", { className: "rdt-warn" }, "production build — dev tool mounted"), h("span", { className: "rdt-spacer" }),
|
|
413
|
+
// Theme toggle: cycles System → Light → Dark → System, persisted.
|
|
414
|
+
h("button", {
|
|
415
|
+
className: "rdt-btn",
|
|
416
|
+
onClick: cycleTheme,
|
|
417
|
+
title: `Theme: ${theme} (click to cycle System → Light → Dark)`,
|
|
418
|
+
"aria-label": `Theme: ${theme}`,
|
|
419
|
+
}, theme === "light" ? "☀" : theme === "dark" ? "🌙" : "◐"), !popup &&
|
|
420
|
+
h("button", {
|
|
421
|
+
className: "rdt-btn",
|
|
422
|
+
onClick: () => setMinimized((m) => !m),
|
|
423
|
+
title: minimized ? "Restore" : "Minimize to the header bar",
|
|
424
|
+
}, minimized ? "▴" : "▾"), !popup &&
|
|
425
|
+
h("button", { className: "rdt-btn", onClick: popOut, title: "Pop out into its own window" }, "⧉"), !popup &&
|
|
426
|
+
h("button", { className: "rdt-btn", onClick: () => setOpen(false), title: "Collapse to the pill" }, "✕")),
|
|
427
|
+
// T3.1: wrap the tab body in a div with role="tabpanel" so screen readers
|
|
428
|
+
// can associate it with the active tab.
|
|
429
|
+
body !== null &&
|
|
430
|
+
h("div", {
|
|
431
|
+
id: `rdt-tabpanel-${tab}`,
|
|
432
|
+
role: "tabpanel",
|
|
433
|
+
"aria-labelledby": `rdt-tab-${tab}`,
|
|
434
|
+
style: { display: "contents" },
|
|
435
|
+
}, body));
|
|
436
|
+
return popup ? createPortal(panel, popup.document.body) : panel;
|
|
437
|
+
};
|
|
438
|
+
//# sourceMappingURL=panel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"panel.js","sourceRoot":"","sources":["../src/panel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { RouterRegistry, type RouteState } from "@reactra/router";
|
|
2
|
+
/** One recent-navigation entry (Devtools §6). */
|
|
3
|
+
export interface NavEntry {
|
|
4
|
+
timestamp: number;
|
|
5
|
+
pathname: string;
|
|
6
|
+
params: Record<string, string>;
|
|
7
|
+
query: Record<string, string | string[]>;
|
|
8
|
+
}
|
|
9
|
+
/** Current route snapshot — id/pattern/params/coerced query live here. */
|
|
10
|
+
export declare const currentRoute: () => RouteState;
|
|
11
|
+
/**
|
|
12
|
+
* Re-drive the route to a path string — used by Time Travel to replay
|
|
13
|
+
* navigation on scrub. Consumes the router's public `navigate` (Router spec);
|
|
14
|
+
* the panel never redefines routing.
|
|
15
|
+
*/
|
|
16
|
+
export declare const navigate: (to: string) => void;
|
|
17
|
+
/**
|
|
18
|
+
* A re-drivable route snapshot for the time-travel ring: the exact URL string
|
|
19
|
+
* (`pathname + search`, so `navigate()` reconstructs it) plus the coerced
|
|
20
|
+
* params/query for the card display. `location` is read only inside this
|
|
21
|
+
* function (browser-only — UI-companion tier rule), falling back to the
|
|
22
|
+
* registry pathname under SSR/Node.
|
|
23
|
+
*/
|
|
24
|
+
export declare const routeSnapshot: () => {
|
|
25
|
+
path: string;
|
|
26
|
+
pathname: string;
|
|
27
|
+
params: Record<string, string>;
|
|
28
|
+
query: Record<string, string | string[]>;
|
|
29
|
+
};
|
|
30
|
+
/** The registered manifest (all routes). */
|
|
31
|
+
export declare const listRoutes: () => ReturnType<typeof RouterRegistry.getRoutes>;
|
|
32
|
+
/** Subscribe to route transitions (panel re-render). */
|
|
33
|
+
export declare const subscribeRouter: (onChange: () => void) => (() => void);
|
|
34
|
+
export interface NavLog {
|
|
35
|
+
/**
|
|
36
|
+
* Begin recording transitions. Returns the stopper (panel unmount).
|
|
37
|
+
* `shouldRecord`, when supplied, gates each entry — the panel passes a
|
|
38
|
+
* "not currently time-traveling" predicate so route changes the Time Travel
|
|
39
|
+
* tab itself drives during scrub are NOT logged as real navigations.
|
|
40
|
+
*/
|
|
41
|
+
start(shouldRecord?: () => boolean): () => void;
|
|
42
|
+
/** Recorded entries, newest first. */
|
|
43
|
+
entries(): readonly NavEntry[];
|
|
44
|
+
}
|
|
45
|
+
/** A bounded recent-navigations log (default 50 entries, newest first). */
|
|
46
|
+
export declare const createNavLog: (limit?: number, now?: () => number) => NavLog;
|
|
47
|
+
//# sourceMappingURL=routerWatcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routerWatcher.d.ts","sourceRoot":"","sources":["../src/routerWatcher.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,cAAc,EAA8B,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE7F,iDAAiD;AACjD,MAAM,WAAW,QAAQ;IACvB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAA;CACzC;AAED,0EAA0E;AAC1E,eAAO,MAAM,YAAY,QAAO,UAA0C,CAAA;AAE1E;;;;GAIG;AACH,eAAO,MAAM,QAAQ,GAAI,IAAI,MAAM,KAAG,IAA0B,CAAA;AAEhE;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,QAAO;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAA;CAMzC,CAAA;AAED,4CAA4C;AAC5C,eAAO,MAAM,UAAU,QAAO,UAAU,CAAC,OAAO,cAAc,CAAC,SAAS,CAC5C,CAAA;AAE5B,wDAAwD;AACxD,eAAO,MAAM,eAAe,GAAI,UAAU,MAAM,IAAI,KAAG,CAAC,MAAM,IAAI,CAC9B,CAAA;AAEpC,MAAM,WAAW,MAAM;IACrB;;;;;OAKG;IACH,KAAK,CAAC,YAAY,CAAC,EAAE,MAAM,OAAO,GAAG,MAAM,IAAI,CAAA;IAC/C,sCAAsC;IACtC,OAAO,IAAI,SAAS,QAAQ,EAAE,CAAA;CAC/B;AAED,2EAA2E;AAC3E,eAAO,MAAM,YAAY,GAAI,cAAU,EAAE,MAAK,MAAM,MAAiB,KAAG,MAiBvE,CAAA"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// @reactra/devtools — the Router-tab data layer.
|
|
2
|
+
//
|
|
3
|
+
// Owner: reactra-devtools-spec.md §6 (read-only v1). Thin reads over
|
|
4
|
+
// `@reactra/router`'s registry plus a bounded navigation log that records
|
|
5
|
+
// only while started (the panel's mount is the opt-in — Devtools §2).
|
|
6
|
+
import { RouterRegistry, navigate as routerNavigate } from "@reactra/router";
|
|
7
|
+
/** Current route snapshot — id/pattern/params/coerced query live here. */
|
|
8
|
+
export const currentRoute = () => RouterRegistry.getSnapshot();
|
|
9
|
+
/**
|
|
10
|
+
* Re-drive the route to a path string — used by Time Travel to replay
|
|
11
|
+
* navigation on scrub. Consumes the router's public `navigate` (Router spec);
|
|
12
|
+
* the panel never redefines routing.
|
|
13
|
+
*/
|
|
14
|
+
export const navigate = (to) => routerNavigate(to);
|
|
15
|
+
/**
|
|
16
|
+
* A re-drivable route snapshot for the time-travel ring: the exact URL string
|
|
17
|
+
* (`pathname + search`, so `navigate()` reconstructs it) plus the coerced
|
|
18
|
+
* params/query for the card display. `location` is read only inside this
|
|
19
|
+
* function (browser-only — UI-companion tier rule), falling back to the
|
|
20
|
+
* registry pathname under SSR/Node.
|
|
21
|
+
*/
|
|
22
|
+
export const routeSnapshot = () => {
|
|
23
|
+
const s = RouterRegistry.getSnapshot();
|
|
24
|
+
const path = typeof location !== "undefined" ? location.pathname + location.search : s.pathname;
|
|
25
|
+
return { path, pathname: s.pathname, params: s.params, query: s.query };
|
|
26
|
+
};
|
|
27
|
+
/** The registered manifest (all routes). */
|
|
28
|
+
export const listRoutes = () => RouterRegistry.getRoutes();
|
|
29
|
+
/** Subscribe to route transitions (panel re-render). */
|
|
30
|
+
export const subscribeRouter = (onChange) => RouterRegistry.subscribe(onChange);
|
|
31
|
+
/** A bounded recent-navigations log (default 50 entries, newest first). */
|
|
32
|
+
export const createNavLog = (limit = 50, now = Date.now) => {
|
|
33
|
+
const entries = [];
|
|
34
|
+
return {
|
|
35
|
+
start: (shouldRecord) => RouterRegistry.subscribe(() => {
|
|
36
|
+
if (shouldRecord && !shouldRecord())
|
|
37
|
+
return;
|
|
38
|
+
const s = RouterRegistry.getSnapshot();
|
|
39
|
+
entries.unshift({
|
|
40
|
+
timestamp: now(),
|
|
41
|
+
pathname: s.pathname,
|
|
42
|
+
params: s.params,
|
|
43
|
+
query: s.query,
|
|
44
|
+
});
|
|
45
|
+
if (entries.length > limit)
|
|
46
|
+
entries.length = limit;
|
|
47
|
+
}),
|
|
48
|
+
entries: () => entries,
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=routerWatcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routerWatcher.js","sourceRoot":"","sources":["../src/routerWatcher.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,EAAE;AACF,qEAAqE;AACrE,0EAA0E;AAC1E,sEAAsE;AAEtE,OAAO,EAAE,cAAc,EAAE,QAAQ,IAAI,cAAc,EAAmB,MAAM,iBAAiB,CAAA;AAU7F,0EAA0E;AAC1E,MAAM,CAAC,MAAM,YAAY,GAAG,GAAe,EAAE,CAAC,cAAc,CAAC,WAAW,EAAE,CAAA;AAE1E;;;;GAIG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,EAAU,EAAQ,EAAE,CAAC,cAAc,CAAC,EAAE,CAAC,CAAA;AAEhE;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,GAK3B,EAAE;IACF,MAAM,CAAC,GAAG,cAAc,CAAC,WAAW,EAAE,CAAA;IACtC,MAAM,IAAI,GACR,OAAO,QAAQ,KAAK,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAA;IACpF,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAA;AACzE,CAAC,CAAA;AAED,4CAA4C;AAC5C,MAAM,CAAC,MAAM,UAAU,GAAG,GAAgD,EAAE,CAC1E,cAAc,CAAC,SAAS,EAAE,CAAA;AAE5B,wDAAwD;AACxD,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,QAAoB,EAAgB,EAAE,CACpE,cAAc,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAA;AAcpC,2EAA2E;AAC3E,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,KAAK,GAAG,EAAE,EAAE,MAAoB,IAAI,CAAC,GAAG,EAAU,EAAE;IAC/E,MAAM,OAAO,GAAe,EAAE,CAAA;IAC9B,OAAO;QACL,KAAK,EAAE,CAAC,YAAY,EAAE,EAAE,CACtB,cAAc,CAAC,SAAS,CAAC,GAAG,EAAE;YAC5B,IAAI,YAAY,IAAI,CAAC,YAAY,EAAE;gBAAE,OAAM;YAC3C,MAAM,CAAC,GAAG,cAAc,CAAC,WAAW,EAAE,CAAA;YACtC,OAAO,CAAC,OAAO,CAAC;gBACd,SAAS,EAAE,GAAG,EAAE;gBAChB,QAAQ,EAAE,CAAC,CAAC,QAAQ;gBACpB,MAAM,EAAE,CAAC,CAAC,MAAM;gBAChB,KAAK,EAAE,CAAC,CAAC,KAAK;aACf,CAAC,CAAA;YACF,IAAI,OAAO,CAAC,MAAM,GAAG,KAAK;gBAAE,OAAO,CAAC,MAAM,GAAG,KAAK,CAAA;QACpD,CAAC,CAAC;QACJ,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO;KACvB,CAAA;AACH,CAAC,CAAA"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/** Sentinel for values that can't be serialized cleanly. */
|
|
2
|
+
export declare const SENTINEL = "[unserializable]";
|
|
3
|
+
/**
|
|
4
|
+
* Resource-status projection shape (DVT-LIM-04 resolution).
|
|
5
|
+
* Emitted instead of `SENTINEL` when the value looks like a resource handle.
|
|
6
|
+
*/
|
|
7
|
+
export interface ResourceStatusProjection {
|
|
8
|
+
status: "pending" | "resolved" | "error";
|
|
9
|
+
value?: unknown;
|
|
10
|
+
}
|
|
11
|
+
/** Serializer caps — both have tested defaults. */
|
|
12
|
+
export interface SerializeCaps {
|
|
13
|
+
/** Max object/array nesting depth before summarizing (default 5). */
|
|
14
|
+
maxDepth?: number;
|
|
15
|
+
/** Max keys per object / items per array before truncating (default 50). */
|
|
16
|
+
maxKeys?: number;
|
|
17
|
+
}
|
|
18
|
+
/** A serialized value — plain data, no functions, cycles replaced. */
|
|
19
|
+
export type Serialized = null | boolean | number | string | readonly Serialized[] | {
|
|
20
|
+
readonly [k: string]: Serialized;
|
|
21
|
+
} | ResourceStatusProjection;
|
|
22
|
+
/**
|
|
23
|
+
* Serialize a single value to a depth/size-capped representation.
|
|
24
|
+
* Functions are dropped from objects; cyclic references become `SENTINEL`.
|
|
25
|
+
*
|
|
26
|
+
* @param value - The value to serialize.
|
|
27
|
+
* @param caps - Optional depth/size caps (defaults: depth=5, keys=50).
|
|
28
|
+
* @returns A plain JSON-compatible representation, or `SENTINEL`/summary.
|
|
29
|
+
*/
|
|
30
|
+
export declare const serialize: (value: unknown, caps?: SerializeCaps) => Serialized;
|
|
31
|
+
/**
|
|
32
|
+
* Serialize a bindings object for display: functions are dropped, values
|
|
33
|
+
* are depth/size-capped, unserializable values become `SENTINEL`.
|
|
34
|
+
* Mirrors the old `dataBindings` contract but with proper caps and resource
|
|
35
|
+
* projection (DVT-LIM-04 resolution). Exposed for use by helpers.ts.
|
|
36
|
+
*/
|
|
37
|
+
export declare const serializeBindings: (bindings: Record<string, unknown>, caps?: SerializeCaps) => Record<string, Serialized>;
|
|
38
|
+
//# sourceMappingURL=serialize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serialize.d.ts","sourceRoot":"","sources":["../src/serialize.ts"],"names":[],"mappings":"AAiBA,4DAA4D;AAC5D,eAAO,MAAM,QAAQ,qBAAqB,CAAA;AAE1C;;;GAGG;AACH,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,OAAO,CAAA;IACxC,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,mDAAmD;AACnD,MAAM,WAAW,aAAa;IAC5B,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,sEAAsE;AACtE,MAAM,MAAM,UAAU,GAClB,IAAI,GACJ,OAAO,GACP,MAAM,GACN,MAAM,GACN,SAAS,UAAU,EAAE,GACrB;IAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,GAAG,UAAU,CAAA;CAAE,GACpC,wBAAwB,CAAA;AAgC5B;;;;;;;GAOG;AACH,eAAO,MAAM,SAAS,GAAI,OAAO,OAAO,EAAE,OAAO,aAAa,KAAG,UAqIhE,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAC5B,UAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,OAAO,aAAa,KACnB,MAAM,CAAC,MAAM,EAAE,UAAU,CAS3B,CAAA"}
|