cmdzero 0.6.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/overlay/overlay.js +67 -42
- package/package.json +1 -1
package/overlay/overlay.js
CHANGED
|
@@ -43,12 +43,19 @@
|
|
|
43
43
|
.cz-pop button.cz-primary{background:#6366f1}
|
|
44
44
|
.cz-pop input{flex:1;background:#1f2937;border:1px solid #374151;border-radius:6px;color:#f9fafb;padding:5px 8px;font-size:12px;outline:none}
|
|
45
45
|
.cz-pop select{background:#1f2937;border:1px solid #374151;border-radius:6px;color:#f9fafb;padding:3px 4px;font-size:11.5px;outline:none}
|
|
46
|
-
.cz-panel{position:fixed;left:
|
|
46
|
+
.cz-panel{position:fixed;left:0;top:30px;bottom:0;width:264px;box-sizing:border-box;overflow-y:auto;background:#0f1523;color:#f9fafb;border-right:1.5px solid #10b981;box-shadow:8px 0 30px rgba(0,0,0,.4);padding:12px 12px 28px;pointer-events:auto;display:flex;flex-direction:column;gap:6px;font-size:12px;z-index:2147483100;transform:translateX(0);transition:transform .26s cubic-bezier(.4,0,.2,1)}
|
|
47
|
+
.cz-panel.cz-collapsed{transform:translateX(-100%)}
|
|
48
|
+
.cz-phead{display:flex;align-items:center;justify-content:space-between;gap:8px;padding-bottom:7px;border-bottom:1px solid #1f2937}
|
|
49
|
+
.cz-min{background:#1f2937;color:#cbd5e1;border:none;border-radius:6px;padding:2px 9px;font-size:14px;line-height:1;cursor:pointer}
|
|
50
|
+
.cz-min:hover{background:#374151;color:#fff}
|
|
51
|
+
.cz-ptab{position:fixed;left:0;top:calc(50% + 15px);transform:translateY(-50%);z-index:2147483110;display:none;align-items:center;gap:5px;background:#10b981;color:#052e1b;border:none;border-radius:0 9px 9px 0;padding:13px 6px;cursor:pointer;pointer-events:auto;writing-mode:vertical-rl;font-size:11px;font-weight:700;letter-spacing:.05em;box-shadow:2px 0 10px rgba(0,0,0,.35)}
|
|
52
|
+
.cz-ptab.cz-show{display:flex}
|
|
53
|
+
.cz-ptab:hover{background:#34d399}
|
|
47
54
|
.cz-panel .cz-row{display:flex;gap:6px;align-items:center;flex-wrap:wrap}
|
|
48
55
|
.cz-panel button{background:#374151;color:#f9fafb;border:none;border-radius:6px;padding:4px 9px;font-size:12px;cursor:pointer}
|
|
49
56
|
.cz-panel button:hover{background:#4b5563}
|
|
50
57
|
.cz-panel select{background:#1f2937;border:1px solid #374151;border-radius:6px;color:#f9fafb;padding:3px 4px;font-size:11.5px;outline:none}
|
|
51
|
-
.cz-ptitle{font-family:ui-monospace,monospace;font-size:11px;color:#6ee7b7;
|
|
58
|
+
.cz-ptitle{font-family:ui-monospace,monospace;font-size:11px;color:#6ee7b7;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
52
59
|
.cz-sec{color:#94a3b8;font-size:9.5px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;margin:5px 0 1px}
|
|
53
60
|
.cz-label{color:#9ca3af;min-width:50px}
|
|
54
61
|
.cz-note{color:#fbbf24;font-size:11px;line-height:1.35;background:rgba(245,158,11,.1);border-radius:6px;padding:4px 7px}
|
|
@@ -58,8 +65,14 @@
|
|
|
58
65
|
.cz-swatch{width:18px;height:18px;border-radius:4px;border:1px solid rgba(255,255,255,.25);cursor:pointer;padding:0}
|
|
59
66
|
.cz-swatch:hover{transform:scale(1.15)}
|
|
60
67
|
.cz-chip{font-size:10.5px !important;padding:2px 6px !important}
|
|
61
|
-
.cz-tray{position:fixed;right:14px;bottom:14px;display:flex;flex-direction:column;align-items:flex-end;gap:6px;pointer-events:auto
|
|
62
|
-
|
|
68
|
+
.cz-tray{position:fixed;right:14px;bottom:14px;display:flex;flex-direction:column;align-items:flex-end;gap:6px;pointer-events:auto}
|
|
69
|
+
/* Compressed by default (just a dot + short label); hovering the tray expands
|
|
70
|
+
every alert to full detail with undo/cancel. */
|
|
71
|
+
.cz-tweak{transition:padding .12s ease}
|
|
72
|
+
.cz-tray:not(:hover) .cz-tweak{padding:4px 10px;font-size:12px}
|
|
73
|
+
.cz-tray:not(:hover) .cz-tweak .cz-meta,
|
|
74
|
+
.cz-tray:not(:hover) .cz-tweak button{display:none}
|
|
75
|
+
.cz-tray:not(:hover) .cz-tlabel{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:230px;display:inline-block;vertical-align:bottom}
|
|
63
76
|
.cz-banner{position:fixed;top:0;left:0;right:0;height:30px;display:flex;align-items:center;justify-content:space-between;gap:14px;padding:0 14px;background:rgba(9,13,20,.94);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);border-bottom:1px solid #1f2937;color:#cbd5e1;font-size:12px;line-height:1;pointer-events:auto;z-index:2147483200;box-sizing:border-box}
|
|
64
77
|
.cz-banner .cz-brand{display:flex;align-items:center;gap:6px;font-weight:600;color:#e2e8f0;flex:none}
|
|
65
78
|
.cz-banner .cz-brand kbd{background:#10b981;color:#052e1b;border-radius:5px;padding:2px 6px;font-size:10.5px;font-family:ui-monospace,monospace;font-weight:700}
|
|
@@ -72,7 +85,7 @@
|
|
|
72
85
|
.cz-banner .cz-idle{color:#64748b}
|
|
73
86
|
.cz-wrap{display:flex;flex-direction:column;align-items:flex-end;gap:6px}
|
|
74
87
|
.cz-wrap.cz-expanded{max-height:calc(100vh - 90px);overflow-y:auto;overflow-x:hidden;padding:2px}
|
|
75
|
-
.cz-wrap:not(.cz-expanded) > .cz-tweak:nth-child(n+
|
|
88
|
+
.cz-wrap:not(.cz-expanded) > .cz-tweak:nth-child(n+4){display:none}
|
|
76
89
|
.cz-fade{height:16px;width:160px;background:linear-gradient(to bottom,rgba(17,24,39,0),rgba(17,24,39,.55));pointer-events:none;margin-top:-10px}
|
|
77
90
|
.cz-history{background:#0b1220;color:#93c5fd;border:1px solid #263041;border-radius:8px;padding:4px 10px;font-size:11.5px;cursor:pointer;pointer-events:auto;box-shadow:0 4px 14px rgba(0,0,0,.3)}
|
|
78
91
|
.cz-history:hover{border-color:#6366f1}
|
|
@@ -104,8 +117,10 @@
|
|
|
104
117
|
model: 'auto', // NL model override; 'auto' = router picks
|
|
105
118
|
multi: [], // [{ el, loc }] shift-click multi-selection
|
|
106
119
|
autoReload: true, // seamlessly reload after a write so changes always show live
|
|
120
|
+
panelCollapsed: false, // left style panel minimized to a tab
|
|
107
121
|
};
|
|
108
122
|
try { state.autoReload = localStorage.getItem('cz-autoreload') !== '0'; } catch { /* no storage */ }
|
|
123
|
+
try { state.panelCollapsed = localStorage.getItem('cz-panel-collapsed') === '1'; } catch { /* no storage */ }
|
|
109
124
|
|
|
110
125
|
// Stack of undoable tweak ids (LIFO) for ⌘Z / Ctrl-Z global undo.
|
|
111
126
|
const undoStack = [];
|
|
@@ -230,11 +245,31 @@
|
|
|
230
245
|
const pop = el('div', 'cz-pop');
|
|
231
246
|
pop.style.display = 'none';
|
|
232
247
|
root.appendChild(pop);
|
|
233
|
-
// Left-side style inspector —
|
|
234
|
-
//
|
|
235
|
-
const
|
|
236
|
-
panel
|
|
248
|
+
// Left-side style inspector — a full-height dock that slides in from the left
|
|
249
|
+
// and pushes the page over (no overlap). Minimizable to a left-edge tab.
|
|
250
|
+
const PANEL_W = 264;
|
|
251
|
+
const panel = el('div', 'cz-panel cz-collapsed');
|
|
237
252
|
root.appendChild(panel);
|
|
253
|
+
const panelTab = el('button', 'cz-ptab');
|
|
254
|
+
panelTab.innerHTML = '<span>▸</span><span>STYLE</span>';
|
|
255
|
+
panelTab.title = 'Show style panel';
|
|
256
|
+
panelTab.onclick = () => setPanelCollapsed(false);
|
|
257
|
+
root.appendChild(panelTab);
|
|
258
|
+
try { document.body.style.transition = 'margin-left .26s cubic-bezier(.4,0,.2,1)'; } catch { /* ignore */ }
|
|
259
|
+
|
|
260
|
+
function setPanelCollapsed(v) {
|
|
261
|
+
state.panelCollapsed = v;
|
|
262
|
+
try { localStorage.setItem('cz-panel-collapsed', v ? '1' : '0'); } catch { /* no storage */ }
|
|
263
|
+
applyPanelLayout();
|
|
264
|
+
}
|
|
265
|
+
// Slide the panel in/out and push the page so nothing is covered.
|
|
266
|
+
function applyPanelLayout() {
|
|
267
|
+
const open = !!state.selected && !state.panelCollapsed;
|
|
268
|
+
panel.classList.toggle('cz-collapsed', !open);
|
|
269
|
+
panelTab.classList.toggle('cz-show', !!state.selected && state.panelCollapsed);
|
|
270
|
+
try { document.body.style.marginLeft = open ? PANEL_W + 'px' : '0px'; } catch { /* ignore */ }
|
|
271
|
+
}
|
|
272
|
+
|
|
238
273
|
const popLabel = el('div', 'cz-pop-label');
|
|
239
274
|
popLabel.style.display = 'none';
|
|
240
275
|
root.appendChild(popLabel);
|
|
@@ -351,7 +386,7 @@
|
|
|
351
386
|
grip.style.cursor = 'grabbing';
|
|
352
387
|
s.el.style.opacity = '0.45'; // show what's moving
|
|
353
388
|
// hide the panels/popover so they don't block the drop targets
|
|
354
|
-
pop.style.display = 'none';
|
|
389
|
+
pop.style.display = 'none'; popLabel.style.display = 'none'; // panel is docked left, doesn't block drop targets
|
|
355
390
|
};
|
|
356
391
|
|
|
357
392
|
const onMove = (ev) => {
|
|
@@ -439,7 +474,7 @@
|
|
|
439
474
|
state.selected = null;
|
|
440
475
|
selBox.style.display = 'none';
|
|
441
476
|
pop.style.display = 'none';
|
|
442
|
-
panel
|
|
477
|
+
applyPanelLayout(); // slides the panel out + un-shifts the page
|
|
443
478
|
popLabel.style.display = 'none';
|
|
444
479
|
deleteBtn.style.display = 'none';
|
|
445
480
|
moveBar.style.display = 'none';
|
|
@@ -826,10 +861,16 @@
|
|
|
826
861
|
// Left inspector panel: every style attribute broken out into its own control.
|
|
827
862
|
function renderPanel() {
|
|
828
863
|
const s = state.selected;
|
|
829
|
-
|
|
830
|
-
|
|
864
|
+
applyPanelLayout();
|
|
865
|
+
if (!s) return;
|
|
831
866
|
panel.textContent = '';
|
|
832
|
-
|
|
867
|
+
const head = el('div', 'cz-phead');
|
|
868
|
+
head.append(el('div', 'cz-ptitle', `<${s.el.tagName.toLowerCase()}> ${shortLoc(s.loc)}${s.instances > 1 ? ` · ${s.instances}×` : ''}`));
|
|
869
|
+
const min = el('button', 'cz-min', '‹');
|
|
870
|
+
min.title = 'Minimize panel';
|
|
871
|
+
min.onclick = () => setPanelCollapsed(true);
|
|
872
|
+
head.append(min);
|
|
873
|
+
panel.appendChild(head);
|
|
833
874
|
const tw = state.tailwind;
|
|
834
875
|
|
|
835
876
|
panel.appendChild(el('div', 'cz-sec', 'Spacing'));
|
|
@@ -1038,17 +1079,23 @@
|
|
|
1038
1079
|
banner.append(brand, bannerStats, reportLink);
|
|
1039
1080
|
root.appendChild(banner);
|
|
1040
1081
|
// Push the page down so the banner sits ABOVE the site rather than over it.
|
|
1082
|
+
// Inject a stylesheet instead of mutating body's style attribute: frameworks
|
|
1083
|
+
// that hydrate (React 19+) diff server-rendered attributes and flag a bare
|
|
1084
|
+
// style mutation as a hydration mismatch.
|
|
1041
1085
|
try {
|
|
1042
1086
|
const prevPad = getComputedStyle(document.body).paddingTop;
|
|
1043
|
-
|
|
1087
|
+
const pad = document.createElement('style');
|
|
1088
|
+
pad.setAttribute('data-cz-banner-pad', '');
|
|
1089
|
+
pad.textContent = `body { padding-top: calc(${prevPad} + 30px) !important; }`;
|
|
1090
|
+
document.head.appendChild(pad);
|
|
1044
1091
|
} catch { /* no body yet */ }
|
|
1045
1092
|
|
|
1046
1093
|
// ---------- tray ----------
|
|
1047
1094
|
const tray = el('div', 'cz-tray');
|
|
1048
1095
|
root.appendChild(tray);
|
|
1049
1096
|
// Alerts live in their own wrap so history can collapse independently.
|
|
1050
|
-
// Newest is inserted at the top; the
|
|
1051
|
-
//
|
|
1097
|
+
// Newest is inserted at the top; the 3 newest stay visible (compressed; hover to expand) and older
|
|
1098
|
+
// ones fold behind an expander.
|
|
1052
1099
|
const tweaksWrap = el('div', 'cz-wrap');
|
|
1053
1100
|
tray.appendChild(tweaksWrap);
|
|
1054
1101
|
const fade = el('div', 'cz-fade');
|
|
@@ -1066,8 +1113,8 @@
|
|
|
1066
1113
|
function updateHistoryUI() {
|
|
1067
1114
|
const rows = tweaksWrap.children.length;
|
|
1068
1115
|
const expanded = tweaksWrap.classList.contains('cz-expanded');
|
|
1069
|
-
const hidden = Math.max(0, rows -
|
|
1070
|
-
if (rows <=
|
|
1116
|
+
const hidden = Math.max(0, rows - 3);
|
|
1117
|
+
if (rows <= 3) { historyChip.style.display = 'none'; fade.style.display = 'none'; return; }
|
|
1071
1118
|
historyChip.style.display = '';
|
|
1072
1119
|
historyChip.textContent = expanded ? 'collapse ▴' : `+ ${hidden} older ▾`;
|
|
1073
1120
|
fade.style.display = expanded ? 'none' : '';
|
|
@@ -1120,7 +1167,7 @@
|
|
|
1120
1167
|
row = el('div', 'cz-tweak');
|
|
1121
1168
|
row._id = key;
|
|
1122
1169
|
row._dot = el('span', 'cz-dot');
|
|
1123
|
-
row._label = el('span',
|
|
1170
|
+
row._label = el('span', 'cz-tlabel', '');
|
|
1124
1171
|
row._meta = el('span', 'cz-meta', '');
|
|
1125
1172
|
row._cancel = el('button', null, 'cancel');
|
|
1126
1173
|
row._cancel.style.display = 'none';
|
|
@@ -1384,28 +1431,6 @@
|
|
|
1384
1431
|
else deselect();
|
|
1385
1432
|
}, true);
|
|
1386
1433
|
|
|
1387
|
-
// Alert tray dodges the cursor: when the pointer enters its region, slide it
|
|
1388
|
-
// off to the right so you can click the elements underneath; slide back once
|
|
1389
|
-
// the pointer leaves the original region (hysteresis avoids flicker).
|
|
1390
|
-
let trayDodged = false, trayZone = null;
|
|
1391
|
-
addEventListener('mousemove', (e) => {
|
|
1392
|
-
const x = e.clientX, y = e.clientY;
|
|
1393
|
-
if (!trayDodged) {
|
|
1394
|
-
if (!tweaksWrap.children.length) return; // nothing to dodge
|
|
1395
|
-
const r = tray.getBoundingClientRect();
|
|
1396
|
-
if (r.width && x >= r.left - 8 && x <= r.right + 8 && y >= r.top - 8 && y <= r.bottom + 8) {
|
|
1397
|
-
trayZone = r;
|
|
1398
|
-
trayDodged = true;
|
|
1399
|
-
tray.classList.add('cz-dodged');
|
|
1400
|
-
}
|
|
1401
|
-
} else {
|
|
1402
|
-
const r = trayZone, m = 34;
|
|
1403
|
-
if (!r || x < r.left - m || x > r.right + m || y < r.top - m || y > r.bottom + m) {
|
|
1404
|
-
trayDodged = false;
|
|
1405
|
-
tray.classList.remove('cz-dodged');
|
|
1406
|
-
}
|
|
1407
|
-
}
|
|
1408
|
-
}, true);
|
|
1409
1434
|
|
|
1410
1435
|
addEventListener('scroll', () => { reposition(); positionMulti(); setHover(state.hoverEl); }, true);
|
|
1411
1436
|
addEventListener('resize', () => { reposition(); positionMulti(); });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cmdzero",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Tweak your UI live in the browser and write the changes straight to source. Copy and Tailwind edits cost zero tokens; everything else routes to a right-sized model via headless claude.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|