@chuvenger/devdock 0.4.0 → 0.5.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.
Files changed (44) hide show
  1. package/README.md +171 -16
  2. package/dist/chunk-3MVFATRN.js +60 -0
  3. package/dist/chunk-3MVFATRN.js.map +1 -0
  4. package/dist/{chunk-F2KWDPMA.js → chunk-NXZNFF34.js} +238 -42
  5. package/dist/chunk-NXZNFF34.js.map +1 -0
  6. package/dist/{dock-CvTtAelh.d.ts → dock-P6l6pKjS.d.ts} +1 -1
  7. package/dist/{dock-Du6Im767.d.cts → dock-d3HqT25k.d.cts} +1 -1
  8. package/dist/index.cjs +235 -39
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.d.cts +2 -2
  11. package/dist/index.d.ts +2 -2
  12. package/dist/index.js +1 -1
  13. package/dist/{match-B6LN1RRP.d.cts → match-DDSJIRYW.d.cts} +1 -1
  14. package/dist/{match-C-mY8W8T.d.ts → match-DwGIF1Xt.d.ts} +1 -1
  15. package/dist/react-router.cjs +276 -47
  16. package/dist/react-router.cjs.map +1 -1
  17. package/dist/react-router.d.cts +2 -2
  18. package/dist/react-router.d.ts +2 -2
  19. package/dist/react-router.js +2 -2
  20. package/dist/react.cjs +277 -47
  21. package/dist/react.cjs.map +1 -1
  22. package/dist/react.d.cts +28 -8
  23. package/dist/react.d.ts +28 -8
  24. package/dist/react.js +2 -2
  25. package/dist/svelte.cjs +235 -39
  26. package/dist/svelte.cjs.map +1 -1
  27. package/dist/svelte.d.cts +3 -3
  28. package/dist/svelte.d.ts +3 -3
  29. package/dist/svelte.js +2 -2
  30. package/dist/svelte.js.map +1 -1
  31. package/dist/sveltekit.cjs +235 -39
  32. package/dist/sveltekit.cjs.map +1 -1
  33. package/dist/sveltekit.d.cts +4 -4
  34. package/dist/sveltekit.d.ts +4 -4
  35. package/dist/sveltekit.js +2 -2
  36. package/dist/sveltekit.js.map +1 -1
  37. package/dist/types-B_SpF32A.d.cts +157 -0
  38. package/dist/types-B_SpF32A.d.ts +157 -0
  39. package/package.json +1 -1
  40. package/dist/chunk-D5IQBV2K.js +0 -24
  41. package/dist/chunk-D5IQBV2K.js.map +0 -1
  42. package/dist/chunk-F2KWDPMA.js.map +0 -1
  43. package/dist/types-fhhRek-e.d.cts +0 -88
  44. package/dist/types-fhhRek-e.d.ts +0 -88
@@ -0,0 +1,157 @@
1
+ type DockPosition = "bottom-left" | "bottom-right" | "top-left" | "top-right";
2
+ /** A navigable destination shown in the dock's "Routes" section. */
3
+ interface DevRoute {
4
+ /** Path to navigate to, e.g. "/admin/users". */
5
+ path: string;
6
+ /** Human label. Defaults to `path`. */
7
+ label?: string;
8
+ /** Optional group heading to organize the list. */
9
+ group?: string;
10
+ }
11
+ /** A custom action shown in the dock's "Commands" section. */
12
+ interface DevCommand {
13
+ /**
14
+ * Stable id (used as key). Defaults to `label` — pass one explicitly when
15
+ * `label` is a function, so the row survives a label change.
16
+ */
17
+ id?: string;
18
+ /**
19
+ * Human label shown in the list. A function is re-read on every render of
20
+ * the open panel, so the row can show live state ("Theme: Dark", "42 keys").
21
+ */
22
+ label: string | (() => string);
23
+ /** Called when the command is selected. May be async. */
24
+ run: () => void | Promise<void>;
25
+ /**
26
+ * Makes the command a toggle: a check mark is rendered when this returns
27
+ * `true`, and the row exposes `role="checkbox"` + `aria-checked`. Re-read on
28
+ * every render of the open panel, like a function `label`.
29
+ *
30
+ * @example
31
+ * { label: "Freeze animations", checked: () => frozen, run: () => toggle() }
32
+ */
33
+ checked?: () => boolean;
34
+ /** Optional group heading to organize the list. */
35
+ group?: string;
36
+ /** Keep the popup open after running (default: false — it closes). */
37
+ keepOpen?: boolean;
38
+ }
39
+ /**
40
+ * A custom panel rendered inside the popup — anything the routes/commands
41
+ * list can't express: a live meter, a status readout, a segmented control.
42
+ *
43
+ * Views are mounted when the popup opens and torn down when it closes, so a
44
+ * `requestAnimationFrame` loop or an event listener set up in `mount` has a
45
+ * well-defined place to stop. The teardown function you return is what runs.
46
+ */
47
+ interface DevView {
48
+ /**
49
+ * Stable id. Views are reconciled by id across `update()` calls: a view
50
+ * whose id is unchanged is never remounted. Defaults to the index, so give
51
+ * an id to any view in a list that can reorder or change length.
52
+ */
53
+ id?: string;
54
+ /** Section heading shown above the view. Omit for no heading. */
55
+ label?: string;
56
+ /**
57
+ * Put several views under one shared heading. Views with the same `group`
58
+ * render in one section titled with the group name, each one labelled with
59
+ * its own `label`.
60
+ */
61
+ group?: string;
62
+ /**
63
+ * Fill `host` with your UI. Return a teardown function to undo it — stop
64
+ * timers, remove listeners, unmount your framework's component tree.
65
+ * Called with `host` already connected to the document.
66
+ */
67
+ mount: (host: HTMLElement) => void | (() => void);
68
+ /**
69
+ * Place the view before or after the routes/commands list.
70
+ * Default: `"before"`.
71
+ */
72
+ order?: "before" | "after";
73
+ }
74
+ /** Framework-agnostic configuration for the dock. */
75
+ interface DevDockOptions {
76
+ /** Routes to list. */
77
+ routes?: DevRoute[];
78
+ /** Custom commands to list. */
79
+ commands?: DevCommand[];
80
+ /**
81
+ * Custom panels rendered inside the popup, mounted on open and torn down on
82
+ * close. See {@link DevView}.
83
+ *
84
+ * A view renders inside the dock's shadow root, which the document's
85
+ * stylesheets don't cross — pass `shadow: "inherit"` (or `shadow: false`) if
86
+ * the view uses the host app's CSS.
87
+ */
88
+ views?: DevView[];
89
+ /**
90
+ * Whether the dock renders at all. Accepts a boolean or a predicate
91
+ * (re-evaluated on every `update`). Takes over the gating completely — both
92
+ * the build and the dev-host check are skipped when it's set.
93
+ *
94
+ * When omitted, the dock renders only in development: a dev build
95
+ * (`import.meta.env.DEV` under Vite-family bundlers, otherwise
96
+ * `process.env.NODE_ENV !== "production"`) served from a dev host (see
97
+ * {@link DevDockOptions.devHostOnly}).
98
+ *
99
+ * @example enabled: () => location.search.includes("debug")
100
+ */
101
+ enabled?: boolean | (() => boolean);
102
+ /**
103
+ * Also require the page to be served from a developer's machine — loopback,
104
+ * an mDNS `.local` name, or a private LAN address. Default: `true`.
105
+ *
106
+ * This catches the case the build check can't: a development build deployed
107
+ * to a real URL (a preview deploy, a staging box) still reports itself as a
108
+ * dev build. Set `false` to drop the hostname check and gate on the build
109
+ * alone — e.g. to keep the dock on a shared staging
110
+ * environment or behind a dev tunnel. Ignored when `enabled` is set.
111
+ */
112
+ devHostOnly?: boolean;
113
+ /**
114
+ * How to navigate when a route is selected.
115
+ * Defaults to `window.location.assign(path)`.
116
+ */
117
+ onNavigate?: (path: string) => void;
118
+ /** Corner to anchor the button. Default: "bottom-right". */
119
+ position?: DockPosition;
120
+ /** Text on the floating button. Default: "DEV". */
121
+ label?: string;
122
+ /** Heading shown at the top of the popup. Default: "Dev Menu". */
123
+ title?: string;
124
+ /**
125
+ * Optional keyboard shortcut to toggle the popup, e.g. "mod+." or
126
+ * "ctrl+k". "mod" maps to ⌘ on Mac and Ctrl elsewhere. Default: none.
127
+ */
128
+ hotkey?: string | null;
129
+ /** Base z-index for the floating UI. Default: 2147483000. */
130
+ zIndex?: number;
131
+ /** Where to mount the dock. Default: `document.body`. */
132
+ container?: HTMLElement;
133
+ /**
134
+ * Render inside a shadow root so the host page's CSS can't affect the dock
135
+ * (and vice versa). Default: `true` where supported. Set `false` to render
136
+ * in the light DOM (e.g. if you want to style it from the page).
137
+ *
138
+ * `"inherit"` keeps the shadow root but copies the document's styles into
139
+ * it — `document.adoptedStyleSheets` plus every `<style>` and
140
+ * `<link rel="stylesheet">` node, re-synced as they change. Use it when a
141
+ * {@link DevView} renders your app's own components and needs its CSS; the
142
+ * cost is that the page's CSS can now reach the dock too.
143
+ *
144
+ * Read once, when the dock is created: a shadow root can't be detached, so
145
+ * `update()` ignores this.
146
+ */
147
+ shadow?: boolean | "inherit";
148
+ }
149
+ /** A live dock instance returned by {@link createDevDock}. */
150
+ interface DevDockInstance {
151
+ /** Re-render with new options (merged over the current ones). */
152
+ update(options: DevDockOptions): void;
153
+ /** Remove the dock and all its listeners. */
154
+ destroy(): void;
155
+ }
156
+
157
+ export type { DevCommand as D, DevDockInstance as a, DevDockOptions as b, DevRoute as c, DevView as d, DockPosition as e };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chuvenger/devdock",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "A tiny dev-only floating button that opens a popup to jump between dev routes and run custom commands.",
5
5
  "author": "Ruven Chu",
6
6
  "repository": {
@@ -1,24 +0,0 @@
1
- import { createDevDock } from './chunk-F2KWDPMA.js';
2
- import { useRef, useEffect } from 'react';
3
-
4
- function DevDock(props) {
5
- const instance = useRef(null);
6
- const latest = useRef(props);
7
- latest.current = props;
8
- useEffect(() => {
9
- const inst = createDevDock(latest.current);
10
- instance.current = inst;
11
- return () => {
12
- inst.destroy();
13
- instance.current = null;
14
- };
15
- }, []);
16
- useEffect(() => {
17
- instance.current?.update(props);
18
- });
19
- return null;
20
- }
21
-
22
- export { DevDock };
23
- //# sourceMappingURL=chunk-D5IQBV2K.js.map
24
- //# sourceMappingURL=chunk-D5IQBV2K.js.map
@@ -1 +0,0 @@
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-D5IQBV2K.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"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/core/hotkey.ts","../src/core/dock.ts"],"names":[],"mappings":"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","file":"chunk-F2KWDPMA.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 isDevBuild = (): 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\n/** Loopback IPv4 (127/8) and the private LAN ranges 10/8, 172.16/12, 192.168/16. */\nconst isLocalIPv4 = (host: string): boolean => {\n const parts = /^(\\d{1,3})\\.(\\d{1,3})\\.\\d{1,3}\\.\\d{1,3}$/.exec(host);\n if (!parts) return false;\n const a = Number(parts[1]);\n const b = Number(parts[2]);\n return (\n a === 127 ||\n a === 10 ||\n (a === 192 && b === 168) ||\n (a === 172 && b >= 16 && b <= 31)\n );\n};\n\n/**\n * Whether the page is served from a developer's own machine. The `NODE_ENV`\n * check alone can't tell: a development build deployed somewhere real (a\n * preview URL, a staging box) still reports `NODE_ENV !== \"production\"`.\n *\n * Dev hosts are loopback, mDNS `.local` names, and private LAN addresses — so\n * hitting the dev server from a phone on the same Wi-Fi still counts. Any\n * other hostname is treated as a deployed site.\n */\nconst isDevHost = (): boolean => {\n if (typeof location === \"undefined\") return true;\n // IPv6 literals arrive bracketed, e.g. \"[::1]\".\n const host = location.hostname.toLowerCase().replace(/^\\[|\\]$/g, \"\");\n // No hostname at all (file://, about:blank…) is not a deployed site.\n if (!host) return true;\n return (\n host === \"localhost\" ||\n host.endsWith(\".localhost\") ||\n host.endsWith(\".local\") ||\n host === \"::1\" ||\n host === \"0.0.0.0\" ||\n isLocalIPv4(host)\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 if (e != null) return e;\n // Default gate: a dev build, served from a dev machine. `devHostOnly:\n // false` keeps the build check but allows any hostname.\n return isDevBuild() && (opts.devHostOnly === false || isDevHost());\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,88 +0,0 @@
1
- type DockPosition = "bottom-left" | "bottom-right" | "top-left" | "top-right";
2
- /** A navigable destination shown in the dock's "Routes" section. */
3
- interface DevRoute {
4
- /** Path to navigate to, e.g. "/admin/users". */
5
- path: string;
6
- /** Human label. Defaults to `path`. */
7
- label?: string;
8
- /** Optional group heading to organize the list. */
9
- group?: string;
10
- }
11
- /** A custom action shown in the dock's "Commands" section. */
12
- interface DevCommand {
13
- /** Stable id (used as key). Defaults to `label`. */
14
- id?: string;
15
- /** Human label shown in the list. */
16
- label: string;
17
- /** Called when the command is selected. May be async. */
18
- run: () => void | Promise<void>;
19
- /** Optional group heading to organize the list. */
20
- group?: string;
21
- /** Keep the popup open after running (default: false — it closes). */
22
- keepOpen?: boolean;
23
- }
24
- /** Framework-agnostic configuration for the dock. */
25
- interface DevDockOptions {
26
- /** Routes to list. */
27
- routes?: DevRoute[];
28
- /** Custom commands to list. */
29
- commands?: DevCommand[];
30
- /**
31
- * Whether the dock renders at all. Accepts a boolean or a predicate
32
- * (re-evaluated on every `update`). Takes over the gating completely — both
33
- * the `NODE_ENV` and the dev-host check are skipped when it's set.
34
- *
35
- * When omitted, the dock renders only in development: a dev build
36
- * (`process.env.NODE_ENV !== "production"`) served from a dev host (see
37
- * {@link DevDockOptions.devHostOnly}).
38
- *
39
- * @example enabled: () => location.search.includes("debug")
40
- */
41
- enabled?: boolean | (() => boolean);
42
- /**
43
- * Also require the page to be served from a developer's machine — loopback,
44
- * an mDNS `.local` name, or a private LAN address. Default: `true`.
45
- *
46
- * This catches the case `NODE_ENV` can't: a development build deployed to a
47
- * real URL (a preview deploy, a staging box) still reports
48
- * `NODE_ENV !== "production"`. Set `false` to drop the hostname check and
49
- * gate on the build alone — e.g. to keep the dock on a shared staging
50
- * environment or behind a dev tunnel. Ignored when `enabled` is set.
51
- */
52
- devHostOnly?: boolean;
53
- /**
54
- * How to navigate when a route is selected.
55
- * Defaults to `window.location.assign(path)`.
56
- */
57
- onNavigate?: (path: string) => void;
58
- /** Corner to anchor the button. Default: "bottom-right". */
59
- position?: DockPosition;
60
- /** Text on the floating button. Default: "DEV". */
61
- label?: string;
62
- /** Heading shown at the top of the popup. Default: "Dev Menu". */
63
- title?: string;
64
- /**
65
- * Optional keyboard shortcut to toggle the popup, e.g. "mod+." or
66
- * "ctrl+k". "mod" maps to ⌘ on Mac and Ctrl elsewhere. Default: none.
67
- */
68
- hotkey?: string | null;
69
- /** Base z-index for the floating UI. Default: 2147483000. */
70
- zIndex?: number;
71
- /** Where to mount the dock. Default: `document.body`. */
72
- container?: HTMLElement;
73
- /**
74
- * Render inside a shadow root so the host page's CSS can't affect the dock
75
- * (and vice versa). Default: `true` where supported. Set `false` to render
76
- * in the light DOM (e.g. if you want to style it from the page).
77
- */
78
- shadow?: boolean;
79
- }
80
- /** A live dock instance returned by {@link createDevDock}. */
81
- interface DevDockInstance {
82
- /** Re-render with new options (merged over the current ones). */
83
- update(options: DevDockOptions): void;
84
- /** Remove the dock and all its listeners. */
85
- destroy(): void;
86
- }
87
-
88
- export type { DevCommand as D, DevDockInstance as a, DevDockOptions as b, DevRoute as c, DockPosition as d };
@@ -1,88 +0,0 @@
1
- type DockPosition = "bottom-left" | "bottom-right" | "top-left" | "top-right";
2
- /** A navigable destination shown in the dock's "Routes" section. */
3
- interface DevRoute {
4
- /** Path to navigate to, e.g. "/admin/users". */
5
- path: string;
6
- /** Human label. Defaults to `path`. */
7
- label?: string;
8
- /** Optional group heading to organize the list. */
9
- group?: string;
10
- }
11
- /** A custom action shown in the dock's "Commands" section. */
12
- interface DevCommand {
13
- /** Stable id (used as key). Defaults to `label`. */
14
- id?: string;
15
- /** Human label shown in the list. */
16
- label: string;
17
- /** Called when the command is selected. May be async. */
18
- run: () => void | Promise<void>;
19
- /** Optional group heading to organize the list. */
20
- group?: string;
21
- /** Keep the popup open after running (default: false — it closes). */
22
- keepOpen?: boolean;
23
- }
24
- /** Framework-agnostic configuration for the dock. */
25
- interface DevDockOptions {
26
- /** Routes to list. */
27
- routes?: DevRoute[];
28
- /** Custom commands to list. */
29
- commands?: DevCommand[];
30
- /**
31
- * Whether the dock renders at all. Accepts a boolean or a predicate
32
- * (re-evaluated on every `update`). Takes over the gating completely — both
33
- * the `NODE_ENV` and the dev-host check are skipped when it's set.
34
- *
35
- * When omitted, the dock renders only in development: a dev build
36
- * (`process.env.NODE_ENV !== "production"`) served from a dev host (see
37
- * {@link DevDockOptions.devHostOnly}).
38
- *
39
- * @example enabled: () => location.search.includes("debug")
40
- */
41
- enabled?: boolean | (() => boolean);
42
- /**
43
- * Also require the page to be served from a developer's machine — loopback,
44
- * an mDNS `.local` name, or a private LAN address. Default: `true`.
45
- *
46
- * This catches the case `NODE_ENV` can't: a development build deployed to a
47
- * real URL (a preview deploy, a staging box) still reports
48
- * `NODE_ENV !== "production"`. Set `false` to drop the hostname check and
49
- * gate on the build alone — e.g. to keep the dock on a shared staging
50
- * environment or behind a dev tunnel. Ignored when `enabled` is set.
51
- */
52
- devHostOnly?: boolean;
53
- /**
54
- * How to navigate when a route is selected.
55
- * Defaults to `window.location.assign(path)`.
56
- */
57
- onNavigate?: (path: string) => void;
58
- /** Corner to anchor the button. Default: "bottom-right". */
59
- position?: DockPosition;
60
- /** Text on the floating button. Default: "DEV". */
61
- label?: string;
62
- /** Heading shown at the top of the popup. Default: "Dev Menu". */
63
- title?: string;
64
- /**
65
- * Optional keyboard shortcut to toggle the popup, e.g. "mod+." or
66
- * "ctrl+k". "mod" maps to ⌘ on Mac and Ctrl elsewhere. Default: none.
67
- */
68
- hotkey?: string | null;
69
- /** Base z-index for the floating UI. Default: 2147483000. */
70
- zIndex?: number;
71
- /** Where to mount the dock. Default: `document.body`. */
72
- container?: HTMLElement;
73
- /**
74
- * Render inside a shadow root so the host page's CSS can't affect the dock
75
- * (and vice versa). Default: `true` where supported. Set `false` to render
76
- * in the light DOM (e.g. if you want to style it from the page).
77
- */
78
- shadow?: boolean;
79
- }
80
- /** A live dock instance returned by {@link createDevDock}. */
81
- interface DevDockInstance {
82
- /** Re-render with new options (merged over the current ones). */
83
- update(options: DevDockOptions): void;
84
- /** Remove the dock and all its listeners. */
85
- destroy(): void;
86
- }
87
-
88
- export type { DevCommand as D, DevDockInstance as a, DevDockOptions as b, DevRoute as c, DockPosition as d };