clickgo 6.3.0 → 6.4.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.
@@ -7076,7 +7076,7 @@ SVG 内容或 URL 地址。
7076
7076
 
7077
7077
  `(event: ISwitchChangeEvent) => void`
7078
7078
 
7079
- 值改变时触发。
7079
+ 值切换前触发,可调用 `event.preventDefault()` 阻止本次切换。`event.detail.value` 是切换前的当前值;未阻止时,随后更新状态并触发 `update:modelValue`。需要根据新状态执行重绘等操作时,应监听双向绑定的值,不要在此事件中读取尚未更新的值。
7080
7080
 
7081
7081
  ### 样式
7082
7082
 
@@ -7092,6 +7092,7 @@ SVG 内容或 URL 地址。
7092
7092
  <switch v-model="val"></switch>
7093
7093
  ```
7094
7094
 
7095
+
7095
7096
  ## tab
7096
7097
  ---
7097
7098
 
@@ -8710,12 +8711,15 @@ TUMS 监控组件。
8710
8711
 
8711
8712
  使用 iframe 元素,填满容器空间。无边框显示。
8712
8713
 
8714
+ 拖动或调整窗体大小时,会临时遮住网页以保持拖拽操作连续;结束后恢复网页交互。
8715
+
8713
8716
  ### 示例
8714
8717
 
8715
8718
  ```xml
8716
8719
  <web :src="pageUrl"></web>
8717
8720
  ```
8718
8721
 
8722
+
8719
8723
  ## xterm
8720
8724
  ---
8721
8725
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clickgo",
3
- "version": "6.3.0",
3
+ "version": "6.4.0",
4
4
  "description": "Background interface, software interface, mobile phone APP interface operation library.",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -0,0 +1,96 @@
1
+ // Run: node --experimental-vm-modules test/web-drag-mask.mjs
2
+ import assert from 'node:assert/strict';
3
+ import { readFile } from 'node:fs/promises';
4
+ import { SourceTextModule, SyntheticModule } from 'node:vm';
5
+ import { JSDOM } from 'jsdom';
6
+ import ts from 'typescript';
7
+
8
+ const dom = new JSDOM('<!doctype html><html><head></head><body></body></html>');
9
+ for (const name of ['window', 'document', 'Element', 'SVGElement', 'Node', 'HTMLElement']) {
10
+ globalThis[name] = dom.window[name];
11
+ }
12
+ globalThis.getComputedStyle = dom.window.getComputedStyle.bind(dom.window);
13
+ const { createApp, compile, reactive, nextTick } = await import('vue');
14
+ const pointer = await import('@litert/pointer');
15
+ const state = reactive({ move: false });
16
+ const clickgo = new SyntheticModule(['control', 'dom'], function() {
17
+ this.setExport('control', { AbstractControl: class {} });
18
+ this.setExport('dom', { is: state });
19
+ });
20
+ const source = await readFile(new URL('../dist/sources/control/web/code.ts', import.meta.url), 'utf8');
21
+ const web = new SourceTextModule(ts.transpileModule(source, {
22
+ compilerOptions: { target: ts.ScriptTarget.ES2022, module: ts.ModuleKind.ESNext },
23
+ }).outputText);
24
+ await web.link(() => clickgo);
25
+ await web.evaluate();
26
+ const control = new web.namespace.default();
27
+
28
+ // Exercise the actual launcher hooks with the installed Pointer library.
29
+ const launcher = await readFile(new URL('../dist/clickgo.ts', import.meta.url), 'utf8');
30
+ const hookSource = launcher.match(/ modules\.pointer\.addMoveHook\('down',[\s\S]*? modules\.pointer\.addMoveHook\('up',[\s\S]*? \}\);/)[0];
31
+ const hooks = new SourceTextModule(`import { pointer, is } from 'bridge';
32
+ const modules = { pointer }; const lDom = { is }; ${hookSource}`);
33
+ const bridge = new SyntheticModule(['pointer', 'is'], function() {
34
+ this.setExport('pointer', pointer);
35
+ this.setExport('is', state);
36
+ });
37
+ await hooks.link(() => bridge);
38
+ await hooks.evaluate();
39
+
40
+ const template = await readFile(new URL('../dist/sources/control/web/layout.html', import.meta.url), 'utf8');
41
+ const host = document.createElement('div');
42
+ document.body.append(host);
43
+ const app = createApp({
44
+ render: compile(template),
45
+ data: () => ({ src: 'about:blank' }),
46
+ computed: { showMask: () => control.showMask },
47
+ });
48
+ app.mount(host);
49
+ const iframe = host.querySelector('iframe');
50
+ const mask = host.querySelector('.mask');
51
+ assert.equal(iframe.getAttribute('src'), 'about:blank');
52
+ assert.equal(mask.style.display, 'none');
53
+
54
+ function event(type, x, y) {
55
+ const e = new dom.window.Event(type, { bubbles: true, cancelable: true });
56
+ Object.assign(e, { clientX: x, clientY: y, pointerId: 1, pointerType: 'mouse', button: 0 });
57
+ return e;
58
+ }
59
+
60
+ for (const operation of ['move', 'resize']) {
61
+ for (const finish of ['pointerup', 'pointercancel']) {
62
+ let updates = 0;
63
+ const handle = document.createElement('div');
64
+ document.body.append(handle);
65
+ handle.addEventListener('pointerdown', e => {
66
+ if (operation === 'resize') {
67
+ pointer.resize(e, {
68
+ border: 'rb', objectLeft: 0, objectTop: 0,
69
+ objectWidth: 400, objectHeight: 300,
70
+ move: () => { ++updates; },
71
+ });
72
+ }
73
+ else {
74
+ pointer.move(e, { move: () => { ++updates; } });
75
+ }
76
+ });
77
+ handle.dispatchEvent(event('pointerdown', 400, 300));
78
+ await nextTick();
79
+ assert.equal(state.move, true);
80
+ assert.notEqual(mask.style.display, 'none');
81
+ mask.dispatchEvent(event('pointermove', 350, 250));
82
+ mask.dispatchEvent(event('pointermove', 320, 230));
83
+ assert.equal(updates, 2);
84
+ mask.dispatchEvent(event(finish, 320, 230));
85
+ await nextTick();
86
+ assert.equal(state.move, false);
87
+ assert.equal(mask.style.display, 'none');
88
+ mask.dispatchEvent(event('pointermove', 300, 200));
89
+ assert.equal(updates, 2);
90
+ assert.equal(host.querySelector('iframe'), iframe);
91
+ handle.remove();
92
+ }
93
+ }
94
+ app.unmount();
95
+ dom.window.close();
96
+ console.log('WEB drag/resize mask, pointerup/cancel cleanup and iframe preservation checks passed.');