draply-dev 1.4.0 → 1.4.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/bin/cli.js CHANGED
@@ -223,7 +223,7 @@ Rules:
223
223
  - The content inside <search> must be an EXACT substring from the file snippet above (including indentation).
224
224
  - Update HTML/JSX inline styles or Tailwind classes appropriately.
225
225
  - REPLACE old style values if they exist, DO NOT duplicate keys!
226
- - If 'innerText' is provided in Changes, update the text content inside the target HTML element!
226
+ - If 'innerText' is provided in Changes, update the text content inside the target HTML element! Use ONLY the exact text provided in the request. DO NOT add signatures, names, attributions, or "complete" the text based on context.
227
227
  - If 'src' is provided in Changes, update the src attribute of the target HTML element!
228
228
 
229
229
  Example response:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "draply-dev",
3
- "version": "1.4.0",
3
+ "version": "1.4.1",
4
4
  "description": "Visual overlay for any frontend project — move, resize, restyle live in the browser, save to CSS",
5
5
  "author": "Arman",
6
6
  "type": "commonjs",
package/src/overlay.js CHANGED
@@ -629,7 +629,8 @@
629
629
  <input type="file" id="__ast_file__" accept="image/*" style="display:none">
630
630
  <div id="__ast_list__" style="display:flex;flex-wrap:wrap;gap:6px;margin-bottom:6px"></div>
631
631
  <div id="__ast_hint__" style="font-size:10px;color:#44446a;line-height:1.5;display:none">
632
- Click thumbnail place on page<br>then drag to position
632
+ Click to <b>place</b><br>
633
+ ✦ Shift+Click to <b>replace</b> src/bg
633
634
  </div>
634
635
  <!-- Z-INDEX CONTROLS -->
635
636
  <div id="__ast_zctrl__" style="display:none;margin-top:6px;">
@@ -1335,19 +1336,27 @@
1335
1336
  e.preventDefault(); e.stopPropagation();
1336
1337
  if (!pendingAsset || !placingEl) return;
1337
1338
 
1338
- if (e.target.tagName.toLowerCase() === 'img') {
1339
- const prevSrc = e.target.getAttribute('src');
1340
- e.target.src = pendingAsset.src;
1341
- rec(e.target, { src: pendingAsset.src }, { src: prevSrc || '' });
1342
- toast('🖼️ Image replaced!');
1339
+ if (e.shiftKey) {
1340
+ // REPLACE mode
1341
+ if (e.target.tagName.toLowerCase() === 'img') {
1342
+ const prevSrc = e.target.getAttribute('src');
1343
+ e.target.src = pendingAsset.src;
1344
+ rec(e.target, { src: pendingAsset.src }, { src: prevSrc || '' });
1345
+ toast('🖼️ Image source replaced!');
1346
+ } else {
1347
+ const cs = getComputedStyle(e.target);
1348
+ const prevBg = cs.backgroundImage;
1349
+ e.target.style.backgroundImage = `url('${pendingAsset.src}')`;
1350
+ e.target.style.backgroundSize = 'cover';
1351
+ e.target.style.backgroundPosition = 'center';
1352
+ rec(e.target, { backgroundImage: `url('${pendingAsset.src}')`, backgroundSize: 'cover', backgroundPosition: 'center' }, { backgroundImage: prevBg });
1353
+ toast('🖼️ Background image set!');
1354
+ }
1343
1355
  } else {
1344
- const cs = getComputedStyle(e.target);
1345
- const prevBg = cs.backgroundImage;
1346
- e.target.style.backgroundImage = `url('${pendingAsset.src}')`;
1347
- e.target.style.backgroundSize = 'cover';
1348
- e.target.style.backgroundPosition = 'center';
1349
- rec(e.target, { backgroundImage: `url('${pendingAsset.src}')`, backgroundSize: 'cover', backgroundPosition: 'center' }, { backgroundImage: prevBg });
1350
- toast('🖼️ Background image set!');
1356
+ // PLACE mode
1357
+ const x = e.clientX - 60;
1358
+ const y = e.clientY - 60;
1359
+ placeAsset(pendingAsset, x, y, 120, 120);
1351
1360
  }
1352
1361
  cancelPlacing();
1353
1362
  }
@@ -1365,6 +1374,120 @@
1365
1374
  document.removeEventListener('keydown', onPlacingCancel);
1366
1375
  }
1367
1376
 
1377
+ // Place asset permanently on page (absolute positioned)
1378
+ function placeAsset(asset, x, y, w, h) {
1379
+ const wrap = document.createElement('div');
1380
+ wrap.className = 'ps-asset-placed';
1381
+ const uid = 'ps-asset-' + Date.now();
1382
+ wrap.id = uid;
1383
+ wrap.style.cssText = `left:${Math.round(x)}px;top:${Math.round(y)}px;width:${w}px;height:${h}px;z-index:1;`;
1384
+ wrap.innerHTML = `<img src="${asset.src}" draggable="false" alt="${asset.name}">`;
1385
+ document.body.appendChild(wrap);
1386
+
1387
+ // Click to select this placed asset (for z-index control)
1388
+ wrap.addEventListener('click', e => {
1389
+ if (ps(e.target)) return;
1390
+ selectPlaced(wrap);
1391
+ });
1392
+
1393
+ // Make placed asset draggable
1394
+ wrap.addEventListener('mousedown', e => {
1395
+ if (ps(e.target)) return;
1396
+ e.preventDefault();
1397
+ selectPlaced(wrap);
1398
+ astDragEl = wrap;
1399
+ astDragSX = e.clientX; astDragSY = e.clientY;
1400
+ astDragOL = parseFloat(wrap.style.left) || 0;
1401
+ astDragOT = parseFloat(wrap.style.top) || 0;
1402
+ wrap.style.cursor = 'grabbing';
1403
+ state.dragging = true;
1404
+ });
1405
+
1406
+ rec(wrap, {
1407
+ src: asset.src,
1408
+ left: Math.round(x) + 'px',
1409
+ top: Math.round(y) + 'px',
1410
+ width: w + 'px',
1411
+ height: h + 'px',
1412
+ 'z-index': '1',
1413
+ });
1414
+
1415
+ toast('✦ Placed — drag to reposition');
1416
+ selectPlaced(wrap);
1417
+ return wrap;
1418
+ }
1419
+
1420
+ // Track selected placed asset for z-index controls
1421
+ let selectedPlaced = null;
1422
+ const zCtrl = document.getElementById('__ast_zctrl__');
1423
+ const zVal = document.getElementById('__z_val__');
1424
+ const zFront = document.getElementById('__z_front__');
1425
+ const zBack = document.getElementById('__z_back__');
1426
+ const zSet = document.getElementById('__z_set__');
1427
+
1428
+ function selectPlaced(wrap) {
1429
+ // Deselect previous
1430
+ if (selectedPlaced) selectedPlaced.style.outline = '';
1431
+ selectedPlaced = wrap;
1432
+ wrap.style.outline = '2px solid #7fff6e';
1433
+ zVal.value = parseInt(wrap.style.zIndex) || 1;
1434
+ zCtrl.style.display = 'block';
1435
+ }
1436
+
1437
+ zFront.onclick = () => {
1438
+ if (!selectedPlaced) return;
1439
+ // Find max z-index of all placed assets
1440
+ const max = Math.max(0, ...[...document.querySelectorAll('.ps-asset-placed')].map(el => parseInt(el.style.zIndex) || 0));
1441
+ const nz = max + 1;
1442
+ selectedPlaced.style.zIndex = nz;
1443
+ zVal.value = nz;
1444
+ rec(selectedPlaced, { 'z-index': String(nz) });
1445
+ toast('▲ Moved to front (z:' + nz + ')');
1446
+ };
1447
+
1448
+ zBack.onclick = () => {
1449
+ if (!selectedPlaced) return;
1450
+ const min = Math.min(0, ...[...document.querySelectorAll('.ps-asset-placed')].map(el => parseInt(el.style.zIndex) || 0));
1451
+ const nz = min - 1;
1452
+ selectedPlaced.style.zIndex = nz;
1453
+ zVal.value = nz;
1454
+ rec(selectedPlaced, { 'z-index': String(nz) });
1455
+ toast('▼ Moved to back (z:' + nz + ')');
1456
+ };
1457
+
1458
+ zSet.onclick = () => {
1459
+ if (!selectedPlaced) return;
1460
+ const nz = parseInt(zVal.value) || 0;
1461
+ selectedPlaced.style.zIndex = nz;
1462
+ rec(selectedPlaced, { 'z-index': String(nz) });
1463
+ toast('z-index set to ' + nz);
1464
+ };
1465
+
1466
+ zVal.onkeydown = e => { if (e.key === 'Enter') zSet.click(); };
1467
+
1468
+ // Drag placed assets
1469
+ document.addEventListener('mousemove', e => {
1470
+ if (!astDragEl || !state.dragging) return;
1471
+ const dx = e.clientX - astDragSX, dy = e.clientY - astDragSY;
1472
+ astDragEl.style.left = (astDragOL + dx) + 'px';
1473
+ astDragEl.style.top = (astDragOT + dy) + 'px';
1474
+ tip.textContent = `x:${Math.round(astDragOL + dx)} y:${Math.round(astDragOT + dy)}`;
1475
+ tip.style.left = (e.clientX + 14) + 'px'; tip.style.top = (e.clientY - 28) + 'px';
1476
+ tip.classList.add('v');
1477
+ });
1478
+
1479
+ document.addEventListener('mouseup', () => {
1480
+ if (!astDragEl) return;
1481
+ tip.classList.remove('v');
1482
+ const cs = getComputedStyle(astDragEl);
1483
+ rec(astDragEl, {
1484
+ left: Math.round(parseFloat(cs.left)) + 'px',
1485
+ top: Math.round(parseFloat(cs.top)) + 'px',
1486
+ });
1487
+ astDragEl.style.cursor = 'grab';
1488
+ astDragEl = null;
1489
+ });
1490
+
1368
1491
  // ══════════════════════════════════════════
1369
1492
  // RECORD + SAVE
1370
1493
  // ══════════════════════════════════════════