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