@chuvenger/devdock 0.1.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.
@@ -0,0 +1,481 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+ var reactRouterDom = require('react-router-dom');
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+
7
+ // src/react/react-router.tsx
8
+
9
+ // src/core/hotkey.ts
10
+ function matchHotkey(spec, e) {
11
+ const parts = spec.toLowerCase().split("+").map((p) => p.trim()).filter(Boolean);
12
+ if (parts.length === 0) return false;
13
+ const key = parts[parts.length - 1];
14
+ const mods = new Set(parts.slice(0, -1));
15
+ const isMac = typeof navigator !== "undefined" && /mac/i.test(navigator.platform);
16
+ const wantMeta = mods.has("meta") || mods.has("cmd") || mods.has("mod") && isMac;
17
+ const wantCtrl = mods.has("ctrl") || mods.has("control") || mods.has("mod") && !isMac;
18
+ const wantShift = mods.has("shift");
19
+ const wantAlt = mods.has("alt") || mods.has("option");
20
+ if (e.metaKey !== wantMeta) return false;
21
+ if (e.ctrlKey !== wantCtrl) return false;
22
+ if (e.shiftKey !== wantShift) return false;
23
+ if (e.altKey !== wantAlt) return false;
24
+ return e.key.toLowerCase() === key;
25
+ }
26
+
27
+ // src/core/dock.ts
28
+ var isDev = () => {
29
+ try {
30
+ return process.env.NODE_ENV !== "production";
31
+ } catch {
32
+ return false;
33
+ }
34
+ };
35
+ function el(tag, styles, props) {
36
+ const node = document.createElement(tag);
37
+ if (styles) Object.assign(node.style, styles);
38
+ if (props) Object.assign(node, props);
39
+ return node;
40
+ }
41
+ function cornerStyle(position) {
42
+ const gap = "16px";
43
+ switch (position) {
44
+ case "bottom-right":
45
+ return { bottom: gap, right: gap };
46
+ case "top-left":
47
+ return { top: gap, left: gap };
48
+ case "top-right":
49
+ return { top: gap, right: gap };
50
+ default:
51
+ return { bottom: gap, left: gap };
52
+ }
53
+ }
54
+ function panelAnchor(position) {
55
+ const isTop = position.startsWith("top");
56
+ const isRight = position.endsWith("right");
57
+ return {
58
+ position: "absolute",
59
+ [isTop ? "top" : "bottom"]: "calc(100% + 8px)",
60
+ [isRight ? "right" : "left"]: "0"
61
+ };
62
+ }
63
+ var FONT = "ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif";
64
+ function createDevDock(initial = {}) {
65
+ if (typeof document === "undefined") {
66
+ return { update() {
67
+ }, destroy() {
68
+ } };
69
+ }
70
+ let opts = { ...initial };
71
+ let open = false;
72
+ let query = "";
73
+ let active = 0;
74
+ let mounted = false;
75
+ const host = el("div");
76
+ host.setAttribute("data-devdock", "");
77
+ const useShadow = (initial.shadow ?? true) && typeof host.attachShadow === "function";
78
+ const shadowRoot = useShadow ? host.attachShadow({ mode: "open" }) : null;
79
+ const mountPoint = shadowRoot ?? host;
80
+ const root = el("div", { fontFamily: FONT });
81
+ mountPoint.appendChild(root);
82
+ const panel = el("div", {
83
+ width: "280px",
84
+ maxHeight: "min(70vh, 480px)",
85
+ display: "flex",
86
+ flexDirection: "column",
87
+ background: "#16181d",
88
+ color: "#e7e9ee",
89
+ border: "1px solid #2a2e37",
90
+ borderRadius: "12px",
91
+ boxShadow: "0 12px 40px rgba(0,0,0,0.45)",
92
+ overflow: "hidden"
93
+ });
94
+ panel.setAttribute("role", "dialog");
95
+ const heading = el("div", {
96
+ padding: "10px 12px",
97
+ borderBottom: "1px solid #2a2e37",
98
+ fontSize: "12px",
99
+ fontWeight: "600",
100
+ letterSpacing: "0.4px",
101
+ textTransform: "uppercase",
102
+ color: "#8b909c"
103
+ });
104
+ const inputWrap = el("div", { padding: "8px" });
105
+ const input = el("input", {
106
+ width: "100%",
107
+ boxSizing: "border-box",
108
+ padding: "8px 10px",
109
+ fontSize: "13px",
110
+ color: "#e7e9ee",
111
+ background: "#0f1115",
112
+ border: "1px solid #2a2e37",
113
+ borderRadius: "8px",
114
+ outline: "none"
115
+ });
116
+ input.placeholder = "Filter\u2026";
117
+ inputWrap.appendChild(input);
118
+ const list = el("div", { overflowY: "auto", padding: "0 6px 8px" });
119
+ panel.append(heading, inputWrap, list);
120
+ const button = el("button", {
121
+ display: "inline-flex",
122
+ alignItems: "center",
123
+ gap: "6px",
124
+ padding: "8px 12px",
125
+ fontSize: "12px",
126
+ fontWeight: "700",
127
+ letterSpacing: "0.6px",
128
+ color: "#fff",
129
+ background: "#111317",
130
+ border: "1px solid #2a2e37",
131
+ borderRadius: "999px",
132
+ boxShadow: "0 4px 14px rgba(0,0,0,0.35)",
133
+ cursor: "pointer"
134
+ });
135
+ button.type = "button";
136
+ button.setAttribute("aria-label", "Toggle dev menu");
137
+ const dot = el("span", {
138
+ width: "8px",
139
+ height: "8px",
140
+ borderRadius: "999px",
141
+ background: "#22c55e",
142
+ display: "inline-block"
143
+ });
144
+ const buttonLabel = el("span");
145
+ button.append(dot, buttonLabel);
146
+ root.appendChild(button);
147
+ const enabled = () => {
148
+ const e = opts.enabled;
149
+ if (typeof e === "function") return e();
150
+ return e ?? isDev();
151
+ };
152
+ const navigate = (path) => {
153
+ if (opts.onNavigate) opts.onNavigate(path);
154
+ else if (typeof window !== "undefined") window.location.assign(path);
155
+ };
156
+ const buildItems = () => {
157
+ const out = [];
158
+ (opts.routes ?? []).forEach((r, i) => {
159
+ out.push({
160
+ kind: "route",
161
+ key: `route:${r.path}:${i}`,
162
+ label: r.label ?? r.path,
163
+ group: r.group ?? "Routes",
164
+ route: r
165
+ });
166
+ });
167
+ (opts.commands ?? []).forEach((c, i) => {
168
+ out.push({
169
+ kind: "command",
170
+ key: `cmd:${c.id ?? c.label}:${i}`,
171
+ label: c.label,
172
+ group: c.group ?? "Commands",
173
+ command: c
174
+ });
175
+ });
176
+ return out;
177
+ };
178
+ const getFiltered = () => {
179
+ const q = query.trim().toLowerCase();
180
+ const items = buildItems();
181
+ if (!q) return items;
182
+ return items.filter(
183
+ (it) => it.label.toLowerCase().includes(q) || it.kind === "route" && it.route.path.toLowerCase().includes(q)
184
+ );
185
+ };
186
+ const runItem = async (it) => {
187
+ if (it.kind === "route") {
188
+ navigate(it.route.path);
189
+ setOpen(false);
190
+ return;
191
+ }
192
+ try {
193
+ await it.command.run();
194
+ } finally {
195
+ if (!it.command.keepOpen) setOpen(false);
196
+ }
197
+ };
198
+ const renderList = () => {
199
+ const filtered = getFiltered();
200
+ active = Math.min(active, Math.max(0, filtered.length - 1));
201
+ list.replaceChildren();
202
+ if (filtered.length === 0) {
203
+ list.appendChild(
204
+ el(
205
+ "div",
206
+ { padding: "12px", fontSize: "13px", color: "#6b7280" },
207
+ { textContent: "Nothing here." }
208
+ )
209
+ );
210
+ return;
211
+ }
212
+ const groups = /* @__PURE__ */ new Map();
213
+ for (const it of filtered) {
214
+ const arr = groups.get(it.group) ?? [];
215
+ arr.push(it);
216
+ groups.set(it.group, arr);
217
+ }
218
+ for (const [groupName, groupItems] of groups) {
219
+ const section = el("div", { marginTop: "6px" });
220
+ section.appendChild(
221
+ el(
222
+ "div",
223
+ {
224
+ padding: "6px 8px 2px",
225
+ fontSize: "10px",
226
+ fontWeight: "700",
227
+ letterSpacing: "0.6px",
228
+ textTransform: "uppercase",
229
+ color: "#6b7280"
230
+ },
231
+ { textContent: groupName }
232
+ )
233
+ );
234
+ for (const it of groupItems) {
235
+ const idx = filtered.indexOf(it);
236
+ const isActive = idx === active;
237
+ const row = el("button", {
238
+ display: "flex",
239
+ alignItems: "center",
240
+ justifyContent: "space-between",
241
+ gap: "8px",
242
+ width: "100%",
243
+ textAlign: "left",
244
+ padding: "8px 10px",
245
+ fontSize: "13px",
246
+ color: "#e7e9ee",
247
+ background: isActive ? "#2563eb" : "transparent",
248
+ border: "none",
249
+ borderRadius: "8px",
250
+ cursor: "pointer"
251
+ });
252
+ row.type = "button";
253
+ const labelSpan = el(
254
+ "span",
255
+ {
256
+ overflow: "hidden",
257
+ textOverflow: "ellipsis",
258
+ whiteSpace: "nowrap"
259
+ },
260
+ { textContent: it.label }
261
+ );
262
+ row.appendChild(labelSpan);
263
+ if (it.kind === "route" && it.route.path !== it.label) {
264
+ row.appendChild(
265
+ el(
266
+ "span",
267
+ {
268
+ fontSize: "11px",
269
+ color: isActive ? "#cfe0ff" : "#6b7280",
270
+ fontFamily: "ui-monospace, SFMono-Regular, monospace",
271
+ flexShrink: "0"
272
+ },
273
+ { textContent: it.route.path }
274
+ )
275
+ );
276
+ }
277
+ row.addEventListener("mouseenter", () => {
278
+ active = idx;
279
+ renderList();
280
+ });
281
+ row.addEventListener("click", () => void runItem(it));
282
+ section.appendChild(row);
283
+ }
284
+ list.appendChild(section);
285
+ }
286
+ };
287
+ const renderShell = () => {
288
+ const position = opts.position ?? "bottom-left";
289
+ const zIndex = opts.zIndex ?? 2147483e3;
290
+ Object.assign(root.style, {
291
+ position: "fixed",
292
+ zIndex: String(zIndex),
293
+ top: "",
294
+ bottom: "",
295
+ left: "",
296
+ right: ""
297
+ });
298
+ Object.assign(root.style, cornerStyle(position));
299
+ heading.textContent = opts.title ?? "Dev Menu";
300
+ panel.setAttribute("aria-label", opts.title ?? "Dev Menu");
301
+ Object.assign(panel.style, panelAnchor(position));
302
+ buttonLabel.textContent = opts.label ?? "DEV";
303
+ button.style.background = open ? "#2563eb" : "#111317";
304
+ button.setAttribute("aria-expanded", String(open));
305
+ };
306
+ function setOpen(next) {
307
+ if (open === next) return;
308
+ open = next;
309
+ if (open) {
310
+ query = "";
311
+ input.value = "";
312
+ active = 0;
313
+ panel.isConnected || root.insertBefore(panel, button);
314
+ renderShell();
315
+ renderList();
316
+ requestAnimationFrame(() => input.focus());
317
+ } else if (panel.isConnected) {
318
+ panel.remove();
319
+ }
320
+ renderShell();
321
+ }
322
+ input.addEventListener("input", () => {
323
+ query = input.value;
324
+ active = 0;
325
+ renderList();
326
+ });
327
+ panel.addEventListener("keydown", (e) => {
328
+ const filtered = getFiltered();
329
+ if (e.key === "Escape") {
330
+ e.preventDefault();
331
+ setOpen(false);
332
+ } else if (e.key === "ArrowDown") {
333
+ e.preventDefault();
334
+ active = Math.min(active + 1, filtered.length - 1);
335
+ renderList();
336
+ } else if (e.key === "ArrowUp") {
337
+ e.preventDefault();
338
+ active = Math.max(active - 1, 0);
339
+ renderList();
340
+ } else if (e.key === "Enter") {
341
+ e.preventDefault();
342
+ const it = filtered[active];
343
+ if (it) void runItem(it);
344
+ }
345
+ });
346
+ button.addEventListener("click", () => setOpen(!open));
347
+ const onDocMouseDown = (e) => {
348
+ if (open && !e.composedPath().includes(root)) setOpen(false);
349
+ };
350
+ const onKeyDown = (e) => {
351
+ if (opts.hotkey && matchHotkey(opts.hotkey, e)) {
352
+ e.preventDefault();
353
+ setOpen(!open);
354
+ }
355
+ };
356
+ const addListeners = () => {
357
+ document.addEventListener("mousedown", onDocMouseDown);
358
+ window.addEventListener("keydown", onKeyDown);
359
+ };
360
+ const removeListeners = () => {
361
+ document.removeEventListener("mousedown", onDocMouseDown);
362
+ window.removeEventListener("keydown", onKeyDown);
363
+ };
364
+ const mount = () => {
365
+ if (mounted) return;
366
+ (opts.container ?? document.body).appendChild(host);
367
+ addListeners();
368
+ mounted = true;
369
+ };
370
+ const unmount = () => {
371
+ if (!mounted) return;
372
+ removeListeners();
373
+ host.remove();
374
+ mounted = false;
375
+ };
376
+ renderShell();
377
+ if (enabled()) mount();
378
+ return {
379
+ update(next) {
380
+ opts = { ...opts, ...next };
381
+ if (enabled()) {
382
+ mount();
383
+ renderShell();
384
+ if (open) renderList();
385
+ } else {
386
+ setOpen(false);
387
+ unmount();
388
+ }
389
+ },
390
+ destroy() {
391
+ setOpen(false);
392
+ unmount();
393
+ }
394
+ };
395
+ }
396
+
397
+ // src/react/DevDock.tsx
398
+ function DevDock(props) {
399
+ const instance = react.useRef(null);
400
+ const latest = react.useRef(props);
401
+ latest.current = props;
402
+ react.useEffect(() => {
403
+ const inst = createDevDock(latest.current);
404
+ instance.current = inst;
405
+ return () => {
406
+ inst.destroy();
407
+ instance.current = null;
408
+ };
409
+ }, []);
410
+ react.useEffect(() => {
411
+ instance.current?.update(props);
412
+ });
413
+ return null;
414
+ }
415
+ function globToRegExp(glob) {
416
+ const escaped = glob.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
417
+ return new RegExp(`^${escaped}$`);
418
+ }
419
+ function toPredicate(match) {
420
+ if (typeof match === "function") return match;
421
+ const re = match instanceof RegExp ? match : globToRegExp(match);
422
+ return (route) => re.test(route.path);
423
+ }
424
+ function joinPath(parent, child) {
425
+ if (child.startsWith("/")) return child;
426
+ if (!child) return parent || "/";
427
+ const base = parent.endsWith("/") ? parent.slice(0, -1) : parent;
428
+ return `${base}/${child}`;
429
+ }
430
+ function flattenRoutes(routes, parent = "") {
431
+ const out = [];
432
+ for (const r of routes) {
433
+ const full = r.index ? parent : joinPath(parent, r.path ?? "");
434
+ const navigable = !r.index && r.path != null && !full.includes(":") && !full.includes("*") && r.handle?.hidden !== true;
435
+ if (navigable) {
436
+ out.push({
437
+ path: full || "/",
438
+ label: r.handle?.devLabel ?? (full || "/"),
439
+ group: r.handle?.devGroup
440
+ });
441
+ }
442
+ if (r.children?.length) out.push(...flattenRoutes(r.children, full));
443
+ }
444
+ return out;
445
+ }
446
+ function useDetectedRoutes(match) {
447
+ const ctx = react.useContext(reactRouterDom.UNSAFE_DataRouterContext);
448
+ const routes = ctx?.router?.routes ?? [];
449
+ return react.useMemo(() => {
450
+ const seen = /* @__PURE__ */ new Set();
451
+ const deduped = flattenRoutes(routes).filter(
452
+ (r) => seen.has(r.path) ? false : (seen.add(r.path), true)
453
+ );
454
+ return match ? deduped.filter(toPredicate(match)) : deduped;
455
+ }, [routes, match]);
456
+ }
457
+ function ReactRouterDevDock({
458
+ match,
459
+ ...props
460
+ }) {
461
+ const navigate = reactRouterDom.useNavigate();
462
+ const detected = useDetectedRoutes(match);
463
+ const routes = react.useMemo(
464
+ () => [...detected, ...props.routes ?? []],
465
+ [detected, props.routes]
466
+ );
467
+ return /* @__PURE__ */ jsxRuntime.jsx(
468
+ DevDock,
469
+ {
470
+ ...props,
471
+ routes,
472
+ onNavigate: props.onNavigate ?? ((path) => navigate(path))
473
+ }
474
+ );
475
+ }
476
+
477
+ exports.ReactRouterDevDock = ReactRouterDevDock;
478
+ exports.flattenRoutes = flattenRoutes;
479
+ exports.useDetectedRoutes = useDetectedRoutes;
480
+ //# sourceMappingURL=react-router.cjs.map
481
+ //# sourceMappingURL=react-router.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/hotkey.ts","../src/core/dock.ts","../src/react/DevDock.tsx","../src/react/react-router.tsx"],"names":["useRef","useEffect","useContext","DataRouterContext","useMemo","useNavigate","jsx"],"mappings":"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","file":"react-router.cjs","sourcesContent":["/** Parse a hotkey string like \"mod+.\" into a matcher predicate. */\nexport function matchHotkey(spec: string, e: KeyboardEvent): boolean {\n const parts = spec\n .toLowerCase()\n .split(\"+\")\n .map((p) => p.trim())\n .filter(Boolean);\n if (parts.length === 0) return false;\n\n const key = parts[parts.length - 1];\n const mods = new Set(parts.slice(0, -1));\n\n const isMac =\n typeof navigator !== \"undefined\" && /mac/i.test(navigator.platform);\n\n const wantMeta = mods.has(\"meta\") || mods.has(\"cmd\") || (mods.has(\"mod\") && isMac);\n const wantCtrl = mods.has(\"ctrl\") || mods.has(\"control\") || (mods.has(\"mod\") && !isMac);\n const wantShift = mods.has(\"shift\");\n const wantAlt = mods.has(\"alt\") || mods.has(\"option\");\n\n if (e.metaKey !== wantMeta) return false;\n if (e.ctrlKey !== wantCtrl) return false;\n if (e.shiftKey !== wantShift) return false;\n if (e.altKey !== wantAlt) return false;\n\n return e.key.toLowerCase() === key;\n}\n","import { matchHotkey } from \"./hotkey\";\nimport type {\n DevCommand,\n DevDockInstance,\n DevDockOptions,\n DevRoute,\n DockPosition,\n} from \"./types\";\n\nconst isDev = (): boolean => {\n // Bundlers (Vite, webpack, Next, esbuild…) statically replace the full\n // `process.env.NODE_ENV` token, even in browser builds where `process`\n // itself is undefined. Reading it directly lets that replacement work;\n // the try/catch covers runtimes where it's left as a real (missing) global.\n try {\n return process.env.NODE_ENV !== \"production\";\n } catch {\n return false;\n }\n};\n\ntype Item =\n | { kind: \"route\"; key: string; label: string; group: string; route: DevRoute }\n | {\n kind: \"command\";\n key: string;\n label: string;\n group: string;\n command: DevCommand;\n };\n\ntype Styles = Partial<CSSStyleDeclaration>;\n\nfunction el<K extends keyof HTMLElementTagNameMap>(\n tag: K,\n styles?: Styles,\n props?: Partial<HTMLElementTagNameMap[K]>,\n): HTMLElementTagNameMap[K] {\n const node = document.createElement(tag);\n if (styles) Object.assign(node.style, styles);\n if (props) Object.assign(node, props);\n return node;\n}\n\nfunction cornerStyle(position: DockPosition): Styles {\n const gap = \"16px\";\n switch (position) {\n case \"bottom-right\":\n return { bottom: gap, right: gap };\n case \"top-left\":\n return { top: gap, left: gap };\n case \"top-right\":\n return { top: gap, right: gap };\n default:\n return { bottom: gap, left: gap };\n }\n}\n\nfunction panelAnchor(position: DockPosition): Styles {\n const isTop = position.startsWith(\"top\");\n const isRight = position.endsWith(\"right\");\n return {\n position: \"absolute\",\n [isTop ? \"top\" : \"bottom\"]: \"calc(100% + 8px)\",\n [isRight ? \"right\" : \"left\"]: \"0\",\n } as Styles;\n}\n\nconst FONT =\n \"ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif\";\n\n/**\n * Create a framework-agnostic dev dock: a floating button that opens a popup\n * to jump between routes and run commands. Returns a handle to update its\n * options or tear it down. No-ops on the server (when there is no `document`).\n */\nexport function createDevDock(initial: DevDockOptions = {}): DevDockInstance {\n if (typeof document === \"undefined\") {\n return { update() {}, destroy() {} };\n }\n\n let opts: DevDockOptions = { ...initial };\n let open = false;\n let query = \"\";\n let active = 0;\n let mounted = false;\n\n // Light-DOM host that gets appended to the page. When shadow DOM is used,\n // the actual UI lives inside its shadow root — fully isolated from the host\n // page's CSS. `data-devdock` stays on the host so it's discoverable.\n const host = el(\"div\");\n host.setAttribute(\"data-devdock\", \"\");\n const useShadow =\n (initial.shadow ?? true) && typeof host.attachShadow === \"function\";\n const shadowRoot = useShadow ? host.attachShadow({ mode: \"open\" }) : null;\n const mountPoint: Node = shadowRoot ?? host;\n\n const root = el(\"div\", { fontFamily: FONT });\n mountPoint.appendChild(root);\n\n const panel = el(\"div\", {\n width: \"280px\",\n maxHeight: \"min(70vh, 480px)\",\n display: \"flex\",\n flexDirection: \"column\",\n background: \"#16181d\",\n color: \"#e7e9ee\",\n border: \"1px solid #2a2e37\",\n borderRadius: \"12px\",\n boxShadow: \"0 12px 40px rgba(0,0,0,0.45)\",\n overflow: \"hidden\",\n });\n panel.setAttribute(\"role\", \"dialog\");\n\n const heading = el(\"div\", {\n padding: \"10px 12px\",\n borderBottom: \"1px solid #2a2e37\",\n fontSize: \"12px\",\n fontWeight: \"600\",\n letterSpacing: \"0.4px\",\n textTransform: \"uppercase\",\n color: \"#8b909c\",\n });\n\n const inputWrap = el(\"div\", { padding: \"8px\" });\n const input = el(\"input\", {\n width: \"100%\",\n boxSizing: \"border-box\",\n padding: \"8px 10px\",\n fontSize: \"13px\",\n color: \"#e7e9ee\",\n background: \"#0f1115\",\n border: \"1px solid #2a2e37\",\n borderRadius: \"8px\",\n outline: \"none\",\n });\n input.placeholder = \"Filter…\";\n inputWrap.appendChild(input);\n\n const list = el(\"div\", { overflowY: \"auto\", padding: \"0 6px 8px\" });\n\n panel.append(heading, inputWrap, list);\n\n const button = el(\"button\", {\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: \"6px\",\n padding: \"8px 12px\",\n fontSize: \"12px\",\n fontWeight: \"700\",\n letterSpacing: \"0.6px\",\n color: \"#fff\",\n background: \"#111317\",\n border: \"1px solid #2a2e37\",\n borderRadius: \"999px\",\n boxShadow: \"0 4px 14px rgba(0,0,0,0.35)\",\n cursor: \"pointer\",\n });\n button.type = \"button\";\n button.setAttribute(\"aria-label\", \"Toggle dev menu\");\n const dot = el(\"span\", {\n width: \"8px\",\n height: \"8px\",\n borderRadius: \"999px\",\n background: \"#22c55e\",\n display: \"inline-block\",\n });\n const buttonLabel = el(\"span\");\n button.append(dot, buttonLabel);\n\n root.appendChild(button);\n\n // ---- behavior ---------------------------------------------------------\n\n const enabled = (): boolean => {\n const e = opts.enabled;\n if (typeof e === \"function\") return e();\n return e ?? isDev();\n };\n\n const navigate = (path: string) => {\n if (opts.onNavigate) opts.onNavigate(path);\n else if (typeof window !== \"undefined\") window.location.assign(path);\n };\n\n const buildItems = (): Item[] => {\n const out: Item[] = [];\n (opts.routes ?? []).forEach((r, i) => {\n out.push({\n kind: \"route\",\n key: `route:${r.path}:${i}`,\n label: r.label ?? r.path,\n group: r.group ?? \"Routes\",\n route: r,\n });\n });\n (opts.commands ?? []).forEach((c, i) => {\n out.push({\n kind: \"command\",\n key: `cmd:${c.id ?? c.label}:${i}`,\n label: c.label,\n group: c.group ?? \"Commands\",\n command: c,\n });\n });\n return out;\n };\n\n const getFiltered = (): Item[] => {\n const q = query.trim().toLowerCase();\n const items = buildItems();\n if (!q) return items;\n return items.filter(\n (it) =>\n it.label.toLowerCase().includes(q) ||\n (it.kind === \"route\" && it.route.path.toLowerCase().includes(q)),\n );\n };\n\n const runItem = async (it: Item) => {\n if (it.kind === \"route\") {\n navigate(it.route.path);\n setOpen(false);\n return;\n }\n try {\n await it.command.run();\n } finally {\n if (!it.command.keepOpen) setOpen(false);\n }\n };\n\n const renderList = () => {\n const filtered = getFiltered();\n active = Math.min(active, Math.max(0, filtered.length - 1));\n list.replaceChildren();\n\n if (filtered.length === 0) {\n list.appendChild(\n el(\n \"div\",\n { padding: \"12px\", fontSize: \"13px\", color: \"#6b7280\" },\n { textContent: \"Nothing here.\" },\n ),\n );\n return;\n }\n\n const groups = new Map<string, Item[]>();\n for (const it of filtered) {\n const arr = groups.get(it.group) ?? [];\n arr.push(it);\n groups.set(it.group, arr);\n }\n\n for (const [groupName, groupItems] of groups) {\n const section = el(\"div\", { marginTop: \"6px\" });\n section.appendChild(\n el(\n \"div\",\n {\n padding: \"6px 8px 2px\",\n fontSize: \"10px\",\n fontWeight: \"700\",\n letterSpacing: \"0.6px\",\n textTransform: \"uppercase\",\n color: \"#6b7280\",\n },\n { textContent: groupName },\n ),\n );\n\n for (const it of groupItems) {\n const idx = filtered.indexOf(it);\n const isActive = idx === active;\n const row = el(\"button\", {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n gap: \"8px\",\n width: \"100%\",\n textAlign: \"left\",\n padding: \"8px 10px\",\n fontSize: \"13px\",\n color: \"#e7e9ee\",\n background: isActive ? \"#2563eb\" : \"transparent\",\n border: \"none\",\n borderRadius: \"8px\",\n cursor: \"pointer\",\n });\n row.type = \"button\";\n\n const labelSpan = el(\n \"span\",\n {\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n },\n { textContent: it.label },\n );\n row.appendChild(labelSpan);\n\n if (it.kind === \"route\" && it.route.path !== it.label) {\n row.appendChild(\n el(\n \"span\",\n {\n fontSize: \"11px\",\n color: isActive ? \"#cfe0ff\" : \"#6b7280\",\n fontFamily: \"ui-monospace, SFMono-Regular, monospace\",\n flexShrink: \"0\",\n },\n { textContent: it.route.path },\n ),\n );\n }\n\n row.addEventListener(\"mouseenter\", () => {\n active = idx;\n renderList();\n });\n row.addEventListener(\"click\", () => void runItem(it));\n section.appendChild(row);\n }\n list.appendChild(section);\n }\n };\n\n const renderShell = () => {\n const position = opts.position ?? \"bottom-left\";\n const zIndex = opts.zIndex ?? 2147483000;\n\n Object.assign(root.style, {\n position: \"fixed\",\n zIndex: String(zIndex),\n top: \"\",\n bottom: \"\",\n left: \"\",\n right: \"\",\n });\n Object.assign(root.style, cornerStyle(position));\n\n heading.textContent = opts.title ?? \"Dev Menu\";\n panel.setAttribute(\"aria-label\", opts.title ?? \"Dev Menu\");\n Object.assign(panel.style, panelAnchor(position));\n\n buttonLabel.textContent = opts.label ?? \"DEV\";\n button.style.background = open ? \"#2563eb\" : \"#111317\";\n button.setAttribute(\"aria-expanded\", String(open));\n };\n\n function setOpen(next: boolean) {\n if (open === next) return;\n open = next;\n if (open) {\n query = \"\";\n input.value = \"\";\n active = 0;\n panel.isConnected || root.insertBefore(panel, button);\n renderShell();\n renderList();\n requestAnimationFrame(() => input.focus());\n } else if (panel.isConnected) {\n panel.remove();\n }\n renderShell();\n }\n\n // ---- listeners --------------------------------------------------------\n\n input.addEventListener(\"input\", () => {\n query = input.value;\n active = 0;\n renderList();\n });\n\n panel.addEventListener(\"keydown\", (e) => {\n const filtered = getFiltered();\n if (e.key === \"Escape\") {\n e.preventDefault();\n setOpen(false);\n } else if (e.key === \"ArrowDown\") {\n e.preventDefault();\n active = Math.min(active + 1, filtered.length - 1);\n renderList();\n } else if (e.key === \"ArrowUp\") {\n e.preventDefault();\n active = Math.max(active - 1, 0);\n renderList();\n } else if (e.key === \"Enter\") {\n e.preventDefault();\n const it = filtered[active];\n if (it) void runItem(it);\n }\n });\n\n button.addEventListener(\"click\", () => setOpen(!open));\n\n const onDocMouseDown = (e: MouseEvent) => {\n // composedPath() sees through the shadow boundary; a plain\n // `contains(e.target)` would miss clicks inside the shadow root.\n if (open && !e.composedPath().includes(root)) setOpen(false);\n };\n\n const onKeyDown = (e: KeyboardEvent) => {\n if (opts.hotkey && matchHotkey(opts.hotkey, e)) {\n e.preventDefault();\n setOpen(!open);\n }\n };\n\n const addListeners = () => {\n document.addEventListener(\"mousedown\", onDocMouseDown);\n window.addEventListener(\"keydown\", onKeyDown);\n };\n const removeListeners = () => {\n document.removeEventListener(\"mousedown\", onDocMouseDown);\n window.removeEventListener(\"keydown\", onKeyDown);\n };\n\n const mount = () => {\n if (mounted) return;\n (opts.container ?? document.body).appendChild(host);\n addListeners();\n mounted = true;\n };\n const unmount = () => {\n if (!mounted) return;\n removeListeners();\n host.remove();\n mounted = false;\n };\n\n // ---- init -------------------------------------------------------------\n\n renderShell();\n if (enabled()) mount();\n\n return {\n update(next: DevDockOptions) {\n opts = { ...opts, ...next };\n if (enabled()) {\n mount();\n renderShell();\n if (open) renderList();\n } else {\n setOpen(false);\n unmount();\n }\n },\n destroy() {\n setOpen(false);\n unmount();\n },\n };\n}\n","import { useEffect, useRef } from \"react\";\nimport { createDevDock } from \"../core/dock\";\nimport type { DevDockInstance, DevDockOptions } from \"../core/types\";\n\nexport type DevDockProps = DevDockOptions;\n\n/**\n * React wrapper around the framework-agnostic core. Renders nothing itself —\n * the dock mounts into `document.body` (or `container`) and is torn down on\n * unmount. Safe to leave mounted; it renders nothing in production.\n */\nexport function DevDock(props: DevDockProps) {\n const instance = useRef<DevDockInstance | null>(null);\n const latest = useRef(props);\n latest.current = props;\n\n useEffect(() => {\n const inst = createDevDock(latest.current);\n instance.current = inst;\n return () => {\n inst.destroy();\n instance.current = null;\n };\n }, []);\n\n useEffect(() => {\n instance.current?.update(props);\n });\n\n return null;\n}\n","import { useContext, useMemo } from \"react\";\nimport {\n useNavigate,\n // UNSAFE_DataRouterContext is the supported way to reach the active\n // router instance (and its full route tree) for data routers.\n UNSAFE_DataRouterContext as DataRouterContext,\n} from \"react-router-dom\";\nimport { DevDock, type DevDockProps } from \"./DevDock\";\nimport type { DevRoute } from \"../core/types\";\n\n/** Minimal shape of a react-router route object we care about. */\ninterface RRRoute {\n path?: string;\n index?: boolean;\n children?: RRRoute[];\n handle?: { devLabel?: string; devGroup?: string; hidden?: boolean } & Record<\n string,\n unknown\n >;\n}\n\n/**\n * Restricts which auto-detected routes appear. A string is treated as a glob\n * where `*` matches any characters (e.g. `\"/dev/*\"`, `\"/admin/*\"`); or pass a\n * `RegExp` tested against the path, or a predicate for full control.\n */\nexport type RouteMatcher = string | RegExp | ((route: DevRoute) => boolean);\n\nfunction globToRegExp(glob: string): RegExp {\n const escaped = glob.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\").replace(/\\*/g, \".*\");\n return new RegExp(`^${escaped}$`);\n}\n\nfunction toPredicate(match: RouteMatcher): (route: DevRoute) => boolean {\n if (typeof match === \"function\") return match;\n const re = match instanceof RegExp ? match : globToRegExp(match);\n return (route) => re.test(route.path);\n}\n\nfunction joinPath(parent: string, child: string): string {\n if (child.startsWith(\"/\")) return child;\n if (!child) return parent || \"/\";\n const base = parent.endsWith(\"/\") ? parent.slice(0, -1) : parent;\n return `${base}/${child}`;\n}\n\n/**\n * Flatten a react-router route tree into navigable {@link DevRoute}s.\n * Dynamic (`:param`) and splat (`*`) segments are skipped since they\n * can't be navigated to without arguments. Mark a route with\n * `handle.hidden` to exclude it, or `handle.devLabel` to rename it.\n */\nexport function flattenRoutes(routes: RRRoute[], parent = \"\"): DevRoute[] {\n const out: DevRoute[] = [];\n for (const r of routes) {\n const full = r.index ? parent : joinPath(parent, r.path ?? \"\");\n const navigable =\n !r.index &&\n r.path != null &&\n !full.includes(\":\") &&\n !full.includes(\"*\") &&\n r.handle?.hidden !== true;\n if (navigable) {\n out.push({\n path: full || \"/\",\n label: r.handle?.devLabel ?? (full || \"/\"),\n group: r.handle?.devGroup,\n });\n }\n if (r.children?.length) out.push(...flattenRoutes(r.children, full));\n }\n return out;\n}\n\n/**\n * Read every navigable route from the active react-router data router.\n * Pass `match` to scope the results (glob string, RegExp, or predicate).\n */\nexport function useDetectedRoutes(match?: RouteMatcher): DevRoute[] {\n const ctx = useContext(DataRouterContext);\n const routes = (ctx?.router?.routes ?? []) as RRRoute[];\n return useMemo(() => {\n const seen = new Set<string>();\n const deduped = flattenRoutes(routes).filter((r) =>\n seen.has(r.path) ? false : (seen.add(r.path), true),\n );\n return match ? deduped.filter(toPredicate(match)) : deduped;\n }, [routes, match]);\n}\n\nexport interface ReactRouterDevDockProps extends DevDockProps {\n /**\n * Only auto-detect routes that match. A glob string (`*` = any characters,\n * e.g. `\"/dev/*\"`), a `RegExp`, or a predicate. Manual `routes` are always\n * included regardless of this filter.\n */\n match?: RouteMatcher;\n}\n\n/**\n * Drop-in {@link DevDock} for react-router apps: navigates via the SPA\n * router and auto-detects routes from the active data router. Any\n * `routes` you pass are appended to the detected ones.\n */\nexport function ReactRouterDevDock({\n match,\n ...props\n}: ReactRouterDevDockProps) {\n const navigate = useNavigate();\n const detected = useDetectedRoutes(match);\n const routes = useMemo(\n () => [...detected, ...(props.routes ?? [])],\n [detected, props.routes],\n );\n return (\n <DevDock\n {...props}\n routes={routes}\n onNavigate={props.onNavigate ?? ((path) => navigate(path))}\n />\n );\n}\n"]}
@@ -0,0 +1,49 @@
1
+ import * as react from 'react';
2
+ import { DevDockProps } from './react.cjs';
3
+ import { c as DevRoute } from './types-DYQBDvfK.cjs';
4
+
5
+ /** Minimal shape of a react-router route object we care about. */
6
+ interface RRRoute {
7
+ path?: string;
8
+ index?: boolean;
9
+ children?: RRRoute[];
10
+ handle?: {
11
+ devLabel?: string;
12
+ devGroup?: string;
13
+ hidden?: boolean;
14
+ } & Record<string, unknown>;
15
+ }
16
+ /**
17
+ * Restricts which auto-detected routes appear. A string is treated as a glob
18
+ * where `*` matches any characters (e.g. `"/dev/*"`, `"/admin/*"`); or pass a
19
+ * `RegExp` tested against the path, or a predicate for full control.
20
+ */
21
+ type RouteMatcher = string | RegExp | ((route: DevRoute) => boolean);
22
+ /**
23
+ * Flatten a react-router route tree into navigable {@link DevRoute}s.
24
+ * Dynamic (`:param`) and splat (`*`) segments are skipped since they
25
+ * can't be navigated to without arguments. Mark a route with
26
+ * `handle.hidden` to exclude it, or `handle.devLabel` to rename it.
27
+ */
28
+ declare function flattenRoutes(routes: RRRoute[], parent?: string): DevRoute[];
29
+ /**
30
+ * Read every navigable route from the active react-router data router.
31
+ * Pass `match` to scope the results (glob string, RegExp, or predicate).
32
+ */
33
+ declare function useDetectedRoutes(match?: RouteMatcher): DevRoute[];
34
+ interface ReactRouterDevDockProps extends DevDockProps {
35
+ /**
36
+ * Only auto-detect routes that match. A glob string (`*` = any characters,
37
+ * e.g. `"/dev/*"`), a `RegExp`, or a predicate. Manual `routes` are always
38
+ * included regardless of this filter.
39
+ */
40
+ match?: RouteMatcher;
41
+ }
42
+ /**
43
+ * Drop-in {@link DevDock} for react-router apps: navigates via the SPA
44
+ * router and auto-detects routes from the active data router. Any
45
+ * `routes` you pass are appended to the detected ones.
46
+ */
47
+ declare function ReactRouterDevDock({ match, ...props }: ReactRouterDevDockProps): react.JSX.Element;
48
+
49
+ export { ReactRouterDevDock, type ReactRouterDevDockProps, type RouteMatcher, flattenRoutes, useDetectedRoutes };
@@ -0,0 +1,49 @@
1
+ import * as react from 'react';
2
+ import { DevDockProps } from './react.js';
3
+ import { c as DevRoute } from './types-DYQBDvfK.js';
4
+
5
+ /** Minimal shape of a react-router route object we care about. */
6
+ interface RRRoute {
7
+ path?: string;
8
+ index?: boolean;
9
+ children?: RRRoute[];
10
+ handle?: {
11
+ devLabel?: string;
12
+ devGroup?: string;
13
+ hidden?: boolean;
14
+ } & Record<string, unknown>;
15
+ }
16
+ /**
17
+ * Restricts which auto-detected routes appear. A string is treated as a glob
18
+ * where `*` matches any characters (e.g. `"/dev/*"`, `"/admin/*"`); or pass a
19
+ * `RegExp` tested against the path, or a predicate for full control.
20
+ */
21
+ type RouteMatcher = string | RegExp | ((route: DevRoute) => boolean);
22
+ /**
23
+ * Flatten a react-router route tree into navigable {@link DevRoute}s.
24
+ * Dynamic (`:param`) and splat (`*`) segments are skipped since they
25
+ * can't be navigated to without arguments. Mark a route with
26
+ * `handle.hidden` to exclude it, or `handle.devLabel` to rename it.
27
+ */
28
+ declare function flattenRoutes(routes: RRRoute[], parent?: string): DevRoute[];
29
+ /**
30
+ * Read every navigable route from the active react-router data router.
31
+ * Pass `match` to scope the results (glob string, RegExp, or predicate).
32
+ */
33
+ declare function useDetectedRoutes(match?: RouteMatcher): DevRoute[];
34
+ interface ReactRouterDevDockProps extends DevDockProps {
35
+ /**
36
+ * Only auto-detect routes that match. A glob string (`*` = any characters,
37
+ * e.g. `"/dev/*"`), a `RegExp`, or a predicate. Manual `routes` are always
38
+ * included regardless of this filter.
39
+ */
40
+ match?: RouteMatcher;
41
+ }
42
+ /**
43
+ * Drop-in {@link DevDock} for react-router apps: navigates via the SPA
44
+ * router and auto-detects routes from the active data router. Any
45
+ * `routes` you pass are appended to the detected ones.
46
+ */
47
+ declare function ReactRouterDevDock({ match, ...props }: ReactRouterDevDockProps): react.JSX.Element;
48
+
49
+ export { ReactRouterDevDock, type ReactRouterDevDockProps, type RouteMatcher, flattenRoutes, useDetectedRoutes };