@chuvenger/devdock 0.1.3 → 0.2.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/README.md +35 -14
- package/dist/{chunk-TROB6P6B.js → chunk-DUHEBT6Q.js} +6 -6
- package/dist/{chunk-TROB6P6B.js.map → chunk-DUHEBT6Q.js.map} +1 -1
- package/dist/{chunk-KFWO54VP.js → chunk-JZWITFNK.js} +3 -3
- package/dist/{chunk-KFWO54VP.js.map → chunk-JZWITFNK.js.map} +1 -1
- package/dist/{dock-elbtMGsE.d.ts → dock-BQEAjL0s.d.ts} +1 -1
- package/dist/{dock-mQl2WU8n.d.cts → dock-BTK1OArl.d.cts} +1 -1
- package/dist/index.cjs +4 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/react-router.cjs +30 -12
- package/dist/react-router.cjs.map +1 -1
- package/dist/react-router.d.cts +39 -13
- package/dist/react-router.d.ts +39 -13
- package/dist/react-router.js +28 -10
- package/dist/react-router.js.map +1 -1
- package/dist/react.cjs +4 -4
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +2 -2
- package/dist/react.d.ts +2 -2
- package/dist/react.js +2 -2
- package/dist/svelte.cjs +4 -4
- package/dist/svelte.cjs.map +1 -1
- package/dist/svelte.d.cts +3 -3
- package/dist/svelte.d.ts +3 -3
- package/dist/svelte.js +2 -2
- package/dist/{types-DYQBDvfK.d.cts → types-DWX2w51R.d.cts} +1 -1
- package/dist/{types-DYQBDvfK.d.ts → types-DWX2w51R.d.ts} +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ app, **only renders in development**, and opens a popup to jump between dev
|
|
|
8
8
|
routes and run custom commands.
|
|
9
9
|
|
|
10
10
|
- 🔒 **Dev-gated by default** — hidden when `process.env.NODE_ENV === "production"`. Fully overridable.
|
|
11
|
-
- 🧭 **Route jumper** — list routes manually, or auto-detect
|
|
11
|
+
- 🧭 **Route jumper** — list routes manually, or auto-detect your `/dev` routes from React Router.
|
|
12
12
|
- ⚡ **Custom commands** — register any action (reset DB, toggle a flag, copy a token…).
|
|
13
13
|
- 🔎 Filter box + keyboard nav (↑/↓/Enter/Esc) and an optional global hotkey.
|
|
14
14
|
- 🎨 Zero CSS to import — inline-styled, high z-index, no runtime dependencies.
|
|
@@ -92,21 +92,42 @@ The adapter imports `useNavigate` / `UNSAFE_DataRouterContext` from
|
|
|
92
92
|
package comes in via `react-router-dom`; with a strict package manager (pnpm)
|
|
93
93
|
add `react-router` to your own deps so it resolves.
|
|
94
94
|
|
|
95
|
-
Render it inside the router tree.
|
|
96
|
-
|
|
97
|
-
`handle`:
|
|
95
|
+
Render it inside the router tree. **Only dev routes are listed by default.** A
|
|
96
|
+
route counts as one if it lives under `/dev`, or if you opt it in via React
|
|
97
|
+
Router's `handle`:
|
|
98
98
|
|
|
99
99
|
```tsx
|
|
100
|
-
{ path: "
|
|
100
|
+
{ path: "/dev/inspector", element: <Inspector /> } // by convention
|
|
101
|
+
{ path: "reports", element: <Reports />, handle: { dev: true } } // opted in
|
|
102
|
+
{ path: "flags", element: <Flags />, handle: { devLabel: "Feature Flags", devGroup: "Internal" } }
|
|
101
103
|
```
|
|
102
104
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
+
Any of `dev`, `devLabel` or `devGroup` marks a route, and both the convention
|
|
106
|
+
and the mark cover the whole subtree — put one on a section's layout route and
|
|
107
|
+
every page inside shows up (inheriting its `devGroup`). Use `handle.hidden` to
|
|
108
|
+
drop one back out.
|
|
109
|
+
|
|
110
|
+
**Want the whole app listed?** Set `staticRoutes` and every static route is
|
|
111
|
+
detected, marked or not:
|
|
112
|
+
|
|
113
|
+
```tsx
|
|
114
|
+
<ReactRouterDevDock staticRoutes />
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Dynamic (`:id`) and splat (`*`) routes are always skipped since they need
|
|
118
|
+
arguments — to reach one, use a command that navigates to a known id:
|
|
119
|
+
|
|
120
|
+
```tsx
|
|
121
|
+
<ReactRouterDevDock commands={[{ label: "Sample user", run: () => navigate("/users/42") }]} />
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**Scope what's detected** with `match` — a glob (`*` = any characters), a
|
|
125
|
+
`RegExp`, or a predicate. Manual `routes` are always included:
|
|
105
126
|
|
|
106
127
|
```tsx
|
|
107
|
-
<ReactRouterDevDock match="/dev/*" />
|
|
108
|
-
<ReactRouterDevDock match={/^\/(admin|dev)/} />
|
|
109
|
-
<ReactRouterDevDock match={(r) => r.path.length < 20} />
|
|
128
|
+
<ReactRouterDevDock staticRoutes match="/dev/*" /> // only routes under /dev
|
|
129
|
+
<ReactRouterDevDock staticRoutes match={/^\/(admin|dev)/} />
|
|
130
|
+
<ReactRouterDevDock staticRoutes match={(r) => r.path.length < 20} />
|
|
110
131
|
```
|
|
111
132
|
|
|
112
133
|
## Svelte
|
|
@@ -184,7 +205,7 @@ a `data-devdock` attribute either way.
|
|
|
184
205
|
| `commands` | `DevCommand[]` | `[]` | Custom actions. |
|
|
185
206
|
| `enabled` | `boolean \| (() => boolean)` | `NODE_ENV !== "production"` | Whether to render at all. A predicate is re-checked on every update. |
|
|
186
207
|
| `onNavigate` | `(path: string) => void` | `window.location.assign` | How to navigate on route select. |
|
|
187
|
-
| `position` | `"bottom-left" \| "bottom-right" \| "top-left" \| "top-right"` | `"bottom-
|
|
208
|
+
| `position` | `"bottom-left" \| "bottom-right" \| "top-left" \| "top-right"` | `"bottom-right"` | Corner. |
|
|
188
209
|
| `label` | `string` | `"DEV"` | Button text. |
|
|
189
210
|
| `title` | `string` | `"Dev Menu"` | Popup heading. |
|
|
190
211
|
| `hotkey` | `string \| null` | `null` | Toggle shortcut, e.g. `"mod+."`. |
|
|
@@ -203,9 +224,9 @@ a `data-devdock` attribute either way.
|
|
|
203
224
|
|
|
204
225
|
### `@chuvenger/devdock/react-router`
|
|
205
226
|
|
|
206
|
-
- `ReactRouterDevDock(props)` — `DevDock` wired to `useNavigate()` + auto-detected routes. Extra
|
|
207
|
-
- `useDetectedRoutes(
|
|
208
|
-
- `flattenRoutes(routes, parent?): DevRoute[]` — pure helper that flattens a route tree.
|
|
227
|
+
- `ReactRouterDevDock(props)` — `DevDock` wired to `useNavigate()` + auto-detected routes. Extra props: `match?: RouteMatcher`, `staticRoutes?: boolean`.
|
|
228
|
+
- `useDetectedRoutes(options?): DevRoute[]` — the detected routes (build your own UI). Takes `{ match?, staticRoutes? }`, or a bare matcher.
|
|
229
|
+
- `flattenRoutes(routes, parent?, options?): DevRoute[]` — pure helper that flattens a route tree.
|
|
209
230
|
- `RouteMatcher` — `string | RegExp | ((route: DevRoute) => boolean)`.
|
|
210
231
|
|
|
211
232
|
## Examples
|
|
@@ -33,14 +33,14 @@ function el(tag, styles, props) {
|
|
|
33
33
|
function cornerStyle(position) {
|
|
34
34
|
const gap = "16px";
|
|
35
35
|
switch (position) {
|
|
36
|
-
case "bottom-
|
|
37
|
-
return { bottom: gap,
|
|
36
|
+
case "bottom-left":
|
|
37
|
+
return { bottom: gap, left: gap };
|
|
38
38
|
case "top-left":
|
|
39
39
|
return { top: gap, left: gap };
|
|
40
40
|
case "top-right":
|
|
41
41
|
return { top: gap, right: gap };
|
|
42
42
|
default:
|
|
43
|
-
return { bottom: gap,
|
|
43
|
+
return { bottom: gap, right: gap };
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
function panelAnchor(position) {
|
|
@@ -306,7 +306,7 @@ function createDevDock(initial = {}) {
|
|
|
306
306
|
paintActive();
|
|
307
307
|
};
|
|
308
308
|
const renderShell = () => {
|
|
309
|
-
const position = opts.position ?? "bottom-
|
|
309
|
+
const position = opts.position ?? "bottom-right";
|
|
310
310
|
const zIndex = opts.zIndex ?? 2147483e3;
|
|
311
311
|
Object.assign(root.style, {
|
|
312
312
|
position: "fixed",
|
|
@@ -413,5 +413,5 @@ function createDevDock(initial = {}) {
|
|
|
413
413
|
}
|
|
414
414
|
|
|
415
415
|
export { createDevDock, matchHotkey };
|
|
416
|
-
//# sourceMappingURL=chunk-
|
|
417
|
-
//# sourceMappingURL=chunk-
|
|
416
|
+
//# sourceMappingURL=chunk-DUHEBT6Q.js.map
|
|
417
|
+
//# sourceMappingURL=chunk-DUHEBT6Q.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/hotkey.ts","../src/core/dock.ts"],"names":[],"mappings":"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","file":"chunk-TROB6P6B.js","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 type Row = {\n item: Item;\n node: HTMLButtonElement;\n pathSpan: HTMLSpanElement | null;\n };\n\n // The rendered rows, parallel to the current filtered list. They are kept\n // around so hovering or arrowing only repaints the highlight: rebuilding the\n // rows would destroy the node under the pointer, and the browser then never\n // dispatches a `click` on it (mousedown/mouseup retarget to the parent).\n let rows: Row[] = [];\n // Signature of the item list the rows were built from; identical signature\n // means the existing nodes can be reused as-is.\n let rowsSig: string | null = null;\n\n const itemSig = (it: Item): string =>\n [it.key, it.group, it.label, it.kind === \"route\" ? it.route.path : \"\"].join(\n \"\\u0000\",\n );\n\n const paintActive = () => {\n rows.forEach((row, idx) => {\n const isActive = idx === active;\n row.node.style.background = isActive ? \"#2563eb\" : \"transparent\";\n if (row.pathSpan)\n row.pathSpan.style.color = isActive ? \"#cfe0ff\" : \"#6b7280\";\n });\n };\n\n const setActive = (next: number, scroll = false) => {\n if (next === active || next < 0 || next >= rows.length) return;\n active = next;\n paintActive();\n // `scrollIntoView` is absent in jsdom, hence the optional call.\n if (scroll) rows[active]?.node.scrollIntoView?.({ block: \"nearest\" });\n };\n\n const renderList = () => {\n const filtered = getFiltered();\n active = Math.min(active, Math.max(0, filtered.length - 1));\n\n const sig = filtered.map(itemSig).join(\"\\n\");\n if (sig === rowsSig) {\n // Same items in the same order: keep the nodes, refresh the highlight.\n // The items themselves are rebuilt on every call, so re-point each row\n // at its current one (its `run`/`route` may have been swapped by\n // `update()`).\n filtered.forEach((it, idx) => {\n const row = rows[idx];\n if (row) row.item = it;\n });\n paintActive();\n return;\n }\n rowsSig = sig;\n rows = [];\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 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: \"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 let pathSpan: HTMLSpanElement | null = null;\n if (it.kind === \"route\" && it.route.path !== it.label) {\n pathSpan = el(\n \"span\",\n {\n fontSize: \"11px\",\n color: \"#6b7280\",\n fontFamily: \"ui-monospace, SFMono-Regular, monospace\",\n flexShrink: \"0\",\n },\n { textContent: it.route.path },\n );\n row.appendChild(pathSpan);\n }\n\n const rec: Row = { item: it, node: row, pathSpan };\n rows[idx] = rec;\n\n row.addEventListener(\"mouseenter\", () => setActive(idx));\n row.addEventListener(\"click\", () => void runItem(rec.item));\n section.appendChild(row);\n }\n list.appendChild(section);\n }\n\n paintActive();\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 if (e.key === \"Escape\") {\n e.preventDefault();\n setOpen(false);\n } else if (e.key === \"ArrowDown\") {\n e.preventDefault();\n setActive(Math.min(active + 1, rows.length - 1), true);\n } else if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setActive(Math.max(active - 1, 0), true);\n } else if (e.key === \"Enter\") {\n e.preventDefault();\n const it = rows[active]?.item;\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"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/hotkey.ts","../src/core/dock.ts"],"names":[],"mappings":"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","file":"chunk-DUHEBT6Q.js","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-left\":\n return { bottom: gap, left: 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, right: 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 type Row = {\n item: Item;\n node: HTMLButtonElement;\n pathSpan: HTMLSpanElement | null;\n };\n\n // The rendered rows, parallel to the current filtered list. They are kept\n // around so hovering or arrowing only repaints the highlight: rebuilding the\n // rows would destroy the node under the pointer, and the browser then never\n // dispatches a `click` on it (mousedown/mouseup retarget to the parent).\n let rows: Row[] = [];\n // Signature of the item list the rows were built from; identical signature\n // means the existing nodes can be reused as-is.\n let rowsSig: string | null = null;\n\n const itemSig = (it: Item): string =>\n [it.key, it.group, it.label, it.kind === \"route\" ? it.route.path : \"\"].join(\n \"\\u0000\",\n );\n\n const paintActive = () => {\n rows.forEach((row, idx) => {\n const isActive = idx === active;\n row.node.style.background = isActive ? \"#2563eb\" : \"transparent\";\n if (row.pathSpan)\n row.pathSpan.style.color = isActive ? \"#cfe0ff\" : \"#6b7280\";\n });\n };\n\n const setActive = (next: number, scroll = false) => {\n if (next === active || next < 0 || next >= rows.length) return;\n active = next;\n paintActive();\n // `scrollIntoView` is absent in jsdom, hence the optional call.\n if (scroll) rows[active]?.node.scrollIntoView?.({ block: \"nearest\" });\n };\n\n const renderList = () => {\n const filtered = getFiltered();\n active = Math.min(active, Math.max(0, filtered.length - 1));\n\n const sig = filtered.map(itemSig).join(\"\\n\");\n if (sig === rowsSig) {\n // Same items in the same order: keep the nodes, refresh the highlight.\n // The items themselves are rebuilt on every call, so re-point each row\n // at its current one (its `run`/`route` may have been swapped by\n // `update()`).\n filtered.forEach((it, idx) => {\n const row = rows[idx];\n if (row) row.item = it;\n });\n paintActive();\n return;\n }\n rowsSig = sig;\n rows = [];\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 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: \"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 let pathSpan: HTMLSpanElement | null = null;\n if (it.kind === \"route\" && it.route.path !== it.label) {\n pathSpan = el(\n \"span\",\n {\n fontSize: \"11px\",\n color: \"#6b7280\",\n fontFamily: \"ui-monospace, SFMono-Regular, monospace\",\n flexShrink: \"0\",\n },\n { textContent: it.route.path },\n );\n row.appendChild(pathSpan);\n }\n\n const rec: Row = { item: it, node: row, pathSpan };\n rows[idx] = rec;\n\n row.addEventListener(\"mouseenter\", () => setActive(idx));\n row.addEventListener(\"click\", () => void runItem(rec.item));\n section.appendChild(row);\n }\n list.appendChild(section);\n }\n\n paintActive();\n };\n\n const renderShell = () => {\n const position = opts.position ?? \"bottom-right\";\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 if (e.key === \"Escape\") {\n e.preventDefault();\n setOpen(false);\n } else if (e.key === \"ArrowDown\") {\n e.preventDefault();\n setActive(Math.min(active + 1, rows.length - 1), true);\n } else if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setActive(Math.max(active - 1, 0), true);\n } else if (e.key === \"Enter\") {\n e.preventDefault();\n const it = rows[active]?.item;\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"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createDevDock } from './chunk-
|
|
1
|
+
import { createDevDock } from './chunk-DUHEBT6Q.js';
|
|
2
2
|
import { useRef, useEffect } from 'react';
|
|
3
3
|
|
|
4
4
|
function DevDock(props) {
|
|
@@ -20,5 +20,5 @@ function DevDock(props) {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
export { DevDock };
|
|
23
|
-
//# sourceMappingURL=chunk-
|
|
24
|
-
//# sourceMappingURL=chunk-
|
|
23
|
+
//# sourceMappingURL=chunk-JZWITFNK.js.map
|
|
24
|
+
//# sourceMappingURL=chunk-JZWITFNK.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/react/DevDock.tsx"],"names":[],"mappings":";;;AAWO,SAAS,QAAQ,KAAA,EAAqB;AAC3C,EAAA,MAAM,QAAA,GAAW,OAA+B,IAAI,CAAA;AACpD,EAAA,MAAM,MAAA,GAAS,OAAO,KAAK,CAAA;AAC3B,EAAA,MAAA,CAAO,OAAA,GAAU,KAAA;AAEjB,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,IAAA,GAAO,aAAA,CAAc,MAAA,CAAO,OAAO,CAAA;AACzC,IAAA,QAAA,CAAS,OAAA,GAAU,IAAA;AACnB,IAAA,OAAO,MAAM;AACX,MAAA,IAAA,CAAK,OAAA,EAAQ;AACb,MAAA,QAAA,CAAS,OAAA,GAAU,IAAA;AAAA,IACrB,CAAA;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,QAAA,CAAS,OAAA,EAAS,OAAO,KAAK,CAAA;AAAA,EAChC,CAAC,CAAA;AAED,EAAA,OAAO,IAAA;AACT","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/react/DevDock.tsx"],"names":[],"mappings":";;;AAWO,SAAS,QAAQ,KAAA,EAAqB;AAC3C,EAAA,MAAM,QAAA,GAAW,OAA+B,IAAI,CAAA;AACpD,EAAA,MAAM,MAAA,GAAS,OAAO,KAAK,CAAA;AAC3B,EAAA,MAAA,CAAO,OAAA,GAAU,KAAA;AAEjB,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,IAAA,GAAO,aAAA,CAAc,MAAA,CAAO,OAAO,CAAA;AACzC,IAAA,QAAA,CAAS,OAAA,GAAU,IAAA;AACnB,IAAA,OAAO,MAAM;AACX,MAAA,IAAA,CAAK,OAAA,EAAQ;AACb,MAAA,QAAA,CAAS,OAAA,GAAU,IAAA;AAAA,IACrB,CAAA;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,QAAA,CAAS,OAAA,EAAS,OAAO,KAAK,CAAA;AAAA,EAChC,CAAC,CAAA;AAED,EAAA,OAAO,IAAA;AACT","file":"chunk-JZWITFNK.js","sourcesContent":["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"]}
|
package/dist/index.cjs
CHANGED
|
@@ -35,14 +35,14 @@ function el(tag, styles, props) {
|
|
|
35
35
|
function cornerStyle(position) {
|
|
36
36
|
const gap = "16px";
|
|
37
37
|
switch (position) {
|
|
38
|
-
case "bottom-
|
|
39
|
-
return { bottom: gap,
|
|
38
|
+
case "bottom-left":
|
|
39
|
+
return { bottom: gap, left: gap };
|
|
40
40
|
case "top-left":
|
|
41
41
|
return { top: gap, left: gap };
|
|
42
42
|
case "top-right":
|
|
43
43
|
return { top: gap, right: gap };
|
|
44
44
|
default:
|
|
45
|
-
return { bottom: gap,
|
|
45
|
+
return { bottom: gap, right: gap };
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
function panelAnchor(position) {
|
|
@@ -308,7 +308,7 @@ function createDevDock(initial = {}) {
|
|
|
308
308
|
paintActive();
|
|
309
309
|
};
|
|
310
310
|
const renderShell = () => {
|
|
311
|
-
const position = opts.position ?? "bottom-
|
|
311
|
+
const position = opts.position ?? "bottom-right";
|
|
312
312
|
const zIndex = opts.zIndex ?? 2147483e3;
|
|
313
313
|
Object.assign(root.style, {
|
|
314
314
|
position: "fixed",
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/hotkey.ts","../src/core/dock.ts"],"names":[],"mappings":"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","file":"index.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 type Row = {\n item: Item;\n node: HTMLButtonElement;\n pathSpan: HTMLSpanElement | null;\n };\n\n // The rendered rows, parallel to the current filtered list. They are kept\n // around so hovering or arrowing only repaints the highlight: rebuilding the\n // rows would destroy the node under the pointer, and the browser then never\n // dispatches a `click` on it (mousedown/mouseup retarget to the parent).\n let rows: Row[] = [];\n // Signature of the item list the rows were built from; identical signature\n // means the existing nodes can be reused as-is.\n let rowsSig: string | null = null;\n\n const itemSig = (it: Item): string =>\n [it.key, it.group, it.label, it.kind === \"route\" ? it.route.path : \"\"].join(\n \"\\u0000\",\n );\n\n const paintActive = () => {\n rows.forEach((row, idx) => {\n const isActive = idx === active;\n row.node.style.background = isActive ? \"#2563eb\" : \"transparent\";\n if (row.pathSpan)\n row.pathSpan.style.color = isActive ? \"#cfe0ff\" : \"#6b7280\";\n });\n };\n\n const setActive = (next: number, scroll = false) => {\n if (next === active || next < 0 || next >= rows.length) return;\n active = next;\n paintActive();\n // `scrollIntoView` is absent in jsdom, hence the optional call.\n if (scroll) rows[active]?.node.scrollIntoView?.({ block: \"nearest\" });\n };\n\n const renderList = () => {\n const filtered = getFiltered();\n active = Math.min(active, Math.max(0, filtered.length - 1));\n\n const sig = filtered.map(itemSig).join(\"\\n\");\n if (sig === rowsSig) {\n // Same items in the same order: keep the nodes, refresh the highlight.\n // The items themselves are rebuilt on every call, so re-point each row\n // at its current one (its `run`/`route` may have been swapped by\n // `update()`).\n filtered.forEach((it, idx) => {\n const row = rows[idx];\n if (row) row.item = it;\n });\n paintActive();\n return;\n }\n rowsSig = sig;\n rows = [];\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 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: \"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 let pathSpan: HTMLSpanElement | null = null;\n if (it.kind === \"route\" && it.route.path !== it.label) {\n pathSpan = el(\n \"span\",\n {\n fontSize: \"11px\",\n color: \"#6b7280\",\n fontFamily: \"ui-monospace, SFMono-Regular, monospace\",\n flexShrink: \"0\",\n },\n { textContent: it.route.path },\n );\n row.appendChild(pathSpan);\n }\n\n const rec: Row = { item: it, node: row, pathSpan };\n rows[idx] = rec;\n\n row.addEventListener(\"mouseenter\", () => setActive(idx));\n row.addEventListener(\"click\", () => void runItem(rec.item));\n section.appendChild(row);\n }\n list.appendChild(section);\n }\n\n paintActive();\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 if (e.key === \"Escape\") {\n e.preventDefault();\n setOpen(false);\n } else if (e.key === \"ArrowDown\") {\n e.preventDefault();\n setActive(Math.min(active + 1, rows.length - 1), true);\n } else if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setActive(Math.max(active - 1, 0), true);\n } else if (e.key === \"Enter\") {\n e.preventDefault();\n const it = rows[active]?.item;\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"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/hotkey.ts","../src/core/dock.ts"],"names":[],"mappings":"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","file":"index.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-left\":\n return { bottom: gap, left: 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, right: 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 type Row = {\n item: Item;\n node: HTMLButtonElement;\n pathSpan: HTMLSpanElement | null;\n };\n\n // The rendered rows, parallel to the current filtered list. They are kept\n // around so hovering or arrowing only repaints the highlight: rebuilding the\n // rows would destroy the node under the pointer, and the browser then never\n // dispatches a `click` on it (mousedown/mouseup retarget to the parent).\n let rows: Row[] = [];\n // Signature of the item list the rows were built from; identical signature\n // means the existing nodes can be reused as-is.\n let rowsSig: string | null = null;\n\n const itemSig = (it: Item): string =>\n [it.key, it.group, it.label, it.kind === \"route\" ? it.route.path : \"\"].join(\n \"\\u0000\",\n );\n\n const paintActive = () => {\n rows.forEach((row, idx) => {\n const isActive = idx === active;\n row.node.style.background = isActive ? \"#2563eb\" : \"transparent\";\n if (row.pathSpan)\n row.pathSpan.style.color = isActive ? \"#cfe0ff\" : \"#6b7280\";\n });\n };\n\n const setActive = (next: number, scroll = false) => {\n if (next === active || next < 0 || next >= rows.length) return;\n active = next;\n paintActive();\n // `scrollIntoView` is absent in jsdom, hence the optional call.\n if (scroll) rows[active]?.node.scrollIntoView?.({ block: \"nearest\" });\n };\n\n const renderList = () => {\n const filtered = getFiltered();\n active = Math.min(active, Math.max(0, filtered.length - 1));\n\n const sig = filtered.map(itemSig).join(\"\\n\");\n if (sig === rowsSig) {\n // Same items in the same order: keep the nodes, refresh the highlight.\n // The items themselves are rebuilt on every call, so re-point each row\n // at its current one (its `run`/`route` may have been swapped by\n // `update()`).\n filtered.forEach((it, idx) => {\n const row = rows[idx];\n if (row) row.item = it;\n });\n paintActive();\n return;\n }\n rowsSig = sig;\n rows = [];\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 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: \"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 let pathSpan: HTMLSpanElement | null = null;\n if (it.kind === \"route\" && it.route.path !== it.label) {\n pathSpan = el(\n \"span\",\n {\n fontSize: \"11px\",\n color: \"#6b7280\",\n fontFamily: \"ui-monospace, SFMono-Regular, monospace\",\n flexShrink: \"0\",\n },\n { textContent: it.route.path },\n );\n row.appendChild(pathSpan);\n }\n\n const rec: Row = { item: it, node: row, pathSpan };\n rows[idx] = rec;\n\n row.addEventListener(\"mouseenter\", () => setActive(idx));\n row.addEventListener(\"click\", () => void runItem(rec.item));\n section.appendChild(row);\n }\n list.appendChild(section);\n }\n\n paintActive();\n };\n\n const renderShell = () => {\n const position = opts.position ?? \"bottom-right\";\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 if (e.key === \"Escape\") {\n e.preventDefault();\n setOpen(false);\n } else if (e.key === \"ArrowDown\") {\n e.preventDefault();\n setActive(Math.min(active + 1, rows.length - 1), true);\n } else if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setActive(Math.max(active - 1, 0), true);\n } else if (e.key === \"Enter\") {\n e.preventDefault();\n const it = rows[active]?.item;\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"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { c as createDevDock } from './dock-
|
|
2
|
-
export { D as DevCommand, a as DevDockInstance, b as DevDockOptions, c as DevRoute, d as DockPosition } from './types-
|
|
1
|
+
export { c as createDevDock } from './dock-BTK1OArl.cjs';
|
|
2
|
+
export { D as DevCommand, a as DevDockInstance, b as DevDockOptions, c as DevRoute, d as DockPosition } from './types-DWX2w51R.cjs';
|
|
3
3
|
|
|
4
4
|
/** Parse a hotkey string like "mod+." into a matcher predicate. */
|
|
5
5
|
declare function matchHotkey(spec: string, e: KeyboardEvent): boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { c as createDevDock } from './dock-
|
|
2
|
-
export { D as DevCommand, a as DevDockInstance, b as DevDockOptions, c as DevRoute, d as DockPosition } from './types-
|
|
1
|
+
export { c as createDevDock } from './dock-BQEAjL0s.js';
|
|
2
|
+
export { D as DevCommand, a as DevDockInstance, b as DevDockOptions, c as DevRoute, d as DockPosition } from './types-DWX2w51R.js';
|
|
3
3
|
|
|
4
4
|
/** Parse a hotkey string like "mod+." into a matcher predicate. */
|
|
5
5
|
declare function matchHotkey(spec: string, e: KeyboardEvent): boolean;
|
package/dist/index.js
CHANGED
package/dist/react-router.cjs
CHANGED
|
@@ -41,14 +41,14 @@ function el(tag, styles, props) {
|
|
|
41
41
|
function cornerStyle(position) {
|
|
42
42
|
const gap = "16px";
|
|
43
43
|
switch (position) {
|
|
44
|
-
case "bottom-
|
|
45
|
-
return { bottom: gap,
|
|
44
|
+
case "bottom-left":
|
|
45
|
+
return { bottom: gap, left: gap };
|
|
46
46
|
case "top-left":
|
|
47
47
|
return { top: gap, left: gap };
|
|
48
48
|
case "top-right":
|
|
49
49
|
return { top: gap, right: gap };
|
|
50
50
|
default:
|
|
51
|
-
return { bottom: gap,
|
|
51
|
+
return { bottom: gap, right: gap };
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
function panelAnchor(position) {
|
|
@@ -314,7 +314,7 @@ function createDevDock(initial = {}) {
|
|
|
314
314
|
paintActive();
|
|
315
315
|
};
|
|
316
316
|
const renderShell = () => {
|
|
317
|
-
const position = opts.position ?? "bottom-
|
|
317
|
+
const position = opts.position ?? "bottom-right";
|
|
318
318
|
const zIndex = opts.zIndex ?? 2147483e3;
|
|
319
319
|
Object.assign(root.style, {
|
|
320
320
|
position: "fixed",
|
|
@@ -453,39 +453,57 @@ function joinPath(parent, child) {
|
|
|
453
453
|
const base = parent.endsWith("/") ? parent.slice(0, -1) : parent;
|
|
454
454
|
return `${base}/${child}`;
|
|
455
455
|
}
|
|
456
|
-
function
|
|
456
|
+
function isDevMarked(handle) {
|
|
457
|
+
return handle?.dev === true || handle?.devLabel != null || handle?.devGroup != null;
|
|
458
|
+
}
|
|
459
|
+
function isDevPath(path) {
|
|
460
|
+
return path === "/dev" || path.startsWith("/dev/");
|
|
461
|
+
}
|
|
462
|
+
function flattenRoutes(routes, parent = "", options = {}) {
|
|
463
|
+
return walk(routes, parent, options.staticRoutes === true, { dev: false });
|
|
464
|
+
}
|
|
465
|
+
function walk(routes, parent, staticRoutes, inherited) {
|
|
457
466
|
const out = [];
|
|
458
467
|
for (const r of routes) {
|
|
459
468
|
const full = r.index ? parent : joinPath(parent, r.path ?? "");
|
|
460
|
-
const
|
|
469
|
+
const dev = inherited.dev || isDevMarked(r.handle) || isDevPath(full);
|
|
470
|
+
const group = r.handle?.devGroup ?? inherited.group;
|
|
471
|
+
const navigable = !r.index && r.path != null && !full.includes(":") && !full.includes("*") && r.handle?.hidden !== true && (dev || staticRoutes);
|
|
461
472
|
if (navigable) {
|
|
462
473
|
out.push({
|
|
463
474
|
path: full || "/",
|
|
464
475
|
label: r.handle?.devLabel ?? (full || "/"),
|
|
465
|
-
group
|
|
476
|
+
group
|
|
466
477
|
});
|
|
467
478
|
}
|
|
468
|
-
if (r.children?.length)
|
|
479
|
+
if (r.children?.length)
|
|
480
|
+
out.push(...walk(r.children, full, staticRoutes, { dev, group }));
|
|
469
481
|
}
|
|
470
482
|
return out;
|
|
471
483
|
}
|
|
472
|
-
function
|
|
484
|
+
function isMatcher(value) {
|
|
485
|
+
return typeof value === "string" || typeof value === "function" || value instanceof RegExp;
|
|
486
|
+
}
|
|
487
|
+
function useDetectedRoutes(options = {}) {
|
|
488
|
+
const opts = isMatcher(options) ? { match: options } : options;
|
|
489
|
+
const { match, staticRoutes } = opts;
|
|
473
490
|
const ctx = react.useContext(reactRouter.UNSAFE_DataRouterContext);
|
|
474
491
|
const routes = ctx?.router?.routes ?? [];
|
|
475
492
|
return react.useMemo(() => {
|
|
476
493
|
const seen = /* @__PURE__ */ new Set();
|
|
477
|
-
const deduped = flattenRoutes(routes).filter(
|
|
494
|
+
const deduped = flattenRoutes(routes, "", { staticRoutes }).filter(
|
|
478
495
|
(r) => seen.has(r.path) ? false : (seen.add(r.path), true)
|
|
479
496
|
);
|
|
480
497
|
return match ? deduped.filter(toPredicate(match)) : deduped;
|
|
481
|
-
}, [routes, match]);
|
|
498
|
+
}, [routes, match, staticRoutes]);
|
|
482
499
|
}
|
|
483
500
|
function ReactRouterDevDock({
|
|
484
501
|
match,
|
|
502
|
+
staticRoutes,
|
|
485
503
|
...props
|
|
486
504
|
}) {
|
|
487
505
|
const navigate = reactRouter.useNavigate();
|
|
488
|
-
const detected = useDetectedRoutes(match);
|
|
506
|
+
const detected = useDetectedRoutes({ match, staticRoutes });
|
|
489
507
|
const routes = react.useMemo(
|
|
490
508
|
() => [...detected, ...props.routes ?? []],
|
|
491
509
|
[detected, props.routes]
|