chatablex-web-sdk 1.0.34 → 1.0.36
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/dist/index.d.mts +8 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +36 -9
- package/dist/index.mjs +36 -9
- package/package.json +1 -1
- package/src/modules/agentLock.ts +66 -8
- package/src/types.ts +8 -1
package/dist/index.d.mts
CHANGED
|
@@ -279,8 +279,15 @@ interface AgentLockConfig {
|
|
|
279
279
|
allowCancel?: boolean;
|
|
280
280
|
/** Overlay background opacity, 0–1 (default: 0.3). */
|
|
281
281
|
opacity?: number;
|
|
282
|
-
/** Auto-unlock timeout in ms (default: 30000). 0 disables. */
|
|
282
|
+
/** Auto-unlock timeout for a single tool execution, in ms (default: 30000). 0 disables. */
|
|
283
283
|
timeout?: number;
|
|
284
|
+
/**
|
|
285
|
+
* Safety auto-unlock timeout for a whole agent turn, in ms (default: 0 =
|
|
286
|
+
* disabled, rely on the host's turn-end signal). When the host drives a
|
|
287
|
+
* turn-level lock (the lock spans the entire agent response, not just one
|
|
288
|
+
* tool), this acts purely as a fallback in case the turn-end signal is lost.
|
|
289
|
+
*/
|
|
290
|
+
turnTimeout?: number;
|
|
284
291
|
/** Delay before actually removing the overlay after unlock, to avoid flicker between consecutive tools (default: 200ms). */
|
|
285
292
|
debounceUnlock?: number;
|
|
286
293
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -279,8 +279,15 @@ interface AgentLockConfig {
|
|
|
279
279
|
allowCancel?: boolean;
|
|
280
280
|
/** Overlay background opacity, 0–1 (default: 0.3). */
|
|
281
281
|
opacity?: number;
|
|
282
|
-
/** Auto-unlock timeout in ms (default: 30000). 0 disables. */
|
|
282
|
+
/** Auto-unlock timeout for a single tool execution, in ms (default: 30000). 0 disables. */
|
|
283
283
|
timeout?: number;
|
|
284
|
+
/**
|
|
285
|
+
* Safety auto-unlock timeout for a whole agent turn, in ms (default: 0 =
|
|
286
|
+
* disabled, rely on the host's turn-end signal). When the host drives a
|
|
287
|
+
* turn-level lock (the lock spans the entire agent response, not just one
|
|
288
|
+
* tool), this acts purely as a fallback in case the turn-end signal is lost.
|
|
289
|
+
*/
|
|
290
|
+
turnTimeout?: number;
|
|
284
291
|
/** Delay before actually removing the overlay after unlock, to avoid flicker between consecutive tools (default: 200ms). */
|
|
285
292
|
debounceUnlock?: number;
|
|
286
293
|
}
|
package/dist/index.js
CHANGED
|
@@ -553,8 +553,10 @@ var DEFAULT_CONFIG = {
|
|
|
553
553
|
allowCancel: true,
|
|
554
554
|
opacity: 0.3,
|
|
555
555
|
timeout: 3e4,
|
|
556
|
+
turnTimeout: 0,
|
|
556
557
|
debounceUnlock: 200
|
|
557
558
|
};
|
|
559
|
+
var TURN_EVENT = "agentLock";
|
|
558
560
|
var OVERLAY_ID = "__chatablex_agent_lock_overlay__";
|
|
559
561
|
var BLOCKED_EVENTS = [
|
|
560
562
|
"mousedown",
|
|
@@ -580,13 +582,14 @@ function blockEvent(e) {
|
|
|
580
582
|
e.stopPropagation();
|
|
581
583
|
e.preventDefault();
|
|
582
584
|
}
|
|
583
|
-
function createAgentLockModule(
|
|
585
|
+
function createAgentLockModule(bridge, userConfig = {}) {
|
|
584
586
|
const cfg = { ...DEFAULT_CONFIG, ...userConfig };
|
|
585
587
|
const logoSrc = cfg.logoUrl || bee_default;
|
|
586
588
|
const listeners = /* @__PURE__ */ new Map();
|
|
587
589
|
let overlayEl = null;
|
|
588
590
|
let locked = false;
|
|
589
591
|
let lockCount = 0;
|
|
592
|
+
let turnActive = false;
|
|
590
593
|
let timeoutTimer = null;
|
|
591
594
|
let debounceTimer = null;
|
|
592
595
|
let currentMessage = cfg.message;
|
|
@@ -697,6 +700,7 @@ function createAgentLockModule(_bridge, userConfig = {}) {
|
|
|
697
700
|
if (!locked) return;
|
|
698
701
|
locked = false;
|
|
699
702
|
lockCount = 0;
|
|
703
|
+
turnActive = false;
|
|
700
704
|
clearTimeoutTimer();
|
|
701
705
|
clearDebounceTimer();
|
|
702
706
|
if (cfg.mode === "overlay") {
|
|
@@ -704,11 +708,34 @@ function createAgentLockModule(_bridge, userConfig = {}) {
|
|
|
704
708
|
}
|
|
705
709
|
emit("unlock", { requestId });
|
|
706
710
|
}
|
|
711
|
+
function maybeUnlock(requestId) {
|
|
712
|
+
if (turnActive || lockCount > 0) return;
|
|
713
|
+
forceUnlock(requestId);
|
|
714
|
+
}
|
|
715
|
+
function scheduleDebouncedUnlock(requestId) {
|
|
716
|
+
clearDebounceTimer();
|
|
717
|
+
debounceTimer = setTimeout(() => maybeUnlock(requestId), cfg.debounceUnlock);
|
|
718
|
+
}
|
|
707
719
|
function handleCancel() {
|
|
708
720
|
const rid = void 0;
|
|
709
721
|
forceUnlock(rid);
|
|
710
722
|
emit("cancel", { requestId: rid });
|
|
711
723
|
}
|
|
724
|
+
function setTurn(active) {
|
|
725
|
+
if (!cfg.enabled) return;
|
|
726
|
+
if (active) {
|
|
727
|
+
turnActive = true;
|
|
728
|
+
clearDebounceTimer();
|
|
729
|
+
if (!locked) {
|
|
730
|
+
doLock(cfg.message, cfg.turnTimeout);
|
|
731
|
+
} else {
|
|
732
|
+
startTimeout(cfg.turnTimeout);
|
|
733
|
+
}
|
|
734
|
+
} else {
|
|
735
|
+
turnActive = false;
|
|
736
|
+
if (lockCount === 0) scheduleDebouncedUnlock();
|
|
737
|
+
}
|
|
738
|
+
}
|
|
712
739
|
function lock(opts) {
|
|
713
740
|
if (!cfg.enabled) return;
|
|
714
741
|
const msg = opts?.message ?? cfg.message;
|
|
@@ -734,32 +761,32 @@ function createAgentLockModule(_bridge, userConfig = {}) {
|
|
|
734
761
|
clearDebounceTimer();
|
|
735
762
|
lockCount++;
|
|
736
763
|
if (!locked) {
|
|
737
|
-
doLock(cfg.message, cfg.timeout, requestId);
|
|
764
|
+
doLock(cfg.message, turnActive ? cfg.turnTimeout : cfg.timeout, requestId);
|
|
738
765
|
}
|
|
739
766
|
}
|
|
740
767
|
function _autoUnlock(requestId) {
|
|
741
768
|
if (!cfg.enabled) return;
|
|
742
769
|
lockCount = Math.max(0, lockCount - 1);
|
|
743
770
|
if (lockCount === 0) {
|
|
744
|
-
|
|
745
|
-
debounceTimer = setTimeout(() => {
|
|
746
|
-
if (lockCount === 0) {
|
|
747
|
-
forceUnlock(requestId);
|
|
748
|
-
}
|
|
749
|
-
}, cfg.debounceUnlock);
|
|
771
|
+
scheduleDebouncedUnlock(requestId);
|
|
750
772
|
}
|
|
751
773
|
}
|
|
752
774
|
function _destroy() {
|
|
775
|
+
if (removeTurnListener) removeTurnListener();
|
|
753
776
|
forceUnlock();
|
|
754
777
|
listeners.clear();
|
|
755
778
|
}
|
|
779
|
+
const removeTurnListener = bridge.addEventListener(TURN_EVENT, (data) => {
|
|
780
|
+
const active = !!data?.active;
|
|
781
|
+
setTurn(active);
|
|
782
|
+
});
|
|
756
783
|
return { lock, unlock, isLocked, on, off, _autoLock, _autoUnlock, _destroy };
|
|
757
784
|
}
|
|
758
785
|
|
|
759
786
|
// package.json
|
|
760
787
|
var package_default = {
|
|
761
788
|
name: "chatablex-web-sdk",
|
|
762
|
-
version: "1.0.
|
|
789
|
+
version: "1.0.36",
|
|
763
790
|
description: "ChatableX Web SDK for AI App WebUI development. Provides bridge communication with the ChatableX Flutter client.",
|
|
764
791
|
main: "dist/index.js",
|
|
765
792
|
module: "dist/index.mjs",
|
package/dist/index.mjs
CHANGED
|
@@ -521,8 +521,10 @@ var DEFAULT_CONFIG = {
|
|
|
521
521
|
allowCancel: true,
|
|
522
522
|
opacity: 0.3,
|
|
523
523
|
timeout: 3e4,
|
|
524
|
+
turnTimeout: 0,
|
|
524
525
|
debounceUnlock: 200
|
|
525
526
|
};
|
|
527
|
+
var TURN_EVENT = "agentLock";
|
|
526
528
|
var OVERLAY_ID = "__chatablex_agent_lock_overlay__";
|
|
527
529
|
var BLOCKED_EVENTS = [
|
|
528
530
|
"mousedown",
|
|
@@ -548,13 +550,14 @@ function blockEvent(e) {
|
|
|
548
550
|
e.stopPropagation();
|
|
549
551
|
e.preventDefault();
|
|
550
552
|
}
|
|
551
|
-
function createAgentLockModule(
|
|
553
|
+
function createAgentLockModule(bridge, userConfig = {}) {
|
|
552
554
|
const cfg = { ...DEFAULT_CONFIG, ...userConfig };
|
|
553
555
|
const logoSrc = cfg.logoUrl || bee_default;
|
|
554
556
|
const listeners = /* @__PURE__ */ new Map();
|
|
555
557
|
let overlayEl = null;
|
|
556
558
|
let locked = false;
|
|
557
559
|
let lockCount = 0;
|
|
560
|
+
let turnActive = false;
|
|
558
561
|
let timeoutTimer = null;
|
|
559
562
|
let debounceTimer = null;
|
|
560
563
|
let currentMessage = cfg.message;
|
|
@@ -665,6 +668,7 @@ function createAgentLockModule(_bridge, userConfig = {}) {
|
|
|
665
668
|
if (!locked) return;
|
|
666
669
|
locked = false;
|
|
667
670
|
lockCount = 0;
|
|
671
|
+
turnActive = false;
|
|
668
672
|
clearTimeoutTimer();
|
|
669
673
|
clearDebounceTimer();
|
|
670
674
|
if (cfg.mode === "overlay") {
|
|
@@ -672,11 +676,34 @@ function createAgentLockModule(_bridge, userConfig = {}) {
|
|
|
672
676
|
}
|
|
673
677
|
emit("unlock", { requestId });
|
|
674
678
|
}
|
|
679
|
+
function maybeUnlock(requestId) {
|
|
680
|
+
if (turnActive || lockCount > 0) return;
|
|
681
|
+
forceUnlock(requestId);
|
|
682
|
+
}
|
|
683
|
+
function scheduleDebouncedUnlock(requestId) {
|
|
684
|
+
clearDebounceTimer();
|
|
685
|
+
debounceTimer = setTimeout(() => maybeUnlock(requestId), cfg.debounceUnlock);
|
|
686
|
+
}
|
|
675
687
|
function handleCancel() {
|
|
676
688
|
const rid = void 0;
|
|
677
689
|
forceUnlock(rid);
|
|
678
690
|
emit("cancel", { requestId: rid });
|
|
679
691
|
}
|
|
692
|
+
function setTurn(active) {
|
|
693
|
+
if (!cfg.enabled) return;
|
|
694
|
+
if (active) {
|
|
695
|
+
turnActive = true;
|
|
696
|
+
clearDebounceTimer();
|
|
697
|
+
if (!locked) {
|
|
698
|
+
doLock(cfg.message, cfg.turnTimeout);
|
|
699
|
+
} else {
|
|
700
|
+
startTimeout(cfg.turnTimeout);
|
|
701
|
+
}
|
|
702
|
+
} else {
|
|
703
|
+
turnActive = false;
|
|
704
|
+
if (lockCount === 0) scheduleDebouncedUnlock();
|
|
705
|
+
}
|
|
706
|
+
}
|
|
680
707
|
function lock(opts) {
|
|
681
708
|
if (!cfg.enabled) return;
|
|
682
709
|
const msg = opts?.message ?? cfg.message;
|
|
@@ -702,32 +729,32 @@ function createAgentLockModule(_bridge, userConfig = {}) {
|
|
|
702
729
|
clearDebounceTimer();
|
|
703
730
|
lockCount++;
|
|
704
731
|
if (!locked) {
|
|
705
|
-
doLock(cfg.message, cfg.timeout, requestId);
|
|
732
|
+
doLock(cfg.message, turnActive ? cfg.turnTimeout : cfg.timeout, requestId);
|
|
706
733
|
}
|
|
707
734
|
}
|
|
708
735
|
function _autoUnlock(requestId) {
|
|
709
736
|
if (!cfg.enabled) return;
|
|
710
737
|
lockCount = Math.max(0, lockCount - 1);
|
|
711
738
|
if (lockCount === 0) {
|
|
712
|
-
|
|
713
|
-
debounceTimer = setTimeout(() => {
|
|
714
|
-
if (lockCount === 0) {
|
|
715
|
-
forceUnlock(requestId);
|
|
716
|
-
}
|
|
717
|
-
}, cfg.debounceUnlock);
|
|
739
|
+
scheduleDebouncedUnlock(requestId);
|
|
718
740
|
}
|
|
719
741
|
}
|
|
720
742
|
function _destroy() {
|
|
743
|
+
if (removeTurnListener) removeTurnListener();
|
|
721
744
|
forceUnlock();
|
|
722
745
|
listeners.clear();
|
|
723
746
|
}
|
|
747
|
+
const removeTurnListener = bridge.addEventListener(TURN_EVENT, (data) => {
|
|
748
|
+
const active = !!data?.active;
|
|
749
|
+
setTurn(active);
|
|
750
|
+
});
|
|
724
751
|
return { lock, unlock, isLocked, on, off, _autoLock, _autoUnlock, _destroy };
|
|
725
752
|
}
|
|
726
753
|
|
|
727
754
|
// package.json
|
|
728
755
|
var package_default = {
|
|
729
756
|
name: "chatablex-web-sdk",
|
|
730
|
-
version: "1.0.
|
|
757
|
+
version: "1.0.36",
|
|
731
758
|
description: "ChatableX Web SDK for AI App WebUI development. Provides bridge communication with the ChatableX Flutter client.",
|
|
732
759
|
main: "dist/index.js",
|
|
733
760
|
module: "dist/index.mjs",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chatablex-web-sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.36",
|
|
4
4
|
"description": "ChatableX Web SDK for AI App WebUI development. Provides bridge communication with the ChatableX Flutter client.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
package/src/modules/agentLock.ts
CHANGED
|
@@ -16,9 +16,17 @@ const DEFAULT_CONFIG: Required<AgentLockConfig> = {
|
|
|
16
16
|
allowCancel: true,
|
|
17
17
|
opacity: 0.3,
|
|
18
18
|
timeout: 30_000,
|
|
19
|
+
turnTimeout: 0,
|
|
19
20
|
debounceUnlock: 200,
|
|
20
21
|
};
|
|
21
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Bridge event pushed by the Flutter host to lock the UI for the *entire* agent
|
|
25
|
+
* turn (from the moment the agent starts responding until the turn ends),
|
|
26
|
+
* rather than only during each individual tool execution. Payload: `{ active }`.
|
|
27
|
+
*/
|
|
28
|
+
const TURN_EVENT = 'agentLock';
|
|
29
|
+
|
|
22
30
|
const OVERLAY_ID = '__chatablex_agent_lock_overlay__';
|
|
23
31
|
|
|
24
32
|
/**
|
|
@@ -55,7 +63,7 @@ export interface AgentLockModule extends ChatableXAgentLock {
|
|
|
55
63
|
}
|
|
56
64
|
|
|
57
65
|
export function createAgentLockModule(
|
|
58
|
-
|
|
66
|
+
bridge: Bridge,
|
|
59
67
|
userConfig: AgentLockConfig = {},
|
|
60
68
|
): AgentLockModule {
|
|
61
69
|
const cfg: Required<AgentLockConfig> = { ...DEFAULT_CONFIG, ...userConfig };
|
|
@@ -65,6 +73,12 @@ export function createAgentLockModule(
|
|
|
65
73
|
let overlayEl: HTMLDivElement | null = null;
|
|
66
74
|
let locked = false;
|
|
67
75
|
let lockCount = 0;
|
|
76
|
+
/**
|
|
77
|
+
* True while an agent *turn* is in progress (driven by the host's
|
|
78
|
+
* {@link TURN_EVENT}). Keeps the overlay up across the whole response — and
|
|
79
|
+
* across the gaps between individual tool calls — until the turn ends.
|
|
80
|
+
*/
|
|
81
|
+
let turnActive = false;
|
|
68
82
|
let timeoutTimer: ReturnType<typeof setTimeout> | null = null;
|
|
69
83
|
let debounceTimer: ReturnType<typeof setTimeout> | null = null;
|
|
70
84
|
let currentMessage = cfg.message;
|
|
@@ -181,6 +195,7 @@ export function createAgentLockModule(
|
|
|
181
195
|
if (!locked) return;
|
|
182
196
|
locked = false;
|
|
183
197
|
lockCount = 0;
|
|
198
|
+
turnActive = false;
|
|
184
199
|
clearTimeoutTimer();
|
|
185
200
|
clearDebounceTimer();
|
|
186
201
|
if (cfg.mode === 'overlay') {
|
|
@@ -189,12 +204,51 @@ export function createAgentLockModule(
|
|
|
189
204
|
emit('unlock', { requestId });
|
|
190
205
|
}
|
|
191
206
|
|
|
207
|
+
/**
|
|
208
|
+
* Release the lock only when nothing is still holding it — i.e. no agent turn
|
|
209
|
+
* is in progress and no tool execution is outstanding. This is what keeps the
|
|
210
|
+
* overlay from flickering off between tools or mid-turn.
|
|
211
|
+
*/
|
|
212
|
+
function maybeUnlock(requestId?: string): void {
|
|
213
|
+
if (turnActive || lockCount > 0) return;
|
|
214
|
+
forceUnlock(requestId);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function scheduleDebouncedUnlock(requestId?: string): void {
|
|
218
|
+
clearDebounceTimer();
|
|
219
|
+
debounceTimer = setTimeout(() => maybeUnlock(requestId), cfg.debounceUnlock);
|
|
220
|
+
}
|
|
221
|
+
|
|
192
222
|
function handleCancel(): void {
|
|
193
223
|
const rid = undefined; // auto mode tracks this externally
|
|
224
|
+
// Explicit user cancel wins over any in-progress turn/tool tracking.
|
|
194
225
|
forceUnlock(rid);
|
|
195
226
|
emit('cancel', { requestId: rid });
|
|
196
227
|
}
|
|
197
228
|
|
|
229
|
+
/**
|
|
230
|
+
* Turn-level lock driven by the host (see {@link TURN_EVENT}). Holds the
|
|
231
|
+
* overlay for the entire agent response; tool-level auto lock/unlock nests
|
|
232
|
+
* inside without tearing the overlay down.
|
|
233
|
+
*/
|
|
234
|
+
function setTurn(active: boolean): void {
|
|
235
|
+
if (!cfg.enabled) return;
|
|
236
|
+
if (active) {
|
|
237
|
+
turnActive = true;
|
|
238
|
+
clearDebounceTimer();
|
|
239
|
+
if (!locked) {
|
|
240
|
+
doLock(cfg.message, cfg.turnTimeout);
|
|
241
|
+
} else {
|
|
242
|
+
// Already locked by a tool — extend its timeout to the (longer) turn
|
|
243
|
+
// budget so a 30s tool timeout can't drop the overlay mid-turn.
|
|
244
|
+
startTimeout(cfg.turnTimeout);
|
|
245
|
+
}
|
|
246
|
+
} else {
|
|
247
|
+
turnActive = false;
|
|
248
|
+
if (lockCount === 0) scheduleDebouncedUnlock();
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
198
252
|
// Public API -----------------------------------------------------------------
|
|
199
253
|
|
|
200
254
|
function lock(opts?: { message?: string; timeout?: number }): void {
|
|
@@ -229,7 +283,9 @@ export function createAgentLockModule(
|
|
|
229
283
|
clearDebounceTimer();
|
|
230
284
|
lockCount++;
|
|
231
285
|
if (!locked) {
|
|
232
|
-
|
|
286
|
+
// Inside a turn the (longer) turn budget governs; standalone tool calls
|
|
287
|
+
// keep the per-tool timeout.
|
|
288
|
+
doLock(cfg.message, turnActive ? cfg.turnTimeout : cfg.timeout, requestId);
|
|
233
289
|
}
|
|
234
290
|
}
|
|
235
291
|
|
|
@@ -237,19 +293,21 @@ export function createAgentLockModule(
|
|
|
237
293
|
if (!cfg.enabled) return;
|
|
238
294
|
lockCount = Math.max(0, lockCount - 1);
|
|
239
295
|
if (lockCount === 0) {
|
|
240
|
-
|
|
241
|
-
debounceTimer = setTimeout(() => {
|
|
242
|
-
if (lockCount === 0) {
|
|
243
|
-
forceUnlock(requestId);
|
|
244
|
-
}
|
|
245
|
-
}, cfg.debounceUnlock);
|
|
296
|
+
scheduleDebouncedUnlock(requestId);
|
|
246
297
|
}
|
|
247
298
|
}
|
|
248
299
|
|
|
249
300
|
function _destroy(): void {
|
|
301
|
+
if (removeTurnListener) removeTurnListener();
|
|
250
302
|
forceUnlock();
|
|
251
303
|
listeners.clear();
|
|
252
304
|
}
|
|
253
305
|
|
|
306
|
+
// Listen for host-driven turn lock/unlock. Payload shape: `{ active: boolean }`.
|
|
307
|
+
const removeTurnListener = bridge.addEventListener(TURN_EVENT, (data) => {
|
|
308
|
+
const active = !!(data as { active?: unknown } | undefined)?.active;
|
|
309
|
+
setTurn(active);
|
|
310
|
+
});
|
|
311
|
+
|
|
254
312
|
return { lock, unlock, isLocked, on, off, _autoLock, _autoUnlock, _destroy };
|
|
255
313
|
}
|
package/src/types.ts
CHANGED
|
@@ -354,8 +354,15 @@ export interface AgentLockConfig {
|
|
|
354
354
|
allowCancel?: boolean;
|
|
355
355
|
/** Overlay background opacity, 0–1 (default: 0.3). */
|
|
356
356
|
opacity?: number;
|
|
357
|
-
/** Auto-unlock timeout in ms (default: 30000). 0 disables. */
|
|
357
|
+
/** Auto-unlock timeout for a single tool execution, in ms (default: 30000). 0 disables. */
|
|
358
358
|
timeout?: number;
|
|
359
|
+
/**
|
|
360
|
+
* Safety auto-unlock timeout for a whole agent turn, in ms (default: 0 =
|
|
361
|
+
* disabled, rely on the host's turn-end signal). When the host drives a
|
|
362
|
+
* turn-level lock (the lock spans the entire agent response, not just one
|
|
363
|
+
* tool), this acts purely as a fallback in case the turn-end signal is lost.
|
|
364
|
+
*/
|
|
365
|
+
turnTimeout?: number;
|
|
359
366
|
/** Delay before actually removing the overlay after unlock, to avoid flicker between consecutive tools (default: 200ms). */
|
|
360
367
|
debounceUnlock?: number;
|
|
361
368
|
}
|