@vectoriox/iox-builder 3.3.2 → 3.3.4
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.
|
@@ -1140,6 +1140,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
|
|
|
1140
1140
|
type: Injectable
|
|
1141
1141
|
}] });
|
|
1142
1142
|
|
|
1143
|
+
/**
|
|
1144
|
+
* Per-frame exponential smoothing step — moves `current` a fraction of the way
|
|
1145
|
+
* toward `target`. Used to ease the drag ghost toward the pointer instead of
|
|
1146
|
+
* snapping to it 1:1 on every dragmove (see DragEngineService._ghostFollowStep).
|
|
1147
|
+
*/
|
|
1148
|
+
function easeToward(current, target, smoothing) {
|
|
1149
|
+
return current + (target - current) * smoothing;
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1143
1152
|
/**
|
|
1144
1153
|
* SymbolRegistryService — in-memory store for org-level symbols.
|
|
1145
1154
|
*
|
|
@@ -1189,6 +1198,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
|
|
|
1189
1198
|
type: Injectable
|
|
1190
1199
|
}] });
|
|
1191
1200
|
|
|
1201
|
+
// Ease-out-quint — fast start, precise stop, no overshoot. Used for FLIP sibling
|
|
1202
|
+
// reflow and the insertion indicator open/close. Deliberately NOT a spring/back
|
|
1203
|
+
// curve (e.g. cubic-bezier(0.34,1.56,0.64,1)): multiple siblings animating with
|
|
1204
|
+
// overshoot at once reads as jitter, not polish — reserve overshoot for single-
|
|
1205
|
+
// element motion (ghost drop-settle, a later phase).
|
|
1206
|
+
const MOTION_EASE = 'cubic-bezier(0.22, 1, 0.36, 1)';
|
|
1207
|
+
// Per-frame exponential smoothing factor for the drag ghost's cursor-follow.
|
|
1208
|
+
// Was: ghost position set 1:1 to the pointer every dragmove (rigid/teleporty).
|
|
1209
|
+
// Lower = more lag/weight, higher = snappier. 0.35 catches up to the pointer
|
|
1210
|
+
// within ~5-6 frames (~80-100ms) — reads as "responsive but weighted".
|
|
1211
|
+
const GHOST_FOLLOW_SMOOTHING = 0.35;
|
|
1192
1212
|
function deepCloneNode(node) {
|
|
1193
1213
|
const clone = JSON.parse(JSON.stringify(node));
|
|
1194
1214
|
// Fresh ids + remap intra-subtree references (stateTriggers, interaction targets) so a cloned
|
|
@@ -1225,6 +1245,12 @@ class DragEngineService {
|
|
|
1225
1245
|
/** Where on the element the user grabbed it (for accurate ghost positioning). */
|
|
1226
1246
|
this._grabOffsetX = 0;
|
|
1227
1247
|
this._grabOffsetY = 0;
|
|
1248
|
+
// ── Ghost cursor-follow (eased, not 1:1) ───────────────────
|
|
1249
|
+
this._ghostX = 0;
|
|
1250
|
+
this._ghostY = 0;
|
|
1251
|
+
this._ghostTargetX = 0;
|
|
1252
|
+
this._ghostTargetY = 0;
|
|
1253
|
+
this._ghostRaf = 0;
|
|
1228
1254
|
// ── Pointer tracking ──────────────────────────────────────
|
|
1229
1255
|
this._lastPointerX = 0;
|
|
1230
1256
|
this._lastPointerY = 0;
|
|
@@ -1246,6 +1272,17 @@ class DragEngineService {
|
|
|
1246
1272
|
// ── Root-escape ───────────────────────────────────────────
|
|
1247
1273
|
this.ROOT_ESCAPE_PX = 14;
|
|
1248
1274
|
this._rootEscapeActiveFor = null;
|
|
1275
|
+
this._ghostFollowStep = () => {
|
|
1276
|
+
if (!this._overlay) {
|
|
1277
|
+
this._ghostRaf = 0;
|
|
1278
|
+
return;
|
|
1279
|
+
}
|
|
1280
|
+
this._ghostX = easeToward(this._ghostX, this._ghostTargetX, GHOST_FOLLOW_SMOOTHING);
|
|
1281
|
+
this._ghostY = easeToward(this._ghostY, this._ghostTargetY, GHOST_FOLLOW_SMOOTHING);
|
|
1282
|
+
this._overlay.style.left = this._ghostX + 'px';
|
|
1283
|
+
this._overlay.style.top = this._ghostY + 'px';
|
|
1284
|
+
this._ghostRaf = requestAnimationFrame(this._ghostFollowStep);
|
|
1285
|
+
};
|
|
1249
1286
|
}
|
|
1250
1287
|
// ── Shared drop handler — used by all layout components ───────────────────
|
|
1251
1288
|
handleDrop(children, event, dropListId, cdr, afterDrop) {
|
|
@@ -1482,6 +1519,7 @@ class DragEngineService {
|
|
|
1482
1519
|
clone.classList.add('iox-drag-moving');
|
|
1483
1520
|
document.body.appendChild(clone);
|
|
1484
1521
|
this._overlay = clone;
|
|
1522
|
+
this._startGhostFollow(rect.left, rect.top);
|
|
1485
1523
|
// Hide original wrapper in-place (keeps layout space so container size is stable).
|
|
1486
1524
|
el.classList.add('iox-drag-active-source');
|
|
1487
1525
|
}
|
|
@@ -1495,10 +1533,11 @@ class DragEngineService {
|
|
|
1495
1533
|
_onDragMove(event) {
|
|
1496
1534
|
this._lastPointerX = event.client.x;
|
|
1497
1535
|
this._lastPointerY = event.client.y;
|
|
1498
|
-
//
|
|
1536
|
+
// Update the ghost's follow target; the rAF loop (_ghostFollowStep) eases
|
|
1537
|
+
// the clone/chip toward it rather than snapping to it every dragmove.
|
|
1499
1538
|
if (this._overlay) {
|
|
1500
|
-
this.
|
|
1501
|
-
this.
|
|
1539
|
+
this._ghostTargetX = event.client.x - this._grabOffsetX;
|
|
1540
|
+
this._ghostTargetY = event.client.y - this._grabOffsetY;
|
|
1502
1541
|
}
|
|
1503
1542
|
this._updateDeepTarget();
|
|
1504
1543
|
this._updateIndicator();
|
|
@@ -1563,14 +1602,30 @@ class DragEngineService {
|
|
|
1563
1602
|
chip.style.top = (pointerY + 14) + 'px';
|
|
1564
1603
|
document.body.appendChild(chip);
|
|
1565
1604
|
this._overlay = chip;
|
|
1605
|
+
this._startGhostFollow(pointerX + 14, pointerY + 14);
|
|
1566
1606
|
}
|
|
1567
1607
|
_removeOverlay() {
|
|
1608
|
+
this._stopGhostFollow();
|
|
1568
1609
|
this._overlay?.remove();
|
|
1569
1610
|
this._overlay = null;
|
|
1570
1611
|
this._grabOffsetX = 0;
|
|
1571
1612
|
this._grabOffsetY = 0;
|
|
1572
1613
|
}
|
|
1573
1614
|
// ─────────────────────────────────────────────────────────
|
|
1615
|
+
// Ghost cursor-follow — eased toward the pointer via rAF instead of
|
|
1616
|
+
// snapped to it every dragmove event.
|
|
1617
|
+
// ─────────────────────────────────────────────────────────
|
|
1618
|
+
_startGhostFollow(initialLeft, initialTop) {
|
|
1619
|
+
this._ghostX = this._ghostTargetX = initialLeft;
|
|
1620
|
+
this._ghostY = this._ghostTargetY = initialTop;
|
|
1621
|
+
cancelAnimationFrame(this._ghostRaf);
|
|
1622
|
+
this._ghostRaf = requestAnimationFrame(this._ghostFollowStep);
|
|
1623
|
+
}
|
|
1624
|
+
_stopGhostFollow() {
|
|
1625
|
+
cancelAnimationFrame(this._ghostRaf);
|
|
1626
|
+
this._ghostRaf = 0;
|
|
1627
|
+
}
|
|
1628
|
+
// ─────────────────────────────────────────────────────────
|
|
1574
1629
|
// Deep-target detection (smallest bounding-rect area)
|
|
1575
1630
|
// ─────────────────────────────────────────────────────────
|
|
1576
1631
|
_updateDeepTarget() {
|
|
@@ -1767,13 +1822,13 @@ class DragEngineService {
|
|
|
1767
1822
|
this._indicator.style.cssText =
|
|
1768
1823
|
'flex-shrink:0;width:0;align-self:stretch;' +
|
|
1769
1824
|
'background:#6366f1;border-radius:2px;pointer-events:none;margin:0;' +
|
|
1770
|
-
|
|
1825
|
+
`transition:width 140ms ${MOTION_EASE},margin 140ms ${MOTION_EASE};overflow:hidden;`;
|
|
1771
1826
|
}
|
|
1772
1827
|
else {
|
|
1773
1828
|
this._indicator.style.cssText =
|
|
1774
1829
|
'height:0;width:100%;background:#6366f1;border-radius:2px;' +
|
|
1775
1830
|
'pointer-events:none;margin:0;display:block;' +
|
|
1776
|
-
|
|
1831
|
+
`transition:height 140ms ${MOTION_EASE},margin 140ms ${MOTION_EASE};overflow:hidden;`;
|
|
1777
1832
|
}
|
|
1778
1833
|
}
|
|
1779
1834
|
this._indicatorContainerId = containerId;
|
|
@@ -1819,7 +1874,7 @@ class DragEngineService {
|
|
|
1819
1874
|
el.style.transition = 'none';
|
|
1820
1875
|
el.style.transform = `translate(${dx}px,${dy}px)`;
|
|
1821
1876
|
requestAnimationFrame(() => {
|
|
1822
|
-
el.style.transition =
|
|
1877
|
+
el.style.transition = `transform 140ms ${MOTION_EASE}`;
|
|
1823
1878
|
el.style.transform = '';
|
|
1824
1879
|
});
|
|
1825
1880
|
});
|