openzoo 0.50.52 → 0.50.53

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 (2) hide show
  1. package/lib/ozSpendChip.js +66 -24
  2. package/package.json +1 -1
@@ -159,6 +159,7 @@ function ozEnsureSpendCss() {
159
159
  }
160
160
  s.textContent = [
161
161
  '.oz-spend{margin:.55rem 0 0;font-size:12px;color:inherit;opacity:.82;max-width:36em}',
162
+ '#oz-spend-float>summary{cursor:grab}',
162
163
  '.oz-spend>summary{cursor:help;list-style:none;display:inline-flex;align-items:center;gap:.35rem;',
163
164
  'padding:3px 9px;border-radius:999px;border:1px solid rgba(255,255,255,.18);white-space:nowrap;',
164
165
  'max-width:100%;overflow:hidden;text-overflow:ellipsis}',
@@ -339,27 +340,78 @@ function ozEnsureFloatSpend() {
339
340
  document.body.appendChild(el);
340
341
  }
341
342
  ozPlaceFloat(el);
343
+ ozDragFloat(el);
342
344
  const sum = el.querySelector('summary');
343
345
  if (sum) sum.textContent = 'ⓘ ' + label;
344
346
  }
345
347
 
348
+ function ozSavedFloatPos() {
349
+ try {
350
+ const p = JSON.parse(localStorage.getItem('oz-spend-float-pos') || 'null');
351
+ if (p && Number.isFinite(+p.left) && Number.isFinite(+p.top)) return { left: +p.left, top: +p.top };
352
+ } catch (e) {}
353
+ return null;
354
+ }
355
+
346
356
  function ozPlaceFloat(el) {
347
357
  if (!el) return;
348
- const ta = document.querySelector('textarea, [contenteditable="true"]');
349
- const box = ta && ta.getBoundingClientRect();
350
358
  el.style.position = 'fixed';
351
- el.style.right = 'auto';
352
359
  el.style.zIndex = '2147483646';
353
360
  el.style.opacity = '0.95';
354
- if (box && box.width > 80 && box.top > 48) {
355
- el.style.left = Math.round(box.left) + 'px';
356
- el.style.top = Math.round(Math.max(8, box.top - 56)) + 'px';
361
+ const saved = ozSavedFloatPos();
362
+ if (saved) {
363
+ el.style.left = Math.max(8, saved.left) + 'px';
364
+ el.style.top = Math.max(8, saved.top) + 'px';
365
+ el.style.right = 'auto';
357
366
  el.style.bottom = 'auto';
358
- } else {
359
- el.style.left = '96px';
360
- el.style.bottom = '72px';
361
- el.style.top = 'auto';
367
+ return;
362
368
  }
369
+ el.style.left = 'auto';
370
+ el.style.right = '16px';
371
+ el.style.top = '48px';
372
+ el.style.bottom = 'auto';
373
+ }
374
+
375
+ function ozDragFloat(el) {
376
+ if (!el || el.dataset.ozDrag === '1') return;
377
+ el.dataset.ozDrag = '1';
378
+ const sum = el.querySelector('summary') || el;
379
+ let dragging = false;
380
+ let moved = false;
381
+ let dx = 0;
382
+ let dy = 0;
383
+ sum.addEventListener('pointerdown', (ev) => {
384
+ if (ev.button !== 0) return;
385
+ dragging = true;
386
+ moved = false;
387
+ const r = el.getBoundingClientRect();
388
+ dx = ev.clientX - r.left;
389
+ dy = ev.clientY - r.top;
390
+ el.style.cursor = 'grabbing';
391
+ try { sum.setPointerCapture(ev.pointerId); } catch (e) {}
392
+ ev.preventDefault();
393
+ ev.stopPropagation();
394
+ });
395
+ sum.addEventListener('pointermove', (ev) => {
396
+ if (!dragging) return;
397
+ moved = true;
398
+ el.style.left = Math.max(8, ev.clientX - dx) + 'px';
399
+ el.style.top = Math.max(8, ev.clientY - dy) + 'px';
400
+ el.style.right = 'auto';
401
+ el.style.bottom = 'auto';
402
+ });
403
+ const end = () => {
404
+ if (!dragging) return;
405
+ dragging = false;
406
+ el.style.cursor = 'grab';
407
+ const r = el.getBoundingClientRect();
408
+ try { localStorage.setItem('oz-spend-float-pos', JSON.stringify({ left: r.left, top: r.top })); } catch (e) {}
409
+ };
410
+ sum.addEventListener('pointerup', end);
411
+ sum.addEventListener('pointercancel', end);
412
+ sum.addEventListener('click', (ev) => {
413
+ if (moved) { ev.preventDefault(); ev.stopPropagation(); }
414
+ }, true);
363
415
  }
364
416
 
365
417
  function ozWatchSpend() {
@@ -385,20 +437,8 @@ export function spendChipSource() {
385
437
  return [
386
438
  '(function ozSpendChip(){',
387
439
  "'use strict';",
388
- 'if (window.__OZ_SPEND_CHIP__ === 11) {',
389
- ' const el = document.getElementById("oz-spend-float");',
390
- ' const ta = document.querySelector("textarea, [contenteditable=\\"true\\"]");',
391
- ' const box = ta && ta.getBoundingClientRect();',
392
- ' if (el && box && box.width > 80) {',
393
- ' el.style.position = "fixed";',
394
- ' el.style.left = Math.round(box.left) + "px";',
395
- ' el.style.top = Math.round(Math.max(8, box.top - 56)) + "px";',
396
- ' el.style.right = "auto";',
397
- ' el.style.bottom = "auto";',
398
- ' }',
399
- ' return;',
400
- '}',
401
- 'window.__OZ_SPEND_CHIP__ = 11;',
440
+ 'if (window.__OZ_SPEND_CHIP__ === 12) return;',
441
+ 'window.__OZ_SPEND_CHIP__ = 12;',
402
442
  chipUsd.toString(),
403
443
  labelFromSpendBody.toString(),
404
444
  spendLinesOnly.toString(),
@@ -414,7 +454,9 @@ export function spendChipSource() {
414
454
  ozAttachSpendChip.toString(),
415
455
  ozCollapseSpend.toString(),
416
456
  ozEnsureFloatSpend.toString(),
457
+ ozSavedFloatPos.toString(),
417
458
  ozPlaceFloat.toString(),
459
+ ozDragFloat.toString(),
418
460
  ozWatchSpend.toString(),
419
461
  'ozWatchSpend();',
420
462
  '})();',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openzoo",
3
- "version": "0.50.52",
3
+ "version": "0.50.53",
4
4
  "description": "Local x402-paying proxy + MCP server for openzoo.fun — point any OpenAI-compatible harness (Cursor, Claude Code, aider, SDKs) at localhost and it pays per call from a local burner wallet. Solana and Base rails live; Robinhood experimental.",
5
5
  "license": "MIT",
6
6
  "type": "module",