@tanzerfe/page-use 0.0.9 → 0.0.10

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.
@@ -442,11 +442,18 @@ declare class PageUseLauncherElement extends LitElement {
442
442
  private fabFromWidth;
443
443
  /** 进行中宽度过渡的结束回调注销函数;过渡中再次切换时先注销,避免旧回调提前清除宽度 */
444
444
  private fabWidthCleanup;
445
+ /** 本次入口手势是否已判定为拖动。指针捕获会把手势结束后浏览器补发的 click 重定向到入口,该 click 不是点击意图,不得展开面板。 */
446
+ private fabDragged;
445
447
  /**
446
- * 本次入口手势是否已判定为拖动。
447
- * 指针捕获会把手势结束后浏览器补发的 click 重定向到入口,该 click 不是点击意图,不得展开面板。
448
+ * 移动端面板的纵向位移(px,0 为贴底原位)。跟手期间由指针事件直写样式,不进入响应式状态:
449
+ * 每帧触发模板重渲染会带来不必要的开销,且重渲染写 style 属性会覆盖内联位移。
450
+ * 也不写入设置,位移不持久化。
448
451
  */
449
- private fabDragged;
452
+ private sheetOffsetY;
453
+ /** 本次下拉手势的纵向位移采样,用于松手判定与速度计算 */
454
+ private sheetSamples;
455
+ /** 进行中的面板位移动效的取消函数;调用后等待中的收起流程会中止 */
456
+ private sheetAnimCancel;
450
457
  private cleanups;
451
458
  /** 生效的面板布局:未声明或取值非法时按桌面端处理,既有接入方的行为不变 */
452
459
  private get isMobileLayout();
@@ -521,7 +528,31 @@ declare class PageUseLauncherElement extends LitElement {
521
528
  /** 在面板内显示轻提示,TOAST_DURATION_MS 后自动消失;连续触发时以最后一次为准并重新计时 */
522
529
  private showToast;
523
530
  private clearHistory;
531
+ /**
532
+ * 收起面板为浮动入口。移动端先向下滑出视口再隐藏,滑出期间面板不拦截页面点击——
533
+ * 「执行后自动收起」时页面上紧接着就是 agent 的操作,动画不能挡住它。
534
+ * 系统关闭动态效果(过渡时长为 0)时直接隐藏,不做动效。
535
+ */
524
536
  private collapse;
537
+ /** 面板过渡被禁用时为 true:系统「减少动态效果」或样式未生效,此时直接切换状态 */
538
+ private sheetMotionDisabled;
539
+ /** 写入面板纵向位移;0 表示回到贴底原位 */
540
+ private setSheetOffset;
541
+ /** 清除位移与内联过渡:先关过渡再清位移,避免清除动作本身被过渡动画化 */
542
+ private resetSheetStyles;
543
+ /** 取消进行中的位移动效并让面板回到原位;等待中的收起流程因取消而中止 */
544
+ private cancelSheetAnimation;
545
+ /**
546
+ * 把面板位移过渡到目标值,返回是否走到终点(被 cancelSheetAnimation 取消时为 false)。
547
+ * 过渡事件缺失(元素被隐藏、标签页切到后台)时由定时器兜底结束,面板不停在半途。
548
+ */
549
+ private sheetTransition;
550
+ /** 下拉手势开始:终止进行中的动效,并关闭过渡让面板直接跟手 */
551
+ private beginSheetGesture;
552
+ /** 跟手位移:只认纵向占优的向下拖动;上滑与横向拖动不移动面板(面板没有第二档高度可展开) */
553
+ private onSheetDragMove;
554
+ /** 松手:按位移或速度判定收起,否则回弹归位 */
555
+ private onSheetDragEnd;
525
556
  /** tourStyle:快捷指令携带的讲解风格;输入框提交时不传,按面板设置与宿主默认 */
526
557
  private submit;
527
558
  private applyPreset;
package/dist/index.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { $ as DEFAULT_TOUR_MAX_TAB_SWITCHES, A as PageUseGlobal, B as MountPageUseUIOptions, C as getElapsedSeconds, Ct as PageUseTaskResult, D as pageUseStore, E as isRunning, F as PAGE_USE_TOOL_NAME, G as PageUseLauncherElement, H as mountPageUseUI, I as PageUseCommand, J as createPageUse, K as PageUseLauncherLayout, L as formatPageUseResultForModel, M as showPageUseLauncher, N as PAGE_USE_COMMAND_TYPE, O as ReadonlyStore, P as PAGE_USE_TOOL, Q as DEFAULT_STORAGE_KEY_PREFIX, R as isPageUseCommand, S as clearPageUseLog, St as PageUseStepLog, T as isPageUseConfigured, Tt as PageUseTaskStatus, U as PAGE_USE_LAUNCHER_TAG, V as definePageUseElements, W as PageUseLauncherConfig, X as DEFAULT_MODEL, Y as DEFAULT_MAX_STEPS, Z as DEFAULT_SESSION_HEADER, _ as pageUseSettings, _t as PageUseMenuNode, a as PAGE_USE_ROBOT_ICON_SVG, at as normalizeOptions, b as PageUseQuestion, bt as PageUseRunOptions, c as PageUseCustomPreset, ct as PageUseTtsSpeakOptions, d as pageUsePresets, dt as PageUseTourStyle, et as NormalizedPageUseOptions, f as PageUseHistoryEntry, ft as TOUR_STYLE_TRAINER, g as PageUseSettings, gt as PageUseErrorCode, h as PageUsePoint, ht as pageUseCapability, i as PageUseGlowElement, it as PageUseTourOptions, j as hidePageUseLauncher, k as PAGE_USE_GLOBAL_KEY, l as PageUsePresetSaveResult, lt as PageUseTtsVoice, m as DEFAULT_PAGE_USE_SETTINGS, mt as PageUseCapability, n as SIMULATOR_MASK_ID, nt as PageUseOptions, o as PAGE_USE_STATIC_PRESETS, ot as readLauncherSwitch, p as pageUseHistory, pt as TOUR_STYLE_USER, q as PageUseHandle, r as PAGE_USE_GLOW_TAG, rt as PageUseRouterMode, s as buildMenuPresets, st as PageUseTtsEngine, t as PAGE_USE_MASK_COLORS, tt as PageUseLLMOptions, u as PageUsePresetState, ut as DEFAULT_TOUR_STYLES, v as BROWSER_ENGINE_ID, vt as PageUsePreset, w as getPageUseConfig, wt as PageUseTaskSource, x as PageUseState, xt as PageUseSnapshot, y as browserTtsEngine, yt as PageUseProgressEvent, z as runPageUseTool } from "./index-BACVE8Ig.mjs";
1
+ import { $ as DEFAULT_TOUR_MAX_TAB_SWITCHES, A as PageUseGlobal, B as MountPageUseUIOptions, C as getElapsedSeconds, Ct as PageUseTaskResult, D as pageUseStore, E as isRunning, F as PAGE_USE_TOOL_NAME, G as PageUseLauncherElement, H as mountPageUseUI, I as PageUseCommand, J as createPageUse, K as PageUseLauncherLayout, L as formatPageUseResultForModel, M as showPageUseLauncher, N as PAGE_USE_COMMAND_TYPE, O as ReadonlyStore, P as PAGE_USE_TOOL, Q as DEFAULT_STORAGE_KEY_PREFIX, R as isPageUseCommand, S as clearPageUseLog, St as PageUseStepLog, T as isPageUseConfigured, Tt as PageUseTaskStatus, U as PAGE_USE_LAUNCHER_TAG, V as definePageUseElements, W as PageUseLauncherConfig, X as DEFAULT_MODEL, Y as DEFAULT_MAX_STEPS, Z as DEFAULT_SESSION_HEADER, _ as pageUseSettings, _t as PageUseMenuNode, a as PAGE_USE_ROBOT_ICON_SVG, at as normalizeOptions, b as PageUseQuestion, bt as PageUseRunOptions, c as PageUseCustomPreset, ct as PageUseTtsSpeakOptions, d as pageUsePresets, dt as PageUseTourStyle, et as NormalizedPageUseOptions, f as PageUseHistoryEntry, ft as TOUR_STYLE_TRAINER, g as PageUseSettings, gt as PageUseErrorCode, h as PageUsePoint, ht as pageUseCapability, i as PageUseGlowElement, it as PageUseTourOptions, j as hidePageUseLauncher, k as PAGE_USE_GLOBAL_KEY, l as PageUsePresetSaveResult, lt as PageUseTtsVoice, m as DEFAULT_PAGE_USE_SETTINGS, mt as PageUseCapability, n as SIMULATOR_MASK_ID, nt as PageUseOptions, o as PAGE_USE_STATIC_PRESETS, ot as readLauncherSwitch, p as pageUseHistory, pt as TOUR_STYLE_USER, q as PageUseHandle, r as PAGE_USE_GLOW_TAG, rt as PageUseRouterMode, s as buildMenuPresets, st as PageUseTtsEngine, t as PAGE_USE_MASK_COLORS, tt as PageUseLLMOptions, u as PageUsePresetState, ut as DEFAULT_TOUR_STYLES, v as BROWSER_ENGINE_ID, vt as PageUsePreset, w as getPageUseConfig, wt as PageUseTaskSource, x as PageUseState, xt as PageUseSnapshot, y as browserTtsEngine, yt as PageUseProgressEvent, z as runPageUseTool } from "./index-DAwlbs2a.mjs";
2
2
  export { BROWSER_ENGINE_ID, DEFAULT_MAX_STEPS, DEFAULT_MODEL, DEFAULT_PAGE_USE_SETTINGS, DEFAULT_SESSION_HEADER, DEFAULT_STORAGE_KEY_PREFIX, DEFAULT_TOUR_MAX_TAB_SWITCHES, DEFAULT_TOUR_STYLES, type MountPageUseUIOptions, type NormalizedPageUseOptions, PAGE_USE_COMMAND_TYPE, PAGE_USE_GLOBAL_KEY, PAGE_USE_GLOW_TAG, PAGE_USE_LAUNCHER_TAG, PAGE_USE_MASK_COLORS, PAGE_USE_ROBOT_ICON_SVG, PAGE_USE_STATIC_PRESETS, PAGE_USE_TOOL, PAGE_USE_TOOL_NAME, type PageUseCapability, type PageUseCommand, type PageUseCustomPreset, type PageUseErrorCode, type PageUseGlobal, PageUseGlowElement, type PageUseHandle, type PageUseHistoryEntry, type PageUseLLMOptions, type PageUseLauncherConfig, PageUseLauncherElement, type PageUseLauncherLayout, type PageUseMenuNode, type PageUseOptions, type PageUsePoint, type PageUsePreset, type PageUsePresetSaveResult, type PageUsePresetState, type PageUseProgressEvent, type PageUseQuestion, type PageUseRouterMode, type PageUseRunOptions, type PageUseSettings, type PageUseSnapshot, type PageUseState, type PageUseStepLog, type PageUseTaskResult, type PageUseTaskSource, type PageUseTaskStatus, type PageUseTourOptions, type PageUseTourStyle, type PageUseTtsEngine, type PageUseTtsSpeakOptions, type PageUseTtsVoice, type ReadonlyStore, SIMULATOR_MASK_ID, TOUR_STYLE_TRAINER, TOUR_STYLE_USER, browserTtsEngine, buildMenuPresets, clearPageUseLog, createPageUse, definePageUseElements, formatPageUseResultForModel, getElapsedSeconds, getPageUseConfig, hidePageUseLauncher, isPageUseCommand, isPageUseConfigured, isRunning, mountPageUseUI, normalizeOptions, pageUseCapability, pageUseHistory, pageUsePresets, pageUseSettings, pageUseStore, readLauncherSwitch, runPageUseTool, showPageUseLauncher };
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { A as pageUseSettings, B as BROWSER_ENGINE_ID, C as getPageUseConfig, D as pageUsePresets, E as pageUseStore, F as DEFAULT_TOUR_MAX_TAB_SWITCHES, H as DEFAULT_TOUR_STYLES, I as normalizeOptions, L as readLauncherSwitch, M as DEFAULT_MODEL, N as DEFAULT_SESSION_HEADER, O as pageUseHistory, P as DEFAULT_STORAGE_KEY_PREFIX, R as PAGE_USE_MASK_COLORS, S as getElapsedSeconds, T as isRunning, U as TOUR_STYLE_TRAINER, V as browserTtsEngine, W as TOUR_STYLE_USER, _ as runPageUseTool, a as PAGE_USE_STATIC_PRESETS, b as pageUseCapability, c as PAGE_USE_GLOW_TAG, d as PAGE_USE_GLOBAL_KEY, f as PAGE_USE_COMMAND_TYPE, g as isPageUseCommand, h as formatPageUseResultForModel, i as PageUseLauncherElement, j as DEFAULT_MAX_STEPS, k as DEFAULT_PAGE_USE_SETTINGS, l as PageUseGlowElement, m as PAGE_USE_TOOL_NAME, n as mountPageUseUI, o as buildMenuPresets, p as PAGE_USE_TOOL, r as PAGE_USE_LAUNCHER_TAG, s as PAGE_USE_ROBOT_ICON_SVG, t as definePageUseElements, u as createPageUse, v as hidePageUseLauncher, w as isPageUseConfigured, x as clearPageUseLog, y as showPageUseLauncher, z as SIMULATOR_MASK_ID } from "./src-MjVXh_cW.mjs";
1
+ import { A as pageUseSettings, B as BROWSER_ENGINE_ID, C as getPageUseConfig, D as pageUsePresets, E as pageUseStore, F as DEFAULT_TOUR_MAX_TAB_SWITCHES, H as DEFAULT_TOUR_STYLES, I as normalizeOptions, L as readLauncherSwitch, M as DEFAULT_MODEL, N as DEFAULT_SESSION_HEADER, O as pageUseHistory, P as DEFAULT_STORAGE_KEY_PREFIX, R as PAGE_USE_MASK_COLORS, S as getElapsedSeconds, T as isRunning, U as TOUR_STYLE_TRAINER, V as browserTtsEngine, W as TOUR_STYLE_USER, _ as runPageUseTool, a as PAGE_USE_STATIC_PRESETS, b as pageUseCapability, c as PAGE_USE_GLOW_TAG, d as PAGE_USE_GLOBAL_KEY, f as PAGE_USE_COMMAND_TYPE, g as isPageUseCommand, h as formatPageUseResultForModel, i as PageUseLauncherElement, j as DEFAULT_MAX_STEPS, k as DEFAULT_PAGE_USE_SETTINGS, l as PageUseGlowElement, m as PAGE_USE_TOOL_NAME, n as mountPageUseUI, o as buildMenuPresets, p as PAGE_USE_TOOL, r as PAGE_USE_LAUNCHER_TAG, s as PAGE_USE_ROBOT_ICON_SVG, t as definePageUseElements, u as createPageUse, v as hidePageUseLauncher, w as isPageUseConfigured, x as clearPageUseLog, y as showPageUseLauncher, z as SIMULATOR_MASK_ID } from "./src-nVu9CCnz.mjs";
2
2
 
3
3
  export { BROWSER_ENGINE_ID, DEFAULT_MAX_STEPS, DEFAULT_MODEL, DEFAULT_PAGE_USE_SETTINGS, DEFAULT_SESSION_HEADER, DEFAULT_STORAGE_KEY_PREFIX, DEFAULT_TOUR_MAX_TAB_SWITCHES, DEFAULT_TOUR_STYLES, PAGE_USE_COMMAND_TYPE, PAGE_USE_GLOBAL_KEY, PAGE_USE_GLOW_TAG, PAGE_USE_LAUNCHER_TAG, PAGE_USE_MASK_COLORS, PAGE_USE_ROBOT_ICON_SVG, PAGE_USE_STATIC_PRESETS, PAGE_USE_TOOL, PAGE_USE_TOOL_NAME, PageUseGlowElement, PageUseLauncherElement, SIMULATOR_MASK_ID, TOUR_STYLE_TRAINER, TOUR_STYLE_USER, browserTtsEngine, buildMenuPresets, clearPageUseLog, createPageUse, definePageUseElements, formatPageUseResultForModel, getElapsedSeconds, getPageUseConfig, hidePageUseLauncher, isPageUseCommand, isPageUseConfigured, isRunning, mountPageUseUI, normalizeOptions, pageUseCapability, pageUseHistory, pageUsePresets, pageUseSettings, pageUseStore, readLauncherSwitch, runPageUseTool, showPageUseLauncher };
@@ -3045,7 +3045,7 @@ var PageUseGlowElement = class extends LitElement {
3045
3045
 
3046
3046
  //#endregion
3047
3047
  //#region package.json
3048
- var version = "0.0.9";
3048
+ var version = "0.0.10";
3049
3049
 
3050
3050
  //#endregion
3051
3051
  //#region src/ui/drag.ts
@@ -3085,25 +3085,30 @@ function createDrag(options) {
3085
3085
  if (!moved && Math.hypot(dx, dy) < DRAG_THRESHOLD) return;
3086
3086
  if (!moved) options.onDragStart?.();
3087
3087
  moved = true;
3088
+ options.onMove?.(dx, dy);
3088
3089
  options.setPos(clampToViewport({
3089
3090
  x: rect.left + dx,
3090
3091
  y: rect.top + dy
3091
3092
  }, el));
3092
3093
  };
3093
- const onUp = () => {
3094
+ const finish = (cancelled) => {
3095
+ if (!dragging) return;
3094
3096
  dragging = false;
3095
3097
  handle.removeEventListener("pointermove", onMove);
3096
3098
  handle.removeEventListener("pointerup", onUp);
3097
- handle.removeEventListener("pointercancel", onUp);
3099
+ handle.removeEventListener("pointercancel", onCancel);
3098
3100
  try {
3099
3101
  handle.releasePointerCapture(event.pointerId);
3100
3102
  } catch {}
3103
+ options.onEnd?.({ cancelled });
3101
3104
  if (!moved) options.onTap?.(tapTarget);
3102
3105
  };
3106
+ const onUp = () => finish(false);
3107
+ const onCancel = () => finish(true);
3103
3108
  handle.setPointerCapture(event.pointerId);
3104
3109
  handle.addEventListener("pointermove", onMove);
3105
3110
  handle.addEventListener("pointerup", onUp);
3106
- handle.addEventListener("pointercancel", onUp);
3111
+ handle.addEventListener("pointercancel", onCancel);
3107
3112
  event.preventDefault();
3108
3113
  }
3109
3114
  /** 视口尺寸变化后把已存位置夹回可见区域 */
@@ -3117,6 +3122,46 @@ function createDrag(options) {
3117
3122
  reclamp
3118
3123
  };
3119
3124
  }
3125
+ /** 判定收起所需的纵向位移占面板高度的比例 */
3126
+ const SHEET_DISTANCE_RATIO = .25;
3127
+ /** 判定收起所需的纵向速度(px/ms) */
3128
+ const SHEET_VELOCITY_THRESHOLD = .5;
3129
+ /** 速度取样的时间窗口(ms):只取最近这一段,避免起手时的慢速稀释甩动判定 */
3130
+ const SHEET_VELOCITY_WINDOW_MS = 100;
3131
+ /** 速度判定要求的最小位移(px):防止轻微抖动被当成甩动 */
3132
+ const SHEET_VELOCITY_MIN_DISTANCE = 24;
3133
+ /** 滑出时长的基准值(ms)与折算系数:剩余距离越短越快结束,避免短距离也拖满整个时长 */
3134
+ const SHEET_EXIT_BASE_MS = 120;
3135
+ const SHEET_EXIT_MAX_MS = 220;
3136
+ const SHEET_EXIT_PER_PX = .35;
3137
+ /** 滑出时长(ms):随剩余距离增长,上限 220ms(需求上限为 240ms) */
3138
+ function sheetExitDuration(remainingPx) {
3139
+ return Math.min(SHEET_EXIT_MAX_MS, SHEET_EXIT_BASE_MS + Math.max(0, remainingPx) * SHEET_EXIT_PER_PX);
3140
+ }
3141
+ /**
3142
+ * 松手判定:位移达到面板高度的四分之一,或最近 100ms 的平均速度达到阈值且位移足够时收起。
3143
+ * 手势被系统中断时一律回弹——中断不代表用户表达了收起意图。
3144
+ */
3145
+ function decideSheetRelease(samples, options) {
3146
+ if (options.cancelled) return "snapback";
3147
+ const last = samples[samples.length - 1];
3148
+ if (!last) return "snapback";
3149
+ if (last.dy >= options.panelHeight * SHEET_DISTANCE_RATIO) return "dismiss";
3150
+ if (last.dy < SHEET_VELOCITY_MIN_DISTANCE) return "snapback";
3151
+ return sheetReleaseVelocity(samples, last) >= SHEET_VELOCITY_THRESHOLD ? "dismiss" : "snapback";
3152
+ }
3153
+ /**
3154
+ * 最近一个时间窗口内的平均纵向速度(px/ms)。
3155
+ * 窗口内不足两个采样时(采样稀疏、间隔超过窗口)退回上一个采样,否则速度不可测。
3156
+ */
3157
+ function sheetReleaseVelocity(samples, last) {
3158
+ const windowStart = last.t - SHEET_VELOCITY_WINDOW_MS;
3159
+ const index = samples.findIndex((sample) => sample.t >= windowStart);
3160
+ const start = index < samples.length - 1 ? samples[index] : samples[Math.max(0, samples.length - 2)];
3161
+ const dt = last.t - start.t;
3162
+ if (dt <= 0) return 0;
3163
+ return (last.dy - start.dy) / dt;
3164
+ }
3120
3165
 
3121
3166
  //#endregion
3122
3167
  //#region src/ui/formatTokens.ts
@@ -3419,6 +3464,10 @@ const launcherStyles = css`
3419
3464
  .fab {
3420
3465
  transition: none;
3421
3466
  }
3467
+ /* 面板位移过渡关闭后,launcher 读到 transitionDuration 为 0,收起与回弹直接切换状态 */
3468
+ .panel.mobile {
3469
+ transition: none;
3470
+ }
3422
3471
  .fab,
3423
3472
  .panel::before,
3424
3473
  .fab.running .robot-antenna,
@@ -3526,12 +3575,34 @@ const launcherStyles = css`
3526
3575
  height: 70dvh;
3527
3576
  /* 底边与屏幕贴合,去掉下圆角 */
3528
3577
  border-radius: 12px 12px 0 0;
3578
+ /*
3579
+ * 下拉收起与回弹通过 transform 位移实现。过渡声明的另一作用是作为「可播放动效」的判据:
3580
+ * launcher 读取生效的 transitionDuration,为 0 时(下方减少动态效果媒体查询)直接切换状态。
3581
+ * 跟手期间由 launcher 临时置为 none,避免位移被过渡拖慢。
3582
+ */
3583
+ transition: transform 180ms cubic-bezier(0.22, 1, 0.36, 1);
3529
3584
  }
3530
- /* 位置由布局决定,头部不再是拖动区域;仍保留按下检测,用于标题连点解锁元信息 */
3585
+ /*
3586
+ * 移动端头部:位置由布局决定,不再是拖动改位置的区域,但仍保留按下检测——
3587
+ * 向下拉动即收起面板。touch-action 必须保持 none:否则浏览器把手势解释为滚动或下拉刷新,
3588
+ * 中途以 pointercancel 打断指针流,且 pointerdown 上的 preventDefault 对触摸滚动无效。
3589
+ */
3531
3590
  .panel.mobile .head,
3532
3591
  .panel.mobile .head:active {
3592
+ position: relative;
3533
3593
  cursor: default;
3534
- touch-action: auto;
3594
+ touch-action: none;
3595
+ }
3596
+ /* 抓取条:绝对定位在头部顶端居中,不参与布局流,面板几何与桌面端头部高度均不受影响 */
3597
+ .panel.mobile .grabber {
3598
+ position: absolute;
3599
+ top: 4px;
3600
+ left: 50%;
3601
+ width: 32px;
3602
+ height: 4px;
3603
+ margin-left: -16px;
3604
+ border-radius: 2px;
3605
+ background: rgba(100, 116, 139, 0.45);
3535
3606
  }
3536
3607
  /* 底边与屏幕贴合,不需要下圆角;底部内边距让出 iPhone 手势条 */
3537
3608
  .panel.mobile .composer {
@@ -4220,6 +4291,10 @@ const TEXTAREA_MIN_ROWS = 2;
4220
4291
  /** 元信息面板解锁:任意连续 META_UNLOCK_WINDOW_MS 毫秒内点击标题达到 META_UNLOCK_CLICKS 次(滑动窗口) */
4221
4292
  const META_UNLOCK_WINDOW_MS = 5e3;
4222
4293
  const META_UNLOCK_CLICKS = 10;
4294
+ /** 面板位移过渡曲线:下拉滑出与回弹共用,接近 iOS 的减速曲线 */
4295
+ const SHEET_EASING = "cubic-bezier(0.22, 1, 0.36, 1)";
4296
+ /** 面板位移动效兜底时长(ms):过渡事件丢失时据此结束动效,避免面板停在半途 */
4297
+ const SHEET_ANIM_FALLBACK_MS = 60;
4223
4298
  /** 面板内轻提示(toast)的显示时长(毫秒) */
4224
4299
  const TOAST_DURATION_MS = 2e3;
4225
4300
  /** 标题栏返回按钮的目标视图:按层级返回;main 无上级,此时按钮用于进入设置页 */
@@ -4320,11 +4395,18 @@ var PageUseLauncherElement = class extends LitElement {
4320
4395
  fabFromWidth = null;
4321
4396
  /** 进行中宽度过渡的结束回调注销函数;过渡中再次切换时先注销,避免旧回调提前清除宽度 */
4322
4397
  fabWidthCleanup = null;
4398
+ /** 本次入口手势是否已判定为拖动。指针捕获会把手势结束后浏览器补发的 click 重定向到入口,该 click 不是点击意图,不得展开面板。 */
4399
+ fabDragged = false;
4323
4400
  /**
4324
- * 本次入口手势是否已判定为拖动。
4325
- * 指针捕获会把手势结束后浏览器补发的 click 重定向到入口,该 click 不是点击意图,不得展开面板。
4401
+ * 移动端面板的纵向位移(px,0 为贴底原位)。跟手期间由指针事件直写样式,不进入响应式状态:
4402
+ * 每帧触发模板重渲染会带来不必要的开销,且重渲染写 style 属性会覆盖内联位移。
4403
+ * 也不写入设置,位移不持久化。
4326
4404
  */
4327
- fabDragged = false;
4405
+ sheetOffsetY = 0;
4406
+ /** 本次下拉手势的纵向位移采样,用于松手判定与速度计算 */
4407
+ sheetSamples = [];
4408
+ /** 进行中的面板位移动效的取消函数;调用后等待中的收起流程会中止 */
4409
+ sheetAnimCancel = null;
4328
4410
  cleanups = [];
4329
4411
  /** 生效的面板布局:未声明或取值非法时按桌面端处理,既有接入方的行为不变 */
4330
4412
  get isMobileLayout() {
@@ -4365,6 +4447,9 @@ var PageUseLauncherElement = class extends LitElement {
4365
4447
  onTap: (target) => {
4366
4448
  if (target?.closest?.(".title")) this.onTitleTap();
4367
4449
  },
4450
+ onDragStart: () => this.beginSheetGesture(),
4451
+ onMove: (dx, dy) => this.onSheetDragMove(dx, dy),
4452
+ onEnd: ({ cancelled }) => this.onSheetDragEnd(cancelled),
4368
4453
  setPos: ({ x, y }) => {
4369
4454
  if (this.isMobileLayout) return;
4370
4455
  const el = this.panelEl;
@@ -4403,6 +4488,7 @@ var PageUseLauncherElement = class extends LitElement {
4403
4488
  this.unregisterPanelName?.();
4404
4489
  this.unregisterPanelName = null;
4405
4490
  stopPreview();
4491
+ this.cancelSheetAnimation();
4406
4492
  window.removeEventListener("resize", this.onResize);
4407
4493
  if (this.toastTimer) clearTimeout(this.toastTimer);
4408
4494
  this.toastTimer = null;
@@ -4593,6 +4679,7 @@ var PageUseLauncherElement = class extends LitElement {
4593
4679
  }
4594
4680
  this.measureFab();
4595
4681
  this.resolvePanelAnchor();
4682
+ this.cancelSheetAnimation();
4596
4683
  this.open = true;
4597
4684
  this.requestUpdate();
4598
4685
  };
@@ -4601,6 +4688,7 @@ var PageUseLauncherElement = class extends LitElement {
4601
4688
  await this.updateComplete;
4602
4689
  this.measureFab();
4603
4690
  this.resolvePanelAnchor();
4691
+ this.cancelSheetAnimation();
4604
4692
  this.open = true;
4605
4693
  this.requestUpdate();
4606
4694
  }
@@ -4645,13 +4733,125 @@ var PageUseLauncherElement = class extends LitElement {
4645
4733
  pageUseHistory.clear();
4646
4734
  this.showToast(count ? `已清空 ${count} 条历史指令` : "暂无历史指令");
4647
4735
  }
4736
+ /**
4737
+ * 收起面板为浮动入口。移动端先向下滑出视口再隐藏,滑出期间面板不拦截页面点击——
4738
+ * 「执行后自动收起」时页面上紧接着就是 agent 的操作,动画不能挡住它。
4739
+ * 系统关闭动态效果(过渡时长为 0)时直接隐藏,不做动效。
4740
+ */
4648
4741
  async collapse() {
4649
4742
  stopPreview();
4743
+ const el = this.panelEl;
4744
+ if (this.isMobileLayout && el && !this.sheetMotionDisabled(el)) {
4745
+ el.style.pointerEvents = "none";
4746
+ const remaining = Math.max(0, el.offsetHeight - this.sheetOffsetY);
4747
+ const completed = await this.sheetTransition(el, el.offsetHeight, sheetExitDuration(remaining));
4748
+ el.style.pointerEvents = "";
4749
+ if (!completed) return;
4750
+ }
4650
4751
  this.open = false;
4651
4752
  this.requestUpdate();
4652
4753
  await this.updateComplete;
4653
4754
  this.measureFab();
4654
4755
  this.fabDrag.reclamp();
4756
+ if (el) this.resetSheetStyles(el);
4757
+ }
4758
+ /** 面板过渡被禁用时为 true:系统「减少动态效果」或样式未生效,此时直接切换状态 */
4759
+ sheetMotionDisabled(el) {
4760
+ return parseFloat(getComputedStyle(el).transitionDuration) === 0;
4761
+ }
4762
+ /** 写入面板纵向位移;0 表示回到贴底原位 */
4763
+ setSheetOffset(el, offsetY) {
4764
+ this.sheetOffsetY = offsetY;
4765
+ el.style.transform = offsetY ? `translateY(${offsetY}px)` : "";
4766
+ }
4767
+ /** 清除位移与内联过渡:先关过渡再清位移,避免清除动作本身被过渡动画化 */
4768
+ resetSheetStyles(el) {
4769
+ el.style.transition = "none";
4770
+ this.setSheetOffset(el, 0);
4771
+ el.style.transition = "";
4772
+ }
4773
+ /** 取消进行中的位移动效并让面板回到原位;等待中的收起流程因取消而中止 */
4774
+ cancelSheetAnimation() {
4775
+ const cancel = this.sheetAnimCancel;
4776
+ this.sheetAnimCancel = null;
4777
+ cancel?.();
4778
+ const el = this.panelEl;
4779
+ if (el && this.sheetOffsetY) this.resetSheetStyles(el);
4780
+ }
4781
+ /**
4782
+ * 把面板位移过渡到目标值,返回是否走到终点(被 cancelSheetAnimation 取消时为 false)。
4783
+ * 过渡事件缺失(元素被隐藏、标签页切到后台)时由定时器兜底结束,面板不停在半途。
4784
+ */
4785
+ sheetTransition(el, target, duration) {
4786
+ return new Promise((resolve) => {
4787
+ let settled = false;
4788
+ let timer;
4789
+ const finish = (completed) => {
4790
+ if (settled) return;
4791
+ settled = true;
4792
+ el.removeEventListener("transitionend", onEnd);
4793
+ el.removeEventListener("transitioncancel", onCancel);
4794
+ if (timer !== void 0) clearTimeout(timer);
4795
+ if (this.sheetAnimCancel === cancel) this.sheetAnimCancel = null;
4796
+ resolve(completed);
4797
+ };
4798
+ const cancel = () => finish(false);
4799
+ const onEnd = (event) => {
4800
+ if (event.propertyName === "transform") finish(true);
4801
+ };
4802
+ const onCancel = (event) => {
4803
+ if (event.propertyName === "transform") finish(false);
4804
+ };
4805
+ timer = setTimeout(() => finish(true), duration + SHEET_ANIM_FALLBACK_MS);
4806
+ this.sheetAnimCancel = cancel;
4807
+ el.addEventListener("transitionend", onEnd);
4808
+ el.addEventListener("transitioncancel", onCancel);
4809
+ el.style.transition = `transform ${duration}ms ${SHEET_EASING}`;
4810
+ el.style.transform = `translateY(${target}px)`;
4811
+ });
4812
+ }
4813
+ /** 下拉手势开始:终止进行中的动效,并关闭过渡让面板直接跟手 */
4814
+ beginSheetGesture() {
4815
+ if (!this.isMobileLayout) return;
4816
+ this.cancelSheetAnimation();
4817
+ this.sheetSamples = [];
4818
+ const el = this.panelEl;
4819
+ if (el) el.style.transition = "none";
4820
+ }
4821
+ /** 跟手位移:只认纵向占优的向下拖动;上滑与横向拖动不移动面板(面板没有第二档高度可展开) */
4822
+ onSheetDragMove(dx, dy) {
4823
+ if (!this.isMobileLayout) return;
4824
+ const el = this.panelEl;
4825
+ if (!el) return;
4826
+ const offsetY = dy > 0 && Math.abs(dy) > Math.abs(dx) ? dy : 0;
4827
+ this.sheetSamples.push({
4828
+ t: performance.now(),
4829
+ dy: offsetY
4830
+ });
4831
+ this.setSheetOffset(el, offsetY);
4832
+ }
4833
+ /** 松手:按位移或速度判定收起,否则回弹归位 */
4834
+ onSheetDragEnd(cancelled) {
4835
+ if (!this.isMobileLayout) return;
4836
+ const el = this.panelEl;
4837
+ const samples = this.sheetSamples;
4838
+ this.sheetSamples = [];
4839
+ if (!el) return;
4840
+ if (decideSheetRelease(samples, {
4841
+ panelHeight: el.offsetHeight,
4842
+ cancelled
4843
+ }) === "dismiss") {
4844
+ this.collapse();
4845
+ return;
4846
+ }
4847
+ if (!this.sheetOffsetY) return;
4848
+ if (this.sheetMotionDisabled(el)) {
4849
+ this.resetSheetStyles(el);
4850
+ return;
4851
+ }
4852
+ this.sheetTransition(el, 0, 180).then((completed) => {
4853
+ if (completed) this.resetSheetStyles(el);
4854
+ });
4655
4855
  }
4656
4856
  /** tourStyle:快捷指令携带的讲解风格;输入框提交时不传,按面板设置与宿主默认 */
4657
4857
  async submit(tourStyle) {
@@ -5306,6 +5506,7 @@ var PageUseLauncherElement = class extends LitElement {
5306
5506
  style=${this.open ? this.panelStyle(settings) : ""}
5307
5507
  >
5308
5508
  <header class="head" @pointerdown=${this.panelDrag.onPointerDown}>
5509
+ ${this.isMobileLayout ? html`<span class="grabber" aria-hidden="true"></span>` : nothing}
5309
5510
  <span class="dot ${state.status}" title=${STATUS_LABELS[state.status] || state.status}></span>
5310
5511
  <span class="title">${title}</span>
5311
5512
  <span class="status">
package/dist/vue.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as DEFAULT_TOUR_MAX_TAB_SWITCHES, A as PageUseGlobal, B as MountPageUseUIOptions, C as getElapsedSeconds, Ct as PageUseTaskResult, D as pageUseStore, E as isRunning, F as PAGE_USE_TOOL_NAME, G as PageUseLauncherElement, H as mountPageUseUI, I as PageUseCommand, J as createPageUse, K as PageUseLauncherLayout, L as formatPageUseResultForModel, M as showPageUseLauncher, N as PAGE_USE_COMMAND_TYPE, O as ReadonlyStore, P as PAGE_USE_TOOL, Q as DEFAULT_STORAGE_KEY_PREFIX, R as isPageUseCommand, S as clearPageUseLog, St as PageUseStepLog, T as isPageUseConfigured, Tt as PageUseTaskStatus, U as PAGE_USE_LAUNCHER_TAG, V as definePageUseElements, W as PageUseLauncherConfig, X as DEFAULT_MODEL, Y as DEFAULT_MAX_STEPS, Z as DEFAULT_SESSION_HEADER, _ as pageUseSettings, _t as PageUseMenuNode, a as PAGE_USE_ROBOT_ICON_SVG, at as normalizeOptions, b as PageUseQuestion, bt as PageUseRunOptions, c as PageUseCustomPreset, ct as PageUseTtsSpeakOptions, d as pageUsePresets, dt as PageUseTourStyle, et as NormalizedPageUseOptions, f as PageUseHistoryEntry, ft as TOUR_STYLE_TRAINER, g as PageUseSettings, gt as PageUseErrorCode, h as PageUsePoint, ht as pageUseCapability, i as PageUseGlowElement, it as PageUseTourOptions, j as hidePageUseLauncher, k as PAGE_USE_GLOBAL_KEY, l as PageUsePresetSaveResult, lt as PageUseTtsVoice, m as DEFAULT_PAGE_USE_SETTINGS, mt as PageUseCapability, n as SIMULATOR_MASK_ID, nt as PageUseOptions, o as PAGE_USE_STATIC_PRESETS, ot as readLauncherSwitch, p as pageUseHistory, pt as TOUR_STYLE_USER, q as PageUseHandle, r as PAGE_USE_GLOW_TAG, rt as PageUseRouterMode, s as buildMenuPresets, st as PageUseTtsEngine, t as PAGE_USE_MASK_COLORS, tt as PageUseLLMOptions, u as PageUsePresetState, ut as DEFAULT_TOUR_STYLES, v as BROWSER_ENGINE_ID, vt as PageUsePreset, w as getPageUseConfig, wt as PageUseTaskSource, x as PageUseState, xt as PageUseSnapshot, y as browserTtsEngine, yt as PageUseProgressEvent, z as runPageUseTool } from "./index-BACVE8Ig.mjs";
1
+ import { $ as DEFAULT_TOUR_MAX_TAB_SWITCHES, A as PageUseGlobal, B as MountPageUseUIOptions, C as getElapsedSeconds, Ct as PageUseTaskResult, D as pageUseStore, E as isRunning, F as PAGE_USE_TOOL_NAME, G as PageUseLauncherElement, H as mountPageUseUI, I as PageUseCommand, J as createPageUse, K as PageUseLauncherLayout, L as formatPageUseResultForModel, M as showPageUseLauncher, N as PAGE_USE_COMMAND_TYPE, O as ReadonlyStore, P as PAGE_USE_TOOL, Q as DEFAULT_STORAGE_KEY_PREFIX, R as isPageUseCommand, S as clearPageUseLog, St as PageUseStepLog, T as isPageUseConfigured, Tt as PageUseTaskStatus, U as PAGE_USE_LAUNCHER_TAG, V as definePageUseElements, W as PageUseLauncherConfig, X as DEFAULT_MODEL, Y as DEFAULT_MAX_STEPS, Z as DEFAULT_SESSION_HEADER, _ as pageUseSettings, _t as PageUseMenuNode, a as PAGE_USE_ROBOT_ICON_SVG, at as normalizeOptions, b as PageUseQuestion, bt as PageUseRunOptions, c as PageUseCustomPreset, ct as PageUseTtsSpeakOptions, d as pageUsePresets, dt as PageUseTourStyle, et as NormalizedPageUseOptions, f as PageUseHistoryEntry, ft as TOUR_STYLE_TRAINER, g as PageUseSettings, gt as PageUseErrorCode, h as PageUsePoint, ht as pageUseCapability, i as PageUseGlowElement, it as PageUseTourOptions, j as hidePageUseLauncher, k as PAGE_USE_GLOBAL_KEY, l as PageUsePresetSaveResult, lt as PageUseTtsVoice, m as DEFAULT_PAGE_USE_SETTINGS, mt as PageUseCapability, n as SIMULATOR_MASK_ID, nt as PageUseOptions, o as PAGE_USE_STATIC_PRESETS, ot as readLauncherSwitch, p as pageUseHistory, pt as TOUR_STYLE_USER, q as PageUseHandle, r as PAGE_USE_GLOW_TAG, rt as PageUseRouterMode, s as buildMenuPresets, st as PageUseTtsEngine, t as PAGE_USE_MASK_COLORS, tt as PageUseLLMOptions, u as PageUsePresetState, ut as DEFAULT_TOUR_STYLES, v as BROWSER_ENGINE_ID, vt as PageUsePreset, w as getPageUseConfig, wt as PageUseTaskSource, x as PageUseState, xt as PageUseSnapshot, y as browserTtsEngine, yt as PageUseProgressEvent, z as runPageUseTool } from "./index-DAwlbs2a.mjs";
2
2
  import { PropType, ShallowRef } from "vue";
3
3
  import { Router } from "vue-router";
4
4
  //#region src/vue.d.ts
package/dist/vue.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { A as pageUseSettings, B as BROWSER_ENGINE_ID, C as getPageUseConfig, D as pageUsePresets, E as pageUseStore, F as DEFAULT_TOUR_MAX_TAB_SWITCHES, H as DEFAULT_TOUR_STYLES, I as normalizeOptions, L as readLauncherSwitch, M as DEFAULT_MODEL, N as DEFAULT_SESSION_HEADER, O as pageUseHistory, P as DEFAULT_STORAGE_KEY_PREFIX, R as PAGE_USE_MASK_COLORS, S as getElapsedSeconds, T as isRunning, U as TOUR_STYLE_TRAINER, V as browserTtsEngine, W as TOUR_STYLE_USER, _ as runPageUseTool, a as PAGE_USE_STATIC_PRESETS, b as pageUseCapability, c as PAGE_USE_GLOW_TAG, d as PAGE_USE_GLOBAL_KEY, f as PAGE_USE_COMMAND_TYPE, g as isPageUseCommand, h as formatPageUseResultForModel, i as PageUseLauncherElement, j as DEFAULT_MAX_STEPS, k as DEFAULT_PAGE_USE_SETTINGS, l as PageUseGlowElement, m as PAGE_USE_TOOL_NAME, n as mountPageUseUI, o as buildMenuPresets, p as PAGE_USE_TOOL, r as PAGE_USE_LAUNCHER_TAG, s as PAGE_USE_ROBOT_ICON_SVG, t as definePageUseElements, u as createPageUse, v as hidePageUseLauncher, w as isPageUseConfigured, x as clearPageUseLog, y as showPageUseLauncher, z as SIMULATOR_MASK_ID } from "./src-MjVXh_cW.mjs";
1
+ import { A as pageUseSettings, B as BROWSER_ENGINE_ID, C as getPageUseConfig, D as pageUsePresets, E as pageUseStore, F as DEFAULT_TOUR_MAX_TAB_SWITCHES, H as DEFAULT_TOUR_STYLES, I as normalizeOptions, L as readLauncherSwitch, M as DEFAULT_MODEL, N as DEFAULT_SESSION_HEADER, O as pageUseHistory, P as DEFAULT_STORAGE_KEY_PREFIX, R as PAGE_USE_MASK_COLORS, S as getElapsedSeconds, T as isRunning, U as TOUR_STYLE_TRAINER, V as browserTtsEngine, W as TOUR_STYLE_USER, _ as runPageUseTool, a as PAGE_USE_STATIC_PRESETS, b as pageUseCapability, c as PAGE_USE_GLOW_TAG, d as PAGE_USE_GLOBAL_KEY, f as PAGE_USE_COMMAND_TYPE, g as isPageUseCommand, h as formatPageUseResultForModel, i as PageUseLauncherElement, j as DEFAULT_MAX_STEPS, k as DEFAULT_PAGE_USE_SETTINGS, l as PageUseGlowElement, m as PAGE_USE_TOOL_NAME, n as mountPageUseUI, o as buildMenuPresets, p as PAGE_USE_TOOL, r as PAGE_USE_LAUNCHER_TAG, s as PAGE_USE_ROBOT_ICON_SVG, t as definePageUseElements, u as createPageUse, v as hidePageUseLauncher, w as isPageUseConfigured, x as clearPageUseLog, y as showPageUseLauncher, z as SIMULATOR_MASK_ID } from "./src-nVu9CCnz.mjs";
2
2
  import { defineComponent, inject, onBeforeUnmount, onScopeDispose, shallowRef } from "vue";
3
3
  import { routerKey } from "vue-router";
4
4
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tanzerfe/page-use",
3
3
  "private": false,
4
- "version": "0.0.9",
4
+ "version": "0.0.10",
5
5
  "description": "基于 page-agent 的页面操作智能体:自然语言指令驱动页面点击与输入,框架无关,附 Web Component 调试面板与 Vue 适配层",
6
6
  "type": "module",
7
7
  "main": "./dist/index.mjs",