@chuvenger/devdock 0.6.0 → 0.8.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 +165 -15
- package/dist/{chunk-NXZNFF34.js → chunk-7Z3YWV5K.js} +343 -152
- package/dist/chunk-7Z3YWV5K.js.map +1 -0
- package/dist/{chunk-3MVFATRN.js → chunk-MKYQ666Z.js} +3 -3
- package/dist/{chunk-3MVFATRN.js.map → chunk-MKYQ666Z.js.map} +1 -1
- package/dist/{dock-P6l6pKjS.d.ts → dock-C8tR26RP.d.ts} +1 -1
- package/dist/{dock-d3HqT25k.d.cts → dock-Cxh5FIAv.d.cts} +1 -1
- package/dist/index.cjs +344 -149
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +20 -3
- package/dist/index.d.ts +20 -3
- package/dist/index.js +1 -1
- package/dist/{match-DDSJIRYW.d.cts → match-CFB-9KGi.d.cts} +1 -1
- package/dist/{match-DwGIF1Xt.d.ts → match-injUeExB.d.ts} +1 -1
- package/dist/react-router.cjs +339 -149
- package/dist/react-router.cjs.map +1 -1
- package/dist/react-router.d.cts +3 -2
- package/dist/react-router.d.ts +3 -2
- package/dist/react-router.js +2 -2
- package/dist/react.cjs +339 -149
- 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 +342 -149
- 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 +342 -149
- 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-BuYSEeDa.d.cts} +113 -5
- package/dist/{types-B_SpF32A.d.ts → types-BuYSEeDa.d.ts} +113 -5
- package/package.json +4 -1
- package/dist/chunk-NXZNFF34.js.map +0 -1
package/dist/react-router.cjs
CHANGED
|
@@ -3,26 +3,281 @@
|
|
|
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
|
|
9
10
|
|
|
10
11
|
// src/core/hotkey.ts
|
|
12
|
+
var isMac = () => typeof navigator !== "undefined" && /mac/i.test(navigator.platform);
|
|
13
|
+
var KEY_CODES = {
|
|
14
|
+
".": "Period",
|
|
15
|
+
",": "Comma",
|
|
16
|
+
"/": "Slash",
|
|
17
|
+
"\\": "Backslash",
|
|
18
|
+
";": "Semicolon",
|
|
19
|
+
"'": "Quote",
|
|
20
|
+
"[": "BracketLeft",
|
|
21
|
+
"]": "BracketRight",
|
|
22
|
+
"-": "Minus",
|
|
23
|
+
"=": "Equal",
|
|
24
|
+
"`": "Backquote",
|
|
25
|
+
" ": "Space",
|
|
26
|
+
space: "Space"
|
|
27
|
+
};
|
|
28
|
+
var codeFor = (key) => {
|
|
29
|
+
if (/^[a-z]$/.test(key)) return `Key${key.toUpperCase()}`;
|
|
30
|
+
if (/^[0-9]$/.test(key)) return `Digit${key}`;
|
|
31
|
+
return KEY_CODES[key];
|
|
32
|
+
};
|
|
11
33
|
function matchHotkey(spec, e) {
|
|
12
34
|
const parts = spec.toLowerCase().split("+").map((p) => p.trim()).filter(Boolean);
|
|
13
35
|
if (parts.length === 0) return false;
|
|
14
36
|
const key = parts[parts.length - 1];
|
|
15
37
|
const mods = new Set(parts.slice(0, -1));
|
|
16
|
-
const
|
|
17
|
-
const wantMeta = mods.has("meta") || mods.has("cmd") || mods.has("mod") &&
|
|
18
|
-
const wantCtrl = mods.has("ctrl") || mods.has("control") || mods.has("mod") && !
|
|
38
|
+
const mac = isMac();
|
|
39
|
+
const wantMeta = mods.has("meta") || mods.has("cmd") || mods.has("mod") && mac;
|
|
40
|
+
const wantCtrl = mods.has("ctrl") || mods.has("control") || mods.has("mod") && !mac;
|
|
19
41
|
const wantShift = mods.has("shift");
|
|
20
42
|
const wantAlt = mods.has("alt") || mods.has("option");
|
|
21
43
|
if (e.metaKey !== wantMeta) return false;
|
|
22
44
|
if (e.ctrlKey !== wantCtrl) return false;
|
|
23
45
|
if (e.shiftKey !== wantShift) return false;
|
|
24
46
|
if (e.altKey !== wantAlt) return false;
|
|
25
|
-
|
|
47
|
+
if (e.key.toLowerCase() === key) return true;
|
|
48
|
+
return wantAlt && e.code === codeFor(key);
|
|
49
|
+
}
|
|
50
|
+
var DEFAULT_HOTKEY = "alt+shift+d";
|
|
51
|
+
var MAC_SYMBOL = {
|
|
52
|
+
meta: "\u2318",
|
|
53
|
+
cmd: "\u2318",
|
|
54
|
+
ctrl: "\u2303",
|
|
55
|
+
control: "\u2303",
|
|
56
|
+
shift: "\u21E7",
|
|
57
|
+
alt: "\u2325",
|
|
58
|
+
option: "\u2325"
|
|
59
|
+
};
|
|
60
|
+
var PC_NAME = {
|
|
61
|
+
meta: "Win",
|
|
62
|
+
cmd: "Win",
|
|
63
|
+
ctrl: "Ctrl",
|
|
64
|
+
control: "Ctrl",
|
|
65
|
+
shift: "Shift",
|
|
66
|
+
alt: "Alt",
|
|
67
|
+
option: "Alt"
|
|
68
|
+
};
|
|
69
|
+
function formatHotkey(spec) {
|
|
70
|
+
const parts = spec.toLowerCase().split("+").map((p) => p.trim()).filter(Boolean);
|
|
71
|
+
if (parts.length === 0) return "";
|
|
72
|
+
const key = parts[parts.length - 1];
|
|
73
|
+
const mods = parts.slice(0, -1);
|
|
74
|
+
const mac = isMac();
|
|
75
|
+
const label = key.length === 1 ? key.toUpperCase() : key;
|
|
76
|
+
const shown = mods.map(
|
|
77
|
+
(m) => mac ? MAC_SYMBOL[m] ?? (m === "mod" ? "\u2318" : m) : PC_NAME[m] ?? (m === "mod" ? "Ctrl" : m)
|
|
78
|
+
);
|
|
79
|
+
return mac ? [...shown, label].join("") : [...shown, label].join("+");
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// src/core/theme.ts
|
|
83
|
+
var partClass = {
|
|
84
|
+
root: "devdock-root",
|
|
85
|
+
button: "devdock-button",
|
|
86
|
+
dot: "devdock-dot",
|
|
87
|
+
buttonLabel: "devdock-button-label",
|
|
88
|
+
panel: "devdock-panel",
|
|
89
|
+
title: "devdock-title",
|
|
90
|
+
hotkeyHint: "devdock-hotkey-hint",
|
|
91
|
+
inputWrap: "devdock-input-wrap",
|
|
92
|
+
input: "devdock-input",
|
|
93
|
+
body: "devdock-body",
|
|
94
|
+
list: "devdock-list",
|
|
95
|
+
section: "devdock-section",
|
|
96
|
+
group: "devdock-group",
|
|
97
|
+
row: "devdock-row",
|
|
98
|
+
rowActive: "",
|
|
99
|
+
rowLabel: "devdock-row-label",
|
|
100
|
+
rowPath: "devdock-row-path",
|
|
101
|
+
check: "devdock-check",
|
|
102
|
+
empty: "devdock-empty",
|
|
103
|
+
viewLabel: "devdock-view-label",
|
|
104
|
+
view: "devdock-view"
|
|
105
|
+
};
|
|
106
|
+
var STYLE_MARKER = "data-devdock-styles";
|
|
107
|
+
var FONT = "ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif";
|
|
108
|
+
var BASE_CSS = `
|
|
109
|
+
.devdock-root { font-family: var(--devdock-font, ${FONT}); }
|
|
110
|
+
|
|
111
|
+
.devdock-button {
|
|
112
|
+
display: inline-flex;
|
|
113
|
+
align-items: center;
|
|
114
|
+
gap: 6px;
|
|
115
|
+
padding: 8px 12px;
|
|
116
|
+
font-size: 12px;
|
|
117
|
+
font-weight: 700;
|
|
118
|
+
letter-spacing: 0.6px;
|
|
119
|
+
color: var(--devdock-button-fg, #fff);
|
|
120
|
+
background: var(--devdock-button-bg, #111317);
|
|
121
|
+
border: 1px solid var(--devdock-border, #2a2e37);
|
|
122
|
+
border-radius: 999px;
|
|
123
|
+
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);
|
|
124
|
+
cursor: pointer;
|
|
125
|
+
}
|
|
126
|
+
.devdock-button:where([aria-expanded="true"]) {
|
|
127
|
+
background: var(--devdock-accent, #2563eb);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.devdock-dot {
|
|
131
|
+
width: 8px;
|
|
132
|
+
height: 8px;
|
|
133
|
+
border-radius: 999px;
|
|
134
|
+
background: var(--devdock-success, #22c55e);
|
|
135
|
+
display: inline-block;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.devdock-panel {
|
|
139
|
+
width: var(--devdock-width, 280px);
|
|
140
|
+
max-height: var(--devdock-max-height, 70vh);
|
|
141
|
+
display: flex;
|
|
142
|
+
flex-direction: column;
|
|
143
|
+
background: var(--devdock-bg, #16181d);
|
|
144
|
+
color: var(--devdock-fg, #e7e9ee);
|
|
145
|
+
border: 1px solid var(--devdock-border, #2a2e37);
|
|
146
|
+
border-radius: var(--devdock-radius, 12px);
|
|
147
|
+
box-shadow: var(--devdock-shadow, 0 12px 40px rgba(0, 0, 0, 0.45));
|
|
148
|
+
overflow: hidden;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.devdock-title {
|
|
152
|
+
display: flex;
|
|
153
|
+
align-items: center;
|
|
154
|
+
justify-content: space-between;
|
|
155
|
+
gap: 8px;
|
|
156
|
+
padding: 10px 12px;
|
|
157
|
+
border-bottom: 1px solid var(--devdock-border, #2a2e37);
|
|
158
|
+
font-size: 12px;
|
|
159
|
+
font-weight: 600;
|
|
160
|
+
letter-spacing: 0.4px;
|
|
161
|
+
text-transform: uppercase;
|
|
162
|
+
color: var(--devdock-muted, #8b909c);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.devdock-hotkey-hint {
|
|
166
|
+
flex-shrink: 0;
|
|
167
|
+
padding: 1px 5px;
|
|
168
|
+
font-family: inherit;
|
|
169
|
+
font-size: 10px;
|
|
170
|
+
font-weight: 600;
|
|
171
|
+
/* The heading's tracking and casing are for words, not for a key cap. */
|
|
172
|
+
letter-spacing: 0;
|
|
173
|
+
text-transform: none;
|
|
174
|
+
color: var(--devdock-subtle, #6b7280);
|
|
175
|
+
border: 1px solid var(--devdock-border, #2a2e37);
|
|
176
|
+
border-radius: var(--devdock-radius-xs, 4px);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.devdock-input-wrap { padding: 8px; }
|
|
180
|
+
|
|
181
|
+
.devdock-input {
|
|
182
|
+
width: 100%;
|
|
183
|
+
box-sizing: border-box;
|
|
184
|
+
padding: 8px 10px;
|
|
185
|
+
font-size: 13px;
|
|
186
|
+
color: var(--devdock-fg, #e7e9ee);
|
|
187
|
+
background: var(--devdock-input-bg, #0f1115);
|
|
188
|
+
border: 1px solid var(--devdock-border, #2a2e37);
|
|
189
|
+
border-radius: var(--devdock-radius-sm, 8px);
|
|
190
|
+
outline: none;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.devdock-body {
|
|
194
|
+
overflow-y: auto;
|
|
195
|
+
display: flex;
|
|
196
|
+
flex-direction: column;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.devdock-list { padding: 0 6px 8px; }
|
|
200
|
+
|
|
201
|
+
.devdock-section { margin-top: 6px; }
|
|
202
|
+
|
|
203
|
+
.devdock-group {
|
|
204
|
+
padding: 6px 8px 2px;
|
|
205
|
+
font-size: 10px;
|
|
206
|
+
font-weight: 700;
|
|
207
|
+
letter-spacing: 0.6px;
|
|
208
|
+
text-transform: uppercase;
|
|
209
|
+
color: var(--devdock-subtle, #6b7280);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.devdock-row {
|
|
213
|
+
display: flex;
|
|
214
|
+
align-items: center;
|
|
215
|
+
justify-content: space-between;
|
|
216
|
+
gap: 8px;
|
|
217
|
+
width: 100%;
|
|
218
|
+
text-align: left;
|
|
219
|
+
padding: 8px 10px;
|
|
220
|
+
font-size: 13px;
|
|
221
|
+
color: var(--devdock-fg, #e7e9ee);
|
|
222
|
+
background: transparent;
|
|
223
|
+
border: none;
|
|
224
|
+
border-radius: var(--devdock-radius-sm, 8px);
|
|
225
|
+
cursor: pointer;
|
|
226
|
+
}
|
|
227
|
+
.devdock-row:where([data-active]) {
|
|
228
|
+
background: var(--devdock-accent, #2563eb);
|
|
229
|
+
color: var(--devdock-accent-fg, #e7e9ee);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.devdock-row-label {
|
|
233
|
+
overflow: hidden;
|
|
234
|
+
text-overflow: ellipsis;
|
|
235
|
+
white-space: nowrap;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.devdock-row-path {
|
|
239
|
+
font-size: 11px;
|
|
240
|
+
color: var(--devdock-subtle, #6b7280);
|
|
241
|
+
font-family: ui-monospace, SFMono-Regular, monospace;
|
|
242
|
+
flex-shrink: 0;
|
|
243
|
+
}
|
|
244
|
+
:where(.devdock-row[data-active]) .devdock-row-path {
|
|
245
|
+
/* Whatever colour the row ended up with, stepped back: currentColor in the
|
|
246
|
+
color property means the inherited one, so this tracks the row however it
|
|
247
|
+
was set - a token, a class of yours - instead of guessing at the accent. */
|
|
248
|
+
color: color-mix(in oklab, currentColor 75%, transparent);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.devdock-check {
|
|
252
|
+
flex-shrink: 0;
|
|
253
|
+
width: 12px;
|
|
254
|
+
text-align: center;
|
|
255
|
+
color: var(--devdock-success, #22c55e);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.devdock-empty {
|
|
259
|
+
padding: 12px;
|
|
260
|
+
font-size: 13px;
|
|
261
|
+
color: var(--devdock-subtle, #6b7280);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.devdock-view-label {
|
|
265
|
+
padding: 4px 8px 0;
|
|
266
|
+
font-size: 11px;
|
|
267
|
+
color: var(--devdock-muted, #8b909c);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.devdock-view { padding: 2px 8px 6px; }
|
|
271
|
+
`;
|
|
272
|
+
var DEFAULT_LAYER = "devdock";
|
|
273
|
+
function dockStyles(layer) {
|
|
274
|
+
if (!layer) return BASE_CSS;
|
|
275
|
+
const block = `@layer ${layer} {${BASE_CSS}}
|
|
276
|
+
`;
|
|
277
|
+
if (layer !== DEFAULT_LAYER) return block;
|
|
278
|
+
const order = `@layer theme, base, components, ${layer}, utilities;`;
|
|
279
|
+
return `${order}
|
|
280
|
+
${block}`;
|
|
26
281
|
}
|
|
27
282
|
|
|
28
283
|
// src/core/dock.ts
|
|
@@ -55,33 +310,12 @@ var isDevHost = () => {
|
|
|
55
310
|
if (!host) return true;
|
|
56
311
|
return host === "localhost" || host.endsWith(".localhost") || host.endsWith(".local") || host === "::1" || host === "0.0.0.0" || isLocalIPv4(host);
|
|
57
312
|
};
|
|
58
|
-
function el(tag,
|
|
313
|
+
function el(tag, props) {
|
|
59
314
|
const node = document.createElement(tag);
|
|
60
|
-
if (styles) Object.assign(node.style, styles);
|
|
61
315
|
if (props) Object.assign(node, props);
|
|
62
316
|
return node;
|
|
63
317
|
}
|
|
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
|
-
}
|
|
318
|
+
var PARTS = Object.keys(partClass);
|
|
85
319
|
function cornerStyle(position) {
|
|
86
320
|
const gap = "16px";
|
|
87
321
|
switch (position) {
|
|
@@ -104,7 +338,6 @@ function panelAnchor(position) {
|
|
|
104
338
|
[isRight ? "right" : "left"]: "0"
|
|
105
339
|
};
|
|
106
340
|
}
|
|
107
|
-
var FONT = "ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif";
|
|
108
341
|
function keyViews(views) {
|
|
109
342
|
const used = /* @__PURE__ */ new Set();
|
|
110
343
|
return views.map((view, i) => {
|
|
@@ -121,96 +354,72 @@ function createDevDock(initial = {}) {
|
|
|
121
354
|
} };
|
|
122
355
|
}
|
|
123
356
|
let opts = { ...initial };
|
|
357
|
+
const cls = (...parts) => cn.cn(parts.map((part) => [partClass[part], opts.classNames?.[part]]));
|
|
358
|
+
const classSig = () => PARTS.map((p) => cn.cn(opts.classNames?.[p])).join("\0");
|
|
124
359
|
let open = false;
|
|
125
360
|
let query = "";
|
|
126
361
|
let active = 0;
|
|
127
362
|
let mounted = false;
|
|
128
363
|
const host = el("div");
|
|
129
364
|
host.setAttribute("data-devdock", "");
|
|
130
|
-
const shadowMode = initial.shadow ?? true;
|
|
365
|
+
const shadowMode = initial.shadow ?? (initial.classNames ? "inherit" : true);
|
|
131
366
|
const useShadow = shadowMode !== false && typeof host.attachShadow === "function";
|
|
132
367
|
const shadowRoot = useShadow ? host.attachShadow({ mode: "open" }) : null;
|
|
133
368
|
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"
|
|
369
|
+
const baseStyle = el("style", {
|
|
370
|
+
textContent: dockStyles(initial.cssLayer ?? DEFAULT_LAYER)
|
|
149
371
|
});
|
|
372
|
+
baseStyle.setAttribute(STYLE_MARKER, "");
|
|
373
|
+
if (shadowRoot) mountPoint.appendChild(baseStyle);
|
|
374
|
+
const styleSlot = shadowRoot && shadowMode === "inherit" ? el("div") : null;
|
|
375
|
+
if (styleSlot) {
|
|
376
|
+
styleSlot.style.display = "contents";
|
|
377
|
+
mountPoint.appendChild(styleSlot);
|
|
378
|
+
}
|
|
379
|
+
const root = el("div");
|
|
380
|
+
mountPoint.appendChild(root);
|
|
381
|
+
const panel = el("div");
|
|
150
382
|
panel.setAttribute("role", "dialog");
|
|
151
|
-
const heading = el("div"
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
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
|
-
});
|
|
383
|
+
const heading = el("div");
|
|
384
|
+
const headingText = el("span");
|
|
385
|
+
const hotkeyHint = el("kbd");
|
|
386
|
+
heading.append(headingText, hotkeyHint);
|
|
387
|
+
const inputWrap = el("div");
|
|
388
|
+
const input = el("input");
|
|
172
389
|
input.placeholder = "Filter\u2026";
|
|
173
390
|
inputWrap.appendChild(input);
|
|
174
|
-
const list = el("div"
|
|
391
|
+
const list = el("div");
|
|
175
392
|
list.setAttribute("data-devdock-list", "");
|
|
176
393
|
const viewsBefore = el("div");
|
|
177
394
|
viewsBefore.setAttribute("data-devdock-views", "before");
|
|
178
395
|
const viewsAfter = el("div");
|
|
179
396
|
viewsAfter.setAttribute("data-devdock-views", "after");
|
|
180
|
-
const body = el("div"
|
|
181
|
-
overflowY: "auto",
|
|
182
|
-
display: "flex",
|
|
183
|
-
flexDirection: "column"
|
|
184
|
-
});
|
|
397
|
+
const body = el("div");
|
|
185
398
|
body.append(viewsBefore, list, viewsAfter);
|
|
186
399
|
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
|
-
});
|
|
400
|
+
const button = el("button");
|
|
202
401
|
button.type = "button";
|
|
203
402
|
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
|
-
});
|
|
403
|
+
const dot = el("span");
|
|
211
404
|
const buttonLabel = el("span");
|
|
212
405
|
button.append(dot, buttonLabel);
|
|
213
406
|
root.appendChild(button);
|
|
407
|
+
const sectionHeading = (text) => el("div", { className: cls("group"), textContent: text });
|
|
408
|
+
const viewLabel = (text) => el("div", { className: cls("viewLabel"), textContent: text });
|
|
409
|
+
const paintClasses = () => {
|
|
410
|
+
root.className = cls("root");
|
|
411
|
+
button.className = cls("button");
|
|
412
|
+
dot.className = cls("dot");
|
|
413
|
+
buttonLabel.className = cls("buttonLabel");
|
|
414
|
+
panel.className = cls("panel");
|
|
415
|
+
heading.className = cls("title");
|
|
416
|
+
hotkeyHint.className = cls("hotkeyHint");
|
|
417
|
+
inputWrap.className = cls("inputWrap");
|
|
418
|
+
input.className = cls("input");
|
|
419
|
+
body.className = cls("body");
|
|
420
|
+
list.className = cls("list");
|
|
421
|
+
};
|
|
422
|
+
const hotkey = () => opts.hotkey === void 0 ? DEFAULT_HOTKEY : opts.hotkey;
|
|
214
423
|
const enabled = () => {
|
|
215
424
|
const e = opts.enabled;
|
|
216
425
|
if (typeof e === "function") return e();
|
|
@@ -294,9 +503,9 @@ function createDevDock(initial = {}) {
|
|
|
294
503
|
const paintActive = () => {
|
|
295
504
|
rows.forEach((row, idx) => {
|
|
296
505
|
const isActive = idx === active;
|
|
297
|
-
row.node.
|
|
298
|
-
|
|
299
|
-
|
|
506
|
+
if (isActive) row.node.setAttribute("data-active", "");
|
|
507
|
+
else row.node.removeAttribute("data-active");
|
|
508
|
+
row.node.className = isActive ? cls("row", "rowActive") : cls("row");
|
|
300
509
|
});
|
|
301
510
|
};
|
|
302
511
|
const setActive = (next, scroll = false) => {
|
|
@@ -308,7 +517,7 @@ function createDevDock(initial = {}) {
|
|
|
308
517
|
const renderList = () => {
|
|
309
518
|
const filtered = getFiltered();
|
|
310
519
|
active = Math.min(active, Math.max(0, filtered.length - 1));
|
|
311
|
-
const sig = filtered.map(itemSig).join("\n");
|
|
520
|
+
const sig = [classSig(), ...filtered.map(itemSig)].join("\n");
|
|
312
521
|
if (sig === rowsSig) {
|
|
313
522
|
filtered.forEach((it, idx) => {
|
|
314
523
|
const row = rows[idx];
|
|
@@ -324,11 +533,7 @@ function createDevDock(initial = {}) {
|
|
|
324
533
|
list.replaceChildren();
|
|
325
534
|
if (filtered.length === 0) {
|
|
326
535
|
list.appendChild(
|
|
327
|
-
el(
|
|
328
|
-
"div",
|
|
329
|
-
{ padding: "12px", fontSize: "13px", color: "#6b7280" },
|
|
330
|
-
{ textContent: "Nothing here." }
|
|
331
|
-
)
|
|
536
|
+
el("div", { className: cls("empty"), textContent: "Nothing here." })
|
|
332
537
|
);
|
|
333
538
|
return;
|
|
334
539
|
}
|
|
@@ -339,55 +544,26 @@ function createDevDock(initial = {}) {
|
|
|
339
544
|
groups.set(it.group, arr);
|
|
340
545
|
}
|
|
341
546
|
for (const [groupName, groupItems] of groups) {
|
|
342
|
-
const section = el("div", {
|
|
547
|
+
const section = el("div", { className: cls("section") });
|
|
343
548
|
section.appendChild(sectionHeading(groupName));
|
|
344
549
|
for (const it of groupItems) {
|
|
345
550
|
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
|
-
});
|
|
551
|
+
const row = el("button", { className: cls("row") });
|
|
361
552
|
row.type = "button";
|
|
362
|
-
const labelSpan = el("span", {
|
|
363
|
-
overflow: "hidden",
|
|
364
|
-
textOverflow: "ellipsis",
|
|
365
|
-
whiteSpace: "nowrap"
|
|
366
|
-
});
|
|
553
|
+
const labelSpan = el("span", { className: cls("rowLabel") });
|
|
367
554
|
row.appendChild(labelSpan);
|
|
368
555
|
let pathSpan = null;
|
|
369
556
|
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
|
-
);
|
|
557
|
+
pathSpan = el("span", {
|
|
558
|
+
className: cls("rowPath"),
|
|
559
|
+
textContent: it.route.path
|
|
560
|
+
});
|
|
380
561
|
row.appendChild(pathSpan);
|
|
381
562
|
}
|
|
382
563
|
let checkSpan = null;
|
|
383
564
|
if (it.kind === "command" && it.checked !== null) {
|
|
384
565
|
row.setAttribute("role", "checkbox");
|
|
385
|
-
checkSpan = el("span", {
|
|
386
|
-
flexShrink: "0",
|
|
387
|
-
width: "12px",
|
|
388
|
-
textAlign: "center",
|
|
389
|
-
color: "#22c55e"
|
|
390
|
-
});
|
|
566
|
+
checkSpan = el("span", { className: cls("check") });
|
|
391
567
|
row.appendChild(checkSpan);
|
|
392
568
|
}
|
|
393
569
|
const rec = { item: it, node: row, labelSpan, pathSpan, checkSpan };
|
|
@@ -416,11 +592,14 @@ function createDevDock(initial = {}) {
|
|
|
416
592
|
};
|
|
417
593
|
const renderViews = () => {
|
|
418
594
|
const keyed = keyViews(opts.views ?? []);
|
|
419
|
-
const sig =
|
|
420
|
-
(
|
|
421
|
-
|
|
595
|
+
const sig = [
|
|
596
|
+
classSig(),
|
|
597
|
+
...keyed.map(
|
|
598
|
+
({ view, key }) => [key, viewOrder(view), view.group ?? "", view.label ?? ""].join(
|
|
599
|
+
"\0"
|
|
600
|
+
)
|
|
422
601
|
)
|
|
423
|
-
|
|
602
|
+
].join("\n");
|
|
424
603
|
if (sig === viewsSig) return;
|
|
425
604
|
viewsSig = sig;
|
|
426
605
|
const live = new Set(keyed.map(({ key }) => key));
|
|
@@ -448,7 +627,7 @@ function createDevDock(initial = {}) {
|
|
|
448
627
|
});
|
|
449
628
|
}
|
|
450
629
|
for (const section of sections.values()) {
|
|
451
|
-
const wrap = el("div", {
|
|
630
|
+
const wrap = el("div", { className: cls("section") });
|
|
452
631
|
if (section.heading) wrap.appendChild(sectionHeading(section.heading));
|
|
453
632
|
for (const { view, key } of section.items) {
|
|
454
633
|
if (view.group != null && view.label)
|
|
@@ -458,7 +637,7 @@ function createDevDock(initial = {}) {
|
|
|
458
637
|
wrap.appendChild(existing.host);
|
|
459
638
|
continue;
|
|
460
639
|
}
|
|
461
|
-
const viewHost = el("div", {
|
|
640
|
+
const viewHost = el("div", { className: cls("view") });
|
|
462
641
|
viewHost.setAttribute("data-devdock-view", view.id ?? "");
|
|
463
642
|
wrap.appendChild(viewHost);
|
|
464
643
|
pending.push({ view, key, host: viewHost });
|
|
@@ -485,7 +664,9 @@ function createDevDock(initial = {}) {
|
|
|
485
664
|
}
|
|
486
665
|
}
|
|
487
666
|
const sheets = [
|
|
488
|
-
...document.querySelectorAll(
|
|
667
|
+
...document.querySelectorAll(
|
|
668
|
+
`style:not([${STYLE_MARKER}]), link[rel~="stylesheet" i]`
|
|
669
|
+
)
|
|
489
670
|
];
|
|
490
671
|
const sig = sheets.map((n) => `${n.tagName}\0${n.getAttribute("href") ?? n.textContent}`).join("\n");
|
|
491
672
|
if (sig === clonesSig) return;
|
|
@@ -527,12 +708,17 @@ function createDevDock(initial = {}) {
|
|
|
527
708
|
right: ""
|
|
528
709
|
});
|
|
529
710
|
Object.assign(root.style, cornerStyle(position));
|
|
530
|
-
|
|
711
|
+
headingText.textContent = opts.title ?? "Dev Menu";
|
|
531
712
|
panel.setAttribute("aria-label", opts.title ?? "Dev Menu");
|
|
532
713
|
Object.assign(panel.style, panelAnchor(position));
|
|
533
714
|
buttonLabel.textContent = opts.label ?? "DEV";
|
|
534
|
-
|
|
715
|
+
const spec = hotkey();
|
|
716
|
+
const chord = spec ? formatHotkey(spec) : "";
|
|
717
|
+
hotkeyHint.textContent = chord;
|
|
718
|
+
hotkeyHint.hidden = !chord;
|
|
719
|
+
button.title = chord ? `${opts.title ?? "Dev Menu"} (${chord})` : opts.title ?? "Dev Menu";
|
|
535
720
|
button.setAttribute("aria-expanded", String(open));
|
|
721
|
+
paintClasses();
|
|
536
722
|
};
|
|
537
723
|
function setOpen(next) {
|
|
538
724
|
if (open === next) return;
|
|
@@ -579,7 +765,8 @@ function createDevDock(initial = {}) {
|
|
|
579
765
|
if (open && !e.composedPath().includes(root)) setOpen(false);
|
|
580
766
|
};
|
|
581
767
|
const onKeyDown = (e) => {
|
|
582
|
-
|
|
768
|
+
const spec = hotkey();
|
|
769
|
+
if (spec && matchHotkey(spec, e)) {
|
|
583
770
|
e.preventDefault();
|
|
584
771
|
setOpen(!open);
|
|
585
772
|
}
|
|
@@ -594,6 +781,8 @@ function createDevDock(initial = {}) {
|
|
|
594
781
|
};
|
|
595
782
|
const mount = () => {
|
|
596
783
|
if (mounted) return;
|
|
784
|
+
if (!shadowRoot)
|
|
785
|
+
(document.head ?? document.documentElement).prepend(baseStyle);
|
|
597
786
|
(opts.container ?? document.body).appendChild(host);
|
|
598
787
|
addListeners();
|
|
599
788
|
syncStyles();
|
|
@@ -604,6 +793,7 @@ function createDevDock(initial = {}) {
|
|
|
604
793
|
if (!mounted) return;
|
|
605
794
|
removeListeners();
|
|
606
795
|
unwatchStyles();
|
|
796
|
+
if (!shadowRoot) baseStyle.remove();
|
|
607
797
|
host.remove();
|
|
608
798
|
mounted = false;
|
|
609
799
|
};
|