@chuvenger/devdock 0.5.0 → 0.7.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 +200 -12
- package/dist/{chunk-3MVFATRN.js → chunk-2IQRWZ7T.js} +3 -3
- package/dist/{chunk-3MVFATRN.js.map → chunk-2IQRWZ7T.js.map} +1 -1
- package/dist/{chunk-NXZNFF34.js → chunk-2YX4DI2D.js} +253 -145
- package/dist/chunk-2YX4DI2D.js.map +1 -0
- package/dist/{dock-d3HqT25k.d.cts → dock-C7wZ8pQb.d.cts} +1 -1
- package/dist/{dock-P6l6pKjS.d.ts → dock-DJZuGmih.d.ts} +1 -1
- package/dist/index.cjs +253 -143
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +1 -1
- package/dist/{match-DwGIF1Xt.d.ts → match-C8MsaP6h.d.ts} +1 -1
- package/dist/{match-DDSJIRYW.d.cts → match-Dw1CSS0G.d.cts} +1 -1
- package/dist/react-router.cjs +348 -148
- package/dist/react-router.cjs.map +1 -1
- package/dist/react-router.d.cts +59 -11
- package/dist/react-router.d.ts +59 -11
- package/dist/react-router.js +101 -8
- package/dist/react-router.js.map +1 -1
- package/dist/react.cjs +250 -143
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +3 -2
- package/dist/react.d.ts +3 -2
- package/dist/react.js +2 -2
- package/dist/svelte.cjs +253 -143
- package/dist/svelte.cjs.map +1 -1
- package/dist/svelte.d.cts +4 -3
- package/dist/svelte.d.ts +4 -3
- package/dist/svelte.js +2 -2
- package/dist/svelte.js.map +1 -1
- package/dist/sveltekit.cjs +253 -143
- package/dist/sveltekit.cjs.map +1 -1
- package/dist/sveltekit.d.cts +5 -4
- package/dist/sveltekit.d.ts +5 -4
- package/dist/sveltekit.js +2 -2
- package/dist/{types-B_SpF32A.d.cts → types-B8WgSe7o.d.cts} +103 -3
- package/dist/{types-B_SpF32A.d.ts → types-B8WgSe7o.d.ts} +103 -3
- package/package.json +4 -1
- package/dist/chunk-NXZNFF34.js.map +0 -1
package/dist/react-router.cjs
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var react = require('react');
|
|
4
4
|
var reactRouter = require('react-router');
|
|
5
5
|
var reactDom = require('react-dom');
|
|
6
|
+
var cn = require('cn');
|
|
6
7
|
var jsxRuntime = require('react/jsx-runtime');
|
|
7
8
|
|
|
8
9
|
// src/react/react-router.tsx
|
|
@@ -25,6 +26,188 @@ function matchHotkey(spec, e) {
|
|
|
25
26
|
return e.key.toLowerCase() === key;
|
|
26
27
|
}
|
|
27
28
|
|
|
29
|
+
// src/core/theme.ts
|
|
30
|
+
var partClass = {
|
|
31
|
+
root: "devdock-root",
|
|
32
|
+
button: "devdock-button",
|
|
33
|
+
dot: "devdock-dot",
|
|
34
|
+
buttonLabel: "devdock-button-label",
|
|
35
|
+
panel: "devdock-panel",
|
|
36
|
+
title: "devdock-title",
|
|
37
|
+
inputWrap: "devdock-input-wrap",
|
|
38
|
+
input: "devdock-input",
|
|
39
|
+
body: "devdock-body",
|
|
40
|
+
list: "devdock-list",
|
|
41
|
+
section: "devdock-section",
|
|
42
|
+
group: "devdock-group",
|
|
43
|
+
row: "devdock-row",
|
|
44
|
+
rowActive: "",
|
|
45
|
+
rowLabel: "devdock-row-label",
|
|
46
|
+
rowPath: "devdock-row-path",
|
|
47
|
+
check: "devdock-check",
|
|
48
|
+
empty: "devdock-empty",
|
|
49
|
+
viewLabel: "devdock-view-label",
|
|
50
|
+
view: "devdock-view"
|
|
51
|
+
};
|
|
52
|
+
var STYLE_MARKER = "data-devdock-styles";
|
|
53
|
+
var FONT = "ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif";
|
|
54
|
+
var BASE_CSS = `
|
|
55
|
+
.devdock-root { font-family: var(--devdock-font, ${FONT}); }
|
|
56
|
+
|
|
57
|
+
.devdock-button {
|
|
58
|
+
display: inline-flex;
|
|
59
|
+
align-items: center;
|
|
60
|
+
gap: 6px;
|
|
61
|
+
padding: 8px 12px;
|
|
62
|
+
font-size: 12px;
|
|
63
|
+
font-weight: 700;
|
|
64
|
+
letter-spacing: 0.6px;
|
|
65
|
+
color: var(--devdock-button-fg, #fff);
|
|
66
|
+
background: var(--devdock-button-bg, #111317);
|
|
67
|
+
border: 1px solid var(--devdock-border, #2a2e37);
|
|
68
|
+
border-radius: 999px;
|
|
69
|
+
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);
|
|
70
|
+
cursor: pointer;
|
|
71
|
+
}
|
|
72
|
+
.devdock-button:where([aria-expanded="true"]) {
|
|
73
|
+
background: var(--devdock-accent, #2563eb);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.devdock-dot {
|
|
77
|
+
width: 8px;
|
|
78
|
+
height: 8px;
|
|
79
|
+
border-radius: 999px;
|
|
80
|
+
background: var(--devdock-success, #22c55e);
|
|
81
|
+
display: inline-block;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.devdock-panel {
|
|
85
|
+
width: var(--devdock-width, 280px);
|
|
86
|
+
max-height: var(--devdock-max-height, 70vh);
|
|
87
|
+
display: flex;
|
|
88
|
+
flex-direction: column;
|
|
89
|
+
background: var(--devdock-bg, #16181d);
|
|
90
|
+
color: var(--devdock-fg, #e7e9ee);
|
|
91
|
+
border: 1px solid var(--devdock-border, #2a2e37);
|
|
92
|
+
border-radius: var(--devdock-radius, 12px);
|
|
93
|
+
box-shadow: var(--devdock-shadow, 0 12px 40px rgba(0, 0, 0, 0.45));
|
|
94
|
+
overflow: hidden;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.devdock-title {
|
|
98
|
+
padding: 10px 12px;
|
|
99
|
+
border-bottom: 1px solid var(--devdock-border, #2a2e37);
|
|
100
|
+
font-size: 12px;
|
|
101
|
+
font-weight: 600;
|
|
102
|
+
letter-spacing: 0.4px;
|
|
103
|
+
text-transform: uppercase;
|
|
104
|
+
color: var(--devdock-muted, #8b909c);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.devdock-input-wrap { padding: 8px; }
|
|
108
|
+
|
|
109
|
+
.devdock-input {
|
|
110
|
+
width: 100%;
|
|
111
|
+
box-sizing: border-box;
|
|
112
|
+
padding: 8px 10px;
|
|
113
|
+
font-size: 13px;
|
|
114
|
+
color: var(--devdock-fg, #e7e9ee);
|
|
115
|
+
background: var(--devdock-input-bg, #0f1115);
|
|
116
|
+
border: 1px solid var(--devdock-border, #2a2e37);
|
|
117
|
+
border-radius: var(--devdock-radius-sm, 8px);
|
|
118
|
+
outline: none;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.devdock-body {
|
|
122
|
+
overflow-y: auto;
|
|
123
|
+
display: flex;
|
|
124
|
+
flex-direction: column;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.devdock-list { padding: 0 6px 8px; }
|
|
128
|
+
|
|
129
|
+
.devdock-section { margin-top: 6px; }
|
|
130
|
+
|
|
131
|
+
.devdock-group {
|
|
132
|
+
padding: 6px 8px 2px;
|
|
133
|
+
font-size: 10px;
|
|
134
|
+
font-weight: 700;
|
|
135
|
+
letter-spacing: 0.6px;
|
|
136
|
+
text-transform: uppercase;
|
|
137
|
+
color: var(--devdock-subtle, #6b7280);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.devdock-row {
|
|
141
|
+
display: flex;
|
|
142
|
+
align-items: center;
|
|
143
|
+
justify-content: space-between;
|
|
144
|
+
gap: 8px;
|
|
145
|
+
width: 100%;
|
|
146
|
+
text-align: left;
|
|
147
|
+
padding: 8px 10px;
|
|
148
|
+
font-size: 13px;
|
|
149
|
+
color: var(--devdock-fg, #e7e9ee);
|
|
150
|
+
background: transparent;
|
|
151
|
+
border: none;
|
|
152
|
+
border-radius: var(--devdock-radius-sm, 8px);
|
|
153
|
+
cursor: pointer;
|
|
154
|
+
}
|
|
155
|
+
.devdock-row:where([data-active]) {
|
|
156
|
+
background: var(--devdock-accent, #2563eb);
|
|
157
|
+
color: var(--devdock-accent-fg, #e7e9ee);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.devdock-row-label {
|
|
161
|
+
overflow: hidden;
|
|
162
|
+
text-overflow: ellipsis;
|
|
163
|
+
white-space: nowrap;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.devdock-row-path {
|
|
167
|
+
font-size: 11px;
|
|
168
|
+
color: var(--devdock-subtle, #6b7280);
|
|
169
|
+
font-family: ui-monospace, SFMono-Regular, monospace;
|
|
170
|
+
flex-shrink: 0;
|
|
171
|
+
}
|
|
172
|
+
:where(.devdock-row[data-active]) .devdock-row-path {
|
|
173
|
+
/* Whatever colour the row ended up with, stepped back: currentColor in the
|
|
174
|
+
color property means the inherited one, so this tracks the row however it
|
|
175
|
+
was set - a token, a class of yours - instead of guessing at the accent. */
|
|
176
|
+
color: color-mix(in oklab, currentColor 75%, transparent);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.devdock-check {
|
|
180
|
+
flex-shrink: 0;
|
|
181
|
+
width: 12px;
|
|
182
|
+
text-align: center;
|
|
183
|
+
color: var(--devdock-success, #22c55e);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.devdock-empty {
|
|
187
|
+
padding: 12px;
|
|
188
|
+
font-size: 13px;
|
|
189
|
+
color: var(--devdock-subtle, #6b7280);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.devdock-view-label {
|
|
193
|
+
padding: 4px 8px 0;
|
|
194
|
+
font-size: 11px;
|
|
195
|
+
color: var(--devdock-muted, #8b909c);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
.devdock-view { padding: 2px 8px 6px; }
|
|
199
|
+
`;
|
|
200
|
+
var DEFAULT_LAYER = "devdock";
|
|
201
|
+
function dockStyles(layer) {
|
|
202
|
+
if (!layer) return BASE_CSS;
|
|
203
|
+
const block = `@layer ${layer} {${BASE_CSS}}
|
|
204
|
+
`;
|
|
205
|
+
if (layer !== DEFAULT_LAYER) return block;
|
|
206
|
+
const order = `@layer theme, base, components, ${layer}, utilities;`;
|
|
207
|
+
return `${order}
|
|
208
|
+
${block}`;
|
|
209
|
+
}
|
|
210
|
+
|
|
28
211
|
// src/core/dock.ts
|
|
29
212
|
var viteDevFlag = () => {
|
|
30
213
|
try {
|
|
@@ -55,33 +238,12 @@ var isDevHost = () => {
|
|
|
55
238
|
if (!host) return true;
|
|
56
239
|
return host === "localhost" || host.endsWith(".localhost") || host.endsWith(".local") || host === "::1" || host === "0.0.0.0" || isLocalIPv4(host);
|
|
57
240
|
};
|
|
58
|
-
function el(tag,
|
|
241
|
+
function el(tag, props) {
|
|
59
242
|
const node = document.createElement(tag);
|
|
60
|
-
if (styles) Object.assign(node.style, styles);
|
|
61
243
|
if (props) Object.assign(node, props);
|
|
62
244
|
return node;
|
|
63
245
|
}
|
|
64
|
-
|
|
65
|
-
return el(
|
|
66
|
-
"div",
|
|
67
|
-
{
|
|
68
|
-
padding: "6px 8px 2px",
|
|
69
|
-
fontSize: "10px",
|
|
70
|
-
fontWeight: "700",
|
|
71
|
-
letterSpacing: "0.6px",
|
|
72
|
-
textTransform: "uppercase",
|
|
73
|
-
color: "#6b7280"
|
|
74
|
-
},
|
|
75
|
-
{ textContent: text }
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
function viewLabel(text) {
|
|
79
|
-
return el(
|
|
80
|
-
"div",
|
|
81
|
-
{ padding: "4px 8px 0", fontSize: "11px", color: "#8b909c" },
|
|
82
|
-
{ textContent: text }
|
|
83
|
-
);
|
|
84
|
-
}
|
|
246
|
+
var PARTS = Object.keys(partClass);
|
|
85
247
|
function cornerStyle(position) {
|
|
86
248
|
const gap = "16px";
|
|
87
249
|
switch (position) {
|
|
@@ -104,7 +266,6 @@ function panelAnchor(position) {
|
|
|
104
266
|
[isRight ? "right" : "left"]: "0"
|
|
105
267
|
};
|
|
106
268
|
}
|
|
107
|
-
var FONT = "ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif";
|
|
108
269
|
function keyViews(views) {
|
|
109
270
|
const used = /* @__PURE__ */ new Set();
|
|
110
271
|
return views.map((view, i) => {
|
|
@@ -121,96 +282,67 @@ function createDevDock(initial = {}) {
|
|
|
121
282
|
} };
|
|
122
283
|
}
|
|
123
284
|
let opts = { ...initial };
|
|
285
|
+
const cls = (...parts) => cn.cn(parts.map((part) => [partClass[part], opts.classNames?.[part]]));
|
|
286
|
+
const classSig = () => PARTS.map((p) => cn.cn(opts.classNames?.[p])).join("\0");
|
|
124
287
|
let open = false;
|
|
125
288
|
let query = "";
|
|
126
289
|
let active = 0;
|
|
127
290
|
let mounted = false;
|
|
128
291
|
const host = el("div");
|
|
129
292
|
host.setAttribute("data-devdock", "");
|
|
130
|
-
const shadowMode = initial.shadow ?? true;
|
|
293
|
+
const shadowMode = initial.shadow ?? (initial.classNames ? "inherit" : true);
|
|
131
294
|
const useShadow = shadowMode !== false && typeof host.attachShadow === "function";
|
|
132
295
|
const shadowRoot = useShadow ? host.attachShadow({ mode: "open" }) : null;
|
|
133
296
|
const mountPoint = shadowRoot ?? host;
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
const root = el("div", { fontFamily: FONT });
|
|
137
|
-
mountPoint.appendChild(root);
|
|
138
|
-
const panel = el("div", {
|
|
139
|
-
width: "280px",
|
|
140
|
-
maxHeight: "min(70vh, 480px)",
|
|
141
|
-
display: "flex",
|
|
142
|
-
flexDirection: "column",
|
|
143
|
-
background: "#16181d",
|
|
144
|
-
color: "#e7e9ee",
|
|
145
|
-
border: "1px solid #2a2e37",
|
|
146
|
-
borderRadius: "12px",
|
|
147
|
-
boxShadow: "0 12px 40px rgba(0,0,0,0.45)",
|
|
148
|
-
overflow: "hidden"
|
|
297
|
+
const baseStyle = el("style", {
|
|
298
|
+
textContent: dockStyles(initial.cssLayer ?? DEFAULT_LAYER)
|
|
149
299
|
});
|
|
300
|
+
baseStyle.setAttribute(STYLE_MARKER, "");
|
|
301
|
+
if (shadowRoot) mountPoint.appendChild(baseStyle);
|
|
302
|
+
const styleSlot = shadowRoot && shadowMode === "inherit" ? el("div") : null;
|
|
303
|
+
if (styleSlot) {
|
|
304
|
+
styleSlot.style.display = "contents";
|
|
305
|
+
mountPoint.appendChild(styleSlot);
|
|
306
|
+
}
|
|
307
|
+
const root = el("div");
|
|
308
|
+
mountPoint.appendChild(root);
|
|
309
|
+
const panel = el("div");
|
|
150
310
|
panel.setAttribute("role", "dialog");
|
|
151
|
-
const heading = el("div"
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
fontSize: "12px",
|
|
155
|
-
fontWeight: "600",
|
|
156
|
-
letterSpacing: "0.4px",
|
|
157
|
-
textTransform: "uppercase",
|
|
158
|
-
color: "#8b909c"
|
|
159
|
-
});
|
|
160
|
-
const inputWrap = el("div", { padding: "8px" });
|
|
161
|
-
const input = el("input", {
|
|
162
|
-
width: "100%",
|
|
163
|
-
boxSizing: "border-box",
|
|
164
|
-
padding: "8px 10px",
|
|
165
|
-
fontSize: "13px",
|
|
166
|
-
color: "#e7e9ee",
|
|
167
|
-
background: "#0f1115",
|
|
168
|
-
border: "1px solid #2a2e37",
|
|
169
|
-
borderRadius: "8px",
|
|
170
|
-
outline: "none"
|
|
171
|
-
});
|
|
311
|
+
const heading = el("div");
|
|
312
|
+
const inputWrap = el("div");
|
|
313
|
+
const input = el("input");
|
|
172
314
|
input.placeholder = "Filter\u2026";
|
|
173
315
|
inputWrap.appendChild(input);
|
|
174
|
-
const list = el("div"
|
|
316
|
+
const list = el("div");
|
|
175
317
|
list.setAttribute("data-devdock-list", "");
|
|
176
318
|
const viewsBefore = el("div");
|
|
177
319
|
viewsBefore.setAttribute("data-devdock-views", "before");
|
|
178
320
|
const viewsAfter = el("div");
|
|
179
321
|
viewsAfter.setAttribute("data-devdock-views", "after");
|
|
180
|
-
const body = el("div"
|
|
181
|
-
overflowY: "auto",
|
|
182
|
-
display: "flex",
|
|
183
|
-
flexDirection: "column"
|
|
184
|
-
});
|
|
322
|
+
const body = el("div");
|
|
185
323
|
body.append(viewsBefore, list, viewsAfter);
|
|
186
324
|
panel.append(heading, inputWrap, body);
|
|
187
|
-
const button = el("button"
|
|
188
|
-
display: "inline-flex",
|
|
189
|
-
alignItems: "center",
|
|
190
|
-
gap: "6px",
|
|
191
|
-
padding: "8px 12px",
|
|
192
|
-
fontSize: "12px",
|
|
193
|
-
fontWeight: "700",
|
|
194
|
-
letterSpacing: "0.6px",
|
|
195
|
-
color: "#fff",
|
|
196
|
-
background: "#111317",
|
|
197
|
-
border: "1px solid #2a2e37",
|
|
198
|
-
borderRadius: "999px",
|
|
199
|
-
boxShadow: "0 4px 14px rgba(0,0,0,0.35)",
|
|
200
|
-
cursor: "pointer"
|
|
201
|
-
});
|
|
325
|
+
const button = el("button");
|
|
202
326
|
button.type = "button";
|
|
203
327
|
button.setAttribute("aria-label", "Toggle dev menu");
|
|
204
|
-
const dot = el("span"
|
|
205
|
-
width: "8px",
|
|
206
|
-
height: "8px",
|
|
207
|
-
borderRadius: "999px",
|
|
208
|
-
background: "#22c55e",
|
|
209
|
-
display: "inline-block"
|
|
210
|
-
});
|
|
328
|
+
const dot = el("span");
|
|
211
329
|
const buttonLabel = el("span");
|
|
212
330
|
button.append(dot, buttonLabel);
|
|
213
331
|
root.appendChild(button);
|
|
332
|
+
const sectionHeading = (text) => el("div", { className: cls("group"), textContent: text });
|
|
333
|
+
const viewLabel = (text) => el("div", { className: cls("viewLabel"), textContent: text });
|
|
334
|
+
const paintClasses = () => {
|
|
335
|
+
root.className = cls("root");
|
|
336
|
+
button.className = cls("button");
|
|
337
|
+
dot.className = cls("dot");
|
|
338
|
+
buttonLabel.className = cls("buttonLabel");
|
|
339
|
+
panel.className = cls("panel");
|
|
340
|
+
heading.className = cls("title");
|
|
341
|
+
inputWrap.className = cls("inputWrap");
|
|
342
|
+
input.className = cls("input");
|
|
343
|
+
body.className = cls("body");
|
|
344
|
+
list.className = cls("list");
|
|
345
|
+
};
|
|
214
346
|
const enabled = () => {
|
|
215
347
|
const e = opts.enabled;
|
|
216
348
|
if (typeof e === "function") return e();
|
|
@@ -294,9 +426,9 @@ function createDevDock(initial = {}) {
|
|
|
294
426
|
const paintActive = () => {
|
|
295
427
|
rows.forEach((row, idx) => {
|
|
296
428
|
const isActive = idx === active;
|
|
297
|
-
row.node.
|
|
298
|
-
|
|
299
|
-
|
|
429
|
+
if (isActive) row.node.setAttribute("data-active", "");
|
|
430
|
+
else row.node.removeAttribute("data-active");
|
|
431
|
+
row.node.className = isActive ? cls("row", "rowActive") : cls("row");
|
|
300
432
|
});
|
|
301
433
|
};
|
|
302
434
|
const setActive = (next, scroll = false) => {
|
|
@@ -308,7 +440,7 @@ function createDevDock(initial = {}) {
|
|
|
308
440
|
const renderList = () => {
|
|
309
441
|
const filtered = getFiltered();
|
|
310
442
|
active = Math.min(active, Math.max(0, filtered.length - 1));
|
|
311
|
-
const sig = filtered.map(itemSig).join("\n");
|
|
443
|
+
const sig = [classSig(), ...filtered.map(itemSig)].join("\n");
|
|
312
444
|
if (sig === rowsSig) {
|
|
313
445
|
filtered.forEach((it, idx) => {
|
|
314
446
|
const row = rows[idx];
|
|
@@ -324,11 +456,7 @@ function createDevDock(initial = {}) {
|
|
|
324
456
|
list.replaceChildren();
|
|
325
457
|
if (filtered.length === 0) {
|
|
326
458
|
list.appendChild(
|
|
327
|
-
el(
|
|
328
|
-
"div",
|
|
329
|
-
{ padding: "12px", fontSize: "13px", color: "#6b7280" },
|
|
330
|
-
{ textContent: "Nothing here." }
|
|
331
|
-
)
|
|
459
|
+
el("div", { className: cls("empty"), textContent: "Nothing here." })
|
|
332
460
|
);
|
|
333
461
|
return;
|
|
334
462
|
}
|
|
@@ -339,55 +467,26 @@ function createDevDock(initial = {}) {
|
|
|
339
467
|
groups.set(it.group, arr);
|
|
340
468
|
}
|
|
341
469
|
for (const [groupName, groupItems] of groups) {
|
|
342
|
-
const section = el("div", {
|
|
470
|
+
const section = el("div", { className: cls("section") });
|
|
343
471
|
section.appendChild(sectionHeading(groupName));
|
|
344
472
|
for (const it of groupItems) {
|
|
345
473
|
const idx = filtered.indexOf(it);
|
|
346
|
-
const row = el("button", {
|
|
347
|
-
display: "flex",
|
|
348
|
-
alignItems: "center",
|
|
349
|
-
justifyContent: "space-between",
|
|
350
|
-
gap: "8px",
|
|
351
|
-
width: "100%",
|
|
352
|
-
textAlign: "left",
|
|
353
|
-
padding: "8px 10px",
|
|
354
|
-
fontSize: "13px",
|
|
355
|
-
color: "#e7e9ee",
|
|
356
|
-
background: "transparent",
|
|
357
|
-
border: "none",
|
|
358
|
-
borderRadius: "8px",
|
|
359
|
-
cursor: "pointer"
|
|
360
|
-
});
|
|
474
|
+
const row = el("button", { className: cls("row") });
|
|
361
475
|
row.type = "button";
|
|
362
|
-
const labelSpan = el("span", {
|
|
363
|
-
overflow: "hidden",
|
|
364
|
-
textOverflow: "ellipsis",
|
|
365
|
-
whiteSpace: "nowrap"
|
|
366
|
-
});
|
|
476
|
+
const labelSpan = el("span", { className: cls("rowLabel") });
|
|
367
477
|
row.appendChild(labelSpan);
|
|
368
478
|
let pathSpan = null;
|
|
369
479
|
if (it.kind === "route" && it.route.path !== it.label) {
|
|
370
|
-
pathSpan = el(
|
|
371
|
-
"
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
color: "#6b7280",
|
|
375
|
-
fontFamily: "ui-monospace, SFMono-Regular, monospace",
|
|
376
|
-
flexShrink: "0"
|
|
377
|
-
},
|
|
378
|
-
{ textContent: it.route.path }
|
|
379
|
-
);
|
|
480
|
+
pathSpan = el("span", {
|
|
481
|
+
className: cls("rowPath"),
|
|
482
|
+
textContent: it.route.path
|
|
483
|
+
});
|
|
380
484
|
row.appendChild(pathSpan);
|
|
381
485
|
}
|
|
382
486
|
let checkSpan = null;
|
|
383
487
|
if (it.kind === "command" && it.checked !== null) {
|
|
384
488
|
row.setAttribute("role", "checkbox");
|
|
385
|
-
checkSpan = el("span", {
|
|
386
|
-
flexShrink: "0",
|
|
387
|
-
width: "12px",
|
|
388
|
-
textAlign: "center",
|
|
389
|
-
color: "#22c55e"
|
|
390
|
-
});
|
|
489
|
+
checkSpan = el("span", { className: cls("check") });
|
|
391
490
|
row.appendChild(checkSpan);
|
|
392
491
|
}
|
|
393
492
|
const rec = { item: it, node: row, labelSpan, pathSpan, checkSpan };
|
|
@@ -416,11 +515,14 @@ function createDevDock(initial = {}) {
|
|
|
416
515
|
};
|
|
417
516
|
const renderViews = () => {
|
|
418
517
|
const keyed = keyViews(opts.views ?? []);
|
|
419
|
-
const sig =
|
|
420
|
-
(
|
|
421
|
-
|
|
518
|
+
const sig = [
|
|
519
|
+
classSig(),
|
|
520
|
+
...keyed.map(
|
|
521
|
+
({ view, key }) => [key, viewOrder(view), view.group ?? "", view.label ?? ""].join(
|
|
522
|
+
"\0"
|
|
523
|
+
)
|
|
422
524
|
)
|
|
423
|
-
|
|
525
|
+
].join("\n");
|
|
424
526
|
if (sig === viewsSig) return;
|
|
425
527
|
viewsSig = sig;
|
|
426
528
|
const live = new Set(keyed.map(({ key }) => key));
|
|
@@ -448,7 +550,7 @@ function createDevDock(initial = {}) {
|
|
|
448
550
|
});
|
|
449
551
|
}
|
|
450
552
|
for (const section of sections.values()) {
|
|
451
|
-
const wrap = el("div", {
|
|
553
|
+
const wrap = el("div", { className: cls("section") });
|
|
452
554
|
if (section.heading) wrap.appendChild(sectionHeading(section.heading));
|
|
453
555
|
for (const { view, key } of section.items) {
|
|
454
556
|
if (view.group != null && view.label)
|
|
@@ -458,7 +560,7 @@ function createDevDock(initial = {}) {
|
|
|
458
560
|
wrap.appendChild(existing.host);
|
|
459
561
|
continue;
|
|
460
562
|
}
|
|
461
|
-
const viewHost = el("div", {
|
|
563
|
+
const viewHost = el("div", { className: cls("view") });
|
|
462
564
|
viewHost.setAttribute("data-devdock-view", view.id ?? "");
|
|
463
565
|
wrap.appendChild(viewHost);
|
|
464
566
|
pending.push({ view, key, host: viewHost });
|
|
@@ -485,7 +587,9 @@ function createDevDock(initial = {}) {
|
|
|
485
587
|
}
|
|
486
588
|
}
|
|
487
589
|
const sheets = [
|
|
488
|
-
...document.querySelectorAll(
|
|
590
|
+
...document.querySelectorAll(
|
|
591
|
+
`style:not([${STYLE_MARKER}]), link[rel~="stylesheet" i]`
|
|
592
|
+
)
|
|
489
593
|
];
|
|
490
594
|
const sig = sheets.map((n) => `${n.tagName}\0${n.getAttribute("href") ?? n.textContent}`).join("\n");
|
|
491
595
|
if (sig === clonesSig) return;
|
|
@@ -531,8 +635,8 @@ function createDevDock(initial = {}) {
|
|
|
531
635
|
panel.setAttribute("aria-label", opts.title ?? "Dev Menu");
|
|
532
636
|
Object.assign(panel.style, panelAnchor(position));
|
|
533
637
|
buttonLabel.textContent = opts.label ?? "DEV";
|
|
534
|
-
button.style.background = open ? "#2563eb" : "#111317";
|
|
535
638
|
button.setAttribute("aria-expanded", String(open));
|
|
639
|
+
paintClasses();
|
|
536
640
|
};
|
|
537
641
|
function setOpen(next) {
|
|
538
642
|
if (open === next) return;
|
|
@@ -594,6 +698,8 @@ function createDevDock(initial = {}) {
|
|
|
594
698
|
};
|
|
595
699
|
const mount = () => {
|
|
596
700
|
if (mounted) return;
|
|
701
|
+
if (!shadowRoot)
|
|
702
|
+
(document.head ?? document.documentElement).prepend(baseStyle);
|
|
597
703
|
(opts.container ?? document.body).appendChild(host);
|
|
598
704
|
addListeners();
|
|
599
705
|
syncStyles();
|
|
@@ -604,6 +710,7 @@ function createDevDock(initial = {}) {
|
|
|
604
710
|
if (!mounted) return;
|
|
605
711
|
removeListeners();
|
|
606
712
|
unwatchStyles();
|
|
713
|
+
if (!shadowRoot) baseStyle.remove();
|
|
607
714
|
host.remove();
|
|
608
715
|
mounted = false;
|
|
609
716
|
};
|
|
@@ -735,23 +842,116 @@ function walk(routes, parent, staticRoutes, inherited) {
|
|
|
735
842
|
}
|
|
736
843
|
return out;
|
|
737
844
|
}
|
|
845
|
+
var NO_ROUTES = [];
|
|
846
|
+
var NO_HANDLES = /* @__PURE__ */ new Map();
|
|
847
|
+
function lazyHandleOf(route) {
|
|
848
|
+
const lazy = route.lazy;
|
|
849
|
+
if (typeof lazy === "function") return async () => (await lazy())?.handle;
|
|
850
|
+
return typeof lazy?.handle === "function" ? lazy.handle : void 0;
|
|
851
|
+
}
|
|
852
|
+
async function readLazyHandle(route) {
|
|
853
|
+
try {
|
|
854
|
+
return await lazyHandleOf(route)?.();
|
|
855
|
+
} catch {
|
|
856
|
+
return void 0;
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
function collectLazy(routes, out = []) {
|
|
860
|
+
for (const r of routes) {
|
|
861
|
+
if (r.handle == null && lazyHandleOf(r) != null) out.push(r);
|
|
862
|
+
if (r.children?.length) collectLazy(r.children, out);
|
|
863
|
+
}
|
|
864
|
+
return out;
|
|
865
|
+
}
|
|
866
|
+
function signature(routes, out = []) {
|
|
867
|
+
for (const r of routes) {
|
|
868
|
+
const h = r.handle;
|
|
869
|
+
out.push(
|
|
870
|
+
`${r.path ?? ""}|${r.index ? 1 : 0}|${h?.dev}|${h?.devLabel}|${h?.devGroup}|${h?.hidden}|${lazyHandleOf(r) ? 1 : 0}`
|
|
871
|
+
);
|
|
872
|
+
if (r.children?.length) signature(r.children, out);
|
|
873
|
+
}
|
|
874
|
+
return out;
|
|
875
|
+
}
|
|
876
|
+
function useRouteTree(router) {
|
|
877
|
+
const routes = router?.routes ?? NO_ROUTES;
|
|
878
|
+
const [sig, setSig] = react.useState(() => signature(routes).join("\n"));
|
|
879
|
+
react.useEffect(() => {
|
|
880
|
+
if (!router?.subscribe) return;
|
|
881
|
+
const check = () => {
|
|
882
|
+
const next = signature(router.routes ?? NO_ROUTES).join("\n");
|
|
883
|
+
setSig((prev) => prev === next ? prev : next);
|
|
884
|
+
};
|
|
885
|
+
check();
|
|
886
|
+
return router.subscribe(check);
|
|
887
|
+
}, [router]);
|
|
888
|
+
return [routes, sig];
|
|
889
|
+
}
|
|
890
|
+
function useLazyHandles(routes, sig, enabled) {
|
|
891
|
+
const [handles, setHandles] = react.useState(NO_HANDLES);
|
|
892
|
+
const started = react.useRef(
|
|
893
|
+
/* @__PURE__ */ new WeakMap()
|
|
894
|
+
);
|
|
895
|
+
react.useEffect(() => {
|
|
896
|
+
if (!enabled) return;
|
|
897
|
+
const targets = collectLazy(routes);
|
|
898
|
+
if (targets.length === 0) return;
|
|
899
|
+
let cancelled = false;
|
|
900
|
+
void Promise.all(
|
|
901
|
+
targets.map((route) => {
|
|
902
|
+
let pending = started.current.get(route);
|
|
903
|
+
if (!pending) {
|
|
904
|
+
pending = readLazyHandle(route);
|
|
905
|
+
started.current.set(route, pending);
|
|
906
|
+
}
|
|
907
|
+
return pending.then((handle) => [route, handle]);
|
|
908
|
+
})
|
|
909
|
+
).then((resolved) => {
|
|
910
|
+
if (cancelled) return;
|
|
911
|
+
const found = resolved.filter(
|
|
912
|
+
(entry) => entry[1] != null
|
|
913
|
+
);
|
|
914
|
+
setHandles(
|
|
915
|
+
(prev) => found.some(([route, handle]) => prev.get(route) !== handle) ? new Map([...prev, ...found]) : prev
|
|
916
|
+
);
|
|
917
|
+
});
|
|
918
|
+
return () => {
|
|
919
|
+
cancelled = true;
|
|
920
|
+
};
|
|
921
|
+
}, [routes, sig, enabled]);
|
|
922
|
+
return handles;
|
|
923
|
+
}
|
|
924
|
+
function mergeHandles(routes, handles) {
|
|
925
|
+
let changed = false;
|
|
926
|
+
const merged = routes.map((r) => {
|
|
927
|
+
const handle = r.handle ?? handles.get(r);
|
|
928
|
+
const children = r.children ? mergeHandles(r.children, handles) : r.children;
|
|
929
|
+
if (handle === r.handle && children === r.children) return r;
|
|
930
|
+
changed = true;
|
|
931
|
+
return { ...r, handle, children };
|
|
932
|
+
});
|
|
933
|
+
return changed ? merged : routes;
|
|
934
|
+
}
|
|
738
935
|
function useDetectedRoutes(options = {}) {
|
|
739
936
|
const opts = isMatcher(options) ? { match: options } : options;
|
|
740
|
-
const { match, staticRoutes } = opts;
|
|
937
|
+
const { match, staticRoutes, loadHandles } = opts;
|
|
741
938
|
const ctx = react.useContext(reactRouter.UNSAFE_DataRouterContext);
|
|
742
|
-
const routes = ctx?.router
|
|
939
|
+
const [routes, sig] = useRouteTree(ctx?.router);
|
|
940
|
+
const handles = useLazyHandles(routes, sig, loadHandles === true);
|
|
743
941
|
return react.useMemo(() => {
|
|
744
|
-
const
|
|
942
|
+
const tree = handles.size > 0 ? mergeHandles(routes, handles) : routes;
|
|
943
|
+
const deduped = dedupeByPath(flattenRoutes(tree, "", { staticRoutes }));
|
|
745
944
|
return match ? deduped.filter(toPredicate(match)) : deduped;
|
|
746
|
-
}, [routes, match, staticRoutes]);
|
|
945
|
+
}, [routes, sig, handles, match, staticRoutes]);
|
|
747
946
|
}
|
|
748
947
|
function ReactRouterDevDock({
|
|
749
948
|
match,
|
|
750
949
|
staticRoutes,
|
|
950
|
+
loadHandles,
|
|
751
951
|
...props
|
|
752
952
|
}) {
|
|
753
953
|
const navigate = reactRouter.useNavigate();
|
|
754
|
-
const detected = useDetectedRoutes({ match, staticRoutes });
|
|
954
|
+
const detected = useDetectedRoutes({ match, staticRoutes, loadHandles });
|
|
755
955
|
const routes = react.useMemo(
|
|
756
956
|
() => [...detected, ...props.routes ?? []],
|
|
757
957
|
[detected, props.routes]
|