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