@co0ontty/wand 1.43.0 → 1.43.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.
@@ -1,6 +1,6 @@
1
1
  {
2
- "commit": "a2fcf61e1ef6825cb1767b63fb9593e8f6e4ecea",
3
- "builtAt": "2026-05-31T02:16:53.049Z",
4
- "version": "1.43.0",
2
+ "commit": "32e84686610853404017c6bab0df94a4819f86b2",
3
+ "builtAt": "2026-05-31T02:55:15.921Z",
4
+ "version": "1.43.1",
5
5
  "channel": "stable"
6
6
  }
@@ -2245,7 +2245,11 @@
2245
2245
  var quickCommitDragState = null;
2246
2246
 
2247
2247
  function normalizeQuickCommitAction(value) {
2248
- if (value === "commit-tag" || value === "commit-tag-push") return value;
2248
+ if (
2249
+ value === "commit-tag" ||
2250
+ value === "commit-tag-push" ||
2251
+ value === "commit-push"
2252
+ ) return value;
2249
2253
  return "commit";
2250
2254
  }
2251
2255
 
@@ -2258,7 +2262,7 @@
2258
2262
  verb: "提交、打 Tag 并推送",
2259
2263
  withTag: true,
2260
2264
  push: true,
2261
- tone: "push",
2265
+ tone: "all",
2262
2266
  };
2263
2267
  }
2264
2268
  if (action === "commit-tag") {
@@ -2271,6 +2275,16 @@
2271
2275
  tone: "tag",
2272
2276
  };
2273
2277
  }
2278
+ if (action === "commit-push") {
2279
+ return {
2280
+ action: action,
2281
+ label: "Commit + Push",
2282
+ verb: "提交并推送",
2283
+ withTag: false,
2284
+ push: true,
2285
+ tone: "push",
2286
+ };
2287
+ }
2274
2288
  return {
2275
2289
  action: "commit",
2276
2290
  label: "Commit",
@@ -2281,16 +2295,34 @@
2281
2295
  };
2282
2296
  }
2283
2297
 
2284
- function getQuickCommitActionFromRatio(ratio) {
2285
- if (ratio >= 0.74) return "commit-tag-push";
2286
- if (ratio >= 0.38) return "commit-tag";
2298
+ // Knob starts at LEFT (Commit). Three zones, left → right:
2299
+ // commit (0.00..0.32) starting position
2300
+ // tag (0.32..0.68) dwell here ~600ms to "arm" the Tag latch
2301
+ // push (0.68..1.00) — release here to push
2302
+ function getQuickCommitZoneFromRatio(ratio) {
2303
+ if (ratio <= 0.32) return "commit";
2304
+ if (ratio >= 0.68) return "push";
2305
+ return "tag";
2306
+ }
2307
+
2308
+ // tagArmed is only true if the user dwelled long enough in the Tag zone.
2309
+ // Sliding straight through Tag → Push without dwelling = commit-push (skip Tag).
2310
+ function composeQuickCommitAction(zone, tagArmed) {
2311
+ if (zone === "push") return tagArmed ? "commit-tag-push" : "commit-push";
2312
+ if (zone === "tag") return "commit-tag";
2287
2313
  return "commit";
2288
2314
  }
2289
2315
 
2316
+ // How long the user must hold the knob inside the Tag zone before the Tag latch arms.
2317
+ // Keep in sync with `--qc-dwell-ms` in styles.css.
2318
+ var QUICK_COMMIT_TAG_DWELL_MS = 1100;
2319
+ var QUICK_COMMIT_ZONE_RANK = { commit: 0, tag: 1, push: 2 };
2320
+
2290
2321
  function openQuickCommitModal() {
2291
2322
  if (!state.selectedId) return;
2292
2323
  state.quickCommitOpen = true;
2293
2324
  state.quickCommitSubmitting = false;
2325
+ state.quickCommitAutoGenerating = false;
2294
2326
  state.quickCommitError = "";
2295
2327
  state.quickCommitForm = {
2296
2328
  customMessage: "",
@@ -2416,30 +2448,71 @@
2416
2448
  attachQuickCommitDrag();
2417
2449
  }
2418
2450
 
2419
- function updateQuickCommitDragVisual(action, ratio) {
2451
+ // ratio: knob CENTER position as fraction of track [0..1]. 0 = left (Commit start), 1 = right (Push).
2452
+ function updateQuickCommitDragVisual(action, ratio, opts) {
2420
2453
  action = normalizeQuickCommitAction(action);
2421
2454
  state.quickCommitDragAction = action;
2422
2455
  var track = document.getElementById("quick-commit-drag-track");
2423
2456
  if (!track) return;
2424
2457
  var meta = getQuickCommitActionMeta(action);
2458
+ // Resting position per action when user isn't dragging.
2459
+ var defaultRatio = 0;
2460
+ if (action === "commit-tag") defaultRatio = 0.5;
2461
+ else if (action === "commit-push" || action === "commit-tag-push") defaultRatio = 1;
2425
2462
  var progress = typeof ratio === "number"
2426
2463
  ? Math.max(0, Math.min(1, ratio))
2427
- : (action === "commit-tag-push" ? 1 : (action === "commit-tag" ? 0.5 : 0));
2464
+ : defaultRatio;
2465
+ var zone = getQuickCommitZoneFromRatio(progress);
2428
2466
  track.setAttribute("data-action", action);
2467
+ track.setAttribute("data-zone", zone);
2468
+ track.setAttribute("data-tag-armed", (action === "commit-tag" || action === "commit-tag-push") ? "1" : "0");
2429
2469
  track.style.setProperty("--qc-progress", (progress * 100).toFixed(1) + "%");
2430
2470
  var knob = document.getElementById("quick-commit-drag-action");
2431
2471
  if (knob) {
2432
- var maxX = Math.max(0, track.clientWidth - knob.offsetWidth - 14);
2433
- track.style.setProperty("--qc-knob-x", (maxX * progress).toFixed(1) + "px");
2472
+ var trackWidth = track.clientWidth;
2473
+ var knobWidth = knob.offsetWidth;
2474
+ var pad = 6;
2475
+ // Knob CENTER tracks ratio * trackWidth, clamped so the knob stays fully inside.
2476
+ var center = progress * trackWidth;
2477
+ var minLeft = pad;
2478
+ var maxLeft = Math.max(pad, trackWidth - knobWidth - pad);
2479
+ var left = Math.max(minLeft, Math.min(maxLeft, center - knobWidth / 2));
2480
+ track.style.setProperty("--qc-knob-x", left.toFixed(1) + "px");
2434
2481
  }
2435
2482
  var label = document.getElementById("quick-commit-drag-label");
2436
- if (label) label.textContent = state.quickCommitSubmitting ? "执行中..." : meta.label;
2483
+ if (label) {
2484
+ var dwell = track.getAttribute("data-tag-dwell") || "idle";
2485
+ var cancelMode = track.getAttribute("data-cancel-mode") === "1";
2486
+ var txt;
2487
+ if (state.quickCommitSubmitting) {
2488
+ txt = state.quickCommitAutoGenerating ? "AI 生成 + 提交中…" : "执行中…";
2489
+ } else if (cancelMode) {
2490
+ txt = "松手取消 ✕";
2491
+ } else if (dwell === "active") {
2492
+ txt = "锁定 Tag 中…";
2493
+ } else if (dwell === "armed" && zone === "tag") {
2494
+ txt = "Tag 已就绪 · 继续推送 →";
2495
+ } else {
2496
+ txt = meta.label;
2497
+ }
2498
+ label.textContent = txt;
2499
+ }
2500
+ // Stage class refresh.
2437
2501
  var stages = track.querySelectorAll("[data-qc-stage]");
2438
- var order = { "commit": 0, "commit-tag": 1, "commit-tag-push": 2 };
2439
2502
  for (var i = 0; i < stages.length; i++) {
2440
- var stageAction = stages[i].getAttribute("data-qc-stage");
2441
- var passed = order[stageAction] <= order[action];
2442
- stages[i].classList.toggle("is-active", stageAction === action);
2503
+ var st = stages[i].getAttribute("data-qc-stage");
2504
+ var active = false, passed = false;
2505
+ if (st === "commit") {
2506
+ active = action === "commit";
2507
+ passed = true;
2508
+ } else if (st === "tag") {
2509
+ active = action === "commit-tag";
2510
+ passed = action === "commit-tag" || action === "commit-tag-push";
2511
+ } else if (st === "push") {
2512
+ active = action === "commit-push" || action === "commit-tag-push";
2513
+ passed = active;
2514
+ }
2515
+ stages[i].classList.toggle("is-active", active);
2443
2516
  stages[i].classList.toggle("is-passed", passed);
2444
2517
  }
2445
2518
  }
@@ -2450,17 +2523,34 @@
2450
2523
  if (!track || !knob) return;
2451
2524
  updateQuickCommitDragVisual(state.quickCommitDragAction || "commit");
2452
2525
 
2526
+ function setDwell(state) { track.setAttribute("data-tag-dwell", state); }
2527
+ function clearArmTimer() {
2528
+ if (quickCommitDragState && quickCommitDragState.tagArmTimer) {
2529
+ clearTimeout(quickCommitDragState.tagArmTimer);
2530
+ quickCommitDragState.tagArmTimer = null;
2531
+ }
2532
+ }
2533
+
2534
+ function setCancelMode(on) { track.setAttribute("data-cancel-mode", on ? "1" : "0"); }
2535
+
2453
2536
  var onPointerDown = function(e) {
2454
2537
  if (knob.disabled || isQuickCommitOpInFlight()) return;
2455
2538
  var rect = track.getBoundingClientRect();
2456
2539
  quickCommitDragState = {
2457
2540
  pointerId: e.pointerId,
2458
2541
  rect: rect,
2542
+ startX: e.clientX,
2459
2543
  moved: false,
2544
+ zone: "commit",
2545
+ maxZone: "commit", // furthest zone the knob ever reached this drag
2546
+ tagArmed: false,
2547
+ tagArmTimer: null,
2460
2548
  action: "commit",
2461
2549
  };
2462
- knob.setPointerCapture(e.pointerId);
2550
+ try { knob.setPointerCapture(e.pointerId); } catch (err) { /* ignored */ }
2463
2551
  track.classList.add("is-dragging");
2552
+ setDwell("idle");
2553
+ setCancelMode(false);
2464
2554
  updateQuickCommitDragVisual("commit", 0);
2465
2555
  e.preventDefault();
2466
2556
  };
@@ -2469,24 +2559,67 @@
2469
2559
  var rect = quickCommitDragState.rect;
2470
2560
  var ratio = rect.width > 0 ? (e.clientX - rect.left) / rect.width : 0;
2471
2561
  ratio = Math.max(0, Math.min(1, ratio));
2472
- if (Math.abs(e.clientX - rect.left) > 6) quickCommitDragState.moved = true;
2473
- var action = getQuickCommitActionFromRatio(ratio);
2562
+ if (Math.abs(e.clientX - quickCommitDragState.startX) > 5) quickCommitDragState.moved = true;
2563
+ var zone = getQuickCommitZoneFromRatio(ratio);
2564
+ // Track furthest zone reached so we can detect a backtrack-to-commit.
2565
+ if (QUICK_COMMIT_ZONE_RANK[zone] > QUICK_COMMIT_ZONE_RANK[quickCommitDragState.maxZone]) {
2566
+ quickCommitDragState.maxZone = zone;
2567
+ }
2568
+ // Zone transitions drive the dwell state machine.
2569
+ if (zone !== quickCommitDragState.zone) {
2570
+ if (zone === "tag" && !quickCommitDragState.tagArmed) {
2571
+ // Entered Tag zone unarmed → kick off the dwell timer + CSS fill animation.
2572
+ clearArmTimer();
2573
+ setDwell("active");
2574
+ quickCommitDragState.tagArmTimer = setTimeout(function() {
2575
+ if (!quickCommitDragState) return;
2576
+ quickCommitDragState.tagArmed = true;
2577
+ quickCommitDragState.tagArmTimer = null;
2578
+ setDwell("armed");
2579
+ var newAction = composeQuickCommitAction(quickCommitDragState.zone, true);
2580
+ quickCommitDragState.action = newAction;
2581
+ updateQuickCommitDragVisual(newAction);
2582
+ }, QUICK_COMMIT_TAG_DWELL_MS);
2583
+ } else if (zone !== "tag" && !quickCommitDragState.tagArmed) {
2584
+ // Left Tag zone before arming → cancel the dwell.
2585
+ clearArmTimer();
2586
+ setDwell("idle");
2587
+ } else if (zone === "tag" && quickCommitDragState.tagArmed) {
2588
+ setDwell("armed");
2589
+ }
2590
+ quickCommitDragState.zone = zone;
2591
+ }
2592
+ // Cancel-mode: backed back to commit after venturing further.
2593
+ // Visual cue is set here; the actual "no-submit" decision is made in finish().
2594
+ var inCancelMode = quickCommitDragState.maxZone !== "commit" && zone === "commit";
2595
+ setCancelMode(inCancelMode);
2596
+ var action = composeQuickCommitAction(zone, quickCommitDragState.tagArmed);
2474
2597
  quickCommitDragState.action = action;
2475
2598
  updateQuickCommitDragVisual(action, ratio);
2476
2599
  };
2477
2600
  var finish = function(e, cancelled) {
2478
2601
  if (!quickCommitDragState) return;
2479
2602
  var current = quickCommitDragState;
2603
+ clearArmTimer();
2480
2604
  quickCommitDragState = null;
2481
2605
  track.classList.remove("is-dragging");
2606
+ setDwell("idle");
2607
+ setCancelMode(false);
2482
2608
  try {
2483
2609
  if (typeof knob.releasePointerCapture === "function") knob.releasePointerCapture(current.pointerId);
2484
2610
  } catch (err) { /* ignored */ }
2485
- if (cancelled) {
2611
+ // Backtrack: user ventured out past Commit, then dragged back and released at Commit → cancel.
2612
+ var isBacktrack = current.moved
2613
+ && current.zone === "commit"
2614
+ && current.maxZone !== "commit";
2615
+ if (cancelled || isBacktrack) {
2486
2616
  updateQuickCommitDragVisual("commit");
2487
2617
  return;
2488
2618
  }
2489
- var action = current.moved ? current.action : "commit";
2619
+ // Tap (no drag) just commit. Auto-message will fire if the message is empty.
2620
+ var action = current.moved
2621
+ ? composeQuickCommitAction(current.zone, current.tagArmed)
2622
+ : "commit";
2490
2623
  updateQuickCommitDragVisual(action);
2491
2624
  submitQuickCommit(action);
2492
2625
  if (e && typeof e.preventDefault === "function") e.preventDefault();
@@ -2499,20 +2632,31 @@
2499
2632
  if (!quickCommitDragState || quickCommitDragState.pointerId !== e.pointerId) return;
2500
2633
  finish(e, true);
2501
2634
  };
2635
+ // Keyboard parity:
2636
+ // → step zone right (commit → commit-tag → commit-tag-push). The first → into Tag arms it instantly.
2637
+ // ← step zone left
2638
+ // Home → reset to commit
2639
+ // Enter / Space → submit current action
2502
2640
  var onKeyDown = function(e) {
2503
2641
  if (knob.disabled || isQuickCommitOpInFlight()) return;
2642
+ var cur = state.quickCommitDragAction || "commit";
2504
2643
  if (e.key === "ArrowRight") {
2505
2644
  e.preventDefault();
2506
- var next = state.quickCommitDragAction === "commit"
2507
- ? "commit-tag"
2508
- : (state.quickCommitDragAction === "commit-tag" ? "commit-tag-push" : "commit-tag-push");
2645
+ var next = cur;
2646
+ if (cur === "commit") next = "commit-tag"; // arm Tag
2647
+ else if (cur === "commit-tag") next = "commit-tag-push";
2648
+ else if (cur === "commit-push") next = "commit-push";
2509
2649
  updateQuickCommitDragVisual(next);
2510
2650
  } else if (e.key === "ArrowLeft") {
2511
2651
  e.preventDefault();
2512
- var prev = state.quickCommitDragAction === "commit-tag-push"
2513
- ? "commit-tag"
2514
- : (state.quickCommitDragAction === "commit-tag" ? "commit" : "commit");
2652
+ var prev = cur;
2653
+ if (cur === "commit-tag-push") prev = "commit-tag";
2654
+ else if (cur === "commit-tag") prev = "commit";
2655
+ else if (cur === "commit-push") prev = "commit";
2515
2656
  updateQuickCommitDragVisual(prev);
2657
+ } else if (e.key === "Home") {
2658
+ e.preventDefault();
2659
+ updateQuickCommitDragVisual("commit");
2516
2660
  } else if (e.key === "Enter" || e.key === " ") {
2517
2661
  e.preventDefault();
2518
2662
  submitQuickCommit(state.quickCommitDragAction || "commit");
@@ -2530,6 +2674,9 @@
2530
2674
  knob.removeEventListener("pointerup", onPointerUp);
2531
2675
  knob.removeEventListener("pointercancel", onPointerCancel);
2532
2676
  knob.removeEventListener("keydown", onKeyDown);
2677
+ if (quickCommitDragState && quickCommitDragState.tagArmTimer) {
2678
+ clearTimeout(quickCommitDragState.tagArmTimer);
2679
+ }
2533
2680
  quickCommitDragState = null;
2534
2681
  };
2535
2682
  }
@@ -2592,11 +2739,9 @@
2592
2739
  var withTag = meta.withTag;
2593
2740
  var userTag = withTag ? (form.tag || "").trim() : "";
2594
2741
  var message = (form.customMessage || "").trim();
2595
- if (!message) {
2596
- state.quickCommitError = "请填写提交信息,或点击「AI 生成」。";
2597
- rerenderQuickCommitModal();
2598
- return;
2599
- }
2742
+ // Auto-generate flow: empty commit message → ask backend to write one (autoMessage:true).
2743
+ // Empty tag (when withTag) → ask backend to derive one (autoTag:true). Both go in one round-trip.
2744
+ var autoMessage = !message;
2600
2745
  var before = {
2601
2746
  branch: (state.gitStatus || {}).branch || "",
2602
2747
  commitHash: (state.gitStatus || {}).lastCommit && (state.gitStatus || {}).lastCommit.shortHash
@@ -2608,13 +2753,14 @@
2608
2753
  tag: (state.gitStatus || {}).latestTag || "",
2609
2754
  };
2610
2755
  var payload = {
2611
- autoMessage: false,
2612
- customMessage: message,
2756
+ autoMessage: autoMessage,
2757
+ customMessage: autoMessage ? "" : message,
2613
2758
  tag: userTag,
2614
2759
  autoTag: !!(withTag && !userTag),
2615
2760
  push: !!meta.push
2616
2761
  };
2617
2762
  state.quickCommitSubmitting = true;
2763
+ state.quickCommitAutoGenerating = autoMessage || payload.autoTag;
2618
2764
  state.quickCommitError = "";
2619
2765
  state.quickCommitPushError = "";
2620
2766
  state.quickCommitResult = null;
@@ -2668,6 +2814,7 @@
2668
2814
  })
2669
2815
  .finally(function() {
2670
2816
  state.quickCommitSubmitting = false;
2817
+ state.quickCommitAutoGenerating = false;
2671
2818
  if (state.quickCommitOpen) rerenderQuickCommitModal();
2672
2819
  });
2673
2820
  }
@@ -2793,20 +2940,42 @@
2793
2940
  var action = normalizeQuickCommitAction(state.quickCommitDragAction || "commit");
2794
2941
  var meta = getQuickCommitActionMeta(action);
2795
2942
  var disabled = !hasChanges || isQuickCommitOpInFlight();
2796
- var label = state.quickCommitSubmitting ? "执行中..." : meta.label;
2943
+ var label = state.quickCommitSubmitting ? "执行中…" : meta.label;
2944
+ // Stage classes derived from the current action.
2945
+ var commitActive = action === "commit";
2946
+ var tagActive = action === "commit-tag";
2947
+ var tagPassed = action === "commit-tag" || action === "commit-tag-push";
2948
+ var pushActive = action === "commit-push" || action === "commit-tag-push";
2949
+ var hint = "向右拖 · 经过 Tag 时停一下打 Tag · 直接划到 Push 跳过 Tag · 留空会自动生成";
2797
2950
  return '<div class="qc-drag-wrap">' +
2798
- '<div id="quick-commit-drag-track" class="qc-drag-track" data-action="' + escapeHtml(action) + '" style="--qc-progress: ' + (action === "commit-tag-push" ? "100%" : (action === "commit-tag" ? "50%" : "0%")) + ';">' +
2799
- '<div class="qc-drag-progress" aria-hidden="true"></div>' +
2951
+ '<div id="quick-commit-drag-track" class="qc-drag-track" data-action="' + escapeHtml(action) + '" data-zone="commit" data-tag-dwell="idle">' +
2952
+ // Baseline track: subtle grey rail under everything, segments brighten as the knob passes.
2953
+ '<svg class="qc-drag-baseline" viewBox="0 0 100 24" preserveAspectRatio="none" aria-hidden="true">' +
2954
+ '<line class="qc-baseline-rail" x1="4" y1="12" x2="96" y2="12" />' +
2955
+ '<line class="qc-baseline-seg qc-baseline-seg--left" x1="4" y1="12" x2="50" y2="12" />' +
2956
+ '<line class="qc-baseline-seg qc-baseline-seg--right" x1="50" y1="12" x2="96" y2="12" />' +
2957
+ '</svg>' +
2958
+ // Three marching chevrons running right — "drag this way".
2959
+ '<div class="qc-chevrons" aria-hidden="true">' +
2960
+ '<svg class="qc-chevron" viewBox="0 0 12 16" width="9" height="12"><path d="M3 2 L9 8 L3 14" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg>' +
2961
+ '<svg class="qc-chevron" viewBox="0 0 12 16" width="9" height="12"><path d="M3 2 L9 8 L3 14" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg>' +
2962
+ '<svg class="qc-chevron" viewBox="0 0 12 16" width="9" height="12"><path d="M3 2 L9 8 L3 14" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></svg>' +
2963
+ '</div>' +
2964
+ // Stage dots / labels along the rail.
2800
2965
  '<div class="qc-drag-stages" aria-hidden="true">' +
2801
- '<span class="qc-drag-stage is-active is-passed" data-qc-stage="commit">Commit</span>' +
2802
- '<span class="qc-drag-stage' + (action !== "commit" ? ' is-passed' : '') + (action === "commit-tag" ? ' is-active' : '') + '" data-qc-stage="commit-tag">Tag</span>' +
2803
- '<span class="qc-drag-stage' + (action === "commit-tag-push" ? ' is-active is-passed' : '') + '" data-qc-stage="commit-tag-push">Push</span>' +
2966
+ '<span class="qc-drag-stage qc-stage-commit' + (commitActive ? ' is-active' : '') + ' is-passed" data-qc-stage="commit">Commit</span>' +
2967
+ '<span class="qc-drag-stage qc-stage-tag' + (tagActive ? ' is-active' : '') + (tagPassed ? ' is-passed' : '') + '" data-qc-stage="tag">Tag</span>' +
2968
+ '<span class="qc-drag-stage qc-stage-push' + (pushActive ? ' is-active is-passed' : '') + '" data-qc-stage="push">Push</span>' +
2804
2969
  '</div>' +
2805
- '<button id="quick-commit-drag-action" class="qc-drag-action" type="button"' + (disabled ? ' disabled' : '') + ' aria-label="' + escapeHtml(meta.verb) + '">' +
2806
- '<span id="quick-commit-drag-label">' + escapeHtml(label) + '</span>' +
2807
- '<svg viewBox="0 0 24 24" width="16" height="16" aria-hidden="true"><path d="M5 12h14"/><path d="M13 6l6 6-6 6" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>' +
2970
+ // Knob starts at left, slides right.
2971
+ '<button id="quick-commit-drag-action" class="qc-drag-action" type="button"' + (disabled ? ' disabled' : '') + ' aria-label="' + escapeHtml(meta.verb) + '" title="' + escapeHtml(hint) + '">' +
2972
+ '<span class="qc-drag-grip" aria-hidden="true"><i></i><i></i><i></i></span>' +
2973
+ '<span id="quick-commit-drag-label" class="qc-drag-label">' + escapeHtml(label) + '</span>' +
2974
+ // Bottom progress bar — fills 0→100% over DWELL_MS while sitting in the Tag zone.
2975
+ '<span class="qc-drag-dwell-bar" aria-hidden="true"></span>' +
2808
2976
  '</button>' +
2809
2977
  '</div>' +
2978
+ '<div class="qc-drag-help" aria-hidden="true">' + escapeHtml(hint) + '</div>' +
2810
2979
  '</div>';
2811
2980
  }
2812
2981