cmdzero 0.8.0 → 0.8.1
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 +8 -2
- package/overlay/overlay.js +44 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
|
+
# CmdZero
|
|
2
|
+
|
|
1
3
|
<p align="center">
|
|
2
|
-
<img src="https://raw.githubusercontent.com/adamcwade/cmdzero/main/assets/hero.png" alt="CmdZero —
|
|
4
|
+
<img src="https://raw.githubusercontent.com/adamcwade/cmdzero/main/assets/hero.png" alt="CmdZero — live in-browser UI editing with a style panel, inline copy editing, and a token-savings banner" width="900">
|
|
3
5
|
</p>
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
<p align="center">
|
|
8
|
+
<strong><a href="https://cmdzero.xyz/demo">▶︎ Try the live demo — no install</a></strong>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
Press `⌘0` and edit a real page with the real overlay, running entirely in your browser. Copy, style, reorder, delete and undo all work; natural-language prompts are scripted (no model is called) and nothing is written to disk.
|
|
6
12
|
|
|
7
13
|
Tweak your UI live in the browser — the changes are written straight to your source files.
|
|
8
14
|
|
package/overlay/overlay.js
CHANGED
|
@@ -265,6 +265,47 @@
|
|
|
265
265
|
try { localStorage.setItem('cz-panel-collapsed', v ? '1' : '0'); } catch { /* no storage */ }
|
|
266
266
|
applyPanelLayout();
|
|
267
267
|
}
|
|
268
|
+
// Everything the overlay draws — outline, popover, move bar, delete button,
|
|
269
|
+
// hover badge — is position:fixed at coordinates measured once from
|
|
270
|
+
// getBoundingClientRect(). The page moves under those coordinates constantly:
|
|
271
|
+
// opening the panel animates <body>'s margin for .26s, that push narrows the
|
|
272
|
+
// viewport so text re-wraps and blocks shift down, an edit changes an
|
|
273
|
+
// element's size, fonts and images land, the page runs its own animations.
|
|
274
|
+
// reposition() on scroll/resize/select catches none of that, which is why a
|
|
275
|
+
// box could sit up to PANEL_W px from its element until something unrelated
|
|
276
|
+
// happened to re-measure.
|
|
277
|
+
//
|
|
278
|
+
// Chasing each cause separately is a losing game, so watch the element
|
|
279
|
+
// itself: compare its rect every frame and redraw only when it actually
|
|
280
|
+
// moved. rAF is the right clock — it's gated on painting exactly like the
|
|
281
|
+
// transitions and reflows we're chasing, so we never measure a layout the
|
|
282
|
+
// user hasn't seen yet. Idle cost is one getBoundingClientRect and a string
|
|
283
|
+
// compare per frame, and the loop only runs while the overlay has something
|
|
284
|
+
// on screen to keep glued.
|
|
285
|
+
let watchRaf = 0;
|
|
286
|
+
let lastRect = '';
|
|
287
|
+
function watchLayout() {
|
|
288
|
+
if (watchRaf) return; // already running
|
|
289
|
+
const step = () => {
|
|
290
|
+
if (!state.selectMode && !state.selected) { watchRaf = 0; lastRect = ''; return; }
|
|
291
|
+
const target = state.selected?.el || state.hoverEl;
|
|
292
|
+
if (target && document.contains(target)) {
|
|
293
|
+
const r = target.getBoundingClientRect();
|
|
294
|
+
const key = `${r.left},${r.top},${r.width},${r.height}`;
|
|
295
|
+
if (key !== lastRect) {
|
|
296
|
+
lastRect = key;
|
|
297
|
+
// the same trio the scroll handler runs — a scroll strands these
|
|
298
|
+
// boxes for exactly the same reason any other layout shift does
|
|
299
|
+
reposition();
|
|
300
|
+
positionMulti();
|
|
301
|
+
setHover(state.hoverEl);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
watchRaf = requestAnimationFrame(step);
|
|
305
|
+
};
|
|
306
|
+
watchRaf = requestAnimationFrame(step);
|
|
307
|
+
}
|
|
308
|
+
|
|
268
309
|
// Slide the panel in/out and push the page so nothing is covered.
|
|
269
310
|
function applyPanelLayout() {
|
|
270
311
|
const open = !!state.selected && !state.panelCollapsed;
|
|
@@ -450,6 +491,7 @@
|
|
|
450
491
|
renderPopover();
|
|
451
492
|
renderPanel();
|
|
452
493
|
reposition();
|
|
494
|
+
watchLayout(); // renderPanel() just started the panel's .26s page push
|
|
453
495
|
loadMeta();
|
|
454
496
|
}
|
|
455
497
|
|
|
@@ -1383,7 +1425,8 @@
|
|
|
1383
1425
|
function setMode(on) {
|
|
1384
1426
|
state.selectMode = on;
|
|
1385
1427
|
hint.textContent = on ? 'select mode — click · shift-click multi · Tab next · ⌘Z undo · Esc exit' : '⌘0 select mode';
|
|
1386
|
-
if (
|
|
1428
|
+
if (on) watchLayout(); // keep the boxes glued while anything on the page moves
|
|
1429
|
+
else { setHover(null); deselect(); clearMulti(); }
|
|
1387
1430
|
}
|
|
1388
1431
|
|
|
1389
1432
|
// Visible, stamped elements in document order — the Tab cycle.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cmdzero",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.1",
|
|
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",
|