@chuvenger/devdock 0.4.1 → 0.6.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 +206 -16
- package/dist/chunk-3MVFATRN.js +60 -0
- package/dist/chunk-3MVFATRN.js.map +1 -0
- package/dist/{chunk-WVRXVSEL.js → chunk-NXZNFF34.js} +229 -42
- package/dist/chunk-NXZNFF34.js.map +1 -0
- package/dist/{dock-DOWeFZJ5.d.ts → dock-P6l6pKjS.d.ts} +1 -1
- package/dist/{dock-dq6OS0Jm.d.cts → dock-d3HqT25k.d.cts} +1 -1
- package/dist/index.cjs +226 -39
- 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/{match-BZoH6rW7.d.cts → match-DDSJIRYW.d.cts} +1 -1
- package/dist/{match-D1am9aTf.d.ts → match-DwGIF1Xt.d.ts} +1 -1
- package/dist/react-router.cjs +365 -52
- package/dist/react-router.cjs.map +1 -1
- package/dist/react-router.d.cts +58 -11
- package/dist/react-router.d.ts +58 -11
- package/dist/react-router.js +101 -8
- package/dist/react-router.js.map +1 -1
- package/dist/react.cjs +268 -47
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +28 -8
- package/dist/react.d.ts +28 -8
- package/dist/react.js +2 -2
- package/dist/svelte.cjs +226 -39
- 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/svelte.js.map +1 -1
- package/dist/sveltekit.cjs +226 -39
- package/dist/sveltekit.cjs.map +1 -1
- package/dist/sveltekit.d.cts +4 -4
- package/dist/sveltekit.d.ts +4 -4
- package/dist/sveltekit.js +2 -2
- package/dist/sveltekit.js.map +1 -1
- package/dist/{types-B-V99upW.d.cts → types-B_SpF32A.d.cts} +73 -5
- package/dist/{types-B-V99upW.d.ts → types-B_SpF32A.d.ts} +73 -5
- package/package.json +1 -1
- package/dist/chunk-P4ZUS4GB.js +0 -24
- package/dist/chunk-P4ZUS4GB.js.map +0 -1
- package/dist/chunk-WVRXVSEL.js.map +0 -1
package/dist/react-router.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { DevDock } from './chunk-
|
|
1
|
+
import { DevDock } from './chunk-3MVFATRN.js';
|
|
2
2
|
import { isDevPath, isMatcher, dedupeByPath, toPredicate } from './chunk-NRBOZ6H5.js';
|
|
3
|
-
import './chunk-
|
|
4
|
-
import { useContext, useMemo } from 'react';
|
|
3
|
+
import './chunk-NXZNFF34.js';
|
|
4
|
+
import { useContext, useMemo, useState, useEffect, useRef } from 'react';
|
|
5
5
|
import { UNSAFE_DataRouterContext, useNavigate } from 'react-router';
|
|
6
6
|
import { jsx } from 'react/jsx-runtime';
|
|
7
7
|
|
|
@@ -36,23 +36,116 @@ function walk(routes, parent, staticRoutes, inherited) {
|
|
|
36
36
|
}
|
|
37
37
|
return out;
|
|
38
38
|
}
|
|
39
|
+
var NO_ROUTES = [];
|
|
40
|
+
var NO_HANDLES = /* @__PURE__ */ new Map();
|
|
41
|
+
function lazyHandleOf(route) {
|
|
42
|
+
const lazy = route.lazy;
|
|
43
|
+
if (typeof lazy === "function") return async () => (await lazy())?.handle;
|
|
44
|
+
return typeof lazy?.handle === "function" ? lazy.handle : void 0;
|
|
45
|
+
}
|
|
46
|
+
async function readLazyHandle(route) {
|
|
47
|
+
try {
|
|
48
|
+
return await lazyHandleOf(route)?.();
|
|
49
|
+
} catch {
|
|
50
|
+
return void 0;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function collectLazy(routes, out = []) {
|
|
54
|
+
for (const r of routes) {
|
|
55
|
+
if (r.handle == null && lazyHandleOf(r) != null) out.push(r);
|
|
56
|
+
if (r.children?.length) collectLazy(r.children, out);
|
|
57
|
+
}
|
|
58
|
+
return out;
|
|
59
|
+
}
|
|
60
|
+
function signature(routes, out = []) {
|
|
61
|
+
for (const r of routes) {
|
|
62
|
+
const h = r.handle;
|
|
63
|
+
out.push(
|
|
64
|
+
`${r.path ?? ""}|${r.index ? 1 : 0}|${h?.dev}|${h?.devLabel}|${h?.devGroup}|${h?.hidden}|${lazyHandleOf(r) ? 1 : 0}`
|
|
65
|
+
);
|
|
66
|
+
if (r.children?.length) signature(r.children, out);
|
|
67
|
+
}
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
function useRouteTree(router) {
|
|
71
|
+
const routes = router?.routes ?? NO_ROUTES;
|
|
72
|
+
const [sig, setSig] = useState(() => signature(routes).join("\n"));
|
|
73
|
+
useEffect(() => {
|
|
74
|
+
if (!router?.subscribe) return;
|
|
75
|
+
const check = () => {
|
|
76
|
+
const next = signature(router.routes ?? NO_ROUTES).join("\n");
|
|
77
|
+
setSig((prev) => prev === next ? prev : next);
|
|
78
|
+
};
|
|
79
|
+
check();
|
|
80
|
+
return router.subscribe(check);
|
|
81
|
+
}, [router]);
|
|
82
|
+
return [routes, sig];
|
|
83
|
+
}
|
|
84
|
+
function useLazyHandles(routes, sig, enabled) {
|
|
85
|
+
const [handles, setHandles] = useState(NO_HANDLES);
|
|
86
|
+
const started = useRef(
|
|
87
|
+
/* @__PURE__ */ new WeakMap()
|
|
88
|
+
);
|
|
89
|
+
useEffect(() => {
|
|
90
|
+
if (!enabled) return;
|
|
91
|
+
const targets = collectLazy(routes);
|
|
92
|
+
if (targets.length === 0) return;
|
|
93
|
+
let cancelled = false;
|
|
94
|
+
void Promise.all(
|
|
95
|
+
targets.map((route) => {
|
|
96
|
+
let pending = started.current.get(route);
|
|
97
|
+
if (!pending) {
|
|
98
|
+
pending = readLazyHandle(route);
|
|
99
|
+
started.current.set(route, pending);
|
|
100
|
+
}
|
|
101
|
+
return pending.then((handle) => [route, handle]);
|
|
102
|
+
})
|
|
103
|
+
).then((resolved) => {
|
|
104
|
+
if (cancelled) return;
|
|
105
|
+
const found = resolved.filter(
|
|
106
|
+
(entry) => entry[1] != null
|
|
107
|
+
);
|
|
108
|
+
setHandles(
|
|
109
|
+
(prev) => found.some(([route, handle]) => prev.get(route) !== handle) ? new Map([...prev, ...found]) : prev
|
|
110
|
+
);
|
|
111
|
+
});
|
|
112
|
+
return () => {
|
|
113
|
+
cancelled = true;
|
|
114
|
+
};
|
|
115
|
+
}, [routes, sig, enabled]);
|
|
116
|
+
return handles;
|
|
117
|
+
}
|
|
118
|
+
function mergeHandles(routes, handles) {
|
|
119
|
+
let changed = false;
|
|
120
|
+
const merged = routes.map((r) => {
|
|
121
|
+
const handle = r.handle ?? handles.get(r);
|
|
122
|
+
const children = r.children ? mergeHandles(r.children, handles) : r.children;
|
|
123
|
+
if (handle === r.handle && children === r.children) return r;
|
|
124
|
+
changed = true;
|
|
125
|
+
return { ...r, handle, children };
|
|
126
|
+
});
|
|
127
|
+
return changed ? merged : routes;
|
|
128
|
+
}
|
|
39
129
|
function useDetectedRoutes(options = {}) {
|
|
40
130
|
const opts = isMatcher(options) ? { match: options } : options;
|
|
41
|
-
const { match, staticRoutes } = opts;
|
|
131
|
+
const { match, staticRoutes, loadHandles } = opts;
|
|
42
132
|
const ctx = useContext(UNSAFE_DataRouterContext);
|
|
43
|
-
const routes = ctx?.router
|
|
133
|
+
const [routes, sig] = useRouteTree(ctx?.router);
|
|
134
|
+
const handles = useLazyHandles(routes, sig, loadHandles === true);
|
|
44
135
|
return useMemo(() => {
|
|
45
|
-
const
|
|
136
|
+
const tree = handles.size > 0 ? mergeHandles(routes, handles) : routes;
|
|
137
|
+
const deduped = dedupeByPath(flattenRoutes(tree, "", { staticRoutes }));
|
|
46
138
|
return match ? deduped.filter(toPredicate(match)) : deduped;
|
|
47
|
-
}, [routes, match, staticRoutes]);
|
|
139
|
+
}, [routes, sig, handles, match, staticRoutes]);
|
|
48
140
|
}
|
|
49
141
|
function ReactRouterDevDock({
|
|
50
142
|
match,
|
|
51
143
|
staticRoutes,
|
|
144
|
+
loadHandles,
|
|
52
145
|
...props
|
|
53
146
|
}) {
|
|
54
147
|
const navigate = useNavigate();
|
|
55
|
-
const detected = useDetectedRoutes({ match, staticRoutes });
|
|
148
|
+
const detected = useDetectedRoutes({ match, staticRoutes, loadHandles });
|
|
56
149
|
const routes = useMemo(
|
|
57
150
|
() => [...detected, ...props.routes ?? []],
|
|
58
151
|
[detected, props.routes]
|
package/dist/react-router.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/react/react-router.tsx"],"names":["DataRouterContext"],"mappings":"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","file":"react-router.js","sourcesContent":["import { useContext, useMemo } from \"react\";\nimport {\n useNavigate,\n // UNSAFE_DataRouterContext is the supported way to reach the active\n // router instance (and its full route tree) for data routers. Imported\n // from `react-router` (not `react-router-dom`) so this works on v6, v7\n // and v8 — v8 dropped the `react-router-dom` package entirely.\n UNSAFE_DataRouterContext as DataRouterContext,\n} from \"react-router\";\nimport { DevDock, type DevDockProps } from \"./DevDock\";\nimport type { DevRoute } from \"../core/types\";\nimport {\n dedupeByPath,\n isDevPath,\n isMatcher,\n toPredicate,\n type RouteMatcher,\n} from \"../core/match\";\n\nexport type { RouteMatcher };\n\n/** Minimal shape of a react-router route object we care about. */\ninterface RRRoute {\n path?: string;\n index?: boolean;\n children?: RRRoute[];\n handle?: {\n dev?: boolean;\n devLabel?: string;\n devGroup?: string;\n hidden?: boolean;\n } & Record<string, unknown>;\n}\n\nfunction joinPath(parent: string, child: string): string {\n if (child.startsWith(\"/\")) return child;\n if (!child) return parent || \"/\";\n const base = parent.endsWith(\"/\") ? parent.slice(0, -1) : parent;\n return `${base}/${child}`;\n}\n\n/** Opt-in markers that make a route a dev destination. */\nfunction isDevMarked(handle: RRRoute[\"handle\"]): boolean {\n return (\n handle?.dev === true || handle?.devLabel != null || handle?.devGroup != null\n );\n}\n\nexport interface DetectOptions {\n /**\n * Only keep routes that match. A glob string (`*` = any characters), a\n * `RegExp`, or a predicate.\n */\n match?: RouteMatcher;\n /**\n * Also list the app's ordinary static routes, not just the dev ones.\n * Default: `false`.\n */\n staticRoutes?: boolean;\n}\n\n/** State handed down to descendants of a dev-marked route. */\ninterface Inherited {\n dev: boolean;\n group?: string;\n}\n\n/**\n * Flatten a react-router route tree into navigable {@link DevRoute}s.\n *\n * Only dev destinations are returned: routes under `/dev`, routes marked with\n * `handle.dev`, `handle.devLabel` or `handle.devGroup`, and everything nested\n * under them. Pass `{ staticRoutes: true }` to list every static route instead.\n *\n * Dynamic (`:param`) and splat (`*`) segments are skipped since they can't be\n * navigated to without arguments. Mark a route with `handle.hidden` to exclude\n * it, or `handle.devLabel` to rename it.\n */\nexport function flattenRoutes(\n routes: RRRoute[],\n parent = \"\",\n options: Pick<DetectOptions, \"staticRoutes\"> = {},\n): DevRoute[] {\n return walk(routes, parent, options.staticRoutes === true, { dev: false });\n}\n\nfunction walk(\n routes: RRRoute[],\n parent: string,\n staticRoutes: boolean,\n inherited: Inherited,\n): DevRoute[] {\n const out: DevRoute[] = [];\n for (const r of routes) {\n const full = r.index ? parent : joinPath(parent, r.path ?? \"\");\n // A dev route makes its whole subtree dev, so marking a section's layout\n // route is enough to surface the pages inside it. The `/dev` check reads\n // the joined path, which also catches flat routes like `dev/inspector`.\n const dev = inherited.dev || isDevMarked(r.handle) || isDevPath(full);\n const group = r.handle?.devGroup ?? inherited.group;\n const navigable =\n !r.index &&\n r.path != null &&\n !full.includes(\":\") &&\n !full.includes(\"*\") &&\n r.handle?.hidden !== true &&\n (dev || staticRoutes);\n if (navigable) {\n out.push({\n path: full || \"/\",\n label: r.handle?.devLabel ?? (full || \"/\"),\n group,\n });\n }\n if (r.children?.length)\n out.push(...walk(r.children, full, staticRoutes, { dev, group }));\n }\n return out;\n}\n\n/**\n * Read the dev routes off the active react-router data router — anything under\n * `/dev` or marked with `handle.dev` / `devLabel` / `devGroup`, plus their\n * children.\n * Pass `{ staticRoutes: true }` to include the app's ordinary routes too, and\n * `{ match }` to scope the results. A bare matcher is accepted as shorthand.\n */\nexport function useDetectedRoutes(\n options: DetectOptions | RouteMatcher = {},\n): DevRoute[] {\n const opts: DetectOptions = isMatcher(options) ? { match: options } : options;\n const { match, staticRoutes } = opts;\n const ctx = useContext(DataRouterContext);\n const routes = (ctx?.router?.routes ?? []) as RRRoute[];\n return useMemo(() => {\n const deduped = dedupeByPath(flattenRoutes(routes, \"\", { staticRoutes }));\n return match ? deduped.filter(toPredicate(match)) : deduped;\n }, [routes, match, staticRoutes]);\n}\n\nexport interface ReactRouterDevDockProps extends DevDockProps {\n /**\n * Only auto-detect routes that match. A glob string (`*` = any characters,\n * e.g. `\"/dev/*\"`), a `RegExp`, or a predicate. Manual `routes` are always\n * included regardless of this filter.\n */\n match?: RouteMatcher;\n /**\n * List the app's ordinary static routes alongside the dev ones.\n * Off by default, so the dock only shows what you opted in.\n */\n staticRoutes?: boolean;\n}\n\n/**\n * Drop-in {@link DevDock} for react-router apps: navigates via the SPA router\n * and auto-detects the dev routes from the active data router. Any `routes`\n * you pass are appended to the detected ones.\n */\nexport function ReactRouterDevDock({\n match,\n staticRoutes,\n ...props\n}: ReactRouterDevDockProps) {\n const navigate = useNavigate();\n const detected = useDetectedRoutes({ match, staticRoutes });\n const routes = useMemo(\n () => [...detected, ...(props.routes ?? [])],\n [detected, props.routes],\n );\n return (\n <DevDock\n {...props}\n routes={routes}\n onNavigate={props.onNavigate ?? ((path) => navigate(path))}\n />\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/react/react-router.tsx"],"names":["DataRouterContext"],"mappings":"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","file":"react-router.js","sourcesContent":["import { useContext, useEffect, useMemo, useRef, useState } from \"react\";\nimport {\n useNavigate,\n // UNSAFE_DataRouterContext is the supported way to reach the active\n // router instance (and its full route tree) for data routers. Imported\n // from `react-router` (not `react-router-dom`) so this works on v6, v7\n // and v8 — v8 dropped the `react-router-dom` package entirely.\n UNSAFE_DataRouterContext as DataRouterContext,\n} from \"react-router\";\nimport { DevDock, type DevDockProps } from \"./DevDock\";\nimport type { DevRoute } from \"../core/types\";\nimport {\n dedupeByPath,\n isDevPath,\n isMatcher,\n toPredicate,\n type RouteMatcher,\n} from \"../core/match\";\n\nexport type { RouteMatcher };\n\n/** The `handle` fields the dock reads off a route. */\ninterface DevHandle {\n dev?: boolean;\n devLabel?: string;\n devGroup?: string;\n hidden?: boolean;\n /** Whatever else the app puts on `handle`; the dock ignores it. */\n [key: string]: unknown;\n}\n\n/** `handle` loader for one route property, as lazy route objects expose it. */\ntype LazyProperty<T> = () => Promise<T | undefined>;\n\n/** Minimal shape of a react-router route object we care about. */\ninterface RRRoute {\n path?: string;\n index?: boolean;\n children?: RRRoute[];\n handle?: DevHandle;\n /**\n * Set while the route's module is still unloaded. Two shapes exist: a\n * function resolving to the module, whose exports are the route's properties\n * (`lazy: () => import(\"./route\")`, v6.19+), and an object with one loader\n * per property (v7.5+, and what framework mode builds for every route).\n * `handle` rides along in both.\n */\n lazy?:\n LazyProperty<{ handle?: DevHandle }> | { handle?: LazyProperty<DevHandle> };\n}\n\n/** The slice of the data router the adapter uses, across v6/v7/v8. */\ninterface RRRouter {\n routes?: RRRoute[];\n subscribe?: (listener: () => void) => () => void;\n}\n\nfunction joinPath(parent: string, child: string): string {\n if (child.startsWith(\"/\")) return child;\n if (!child) return parent || \"/\";\n const base = parent.endsWith(\"/\") ? parent.slice(0, -1) : parent;\n return `${base}/${child}`;\n}\n\n/** Opt-in markers that make a route a dev destination. */\nfunction isDevMarked(handle: RRRoute[\"handle\"]): boolean {\n return (\n handle?.dev === true || handle?.devLabel != null || handle?.devGroup != null\n );\n}\n\nexport interface DetectOptions {\n /**\n * Only keep routes that match. A glob string (`*` = any characters), a\n * `RegExp`, or a predicate.\n */\n match?: RouteMatcher;\n /**\n * Also list the app's ordinary static routes, not just the dev ones.\n * Default: `false`.\n */\n staticRoutes?: boolean;\n /**\n * Import lazy route modules to read their `handle`.\n *\n * In framework mode (`app/routes.ts`) every route is lazy, so `handle` is\n * not on the route object the router exposes — it lives in the route module\n * and only reaches the route once that module loads, i.e. once you visit the\n * page. Without this, framework-mode routes are detected by the `/dev/*`\n * path convention alone and `handle.dev` / `devLabel` / `devGroup` /\n * `hidden` are silently ignored.\n *\n * Opt-in because reading a handle up front means importing the module up\n * front — dev only, but that is still every lazy route's module, and any\n * import side effects with it. Default: `false`.\n */\n loadHandles?: boolean;\n}\n\n/** State handed down to descendants of a dev-marked route. */\ninterface Inherited {\n dev: boolean;\n group?: string;\n}\n\n/**\n * Flatten a react-router route tree into navigable {@link DevRoute}s.\n *\n * Only dev destinations are returned: routes under `/dev`, routes marked with\n * `handle.dev`, `handle.devLabel` or `handle.devGroup`, and everything nested\n * under them. Pass `{ staticRoutes: true }` to list every static route instead.\n *\n * Dynamic (`:param`) and splat (`*`) segments are skipped since they can't be\n * navigated to without arguments. Mark a route with `handle.hidden` to exclude\n * it, or `handle.devLabel` to rename it.\n *\n * Reads `handle` straight off each route object, so a tree whose routes are\n * still lazy has no handles to read — see {@link DetectOptions.loadHandles}.\n */\nexport function flattenRoutes(\n routes: RRRoute[],\n parent = \"\",\n options: Pick<DetectOptions, \"staticRoutes\"> = {},\n): DevRoute[] {\n return walk(routes, parent, options.staticRoutes === true, { dev: false });\n}\n\nfunction walk(\n routes: RRRoute[],\n parent: string,\n staticRoutes: boolean,\n inherited: Inherited,\n): DevRoute[] {\n const out: DevRoute[] = [];\n for (const r of routes) {\n const full = r.index ? parent : joinPath(parent, r.path ?? \"\");\n // A dev route makes its whole subtree dev, so marking a section's layout\n // route is enough to surface the pages inside it. The `/dev` check reads\n // the joined path, which also catches flat routes like `dev/inspector`.\n const dev = inherited.dev || isDevMarked(r.handle) || isDevPath(full);\n const group = r.handle?.devGroup ?? inherited.group;\n const navigable =\n !r.index &&\n r.path != null &&\n !full.includes(\":\") &&\n !full.includes(\"*\") &&\n r.handle?.hidden !== true &&\n (dev || staticRoutes);\n if (navigable) {\n out.push({\n path: full || \"/\",\n label: r.handle?.devLabel ?? (full || \"/\"),\n group,\n });\n }\n if (r.children?.length)\n out.push(...walk(r.children, full, staticRoutes, { dev, group }));\n }\n return out;\n}\n\n// ---- lazy handles ---------------------------------------------------------\n\nconst NO_ROUTES: RRRoute[] = [];\nconst NO_HANDLES: ReadonlyMap<RRRoute, DevHandle> = new Map();\n\n/** The route's `handle` loader, whichever `lazy` shape it uses. */\nfunction lazyHandleOf(route: RRRoute): LazyProperty<DevHandle> | undefined {\n const lazy = route.lazy;\n if (typeof lazy === \"function\") return async () => (await lazy())?.handle;\n return typeof lazy?.handle === \"function\" ? lazy.handle : undefined;\n}\n\nasync function readLazyHandle(route: RRRoute): Promise<DevHandle | undefined> {\n try {\n return await lazyHandleOf(route)?.();\n } catch {\n // A route module that won't load is the app's problem, not the dock's.\n // Fall back to listing the route by path.\n return undefined;\n }\n}\n\nfunction collectLazy(routes: RRRoute[], out: RRRoute[] = []): RRRoute[] {\n for (const r of routes) {\n // A `handle` already on the route is the router's own resolved value.\n if (r.handle == null && lazyHandleOf(r) != null) out.push(r);\n if (r.children?.length) collectLazy(r.children, out);\n }\n return out;\n}\n\n/**\n * Everything the dock reads out of the route tree, as a comparable string.\n *\n * Neither the tree's identity nor its contents are a reliable change signal on\n * their own: the router resolves `lazy` by mutating route objects in place, and\n * patches discovered branches into the arrays it already handed out. Only some\n * versions swap the top-level array. So compare what we actually read.\n */\nfunction signature(routes: RRRoute[], out: string[] = []): string[] {\n for (const r of routes) {\n const h = r.handle;\n out.push(\n `${r.path ?? \"\"}|${r.index ? 1 : 0}|${h?.dev}|${h?.devLabel}` +\n `|${h?.devGroup}|${h?.hidden}|${lazyHandleOf(r) ? 1 : 0}`,\n );\n if (r.children?.length) signature(r.children, out);\n }\n return out;\n}\n\n/**\n * The router's route tree, plus a signature that changes whenever the tree\n * does. Routes arrive late in framework mode — `lazy` modules resolve on\n * navigation and lazy route discovery patches whole branches in as links\n * render — and both land as a router state update.\n */\nfunction useRouteTree(router: RRRouter | undefined): [RRRoute[], string] {\n const routes = router?.routes ?? NO_ROUTES;\n const [sig, setSig] = useState(() => signature(routes).join(\"\\n\"));\n useEffect(() => {\n if (!router?.subscribe) return;\n const check = () => {\n const next = signature(router.routes ?? NO_ROUTES).join(\"\\n\");\n setSig((prev) => (prev === next ? prev : next));\n };\n // The tree can have moved between render and effect.\n check();\n return router.subscribe(check);\n }, [router]);\n return [routes, sig];\n}\n\n/** Handles read out of lazy route modules, keyed by route object. */\nfunction useLazyHandles(\n routes: RRRoute[],\n sig: string,\n enabled: boolean,\n): ReadonlyMap<RRRoute, DevHandle> {\n const [handles, setHandles] = useState(NO_HANDLES);\n // Promises, not values, and keyed by the route objects the router reuses: a\n // module is imported once no matter how often the effect re-runs, and an\n // effect that was cleaned up mid-flight (StrictMode's double invoke) can\n // re-await the same work instead of dropping it.\n const started = useRef(\n new WeakMap<RRRoute, Promise<DevHandle | undefined>>(),\n );\n useEffect(() => {\n if (!enabled) return;\n const targets = collectLazy(routes);\n if (targets.length === 0) return;\n let cancelled = false;\n void Promise.all(\n targets.map((route) => {\n let pending = started.current.get(route);\n if (!pending) {\n pending = readLazyHandle(route);\n started.current.set(route, pending);\n }\n return pending.then((handle) => [route, handle] as const);\n }),\n ).then((resolved) => {\n if (cancelled) return;\n const found = resolved.filter(\n (entry): entry is [RRRoute, DevHandle] => entry[1] != null,\n );\n setHandles((prev) =>\n found.some(([route, handle]) => prev.get(route) !== handle)\n ? new Map([...prev, ...found])\n : prev,\n );\n });\n return () => {\n cancelled = true;\n };\n }, [routes, sig, enabled]);\n return handles;\n}\n\n/**\n * The tree with lazily-read handles filled in. A copy rather than a mutation:\n * assigning `route.handle` ourselves makes the router warn about a \"static\n * property\" and skip its own resolution of the lazy one.\n */\nfunction mergeHandles(\n routes: RRRoute[],\n handles: ReadonlyMap<RRRoute, DevHandle>,\n): RRRoute[] {\n let changed = false;\n const merged = routes.map((r) => {\n const handle = r.handle ?? handles.get(r);\n const children = r.children\n ? mergeHandles(r.children, handles)\n : r.children;\n if (handle === r.handle && children === r.children) return r;\n changed = true;\n return { ...r, handle, children };\n });\n return changed ? merged : routes;\n}\n\n/**\n * Read the dev routes off the active react-router data router — anything under\n * `/dev` or marked with `handle.dev` / `devLabel` / `devGroup`, plus their\n * children.\n * Pass `{ staticRoutes: true }` to include the app's ordinary routes too,\n * `{ match }` to scope the results, and `{ loadHandles: true }` to read\n * `handle` from routes whose module hasn't loaded yet (framework mode). A bare\n * matcher is accepted as shorthand.\n *\n * Re-reads the tree as the router grows it, so routes that are discovered or\n * resolved after the first render show up on their own.\n */\nexport function useDetectedRoutes(\n options: DetectOptions | RouteMatcher = {},\n): DevRoute[] {\n const opts: DetectOptions = isMatcher(options) ? { match: options } : options;\n const { match, staticRoutes, loadHandles } = opts;\n const ctx = useContext(DataRouterContext);\n const [routes, sig] = useRouteTree(ctx?.router as RRRouter | undefined);\n const handles = useLazyHandles(routes, sig, loadHandles === true);\n // `sig` is a dep because the tree is mutated in place (see useRouteTree).\n return useMemo(() => {\n const tree = handles.size > 0 ? mergeHandles(routes, handles) : routes;\n const deduped = dedupeByPath(flattenRoutes(tree, \"\", { staticRoutes }));\n return match ? deduped.filter(toPredicate(match)) : deduped;\n }, [routes, sig, handles, match, staticRoutes]);\n}\n\nexport interface ReactRouterDevDockProps extends DevDockProps {\n /**\n * Only auto-detect routes that match. A glob string (`*` = any characters,\n * e.g. `\"/dev/*\"`), a `RegExp`, or a predicate. Manual `routes` are always\n * included regardless of this filter.\n */\n match?: RouteMatcher;\n /**\n * List the app's ordinary static routes alongside the dev ones.\n * Off by default, so the dock only shows what you opted in.\n */\n staticRoutes?: boolean;\n /**\n * Import lazy route modules so their `handle` is visible. Needed for\n * `handle.dev` / `devLabel` / `devGroup` / `hidden` in React Router\n * framework mode. See {@link DetectOptions.loadHandles}.\n */\n loadHandles?: boolean;\n}\n\n/**\n * Drop-in {@link DevDock} for react-router apps: navigates via the SPA router\n * and auto-detects the dev routes from the active data router. Any `routes`\n * you pass are appended to the detected ones.\n */\nexport function ReactRouterDevDock({\n match,\n staticRoutes,\n loadHandles,\n ...props\n}: ReactRouterDevDockProps) {\n const navigate = useNavigate();\n const detected = useDetectedRoutes({ match, staticRoutes, loadHandles });\n const routes = useMemo(\n () => [...detected, ...(props.routes ?? [])],\n [detected, props.routes],\n );\n return (\n <DevDock\n {...props}\n routes={routes}\n onNavigate={props.onNavigate ?? ((path) => navigate(path))}\n />\n );\n}\n"]}
|
package/dist/react.cjs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var react = require('react');
|
|
4
|
+
var reactDom = require('react-dom');
|
|
5
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
6
|
|
|
5
7
|
// src/react/DevDock.tsx
|
|
6
8
|
|
|
@@ -58,6 +60,27 @@ function el(tag, styles, props) {
|
|
|
58
60
|
if (props) Object.assign(node, props);
|
|
59
61
|
return node;
|
|
60
62
|
}
|
|
63
|
+
function sectionHeading(text) {
|
|
64
|
+
return el(
|
|
65
|
+
"div",
|
|
66
|
+
{
|
|
67
|
+
padding: "6px 8px 2px",
|
|
68
|
+
fontSize: "10px",
|
|
69
|
+
fontWeight: "700",
|
|
70
|
+
letterSpacing: "0.6px",
|
|
71
|
+
textTransform: "uppercase",
|
|
72
|
+
color: "#6b7280"
|
|
73
|
+
},
|
|
74
|
+
{ textContent: text }
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
function viewLabel(text) {
|
|
78
|
+
return el(
|
|
79
|
+
"div",
|
|
80
|
+
{ padding: "4px 8px 0", fontSize: "11px", color: "#8b909c" },
|
|
81
|
+
{ textContent: text }
|
|
82
|
+
);
|
|
83
|
+
}
|
|
61
84
|
function cornerStyle(position) {
|
|
62
85
|
const gap = "16px";
|
|
63
86
|
switch (position) {
|
|
@@ -81,6 +104,15 @@ function panelAnchor(position) {
|
|
|
81
104
|
};
|
|
82
105
|
}
|
|
83
106
|
var FONT = "ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif";
|
|
107
|
+
function keyViews(views) {
|
|
108
|
+
const used = /* @__PURE__ */ new Set();
|
|
109
|
+
return views.map((view, i) => {
|
|
110
|
+
let key = view.id ?? `#${i}`;
|
|
111
|
+
while (used.has(key)) key = `${key}#${i}`;
|
|
112
|
+
used.add(key);
|
|
113
|
+
return { view, key };
|
|
114
|
+
});
|
|
115
|
+
}
|
|
84
116
|
function createDevDock(initial = {}) {
|
|
85
117
|
if (typeof document === "undefined") {
|
|
86
118
|
return { update() {
|
|
@@ -94,9 +126,12 @@ function createDevDock(initial = {}) {
|
|
|
94
126
|
let mounted = false;
|
|
95
127
|
const host = el("div");
|
|
96
128
|
host.setAttribute("data-devdock", "");
|
|
97
|
-
const
|
|
129
|
+
const shadowMode = initial.shadow ?? true;
|
|
130
|
+
const useShadow = shadowMode !== false && typeof host.attachShadow === "function";
|
|
98
131
|
const shadowRoot = useShadow ? host.attachShadow({ mode: "open" }) : null;
|
|
99
132
|
const mountPoint = shadowRoot ?? host;
|
|
133
|
+
const styleSlot = shadowRoot && shadowMode === "inherit" ? el("div", { display: "contents" }) : null;
|
|
134
|
+
if (styleSlot) mountPoint.appendChild(styleSlot);
|
|
100
135
|
const root = el("div", { fontFamily: FONT });
|
|
101
136
|
mountPoint.appendChild(root);
|
|
102
137
|
const panel = el("div", {
|
|
@@ -135,8 +170,19 @@ function createDevDock(initial = {}) {
|
|
|
135
170
|
});
|
|
136
171
|
input.placeholder = "Filter\u2026";
|
|
137
172
|
inputWrap.appendChild(input);
|
|
138
|
-
const list = el("div", {
|
|
139
|
-
|
|
173
|
+
const list = el("div", { padding: "0 6px 8px" });
|
|
174
|
+
list.setAttribute("data-devdock-list", "");
|
|
175
|
+
const viewsBefore = el("div");
|
|
176
|
+
viewsBefore.setAttribute("data-devdock-views", "before");
|
|
177
|
+
const viewsAfter = el("div");
|
|
178
|
+
viewsAfter.setAttribute("data-devdock-views", "after");
|
|
179
|
+
const body = el("div", {
|
|
180
|
+
overflowY: "auto",
|
|
181
|
+
display: "flex",
|
|
182
|
+
flexDirection: "column"
|
|
183
|
+
});
|
|
184
|
+
body.append(viewsBefore, list, viewsAfter);
|
|
185
|
+
panel.append(heading, inputWrap, body);
|
|
140
186
|
const button = el("button", {
|
|
141
187
|
display: "inline-flex",
|
|
142
188
|
alignItems: "center",
|
|
@@ -177,20 +223,35 @@ function createDevDock(initial = {}) {
|
|
|
177
223
|
const buildItems = () => {
|
|
178
224
|
const out = [];
|
|
179
225
|
(opts.routes ?? []).forEach((r, i) => {
|
|
226
|
+
const key = `route:${r.path}:${i}`;
|
|
227
|
+
const label = r.label ?? r.path;
|
|
180
228
|
out.push({
|
|
181
229
|
kind: "route",
|
|
182
|
-
key
|
|
183
|
-
label
|
|
230
|
+
key,
|
|
231
|
+
label,
|
|
184
232
|
group: r.group ?? "Routes",
|
|
233
|
+
sig: [key, r.group ?? "Routes", label, r.path].join("\0"),
|
|
185
234
|
route: r
|
|
186
235
|
});
|
|
187
236
|
});
|
|
188
237
|
(opts.commands ?? []).forEach((c, i) => {
|
|
238
|
+
const live = typeof c.label === "function";
|
|
239
|
+
const label = typeof c.label === "function" ? c.label() : c.label;
|
|
240
|
+
const checked = c.checked ? c.checked() === true : null;
|
|
241
|
+
const key = `cmd:${c.id ?? (live ? "" : label)}:${i}`;
|
|
242
|
+
const group = c.group ?? "Commands";
|
|
189
243
|
out.push({
|
|
190
244
|
kind: "command",
|
|
191
|
-
key
|
|
192
|
-
label
|
|
193
|
-
group
|
|
245
|
+
key,
|
|
246
|
+
label,
|
|
247
|
+
group,
|
|
248
|
+
sig: [
|
|
249
|
+
key,
|
|
250
|
+
group,
|
|
251
|
+
live ? "\0live" : label,
|
|
252
|
+
checked === null ? "" : "\0checkable"
|
|
253
|
+
].join("\0"),
|
|
254
|
+
checked,
|
|
194
255
|
command: c
|
|
195
256
|
});
|
|
196
257
|
});
|
|
@@ -218,9 +279,17 @@ function createDevDock(initial = {}) {
|
|
|
218
279
|
};
|
|
219
280
|
let rows = [];
|
|
220
281
|
let rowsSig = null;
|
|
221
|
-
const itemSig = (it) =>
|
|
222
|
-
|
|
223
|
-
|
|
282
|
+
const itemSig = (it) => it.sig;
|
|
283
|
+
const paintRow = (row) => {
|
|
284
|
+
const it = row.item;
|
|
285
|
+
if (row.labelSpan.textContent !== it.label)
|
|
286
|
+
row.labelSpan.textContent = it.label;
|
|
287
|
+
if (row.checkSpan && it.kind === "command") {
|
|
288
|
+
const on = it.checked === true;
|
|
289
|
+
row.checkSpan.textContent = on ? "\u2713" : "";
|
|
290
|
+
row.node.setAttribute("aria-checked", String(on));
|
|
291
|
+
}
|
|
292
|
+
};
|
|
224
293
|
const paintActive = () => {
|
|
225
294
|
rows.forEach((row, idx) => {
|
|
226
295
|
const isActive = idx === active;
|
|
@@ -242,7 +311,9 @@ function createDevDock(initial = {}) {
|
|
|
242
311
|
if (sig === rowsSig) {
|
|
243
312
|
filtered.forEach((it, idx) => {
|
|
244
313
|
const row = rows[idx];
|
|
245
|
-
if (row)
|
|
314
|
+
if (!row) return;
|
|
315
|
+
row.item = it;
|
|
316
|
+
paintRow(row);
|
|
246
317
|
});
|
|
247
318
|
paintActive();
|
|
248
319
|
return;
|
|
@@ -268,20 +339,7 @@ function createDevDock(initial = {}) {
|
|
|
268
339
|
}
|
|
269
340
|
for (const [groupName, groupItems] of groups) {
|
|
270
341
|
const section = el("div", { marginTop: "6px" });
|
|
271
|
-
section.appendChild(
|
|
272
|
-
el(
|
|
273
|
-
"div",
|
|
274
|
-
{
|
|
275
|
-
padding: "6px 8px 2px",
|
|
276
|
-
fontSize: "10px",
|
|
277
|
-
fontWeight: "700",
|
|
278
|
-
letterSpacing: "0.6px",
|
|
279
|
-
textTransform: "uppercase",
|
|
280
|
-
color: "#6b7280"
|
|
281
|
-
},
|
|
282
|
-
{ textContent: groupName }
|
|
283
|
-
)
|
|
284
|
-
);
|
|
342
|
+
section.appendChild(sectionHeading(groupName));
|
|
285
343
|
for (const it of groupItems) {
|
|
286
344
|
const idx = filtered.indexOf(it);
|
|
287
345
|
const row = el("button", {
|
|
@@ -300,15 +358,11 @@ function createDevDock(initial = {}) {
|
|
|
300
358
|
cursor: "pointer"
|
|
301
359
|
});
|
|
302
360
|
row.type = "button";
|
|
303
|
-
const labelSpan = el(
|
|
304
|
-
"
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
whiteSpace: "nowrap"
|
|
309
|
-
},
|
|
310
|
-
{ textContent: it.label }
|
|
311
|
-
);
|
|
361
|
+
const labelSpan = el("span", {
|
|
362
|
+
overflow: "hidden",
|
|
363
|
+
textOverflow: "ellipsis",
|
|
364
|
+
whiteSpace: "nowrap"
|
|
365
|
+
});
|
|
312
366
|
row.appendChild(labelSpan);
|
|
313
367
|
let pathSpan = null;
|
|
314
368
|
if (it.kind === "route" && it.route.path !== it.label) {
|
|
@@ -324,8 +378,20 @@ function createDevDock(initial = {}) {
|
|
|
324
378
|
);
|
|
325
379
|
row.appendChild(pathSpan);
|
|
326
380
|
}
|
|
327
|
-
|
|
381
|
+
let checkSpan = null;
|
|
382
|
+
if (it.kind === "command" && it.checked !== null) {
|
|
383
|
+
row.setAttribute("role", "checkbox");
|
|
384
|
+
checkSpan = el("span", {
|
|
385
|
+
flexShrink: "0",
|
|
386
|
+
width: "12px",
|
|
387
|
+
textAlign: "center",
|
|
388
|
+
color: "#22c55e"
|
|
389
|
+
});
|
|
390
|
+
row.appendChild(checkSpan);
|
|
391
|
+
}
|
|
392
|
+
const rec = { item: it, node: row, labelSpan, pathSpan, checkSpan };
|
|
328
393
|
rows[idx] = rec;
|
|
394
|
+
paintRow(rec);
|
|
329
395
|
row.addEventListener("mouseenter", () => setActive(idx));
|
|
330
396
|
row.addEventListener("click", () => void runItem(rec.item));
|
|
331
397
|
section.appendChild(row);
|
|
@@ -334,6 +400,120 @@ function createDevDock(initial = {}) {
|
|
|
334
400
|
}
|
|
335
401
|
paintActive();
|
|
336
402
|
};
|
|
403
|
+
const mountedViews = /* @__PURE__ */ new Map();
|
|
404
|
+
let viewsSig = null;
|
|
405
|
+
const viewOrder = (v) => v.order === "after" ? "after" : "before";
|
|
406
|
+
const unmountViews = () => {
|
|
407
|
+
for (const mv of mountedViews.values()) {
|
|
408
|
+
mv.teardown?.();
|
|
409
|
+
mv.host.remove();
|
|
410
|
+
}
|
|
411
|
+
mountedViews.clear();
|
|
412
|
+
viewsBefore.replaceChildren();
|
|
413
|
+
viewsAfter.replaceChildren();
|
|
414
|
+
viewsSig = null;
|
|
415
|
+
};
|
|
416
|
+
const renderViews = () => {
|
|
417
|
+
const keyed = keyViews(opts.views ?? []);
|
|
418
|
+
const sig = keyed.map(
|
|
419
|
+
({ view, key }) => [key, viewOrder(view), view.group ?? "", view.label ?? ""].join(
|
|
420
|
+
"\0"
|
|
421
|
+
)
|
|
422
|
+
).join("\n");
|
|
423
|
+
if (sig === viewsSig) return;
|
|
424
|
+
viewsSig = sig;
|
|
425
|
+
const live = new Set(keyed.map(({ key }) => key));
|
|
426
|
+
for (const [key, mv] of mountedViews) {
|
|
427
|
+
if (live.has(key)) continue;
|
|
428
|
+
mv.teardown?.();
|
|
429
|
+
mv.host.remove();
|
|
430
|
+
mountedViews.delete(key);
|
|
431
|
+
}
|
|
432
|
+
viewsBefore.replaceChildren();
|
|
433
|
+
viewsAfter.replaceChildren();
|
|
434
|
+
const pending = [];
|
|
435
|
+
for (const placement of ["before", "after"]) {
|
|
436
|
+
const container = placement === "before" ? viewsBefore : viewsAfter;
|
|
437
|
+
const here = keyed.filter(({ view }) => viewOrder(view) === placement);
|
|
438
|
+
const sections = /* @__PURE__ */ new Map();
|
|
439
|
+
for (const entry of here) {
|
|
440
|
+
const groupKey = entry.view.group ?? `\0${entry.key}`;
|
|
441
|
+
const section = sections.get(groupKey);
|
|
442
|
+
if (section) section.items.push(entry);
|
|
443
|
+
else
|
|
444
|
+
sections.set(groupKey, {
|
|
445
|
+
heading: entry.view.group ?? entry.view.label,
|
|
446
|
+
items: [entry]
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
for (const section of sections.values()) {
|
|
450
|
+
const wrap = el("div", { marginTop: "6px" });
|
|
451
|
+
if (section.heading) wrap.appendChild(sectionHeading(section.heading));
|
|
452
|
+
for (const { view, key } of section.items) {
|
|
453
|
+
if (view.group != null && view.label)
|
|
454
|
+
wrap.appendChild(viewLabel(view.label));
|
|
455
|
+
const existing = mountedViews.get(key);
|
|
456
|
+
if (existing) {
|
|
457
|
+
wrap.appendChild(existing.host);
|
|
458
|
+
continue;
|
|
459
|
+
}
|
|
460
|
+
const viewHost = el("div", { padding: "2px 8px 6px" });
|
|
461
|
+
viewHost.setAttribute("data-devdock-view", view.id ?? "");
|
|
462
|
+
wrap.appendChild(viewHost);
|
|
463
|
+
pending.push({ view, key, host: viewHost });
|
|
464
|
+
}
|
|
465
|
+
container.appendChild(wrap);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
for (const { view, key, host: viewHost } of pending) {
|
|
469
|
+
const mv = { host: viewHost };
|
|
470
|
+
mountedViews.set(key, mv);
|
|
471
|
+
const teardown = view.mount(viewHost);
|
|
472
|
+
if (typeof teardown === "function") mv.teardown = teardown;
|
|
473
|
+
}
|
|
474
|
+
};
|
|
475
|
+
let clonesSig = null;
|
|
476
|
+
const syncStyles = () => {
|
|
477
|
+
if (!styleSlot || !shadowRoot) return;
|
|
478
|
+
const adopted = document.adoptedStyleSheets;
|
|
479
|
+
if (Array.isArray(adopted)) {
|
|
480
|
+
try {
|
|
481
|
+
const sr = shadowRoot;
|
|
482
|
+
sr.adoptedStyleSheets = [...adopted];
|
|
483
|
+
} catch {
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
const sheets = [
|
|
487
|
+
...document.querySelectorAll('style, link[rel~="stylesheet" i]')
|
|
488
|
+
];
|
|
489
|
+
const sig = sheets.map((n) => `${n.tagName}\0${n.getAttribute("href") ?? n.textContent}`).join("\n");
|
|
490
|
+
if (sig === clonesSig) return;
|
|
491
|
+
clonesSig = sig;
|
|
492
|
+
styleSlot.replaceChildren(...sheets.map((n) => n.cloneNode(true)));
|
|
493
|
+
};
|
|
494
|
+
let styleObserver = null;
|
|
495
|
+
let syncQueued = false;
|
|
496
|
+
const watchStyles = () => {
|
|
497
|
+
if (!styleSlot || styleObserver || !document.head || typeof MutationObserver === "undefined")
|
|
498
|
+
return;
|
|
499
|
+
styleObserver = new MutationObserver(() => {
|
|
500
|
+
if (syncQueued) return;
|
|
501
|
+
syncQueued = true;
|
|
502
|
+
queueMicrotask(() => {
|
|
503
|
+
syncQueued = false;
|
|
504
|
+
syncStyles();
|
|
505
|
+
});
|
|
506
|
+
});
|
|
507
|
+
styleObserver.observe(document.head, {
|
|
508
|
+
childList: true,
|
|
509
|
+
subtree: true,
|
|
510
|
+
characterData: true
|
|
511
|
+
});
|
|
512
|
+
};
|
|
513
|
+
const unwatchStyles = () => {
|
|
514
|
+
styleObserver?.disconnect();
|
|
515
|
+
styleObserver = null;
|
|
516
|
+
};
|
|
337
517
|
const renderShell = () => {
|
|
338
518
|
const position = opts.position ?? "bottom-right";
|
|
339
519
|
const zIndex = opts.zIndex ?? 2147483e3;
|
|
@@ -363,9 +543,12 @@ function createDevDock(initial = {}) {
|
|
|
363
543
|
panel.isConnected || root.insertBefore(panel, button);
|
|
364
544
|
renderShell();
|
|
365
545
|
renderList();
|
|
546
|
+
syncStyles();
|
|
547
|
+
renderViews();
|
|
366
548
|
requestAnimationFrame(() => input.focus());
|
|
367
|
-
} else
|
|
368
|
-
|
|
549
|
+
} else {
|
|
550
|
+
unmountViews();
|
|
551
|
+
if (panel.isConnected) panel.remove();
|
|
369
552
|
}
|
|
370
553
|
renderShell();
|
|
371
554
|
}
|
|
@@ -412,11 +595,14 @@ function createDevDock(initial = {}) {
|
|
|
412
595
|
if (mounted) return;
|
|
413
596
|
(opts.container ?? document.body).appendChild(host);
|
|
414
597
|
addListeners();
|
|
598
|
+
syncStyles();
|
|
599
|
+
watchStyles();
|
|
415
600
|
mounted = true;
|
|
416
601
|
};
|
|
417
602
|
const unmount = () => {
|
|
418
603
|
if (!mounted) return;
|
|
419
604
|
removeListeners();
|
|
605
|
+
unwatchStyles();
|
|
420
606
|
host.remove();
|
|
421
607
|
mounted = false;
|
|
422
608
|
};
|
|
@@ -428,7 +614,10 @@ function createDevDock(initial = {}) {
|
|
|
428
614
|
if (enabled()) {
|
|
429
615
|
mount();
|
|
430
616
|
renderShell();
|
|
431
|
-
if (open)
|
|
617
|
+
if (open) {
|
|
618
|
+
renderList();
|
|
619
|
+
renderViews();
|
|
620
|
+
}
|
|
432
621
|
} else {
|
|
433
622
|
setOpen(false);
|
|
434
623
|
unmount();
|
|
@@ -440,24 +629,56 @@ function createDevDock(initial = {}) {
|
|
|
440
629
|
}
|
|
441
630
|
};
|
|
442
631
|
}
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
function DevDock(props) {
|
|
632
|
+
var NO_VIEWS = [];
|
|
633
|
+
function DevDock({ views = NO_VIEWS, ...options }) {
|
|
446
634
|
const instance = react.useRef(null);
|
|
447
|
-
const
|
|
448
|
-
|
|
635
|
+
const [hosts, setHosts] = react.useState(
|
|
636
|
+
() => /* @__PURE__ */ new Map()
|
|
637
|
+
);
|
|
638
|
+
const alive = react.useRef(true);
|
|
639
|
+
const keyed = react.useMemo(() => keyViews(views), [views]);
|
|
640
|
+
const coreViews = react.useMemo(
|
|
641
|
+
() => keyed.map(({ key, view }) => ({
|
|
642
|
+
id: key,
|
|
643
|
+
label: view.label,
|
|
644
|
+
group: view.group,
|
|
645
|
+
order: view.order,
|
|
646
|
+
mount: (host) => {
|
|
647
|
+
setHosts((prev) => new Map(prev).set(key, host));
|
|
648
|
+
return () => {
|
|
649
|
+
if (!alive.current) return;
|
|
650
|
+
setHosts((prev) => {
|
|
651
|
+
const next = new Map(prev);
|
|
652
|
+
next.delete(key);
|
|
653
|
+
return next;
|
|
654
|
+
});
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
})),
|
|
658
|
+
[keyed]
|
|
659
|
+
);
|
|
660
|
+
const latest = react.useRef({ options, coreViews });
|
|
661
|
+
latest.current = { options, coreViews };
|
|
449
662
|
react.useEffect(() => {
|
|
450
|
-
|
|
663
|
+
alive.current = true;
|
|
664
|
+
const inst = createDevDock({
|
|
665
|
+
...latest.current.options,
|
|
666
|
+
views: latest.current.coreViews
|
|
667
|
+
});
|
|
451
668
|
instance.current = inst;
|
|
452
669
|
return () => {
|
|
670
|
+
alive.current = false;
|
|
453
671
|
inst.destroy();
|
|
454
672
|
instance.current = null;
|
|
455
673
|
};
|
|
456
674
|
}, []);
|
|
457
675
|
react.useEffect(() => {
|
|
458
|
-
instance.current?.update(
|
|
676
|
+
instance.current?.update({ ...options, views: coreViews });
|
|
459
677
|
});
|
|
460
|
-
return
|
|
678
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: keyed.map(({ key, view }) => {
|
|
679
|
+
const host = hosts.get(key);
|
|
680
|
+
return host ? reactDom.createPortal(view.render(), host, key) : null;
|
|
681
|
+
}) });
|
|
461
682
|
}
|
|
462
683
|
|
|
463
684
|
exports.DevDock = DevDock;
|