@avocadostudio-ai/preview-adapter 0.18.0 → 0.19.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.
|
@@ -131,9 +131,10 @@ export function attachBridge(config) {
|
|
|
131
131
|
const isStructural = msg.op?.op === "add_block" || msg.op?.op === "move_block";
|
|
132
132
|
state.pendingScrollIntoView = isStructural || state.pendingScrollIntoView;
|
|
133
133
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
134
|
+
// Assigned, not merely set: a stale `true` from an earlier message would
|
|
135
|
+
// otherwise silence the next real arrival, because the flag is cleared
|
|
136
|
+
// only when a focus poll actually runs.
|
|
137
|
+
state.skipEnterAnimationOnce = msg.animate === false || msg.op?.op === "move_item";
|
|
137
138
|
state.expectingNewBlocks = msg.op?.op === "add_block";
|
|
138
139
|
bridge.smoothRefresh();
|
|
139
140
|
emitPatchAck(msg.txId, true);
|
|
@@ -158,6 +159,10 @@ export function attachBridge(config) {
|
|
|
158
159
|
// scrolled into view after the refresh (a newly added block is only in
|
|
159
160
|
// the DOM now). Explicit so the other ~20 draftUpdated callers are unaffected.
|
|
160
161
|
state.pendingScrollIntoView = msg.payload.scrollIntoView === true;
|
|
162
|
+
// Same contract as applyPatch: the sender says whether this is an
|
|
163
|
+
// arrival worth animating. Typed edits fall back to this path whenever
|
|
164
|
+
// the patch transport is off or its ack was dropped.
|
|
165
|
+
state.skipEnterAnimationOnce = msg.payload.animate === false;
|
|
161
166
|
state.expectingNewBlocks = true;
|
|
162
167
|
bridge.clearLiveDraft();
|
|
163
168
|
clearChildFocus();
|
|
@@ -314,7 +314,21 @@ export type BridgeState = {
|
|
|
314
314
|
} | null;
|
|
315
315
|
suppressClickUntil: number;
|
|
316
316
|
selectionMode: boolean;
|
|
317
|
-
|
|
317
|
+
/**
|
|
318
|
+
* Suppress the focused block's arrival animation for the next refresh only.
|
|
319
|
+
*
|
|
320
|
+
* `applyBlockFocus(id, enter)` normally greets the block it focuses: a
|
|
321
|
+
* `block-enter` keyframe from `opacity: 0`, a 600 ms border flash and a
|
|
322
|
+
* sparkle sweep. That reads as "here is the thing that changed" and is worth
|
|
323
|
+
* having when a block is added, or when the agent edits one.
|
|
324
|
+
*
|
|
325
|
+
* It is wrong whenever the block was already on screen and only its contents
|
|
326
|
+
* changed in place — moving a list item inside it, or the user typing into
|
|
327
|
+
* one of its fields. Then the animation fades out the very block the user is
|
|
328
|
+
* looking at, once per debounce commit, which is read as a flash. The editor
|
|
329
|
+
* says which case it is with `animate: false` on the message.
|
|
330
|
+
*/
|
|
331
|
+
skipEnterAnimationOnce: boolean;
|
|
318
332
|
deleteConfirmTimer: {
|
|
319
333
|
current: number | null;
|
|
320
334
|
};
|
package/dist/bridge-functions.js
CHANGED
|
@@ -783,7 +783,7 @@ export function createBridgeState() {
|
|
|
783
783
|
pendingScrollRestore: null,
|
|
784
784
|
suppressClickUntil: 0,
|
|
785
785
|
selectionMode: false,
|
|
786
|
-
|
|
786
|
+
skipEnterAnimationOnce: false,
|
|
787
787
|
deleteConfirmTimer: { current: null },
|
|
788
788
|
pendingListItemMovePath: null,
|
|
789
789
|
childSelectionLock: null,
|
|
@@ -1301,7 +1301,7 @@ export function createBridgeFunctions(state, callbacks, config) {
|
|
|
1301
1301
|
const nextPath = `${group.listKey}[${targetIndex}]`;
|
|
1302
1302
|
state.pendingListItemMovePath = nextPath;
|
|
1303
1303
|
setChildSelectionLock({ blockId, listKey: group.listKey, index: targetIndex, position: targetPosition });
|
|
1304
|
-
state.
|
|
1304
|
+
state.skipEnterAnimationOnce = true;
|
|
1305
1305
|
state.selectedEditablePath = nextPath;
|
|
1306
1306
|
state.selectedBlockId = blockId;
|
|
1307
1307
|
setHoveredListItem(null);
|
|
@@ -1324,7 +1324,7 @@ export function createBridgeFunctions(state, callbacks, config) {
|
|
|
1324
1324
|
const nextPath = `${group.listKey}[${targetIndex}]`;
|
|
1325
1325
|
state.pendingListItemMovePath = nextPath;
|
|
1326
1326
|
setChildSelectionLock({ blockId, listKey: group.listKey, index: targetIndex, position: targetPosition });
|
|
1327
|
-
state.
|
|
1327
|
+
state.skipEnterAnimationOnce = true;
|
|
1328
1328
|
state.selectedEditablePath = nextPath;
|
|
1329
1329
|
state.selectedBlockId = blockId;
|
|
1330
1330
|
setHoveredListItem(null);
|
|
@@ -1544,7 +1544,7 @@ export function createBridgeFunctions(state, callbacks, config) {
|
|
|
1544
1544
|
return;
|
|
1545
1545
|
let attempts = 0;
|
|
1546
1546
|
const timer = window.setInterval(() => {
|
|
1547
|
-
const shouldAnimate = !state.
|
|
1547
|
+
const shouldAnimate = !state.skipEnterAnimationOnce;
|
|
1548
1548
|
const done = applyBlockFocus(targetId, shouldAnimate, undefined, { scrollIntoView: state.pendingScrollIntoView });
|
|
1549
1549
|
attempts += 1;
|
|
1550
1550
|
if (done || attempts >= 20) {
|
|
@@ -1552,7 +1552,7 @@ export function createBridgeFunctions(state, callbacks, config) {
|
|
|
1552
1552
|
state.pendingFocusId = null;
|
|
1553
1553
|
state.pendingScrollIntoView = false;
|
|
1554
1554
|
state.pendingScrollAnchorY = null;
|
|
1555
|
-
state.
|
|
1555
|
+
state.skipEnterAnimationOnce = false;
|
|
1556
1556
|
}
|
|
1557
1557
|
}, 45);
|
|
1558
1558
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@avocadostudio-ai/preview-adapter",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"src/styles.css"
|
|
38
38
|
],
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@avocadostudio-ai/shared": "^0.
|
|
40
|
+
"@avocadostudio-ai/shared": "^0.19.0"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
43
|
"next": ">=15.0.0",
|