@ptahjs/dnd 0.1.2 → 0.1.3

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.
Files changed (2) hide show
  1. package/dist/dnd.es.js +1277 -2550
  2. package/package.json +4 -6
package/dist/dnd.es.js CHANGED
@@ -1,6 +1,6 @@
1
- (function(){try{const elementStyle=document.createElement('style');elementStyle.appendChild(document.createTextNode("/* 控制点 */\n.draggable-dot-wrap {\n position: absolute;\n inset: 0;\n pointer-events: none;\n z-index: 1;\n box-sizing: border-box;\n}\n\n.draggable-dot {\n display: block;\n position: absolute;\n z-index: 2;\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: #3a7afe;\n transform: translate(-50%, -50%);\n pointer-events: auto;\n}\n\n.draggable-dot[data-pos=\"tl\"] {\n left: 0%;\n top: 0%;\n cursor: nw-resize;\n}\n\n.draggable-dot[data-pos=\"tm\"] {\n left: 50%;\n top: 0%;\n width: 16px;\n height: 8px;\n border-radius: 8px;\n cursor: n-resize;\n}\n\n.draggable-dot[data-pos=\"tr\"] {\n top: 0%;\n right: 0%;\n transform: translate(50%, -50%);\n cursor: ne-resize;\n}\n\n/* right */\n.draggable-dot[data-pos=\"rm\"] {\n top: 50%;\n right: 0%;\n width: 8px;\n height: 16px;\n border-radius: 8px;\n transform: translate(50%, -50%);\n cursor: e-resize;\n}\n\n/* 下 */\n.draggable-dot[data-pos=\"br\"] {\n right: 0%;\n bottom: 0%;\n transform: translate(50%, 50%);\n cursor: se-resize;\n}\n\n.draggable-dot[data-pos=\"bm\"] {\n left: 50%;\n bottom: 0%;\n width: 16px;\n height: 8px;\n border-radius: 8px;\n transform: translate(-50%, 50%);\n cursor: s-resize;\n}\n\n.draggable-dot[data-pos=\"bl\"] {\n left: 0%;\n bottom: 0%;\n transform: translate(-50%, 50%);\n cursor: sw-resize;\n}\n\n/* 左 */\n.draggable-dot[data-pos=\"lm\"] {\n left: 0%;\n top: 50%;\n width: 8px;\n height: 16px;\n border-radius: 8px;\n cursor: w-resize;\n}\n\n/* 旋转 */\n.draggable-rotate {\n position: absolute;\n top: 0;\n left: 50%;\n transform: translate(-50%, -200%);\n z-index: 2;\n cursor: grab;\n pointer-events: auto;\n}\n\n.draggable-rotate::after {\n content: \"\";\n width: 16px;\n height: 16px;\n display: block;\n background: center/contain no-repeat\n url(\"data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%201024%201024%22%3E%3Cpath%20fill%3D%22%233a7afe%22%20d%3D%22M784.512%20230.272v-50.56a32%2032%200%201%201%2064%200v149.056a32%2032%200%200%201-32%2032H667.52a32%2032%200%201%201%200-64h92.992A320%20320%200%201%200%20524.8%20833.152a320%20320%200%200%200%20320-320h64a384%20384%200%200%201-384%20384%20384%20384%200%200%201-384-384%20384%20384%200%200%201%20643.712-282.88z%22/%3E%3C/svg%3E\");\n}\n.draggable-markline-x,\n.draggable-markline-y {\n position: absolute;\n left: 0;\n top: 0;\n display: none;\n z-index: 9999;\n background-color: #3a7afe;\n}\n\n.draggable-markline-x {\n width: 1px;\n height: 100%;\n}\n\n.draggable-markline-y {\n width: 100%;\n height: 1px;\n}\n.dnd-mirror {\n position: fixed;\n left: 0px;\n top: 0px;\n margin: 0px;\n pointer-events: none;\n z-index: 999999;\n will-change: transform;\n transform: translate3d(0, 0, 0);\n opacity: 0.5;\n background: #fff;\n}/* 变量集中管理 */\r\n.dnd-indicator {\r\n --dnd-color: #3a7afe;\r\n --dnd-dot: 6px;\r\n --dnd-line: 2px;\r\n position: absolute;\r\n pointer-events: none;\r\n background: var(--dnd-color);\r\n display: none;\r\n}\r\n\r\n.dnd-indicator.dnd-indicator-active {\r\n display: block;\r\n}\r\n\r\n/* 合并选择器,移除多余 opacity:0 */\r\n.dnd-indicator::before,\r\n.dnd-indicator::after {\r\n content: '';\r\n position: absolute;\r\n background: var(--dnd-color);\r\n width: var(--dnd-dot);\r\n height: var(--dnd-dot);\r\n border-radius: 50%;\r\n opacity: 0;\r\n transition: opacity .15s;\r\n}\r\n\r\n.dnd-indicator-active::before,\r\n.dnd-indicator-active::after {\r\n opacity: 1;\r\n}\r\n\r\n/* 水平方向共用一套规则 */\r\n.dnd-indicator--top,\r\n.dnd-indicator--bottom {\r\n height: var(--dnd-line);\r\n width: 100%;\r\n left: 0;\r\n}\r\n\r\n.dnd-indicator--top {\r\n top: 0;\r\n}\r\n\r\n.dnd-indicator--bottom {\r\n bottom: 0;\r\n}\r\n\r\n.dnd-indicator--top::before,\r\n.dnd-indicator--bottom::before {\r\n left: -2px;\r\n}\r\n\r\n.dnd-indicator--top::after,\r\n.dnd-indicator--bottom::after {\r\n right: -2px;\r\n}\r\n\r\n.dnd-indicator--top::before,\r\n.dnd-indicator--top::after {\r\n top: -2px;\r\n}\r\n\r\n.dnd-indicator--bottom::before,\r\n.dnd-indicator--bottom::after {\r\n bottom: -2px;\r\n}\r\n\r\n/* 垂直方向共用一套规则 */\r\n.dnd-indicator--left,\r\n.dnd-indicator--right {\r\n width: var(--dnd-line);\r\n height: 100%;\r\n top: 0;\r\n}\r\n\r\n.dnd-indicator--left {\r\n left: 0;\r\n}\r\n\r\n.dnd-indicator--right {\r\n right: 0;\r\n}\r\n\r\n.dnd-indicator--left::before,\r\n.dnd-indicator--left::after {\r\n left: -2px;\r\n}\r\n\r\n.dnd-indicator--right::before,\r\n.dnd-indicator--right::after {\r\n right: -2px;\r\n}\r\n\r\n.dnd-indicator--left::before,\r\n.dnd-indicator--right::before {\r\n top: -2px;\r\n}\r\n\r\n.dnd-indicator--left::after,\r\n.dnd-indicator--right::after {\r\n bottom: -2px;\r\n}.dnd-marquee {\n position: absolute;\n background: rgba(64, 150, 255, 0.1);\n border: 1px solid rgba(64, 150, 255, 0.6);\n pointer-events: none;\n z-index: 9999;\n}\n/*$vite$:1*/"));document.head.appendChild(elementStyle)}catch(e){console.error('PtahJs Style Inject:',e)}})();import { EventDispatcher } from "@ptahjs/shared";
1
+ (function(){try{const elementStyle=document.createElement('style');elementStyle.appendChild(document.createTextNode(".draggable-dot-wrap{pointer-events:none;z-index:1;box-sizing:border-box;position:absolute;inset:0}.draggable-dot{z-index:2;pointer-events:auto;background:#3a7afe;border-radius:50%;width:10px;height:10px;display:block;position:absolute;transform:translate(-50%,-50%)}.draggable-dot[data-pos=tl]{cursor:nw-resize;top:0%;left:0%}.draggable-dot[data-pos=tm]{cursor:n-resize;border-radius:8px;width:16px;height:8px;top:0%;left:50%}.draggable-dot[data-pos=tr]{cursor:ne-resize;top:0%;right:0%;transform:translate(50%,-50%)}.draggable-dot[data-pos=rm]{cursor:e-resize;border-radius:8px;width:8px;height:16px;top:50%;right:0%;transform:translate(50%,-50%)}.draggable-dot[data-pos=br]{cursor:se-resize;bottom:0%;right:0%;transform:translate(50%,50%)}.draggable-dot[data-pos=bm]{cursor:s-resize;border-radius:8px;width:16px;height:8px;bottom:0%;left:50%;transform:translate(-50%,50%)}.draggable-dot[data-pos=bl]{cursor:sw-resize;bottom:0%;left:0%;transform:translate(-50%,50%)}.draggable-dot[data-pos=lm]{cursor:w-resize;border-radius:8px;width:8px;height:16px;top:50%;left:0%}.draggable-rotate{z-index:2;cursor:grab;pointer-events:auto;position:absolute;top:0;left:50%;transform:translate(-50%,-200%)}.draggable-rotate:after{content:\"\";background:url(data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%201024%201024%22%3E%3Cpath%20fill%3D%22%233a7afe%22%20d%3D%22M784.512%20230.272v-50.56a32%2032%200%201%201%2064%200v149.056a32%2032%200%200%201-32%2032H667.52a32%2032%200%201%201%200-64h92.992A320%20320%200%201%200%20524.8%20833.152a320%20320%200%200%200%20320-320h64a384%20384%200%200%201-384%20384%20384%20384%200%200%201-384-384%20384%20384%200%200%201%20643.712-282.88z%22/%3E%3C/svg%3E) 50%/contain no-repeat;width:16px;height:16px;display:block}.draggable-markline-x,.draggable-markline-y{z-index:9999;background-color:#3a7afe;display:none;position:absolute;top:0;left:0}.draggable-markline-x{width:1px;height:100%}.draggable-markline-y{width:100%;height:1px}.dnd-mirror{pointer-events:none;z-index:999999;will-change:transform;opacity:.5;background:#fff;margin:0;position:fixed;top:0;left:0;transform:translate(0,0)}.dnd-indicator{--dnd-color:#3a7afe;--dnd-dot:6px;--dnd-line:2px;pointer-events:none;background:var(--dnd-color);display:none;position:absolute}.dnd-indicator.dnd-indicator-active{display:block}.dnd-indicator:before,.dnd-indicator:after{content:\"\";background:var(--dnd-color);width:var(--dnd-dot);height:var(--dnd-dot);opacity:0;border-radius:50%;transition:opacity .15s;position:absolute}.dnd-indicator-active:before,.dnd-indicator-active:after{opacity:1}.dnd-indicator--top,.dnd-indicator--bottom{height:var(--dnd-line);width:100%;left:0}.dnd-indicator--top{top:0}.dnd-indicator--bottom{bottom:0}.dnd-indicator--top:before,.dnd-indicator--bottom:before{left:-2px}.dnd-indicator--top:after,.dnd-indicator--bottom:after{right:-2px}.dnd-indicator--top:before,.dnd-indicator--top:after{top:-2px}.dnd-indicator--bottom:before,.dnd-indicator--bottom:after{bottom:-2px}.dnd-indicator--left,.dnd-indicator--right{width:var(--dnd-line);height:100%;top:0}.dnd-indicator--left{left:0}.dnd-indicator--right{right:0}.dnd-indicator--left:before,.dnd-indicator--left:after{left:-2px}.dnd-indicator--right:before,.dnd-indicator--right:after{right:-2px}.dnd-indicator--left:before,.dnd-indicator--right:before{top:-2px}.dnd-indicator--left:after,.dnd-indicator--right:after{bottom:-2px}.dnd-marquee{pointer-events:none;z-index:9999;background:#4096ff1a;border:1px solid #4096ff99;position:absolute}\n/*$vite$:1*/"));document.head.appendChild(elementStyle)}catch(e){console.error('PtahJs Style Inject:',e)}})();import { EventDispatcher as e } from "@ptahjs/shared";
2
2
  //#region src/constant.js
3
- var ATTR = {
3
+ var t = {
4
4
  dataAttr: "data",
5
5
  copyAttr: "copy",
6
6
  dragAttr: "drag",
@@ -17,8 +17,7 @@ var ATTR = {
17
17
  resizableAttr: "resizable",
18
18
  rotatableAttr: "rotatable",
19
19
  scaleRatioAttr: "scale-ratio"
20
- };
21
- var CLASS_NAMES = {
20
+ }, n = {
22
21
  canDrop: "dnd-canDrop",
23
22
  noDrop: "dnd-noDrop",
24
23
  dragging: "dnd-dragging",
@@ -31,1683 +30,948 @@ var CLASS_NAMES = {
31
30
  indicatorBottom: "dnd-indicator--bottom",
32
31
  indicatorLeft: "dnd-indicator--left",
33
32
  marquee: "dnd-marquee"
34
- };
35
- var VERT_SPLIT = .5;
36
- var HORIZ_SPLIT = 1 / 3;
37
- var THRESHOLDS = {
33
+ }, r = .5, i = 1 / 3, a = {
38
34
  MARQUEE_MOVE: 5,
39
35
  DRAG_START: 3
40
- };
41
- var AUTO_SCROLL = {
36
+ }, o = {
42
37
  EDGE: 48,
43
38
  MIN_SPEED: 180,
44
39
  MAX_SPEED: 600,
45
40
  MIN_DT: 8,
46
41
  MAX_DT: 64,
47
42
  DEFAULT_DT: 16.67
48
- };
49
- var MARQUEE_OVERLAP_RATIO = .5;
50
- var CLAMP_TOLERANCE = .5;
43
+ }, s = .5, c = .5;
51
44
  //#endregion
52
45
  //#region src/utils/computeDropRegion.js
53
- function computeDropRegion(monitor, support) {
54
- let cacheKey;
55
- if (support instanceof Set) cacheKey = support.__regionKey ?? (support.__regionKey = Array.from(support).sort().join(","));
56
- else cacheKey = support;
57
- const fullCacheKey = `dropRegionFns_${cacheKey || "all"}`;
58
- if (monitor?.cache?.[fullCacheKey]) return monitor.cache[fullCacheKey];
59
- const getDropRect = () => {
60
- if (!monitor.currentDrop) return;
61
- return monitor.currentDropRect || void 0;
62
- };
63
- const needsVertical = !support || support === "all" || support instanceof Set && (support.has("top") || support.has("bottom"));
64
- const needsHorizontal = !support || support === "all" || support instanceof Set && (support.has("left") || support.has("right"));
65
- const fns = {
66
- isOverTop: needsVertical ? () => {
67
- const r = getDropRect();
68
- return r ? monitor.y < r.y + r.height * VERT_SPLIT : false;
69
- } : () => false,
70
- isOverBottom: needsVertical ? () => {
71
- const r = getDropRect();
72
- return r ? monitor.y > r.y + r.height * (1 - VERT_SPLIT) : false;
73
- } : () => false,
74
- isOverLeft: needsHorizontal ? () => {
75
- const r = getDropRect();
76
- return r ? monitor.x < r.x + r.width * HORIZ_SPLIT : false;
77
- } : () => false,
78
- isOverRight: needsHorizontal ? () => {
79
- const r = getDropRect();
80
- return r ? monitor.x > r.x + r.width * (1 - HORIZ_SPLIT) : false;
81
- } : () => false
46
+ function l(e, t) {
47
+ let n;
48
+ n = t instanceof Set ? t.__regionKey ??= Array.from(t).sort().join(",") : t;
49
+ let a = `dropRegionFns_${n || "all"}`;
50
+ if (e?.cache?.[a]) return e.cache[a];
51
+ let o = () => {
52
+ if (e.currentDrop) return e.currentDropRect || void 0;
53
+ }, s = !t || t === "all" || t instanceof Set && (t.has("top") || t.has("bottom")), c = !t || t === "all" || t instanceof Set && (t.has("left") || t.has("right")), l = {
54
+ isOverTop: s ? () => {
55
+ let t = o();
56
+ return t ? e.y < t.y + t.height * r : !1;
57
+ } : () => !1,
58
+ isOverBottom: s ? () => {
59
+ let t = o();
60
+ return t ? e.y > t.y + t.height * (1 - r) : !1;
61
+ } : () => !1,
62
+ isOverLeft: c ? () => {
63
+ let t = o();
64
+ return t ? e.x < t.x + t.width * i : !1;
65
+ } : () => !1,
66
+ isOverRight: c ? () => {
67
+ let t = o();
68
+ return t ? e.x > t.x + t.width * (1 - i) : !1;
69
+ } : () => !1
82
70
  };
83
- if (monitor?.cache) monitor.cache[fullCacheKey] = fns;
84
- return fns;
71
+ return e?.cache && (e.cache[a] = l), l;
85
72
  }
86
73
  //#endregion
87
74
  //#region src/utils/parseData.js
88
- /** 解析 data 属性内容(支持 JSON) */
89
- function parseData(raw) {
90
- if (raw === void 0) return;
91
- const s = String(raw).trim();
92
- if (!s) return "";
75
+ function u(e) {
76
+ if (e === void 0) return;
77
+ let t = String(e).trim();
78
+ if (!t) return "";
93
79
  try {
94
- return JSON.parse(s);
80
+ return JSON.parse(t);
95
81
  } catch {
96
- return s;
82
+ return t;
97
83
  }
98
84
  }
99
85
  //#endregion
100
86
  //#region src/utils/createPayload.js
101
- function createPayload(type, monitor) {
102
- const getDropWorldPoint = () => {
103
- const drop = monitor.currentDrop;
104
- if (!drop) return void 0;
105
- const rect = monitor.currentDropRect || drop.getBoundingClientRect();
106
- const raw = monitor.adapter.getAttr(drop, ATTR.scaleRatioAttr) ?? drop.getAttribute?.("data-scale-ratio");
107
- const n = Number(raw);
108
- const scale = Number.isFinite(n) && n > 0 ? n : 1;
109
- const left = rect.left + (drop.clientLeft || 0);
110
- const top = rect.top + (drop.clientTop || 0);
111
- const px = monitor.x - left;
112
- const py = monitor.y - top;
113
- const localPx = px + (drop.scrollLeft || 0);
114
- const localPy = py + (drop.scrollTop || 0);
87
+ function d(e, n) {
88
+ let r = () => {
89
+ let e = n.currentDrop;
90
+ if (!e) return;
91
+ let r = n.currentDropRect || e.getBoundingClientRect(), i = n.adapter.getAttr(e, t.scaleRatioAttr) ?? e.getAttribute?.("data-scale-ratio"), a = Number(i), o = Number.isFinite(a) && a > 0 ? a : 1, s = r.left + (e.clientLeft || 0), c = r.top + (e.clientTop || 0), l = n.x - s, u = n.y - c, d = l + (e.scrollLeft || 0), f = u + (e.scrollTop || 0);
115
92
  return {
116
- x: localPx / scale,
117
- y: localPy / scale,
118
- scale,
119
- px: localPx,
120
- py: localPy
93
+ x: d / o,
94
+ y: f / o,
95
+ scale: o,
96
+ px: d,
97
+ py: f
121
98
  };
122
- };
123
- const getDropData = () => {
124
- const drop = monitor.currentDrop;
125
- const cache = monitor.cache;
126
- if (!drop) {
127
- cache.dropDataEl = void 0;
128
- cache.dropDataRaw = void 0;
129
- cache.dropDataParsed = void 0;
99
+ }, i = () => {
100
+ let e = n.currentDrop, r = n.cache;
101
+ if (!e) {
102
+ r.dropDataEl = void 0, r.dropDataRaw = void 0, r.dropDataParsed = void 0;
130
103
  return;
131
104
  }
132
- const raw = monitor.adapter.getAttr(drop, ATTR.dataAttr);
133
- if (cache.dropDataEl === drop && raw === cache.dropDataRaw) return cache.dropDataParsed;
134
- cache.dropDataEl = drop;
135
- cache.dropDataRaw = raw;
136
- cache.dropDataParsed = parseData(raw);
137
- return cache.dropDataParsed;
105
+ let i = n.adapter.getAttr(e, t.dataAttr);
106
+ return r.dropDataEl === e && i === r.dropDataRaw ? r.dropDataParsed : (r.dropDataEl = e, r.dropDataRaw = i, r.dropDataParsed = u(i), r.dropDataParsed);
138
107
  };
139
- if (!monitor.cache.hitDropFn) {
140
- let lastFrameId = -1;
141
- let lastX = 0;
142
- let lastY = 0;
143
- let lastIgnore = void 0;
144
- let lastResult = void 0;
145
- monitor.cache.hitDropFn = (x, y, ignoreRoot) => {
146
- const frameId = monitor?.adapter?.frameId ?? monitor?.cache?.frameId ?? 0;
147
- if (frameId === lastFrameId && x === lastX && y === lastY && ignoreRoot === lastIgnore) return lastResult;
148
- lastFrameId = frameId;
149
- lastX = x;
150
- lastY = y;
151
- lastIgnore = ignoreRoot;
152
- const adapter = monitor.adapter;
153
- if (!adapter?.hitDrop) throw new Error("createPayload requires monitor.adapter.hitDrop");
154
- lastResult = adapter.hitDrop(x, y, monitor.namespace, ignoreRoot);
155
- return lastResult;
108
+ if (!n.cache.hitDropFn) {
109
+ let e = -1, t = 0, r = 0, i, a;
110
+ n.cache.hitDropFn = (o, s, c) => {
111
+ let l = n?.adapter?.frameId ?? n?.cache?.frameId ?? 0;
112
+ if (l === e && o === t && s === r && c === i) return a;
113
+ e = l, t = o, r = s, i = c;
114
+ let u = n.adapter;
115
+ if (!u?.hitDrop) throw Error("createPayload requires monitor.adapter.hitDrop");
116
+ return a = u.hitDrop(o, s, n.namespace, c), a;
156
117
  };
157
118
  }
158
119
  return {
159
- type,
160
- namespace: monitor.namespace,
161
- data: monitor.data,
120
+ type: e,
121
+ namespace: n.namespace,
122
+ data: n.data,
162
123
  get dropData() {
163
- return getDropData();
124
+ return i();
164
125
  },
165
126
  get dropPoint() {
166
- return getDropWorldPoint();
127
+ return r();
167
128
  },
168
- indicatorRegion: monitor.lastIndicatorRegion,
169
- isDragScope: monitor.isDragScope,
170
- isCopy: monitor.isCopy,
171
- sourceEl: monitor.sourceEl,
172
- handleEl: monitor.handleEl,
173
- originDrop: monitor.originDrop,
174
- currentDrop: monitor.currentDrop,
175
- x: monitor.x,
176
- y: monitor.y,
177
- dx: monitor.dx,
178
- dy: monitor.dy,
179
- started: monitor.started,
180
- hitDrop: monitor.cache.hitDropFn,
181
- ...computeDropRegion(monitor)
129
+ indicatorRegion: n.lastIndicatorRegion,
130
+ isDragScope: n.isDragScope,
131
+ isCopy: n.isCopy,
132
+ sourceEl: n.sourceEl,
133
+ handleEl: n.handleEl,
134
+ originDrop: n.originDrop,
135
+ currentDrop: n.currentDrop,
136
+ x: n.x,
137
+ y: n.y,
138
+ dx: n.dx,
139
+ dy: n.dy,
140
+ started: n.started,
141
+ hitDrop: n.cache.hitDropFn,
142
+ ...l(n)
182
143
  };
183
144
  }
184
145
  //#endregion
185
146
  //#region src/utils/createSession.js
186
- /**
187
- * 拖拽 session 状态(一次拖拽过程的运行时容器)
188
- *
189
- * 说明:
190
- * - session 是”短生命周期”:通常在一次 drag 开始创建/复用,结束后 reset。
191
- * - 为了兼容旧插件,这里保留了一些 legacy 字段(mirror/indicator/cache 等),
192
- * 同时新的运行时鼓励按 Measure / Compute / Commit 三阶段去组织逻辑。
193
- */
194
- function createSession(store) {
147
+ function f(e) {
195
148
  return {
196
- /** DOM adapter:由 Dnd 注入(用于命中检测、测量 rect、读写 data/caches 等) */
197
149
  adapter: void 0,
198
- /** 当前命中的 drop 容器 rect(每帧按需测量) */
199
150
  currentDropRect: void 0,
200
- /** 拖拽中止原因/标记(例如外部调用 abort、异常、系统取消等) */
201
151
  dragAbort: void 0,
202
- /** 是否处于”拖拽作用域/拖拽捕获”状态(框架内部用来控制一些分支逻辑) */
203
- isDragScope: false,
204
- /** 是否为”复制拖拽”(来自 sourceEl 的 copy=”true/false”) */
205
- isCopy: false,
206
- /** 是否处于 active(pointer down 后到 drag end 前) */
207
- active: false,
208
- /** pointerId:多指触控/PointerEvent 用于区分指针 */
152
+ isDragScope: !1,
153
+ isCopy: !1,
154
+ active: !1,
209
155
  pointerId: void 0,
210
- /** pointer down 时的起始坐标 */
211
156
  startX: 0,
212
157
  startY: 0,
213
- /** 当前指针坐标(通常来自 move 事件) */
214
158
  x: 0,
215
159
  y: 0,
216
- /** 相对起点位移:dx = x - startX, dy = y - startY */
217
160
  dx: 0,
218
161
  dy: 0,
219
- /** 是否已经”真正开始拖拽”(超过阈值后置 true) */
220
- started: false,
221
- /** 开始拖拽的阈值(像素),避免轻微抖动误触发 drag */
222
- threshold: THRESHOLDS.DRAG_START,
223
- /** 最近一次 move 的时间戳(用于节流/惯性/autoScroll 等逻辑) */
162
+ started: !1,
163
+ threshold: a.DRAG_START,
224
164
  lastMoveTs: 0,
225
- /** 被拖拽的源元素(drag source) */
226
165
  sourceEl: void 0,
227
- /** 触发拖拽的 handle(如果支持把手拖拽) */
228
166
  handleEl: void 0,
229
- /** 拖拽开始时所在的 drop(原始容器/起始落点) */
230
167
  originDrop: void 0,
231
- /** 当前命中的 drop(命中检测结果) */
232
168
  currentDrop: void 0,
233
- /** namespace:用于隔离不同拖拽域(不同画布/列表间互不影响) */
234
169
  namespace: void 0,
235
- /** data:本次拖拽携带的业务数据(payload) */
236
170
  data: void 0,
237
- /** 镜像元素(拖拽时跟随指针移动的预览) */
238
171
  mirrorEl: void 0,
239
- /** 镜像相对指针的偏移(通常用于保持抓取点一致) */
240
172
  mirrorOffsetX: 0,
241
173
  mirrorOffsetY: 0,
242
- /** 当前是否允许 drop(canDrop 计算结果,供 UI/indicator 使用) */
243
- currentAllowed: false,
244
- /** 本帧是否有变更需要在 rAF 里处理(驱动 Measure/Compute/Commit) */
245
- dirty: false,
246
- /** 上一帧坐标(用于计算本帧是否移动、速度等) */
174
+ currentAllowed: !1,
175
+ dirty: !1,
247
176
  prevX: 0,
248
177
  prevY: 0,
249
178
  cache: {
250
- /** 帧 id(自增),标识当前处于第几帧处理 */
251
179
  frameId: 0,
252
- /** drop 数据所在元素(比如 data-* 的宿主元素) */
253
180
  dropDataEl: void 0,
254
- /** drop 原始数据(字符串/对象等原始读取结果) */
255
181
  dropDataRaw: void 0,
256
- /** drop 解析后数据(结构化对象) */
257
182
  dropDataParsed: void 0,
258
- /** drop 区域函数列表/集合(用于自定义命中区域) */
259
183
  dropRegionFns: void 0,
260
- /** 命中检测函数缓存(加速 hitDrop) */
261
184
  hitDropFn: void 0,
262
- /** canDrop 的上下文对象(避免重复创建) */
263
185
  canDropCtx: void 0,
264
- /** dropRect 是否需要重新测量(drop 变化、布局变化等会置脏) */
265
- dropRectDirty: false,
266
- /** 自动滚动计划(例如方向/速度/目标容器) */
186
+ dropRectDirty: !1,
267
187
  autoScrollPlan: void 0,
268
- /** 自动滚动上次执行时间(用于节流) */
269
188
  autoScrollLastTs: 0
270
189
  },
271
- /** indicator 元素(用于显示插入线/高亮等) */
272
190
  indicatorEl: void 0,
273
- /** indicator 当前所在区域/位置描述(用于渲染插入位置等) */
274
191
  indicatorRegion: void 0,
275
192
  lastIndicatorRegion: void 0,
276
- /**
277
- * 持久化选中集(按 namespace 分组)
278
- * 注意:这里不是复制数据,而是引用 store 里的 Map,
279
- * 让多次拖拽 session 之间共享选中状态。
280
- */
281
- selectedByNs: store?.selectedByNs,
282
- /** 最近一次 drag 的时间戳(可用于双击抑制、节流等) */
193
+ selectedByNs: e?.selectedByNs,
283
194
  lastDragTs: 0,
284
- /** 是否抑制下一次 click(防止拖拽结束触发误点击) */
285
- suppressNextClick: false
195
+ suppressNextClick: !1
286
196
  };
287
197
  }
288
198
  //#endregion
289
199
  //#region src/utils/createContext.js
290
- function createContext({ dnd, session, store, frame, adapter }) {
291
- const payloadCache = /* @__PURE__ */ new Map();
292
- const payload = (type = "drag") => {
293
- if (payloadCache.has(type)) return payloadCache.get(type);
294
- const p = createPayload(type, session);
295
- payloadCache.set(type, p);
296
- return p;
297
- };
200
+ function p({ dnd: e, session: t, store: n, frame: r, adapter: i }) {
201
+ let a = /* @__PURE__ */ new Map();
298
202
  return {
299
- dnd,
300
- session,
301
- store,
302
- frame,
303
- adapter,
304
- payload,
203
+ dnd: e,
204
+ session: t,
205
+ store: n,
206
+ frame: r,
207
+ adapter: i,
208
+ payload: (e = "drag") => {
209
+ if (a.has(e)) return a.get(e);
210
+ let n = d(e, t);
211
+ return a.set(e, n), n;
212
+ },
305
213
  resetPayloadCache() {
306
- payloadCache.clear();
214
+ a.clear();
307
215
  }
308
216
  };
309
217
  }
310
218
  //#endregion
311
219
  //#region src/utils/isToggleEnabled.js
312
- function isToggleEnabled(el, attrName, defaultValue = true) {
313
- if (!el?.getAttribute) return defaultValue;
314
- const dataName = `data-${attrName}`;
315
- const v = el.getAttribute(attrName) ?? el.getAttribute(dataName);
316
- if (v === null) return defaultValue;
317
- return String(v).toLowerCase() !== "false";
220
+ function m(e, t, n = !0) {
221
+ if (!e?.getAttribute) return n;
222
+ let r = `data-${t}`, i = e.getAttribute(t) ?? e.getAttribute(r);
223
+ return i === null ? n : String(i).toLowerCase() !== "false";
318
224
  }
319
225
  //#endregion
320
226
  //#region src/utils/matchHandle.js
321
- function matchHandle(target, adapter) {
322
- const draggable = adapter?.closestDraggable?.(target) || target?.closest?.(`[${ATTR.dragAttr}], [${ATTR.dragdropAttr}]`);
323
- if (!draggable) return;
324
- const rotatable = isToggleEnabled(draggable, ATTR.rotatableAttr, true);
325
- const resizable = isToggleEnabled(draggable, ATTR.resizableAttr, true);
326
- if (rotatable && (draggable.hasAttribute(ATTR.handleRotateAttr) || Boolean(draggable.querySelector?.(`[${ATTR.handleRotateAttr}]`))) || resizable && (draggable.hasAttribute(ATTR.handleResizeAttr) || Boolean(draggable.querySelector?.(`[${ATTR.handleResizeAttr}]`)))) {
327
- const h = (rotatable ? target.closest?.(`[${ATTR.handleRotateAttr}]`) : null) || (resizable ? target.closest?.(`[${ATTR.handleResizeAttr}]`) : null);
328
- if (h && draggable.contains(h)) return h;
329
- return draggable;
330
- }
331
- if (draggable.hasAttribute(ATTR.handleAttr) || Boolean(draggable.querySelector?.(`[${ATTR.handleAttr}]`))) {
332
- const h = target.closest?.(`[${ATTR.handleAttr}]`);
333
- if (h && draggable.contains(h)) return h;
334
- return;
335
- }
336
- return draggable;
227
+ function h(e, n) {
228
+ let r = n?.closestDraggable?.(e) || e?.closest?.(`[${t.dragAttr}], [${t.dragdropAttr}]`);
229
+ if (!r) return;
230
+ let i = m(r, t.rotatableAttr, !0), a = m(r, t.resizableAttr, !0);
231
+ if (i && (r.hasAttribute(t.handleRotateAttr) || r.querySelector?.(`[${t.handleRotateAttr}]`)) || a && (r.hasAttribute(t.handleResizeAttr) || r.querySelector?.(`[${t.handleResizeAttr}]`))) {
232
+ let n = (i ? e.closest?.(`[${t.handleRotateAttr}]`) : null) || (a ? e.closest?.(`[${t.handleResizeAttr}]`) : null);
233
+ return n && r.contains(n) ? n : r;
234
+ }
235
+ if (r.hasAttribute(t.handleAttr) || r.querySelector?.(`[${t.handleAttr}]`)) {
236
+ let n = e.closest?.(`[${t.handleAttr}]`);
237
+ return n && r.contains(n) ? n : void 0;
238
+ }
239
+ return r;
337
240
  }
338
241
  //#endregion
339
242
  //#region src/utils/isHTMLElement.js
340
- function isHTMLElement(el) {
341
- return el && typeof el === "object" && el.nodeType === 1;
243
+ function g(e) {
244
+ return e && typeof e == "object" && e.nodeType === 1;
342
245
  }
343
246
  //#endregion
344
247
  //#region src/utils/isIgnoreClick.js
345
- /**
346
- * 检查元素或其祖先是否带有 ignore-click 属性
347
- * @param {Element} el - 要检查的元素
348
- * @returns {boolean} 是否应该忽略点击
349
- */
350
- function isIgnoreClick(el) {
351
- if (!isHTMLElement(el)) return false;
352
- const name = ATTR.ignoreClickAttr;
353
- const dataName = `data-${name}`;
354
- return !!(el.closest?.(`[${name}], [${dataName}]`) || el.hasAttribute?.(name) || el.hasAttribute?.(dataName));
248
+ function _(e) {
249
+ if (!g(e)) return !1;
250
+ let n = t.ignoreClickAttr, r = `data-${n}`;
251
+ return !!(e.closest?.(`[${n}], [${r}]`) || e.hasAttribute?.(n) || e.hasAttribute?.(r));
355
252
  }
356
253
  //#endregion
357
254
  //#region src/utils/scopeHelpers.js
358
- /**
359
- * drag-scope 属性名
360
- */
361
- var SCOPE_ATTR = ATTR.dragScopeAttr;
362
- /**
363
- * drag-scope 选择器(支持标准属性和 data- 前缀)
364
- */
365
- var SCOPE_SEL = `[${SCOPE_ATTR}], [data-${SCOPE_ATTR}]`;
366
- //#endregion
367
- //#region src/core/DomAdapter.js
368
- /**
369
- * DomAdapter
370
- *
371
- * Centralized DOM access + per-frame caching.
372
- */
373
- var DomAdapter = class {
374
- #frameId = 0;
375
- #rectCache = /* @__PURE__ */ new WeakMap();
376
- #nsCache = /* @__PURE__ */ new WeakMap();
255
+ var v = t.dragScopeAttr, y = `[${v}], [data-${v}]`, b = class {
256
+ #e = 0;
257
+ #t = /* @__PURE__ */ new WeakMap();
258
+ #n = /* @__PURE__ */ new WeakMap();
377
259
  get frameId() {
378
- return this.#frameId;
260
+ return this.#e;
379
261
  }
380
262
  beginFrame() {
381
- this.#frameId++;
263
+ this.#e++;
382
264
  }
383
265
  endFrame() {}
384
- resolveRoot(root) {
385
- if (!root) return;
386
- if (typeof root === "string") {
387
- const el = document.querySelector(root);
388
- return el instanceof HTMLElement ? el : void 0;
389
- }
390
- return root instanceof HTMLElement ? root : void 0;
391
- }
392
- getAttr(el, name) {
393
- return el?.getAttribute?.(name) ?? void 0;
394
- }
395
- getNamespace(el) {
396
- if (!el) return "_default";
397
- const cached = this.#nsCache.get(el);
398
- if (cached && cached.frameId === this.#frameId) return cached.ns;
399
- const ns = this.getAttr(el, ATTR.namespaceAttr) || "_default";
400
- this.#nsCache.set(el, {
401
- frameId: this.#frameId,
402
- ns
403
- });
404
- return ns;
405
- }
406
- isDrop(el) {
407
- if (!el) return false;
408
- return el.hasAttribute?.(ATTR.dropAttr) || el.hasAttribute?.(ATTR.dragdropAttr);
409
- }
410
- closestDraggable(el) {
411
- const { dragAttr, dragdropAttr } = ATTR;
412
- if (!el) return;
413
- if (el.hasAttribute(dragAttr) || el.hasAttribute(dragdropAttr)) return el;
414
- return el.closest?.(`[${dragAttr}], [${dragdropAttr}]`) || void 0;
415
- }
416
- closestDrop(el) {
417
- if (el) {
418
- const { dropAttr, dragdropAttr } = ATTR;
419
- return el.closest?.(`[${dropAttr}], [${dragdropAttr}]`) || void 0;
420
- }
421
- }
422
- closestDragScope(el) {
423
- const { dragScopeAttr } = ATTR;
424
- if (!el) return;
425
- if (el.hasAttribute(dragScopeAttr)) return el;
426
- return el.closest?.(`[${dragScopeAttr}]`) || void 0;
427
- }
428
- measureRect(el) {
429
- if (!el) return;
430
- const cached = this.#rectCache.get(el);
431
- if (cached && cached.frameId === this.#frameId) return cached.rect;
432
- const rect = el.getBoundingClientRect();
433
- this.#rectCache.set(el, {
434
- frameId: this.#frameId,
435
- rect
436
- });
437
- return rect;
438
- }
439
- /**
440
- * Hit test drop at (x,y) with namespace validation.
441
- * ignoreRoot: if provided, ignore ignoreRoot and all its descendants.
442
- */
443
- hitDrop(x, y, ns, ignoreRoot) {
444
- const el = document.elementFromPoint(x, y);
445
- if (!el) return;
446
- const targetNs = ns || "_default";
447
- let p = el;
448
- if (ignoreRoot && ignoreRoot.contains(p)) {
449
- p = ignoreRoot.parentElement ?? null;
450
- if (!p) return void 0;
451
- }
452
- while (p) {
453
- if (this.isDrop(p)) {
454
- if (this.getNamespace(p) === targetNs) return p;
266
+ resolveRoot(e) {
267
+ if (e) {
268
+ if (typeof e == "string") {
269
+ let t = document.querySelector(e);
270
+ return t instanceof HTMLElement ? t : void 0;
455
271
  }
456
- p = p.parentElement;
457
- }
272
+ return e instanceof HTMLElement ? e : void 0;
273
+ }
274
+ }
275
+ getAttr(e, t) {
276
+ return e?.getAttribute?.(t) ?? void 0;
277
+ }
278
+ getNamespace(e) {
279
+ if (!e) return "_default";
280
+ let n = this.#n.get(e);
281
+ if (n && n.frameId === this.#e) return n.ns;
282
+ let r = this.getAttr(e, t.namespaceAttr) || "_default";
283
+ return this.#n.set(e, {
284
+ frameId: this.#e,
285
+ ns: r
286
+ }), r;
287
+ }
288
+ isDrop(e) {
289
+ return e ? e.hasAttribute?.(t.dropAttr) || e.hasAttribute?.(t.dragdropAttr) : !1;
290
+ }
291
+ closestDraggable(e) {
292
+ let { dragAttr: n, dragdropAttr: r } = t;
293
+ if (e) return e.hasAttribute(n) || e.hasAttribute(r) ? e : e.closest?.(`[${n}], [${r}]`) || void 0;
294
+ }
295
+ closestDrop(e) {
296
+ if (e) {
297
+ let { dropAttr: n, dragdropAttr: r } = t;
298
+ return e.closest?.(`[${n}], [${r}]`) || void 0;
299
+ }
300
+ }
301
+ closestDragScope(e) {
302
+ let { dragScopeAttr: n } = t;
303
+ if (e) return e.hasAttribute(n) ? e : e.closest?.(`[${n}]`) || void 0;
304
+ }
305
+ measureRect(e) {
306
+ if (!e) return;
307
+ let t = this.#t.get(e);
308
+ if (t && t.frameId === this.#e) return t.rect;
309
+ let n = e.getBoundingClientRect();
310
+ return this.#t.set(e, {
311
+ frameId: this.#e,
312
+ rect: n
313
+ }), n;
314
+ }
315
+ hitDrop(e, t, n, r) {
316
+ let i = document.elementFromPoint(e, t);
317
+ if (!i) return;
318
+ let a = n || "_default", o = i;
319
+ if (!(r && r.contains(o) && (o = r.parentElement ?? null, !o))) for (; o;) {
320
+ if (this.isDrop(o) && this.getNamespace(o) === a) return o;
321
+ o = o.parentElement;
322
+ }
323
+ }
324
+ hitDropForSource(e, t, n, r) {
325
+ let i = this.hitDrop(e, t, n, r);
326
+ if (i && r && this.isDrop(r)) {
327
+ let n = this.measureRect(r);
328
+ if (n && e >= n.left && e <= n.right && t >= n.top && t <= n.bottom) return;
329
+ }
330
+ return i;
331
+ }
332
+ }, x = class {
333
+ #e = !1;
334
+ #t = !1;
335
+ #n = 0;
336
+ #r;
337
+ constructor(e) {
338
+ this.#r = typeof e == "function" ? e : () => !1;
458
339
  }
459
- /**
460
- * Hit test 加“source-as-drop”特判:
461
- * 若 sourceEl 本身是 drop 区,且指针仍在其矩形内,则不激活任何 drop(含父级)。
462
- * onMeasure 与 onPointerUp 共用此判定,避免落点判定与拖拽过程分叉。
463
- */
464
- hitDropForSource(x, y, ns, sourceEl) {
465
- const drop = this.hitDrop(x, y, ns, sourceEl);
466
- if (drop && sourceEl && this.isDrop(sourceEl)) {
467
- const r = this.measureRect(sourceEl);
468
- if (r && x >= r.left && x <= r.right && y >= r.top && y <= r.bottom) return;
469
- }
470
- return drop;
471
- }
472
- };
473
- //#endregion
474
- //#region src/core/RafScheduler.js
475
- /**
476
- * RafScheduler(rAF 调度器)
477
- * - 将同一时间段内多次 `request()` 调用合并(coalesce)为一次 requestAnimationFrame。
478
- * - 每帧回调返回 boolean:是否需要在下一帧继续执行。
479
- */
480
- var RafScheduler = class {
481
- #running = false;
482
- #pending = false;
483
- #rafId = 0;
484
- #frameCb;
485
- constructor(frameCb) {
486
- this.#frameCb = typeof frameCb === "function" ? frameCb : () => false;
487
- }
488
- /**
489
- * 发起一次调度请求:
490
- * - 标记 pending = true
491
- * - 若尚未运行,则启动 rAF 循环
492
- * - 若已在运行,则只做合并标记(下一帧会处理)
493
- */
494
340
  request() {
495
- this.#pending = true;
496
- if (this.#running) return;
497
- this.#running = true;
498
- this.#rafId = requestAnimationFrame(this.#tick);
499
- }
500
- /**
501
- * 取消调度:
502
- * - 停止运行
503
- * - 清空 pending
504
- * - 若已挂了 rAF,则取消之
505
- */
341
+ this.#t = !0, !this.#e && (this.#e = !0, this.#n = requestAnimationFrame(this.#i));
342
+ }
506
343
  cancel() {
507
- if (!this.#running) return;
508
- this.#running = false;
509
- this.#pending = false;
510
- if (this.#rafId) {
511
- cancelAnimationFrame(this.#rafId);
512
- this.#rafId = 0;
513
- }
344
+ this.#e && (this.#e = !1, this.#t = !1, this.#n &&= (cancelAnimationFrame(this.#n), 0));
514
345
  }
515
- /**
516
- * 每帧执行的 tick:
517
- * - 消耗本帧的 pending
518
- * - 执行 frameCb,并根据返回值决定是否继续下一帧
519
- * - 若本帧执行期间又有人 request(),也会继续下一帧
520
- */
521
- #tick = () => {
522
- if (!this.#running) return;
523
- this.#pending = false;
524
- let keepGoing = false;
346
+ #i = () => {
347
+ if (!this.#e) return;
348
+ this.#t = !1;
349
+ let e = !1;
525
350
  try {
526
- keepGoing = Boolean(this.#frameCb(performance.now()));
527
- } catch (err) {
528
- keepGoing = false;
529
- console.error("[RafScheduler] frame callback error:", err);
351
+ e = !!this.#r(performance.now());
352
+ } catch (t) {
353
+ e = !1, console.error("[RafScheduler] frame callback error:", t);
530
354
  }
531
- if (!this.#running) return;
532
- if (keepGoing || this.#pending) {
533
- this.#rafId = requestAnimationFrame(this.#tick);
534
- return;
355
+ if (this.#e) {
356
+ if (e || this.#t) {
357
+ this.#n = requestAnimationFrame(this.#i);
358
+ return;
359
+ }
360
+ this.#e = !1, this.#n = 0;
535
361
  }
536
- this.#running = false;
537
- this.#rafId = 0;
538
362
  };
539
- };
540
- //#endregion
541
- //#region src/core/PointerSensor.js
542
- /**
543
- * PointerSensor(指针传感器)
544
- *
545
- * 职责:
546
- * - 监听 root 上的 `pointerdown`
547
- * - 若 consumer 接受本次交互,则在全局绑定 move/up/cancel/blur 监听(会话级监听)
548
- * - 对 pointermove 做坐标去重(与上一次坐标相同则跳过),只取末点坐标;
549
- * 真正的时间合并/节流交给上层 rAF 调度
550
- */
551
- var PointerSensor = class {
552
- #root;
553
- #abort = new AbortController();
554
- #active = false;
555
- #pointerId;
556
- #lastX = 0;
557
- #lastY = 0;
558
- #onDownCb;
559
- #onMoveCb;
560
- #onUpCb;
561
- constructor({ onDown, onMove, onUp } = {}) {
562
- this.#onDownCb = typeof onDown === "function" ? onDown : void 0;
563
- this.#onMoveCb = typeof onMove === "function" ? onMove : void 0;
564
- this.#onUpCb = typeof onUp === "function" ? onUp : void 0;
565
- }
566
- /**
567
- * 设置/更换 root:
568
- * - 若更换 root,会 abort 掉旧的监听并重新绑定
569
- */
570
- setRoot(root) {
571
- if (root === this.#root) return;
572
- this.#abort.abort();
573
- this.#abort = new AbortController();
574
- this.#root = root;
575
- if (!this.#root) return;
576
- this.#root.addEventListener("pointerdown", this.#onDown, {
577
- passive: false,
578
- signal: this.#abort.signal
579
- });
363
+ }, S = class {
364
+ #e;
365
+ #t = new AbortController();
366
+ #n = !1;
367
+ #r;
368
+ #i = 0;
369
+ #a = 0;
370
+ #o;
371
+ #s;
372
+ #c;
373
+ constructor({ onDown: e, onMove: t, onUp: n } = {}) {
374
+ this.#o = typeof e == "function" ? e : void 0, this.#s = typeof t == "function" ? t : void 0, this.#c = typeof n == "function" ? n : void 0;
375
+ }
376
+ setRoot(e) {
377
+ e !== this.#e && (this.#t.abort(), this.#t = new AbortController(), this.#e = e, this.#e && this.#e.addEventListener("pointerdown", this.#l, {
378
+ passive: !1,
379
+ signal: this.#t.signal
380
+ }));
580
381
  }
581
- /**
582
- * 销毁:
583
- * - 解绑 root 监听
584
- * - 清理会话状态
585
- */
586
382
  destroy() {
587
- this.#abort.abort();
588
- this.#clearSession();
589
- this.#root = void 0;
590
- }
591
- /**
592
- * root 上的 pointerdown 处理:
593
- * - 交给 consumer 判断是否接受本次交互
594
- * - 若接受,拿到 pointerId 和 signal,并绑定全局会话监听
595
- */
596
- #onDown = (event) => {
597
- if (!this.#onDownCb || !this.#root) return;
598
- const result = this.#onDownCb(event);
599
- if (!result?.accepted || !result?.signal || !Number.isFinite(result.pointerId)) return;
600
- this.#active = true;
601
- this.#pointerId = result.pointerId;
602
- this.#lastX = event.clientX;
603
- this.#lastY = event.clientY;
604
- this.#bindSession(result.signal);
383
+ this.#t.abort(), this.#d(), this.#e = void 0;
384
+ }
385
+ #l = (e) => {
386
+ if (!this.#o || !this.#e) return;
387
+ let t = this.#o(e);
388
+ !t?.accepted || !t?.signal || !Number.isFinite(t.pointerId) || (this.#n = !0, this.#r = t.pointerId, this.#i = e.clientX, this.#a = e.clientY, this.#u(t.signal));
605
389
  };
606
- /**
607
- * 绑定会话期的全局监听:
608
- * - 这些监听使用 consumer 提供的 signal 统一管理生命周期
609
- * - consumer abort 时会自动移除(无需本类手动 removeEventListener)
610
- */
611
- #bindSession(signal) {
612
- globalThis.addEventListener("pointermove", this.#onMove, {
613
- passive: false,
614
- signal
615
- });
616
- globalThis.addEventListener("pointerup", this.#onUp, {
617
- passive: false,
618
- signal
619
- });
620
- globalThis.addEventListener("pointercancel", this.#onUp, {
621
- passive: false,
622
- signal
623
- });
624
- globalThis.addEventListener("blur", this.#onUp, {
625
- passive: false,
626
- signal
390
+ #u(e) {
391
+ globalThis.addEventListener("pointermove", this.#f, {
392
+ passive: !1,
393
+ signal: e
394
+ }), globalThis.addEventListener("pointerup", this.#p, {
395
+ passive: !1,
396
+ signal: e
397
+ }), globalThis.addEventListener("pointercancel", this.#p, {
398
+ passive: !1,
399
+ signal: e
400
+ }), globalThis.addEventListener("blur", this.#p, {
401
+ passive: !1,
402
+ signal: e
627
403
  });
628
404
  }
629
- /**
630
- * 清理当前会话状态(不负责解绑全局监听:由 signal 控制)
631
- */
632
- #clearSession() {
633
- this.#active = false;
634
- this.#pointerId = void 0;
635
- }
636
- /**
637
- * 全局 pointermove:
638
- * - 只处理当前会话的 pointerId
639
- * - 使用 coalesced events(若支持)取最后一个点作为最终坐标
640
- * - 节流:在 throttle 时间窗内直接忽略
641
- * - 去重:坐标未变化则忽略
642
- */
643
- #onMove = (event) => {
644
- if (!this.#active || !this.#onMoveCb) return;
645
- if (event.pointerId !== this.#pointerId) return;
646
- const coalesced = event.getCoalescedEvents?.();
647
- const last = coalesced?.length ? coalesced[coalesced.length - 1] : event;
648
- const now = performance.now();
649
- const x = last.clientX;
650
- const y = last.clientY;
651
- if (x === this.#lastX && y === this.#lastY) {
652
- event.preventDefault();
405
+ #d() {
406
+ this.#n = !1, this.#r = void 0;
407
+ }
408
+ #f = (e) => {
409
+ if (!this.#n || !this.#s || e.pointerId !== this.#r) return;
410
+ let t = e.getCoalescedEvents?.(), n = t?.length ? t[t.length - 1] : e, r = performance.now(), i = n.clientX, a = n.clientY;
411
+ if (i === this.#i && a === this.#a) {
412
+ e.preventDefault();
653
413
  return;
654
414
  }
655
- this.#lastX = x;
656
- this.#lastY = y;
657
- this.#onMoveCb({
658
- pointerId: event.pointerId,
659
- x,
660
- y,
661
- event,
662
- now
663
- });
664
- event.preventDefault();
415
+ this.#i = i, this.#a = a, this.#s({
416
+ pointerId: e.pointerId,
417
+ x: i,
418
+ y: a,
419
+ event: e,
420
+ now: r
421
+ }), e.preventDefault();
665
422
  };
666
- /**
667
- * 全局 pointerup / pointercancel / blur:
668
- * - blur 没有 pointerId,需要特殊处理
669
- * - 先清理会话状态再回调,避免回调内副作用导致重入触发第二次 onUp
670
- */
671
- #onUp = (event) => {
672
- if (!this.#active || !this.#onUpCb) return;
673
- if ("pointerId" in event && event.pointerId !== this.#pointerId) return;
674
- const pointerId = this.#pointerId;
675
- const reason = event.type;
676
- this.#clearSession();
677
- this.#onUpCb({
678
- event,
679
- pointerId,
680
- reason
681
- });
682
- event.preventDefault?.();
423
+ #p = (e) => {
424
+ if (!this.#n || !this.#c || "pointerId" in e && e.pointerId !== this.#r) return;
425
+ let t = this.#r, n = e.type;
426
+ this.#d(), this.#c({
427
+ event: e,
428
+ pointerId: t,
429
+ reason: n
430
+ }), e.preventDefault?.();
683
431
  };
684
- };
685
- //#endregion
686
- //#region src/core/FrameContext.js
687
- /**
688
- * FrameContext(帧上下文)
689
- *
690
- * 用于在每一帧中在各个插件之间共享的上下文数据。
691
- *
692
- * 插件约定:
693
- * - 只在 onMeasure 阶段读取 DOM(避免读写交错导致强制回流)
694
- * - 在 onCompute 阶段做纯计算(不触碰 DOM)
695
- * - 在 onCommit 阶段把 DOM 写操作通过 frame 入队(集中提交)
696
- */
697
- var FrameContext = class {
698
- scrolled = false;
432
+ }, C = class {
433
+ scrolled = !1;
699
434
  now = 0;
700
435
  classOps = /* @__PURE__ */ new Map();
701
436
  styleOps = /* @__PURE__ */ new Map();
702
437
  appendOps = /* @__PURE__ */ new Map();
703
438
  removeOps = /* @__PURE__ */ new Set();
704
439
  fnOps = [];
705
- /**
706
- * 重置为新的一帧状态
707
- * @param now 当前帧时间戳
708
- */
709
- reset(now) {
710
- this.now = now;
711
- this.scrolled = false;
712
- this.classOps.clear();
713
- this.styleOps.clear();
714
- this.appendOps.clear();
715
- this.removeOps.clear();
716
- this.fnOps.length = 0;
717
- }
718
- /**
719
- * 记录一次 class toggle 操作(合并到队列中,last-write-wins)
720
- */
721
- toggleClass(el, className, on) {
722
- if (!el || !className) return;
723
- if (this.removeOps.has(el)) return;
724
- let m = this.classOps.get(el);
725
- if (!m) {
726
- m = /* @__PURE__ */ new Map();
727
- this.classOps.set(el, m);
728
- }
729
- m.set(className, Boolean(on));
730
- }
731
- /**
732
- * 记录一次 style 写操作(合并到队列中,last-write-wins)
733
- */
734
- setStyle(el, prop, value) {
735
- if (!el || !prop) return;
736
- if (this.removeOps.has(el)) return;
737
- let m = this.styleOps.get(el);
738
- if (!m) {
739
- m = /* @__PURE__ */ new Map();
740
- this.styleOps.set(el, m);
741
- }
742
- m.set(prop, value);
743
- }
744
- /**
745
- * 记录一次 append 操作(child 的归属 parent 以最后一次为准)
746
- */
747
- append(parent, child) {
748
- if (!parent || !child) return;
749
- if (this.removeOps.has(child)) return;
750
- this.appendOps.set(child, parent);
751
- }
752
- /**
753
- * 记录一次 remove 操作(remove 优先级最高)
754
- */
755
- remove(el) {
756
- if (!el) return;
757
- this.removeOps.add(el);
758
- this.classOps.delete(el);
759
- this.styleOps.delete(el);
760
- this.appendOps.delete(el);
761
- }
762
- /**
763
- * 记录一个待执行函数(保持顺序,允许重复)
764
- */
765
- run(fn) {
766
- if (typeof fn !== "function") return;
767
- this.fnOps.push(fn);
768
- }
769
- /**
770
- * 提交本帧所有操作(按固定顺序执行,尽量避免冲突)
771
- */
440
+ reset(e) {
441
+ this.now = e, this.scrolled = !1, this.classOps.clear(), this.styleOps.clear(), this.appendOps.clear(), this.removeOps.clear(), this.fnOps.length = 0;
442
+ }
443
+ toggleClass(e, t, n) {
444
+ if (!e || !t || this.removeOps.has(e)) return;
445
+ let r = this.classOps.get(e);
446
+ r || (r = /* @__PURE__ */ new Map(), this.classOps.set(e, r)), r.set(t, !!n);
447
+ }
448
+ setStyle(e, t, n) {
449
+ if (!e || !t || this.removeOps.has(e)) return;
450
+ let r = this.styleOps.get(e);
451
+ r || (r = /* @__PURE__ */ new Map(), this.styleOps.set(e, r)), r.set(t, n);
452
+ }
453
+ append(e, t) {
454
+ !e || !t || this.removeOps.has(t) || this.appendOps.set(t, e);
455
+ }
456
+ remove(e) {
457
+ e && (this.removeOps.add(e), this.classOps.delete(e), this.styleOps.delete(e), this.appendOps.delete(e));
458
+ }
459
+ run(e) {
460
+ typeof e == "function" && this.fnOps.push(e);
461
+ }
772
462
  commit() {
773
- for (const el of this.removeOps) el?.parentNode?.removeChild?.(el);
774
- const hasRemovals = this.removeOps.size > 0;
775
- for (const [child, parent] of this.appendOps) if (!hasRemovals || !this.removeOps.has(child) && !this.removeOps.has(parent)) parent?.appendChild?.(child);
776
- for (const [el, classes] of this.classOps) if (!hasRemovals || !this.removeOps.has(el)) for (const [cls, on] of classes) if (on) el?.classList?.add?.(cls);
777
- else el?.classList?.remove?.(cls);
778
- for (const [el, styles] of this.styleOps) if (!hasRemovals || !this.removeOps.has(el)) {
779
- for (const [prop, value] of styles) if (value === void 0 || value === null) {
780
- if (prop.includes("-")) el?.style?.removeProperty?.(prop);
781
- else if (el?.style) el.style[prop] = "";
782
- } else if (prop.includes("-")) el?.style?.setProperty?.(prop, String(value));
783
- else if (el?.style) el.style[prop] = value;
784
- }
785
- for (const fn of this.fnOps) fn?.();
463
+ for (let e of this.removeOps) e?.parentNode?.removeChild?.(e);
464
+ let e = this.removeOps.size > 0;
465
+ for (let [t, n] of this.appendOps) (!e || !this.removeOps.has(t) && !this.removeOps.has(n)) && n?.appendChild?.(t);
466
+ for (let [t, n] of this.classOps) if (!e || !this.removeOps.has(t)) for (let [e, r] of n) r ? t?.classList?.add?.(e) : t?.classList?.remove?.(e);
467
+ for (let [t, n] of this.styleOps) if (!e || !this.removeOps.has(t)) for (let [e, r] of n) r == null ? e.includes("-") ? t?.style?.removeProperty?.(e) : t?.style && (t.style[e] = "") : e.includes("-") ? t?.style?.setProperty?.(e, String(r)) : t?.style && (t.style[e] = r);
468
+ for (let e of this.fnOps) e?.();
786
469
  }
787
- };
788
- //#endregion
789
- //#region src/core/PluginRuntime.js
790
- /**
791
- * PluginRuntime
792
- *
793
- * 插件运行时调度器:负责管理插件的注册、排序,以及在 DnD 生命周期内
794
- * 按顺序分发各阶段回调(onDown/onStart/onMeasure/onCompute/onCommit/onEnd...)。
795
- *
796
- * 设计要点:
797
- * 1) 插件按 order 升序执行(越小越早)。
798
- * 2) 所有回调都是可选的(?. 调用)。
799
- * 3) onAfterDrag 有返回值聚合逻辑:任一插件返回 true 或 { scrolled: true } 都视为发生了滚动。
800
- */
801
- var PluginRuntime = class {
802
- /**
803
- * 已注册插件列表(内部私有)
804
- * @type {Array<any>}
805
- */
806
- #plugins = [];
807
- /**
808
- * 注册插件并排序,然后调用插件的 onAttach(用于做初始化、挂事件、扩展 dnd api 等)
809
- *
810
- * @param {any} plugin 插件实例(可包含 order、onAttach、各生命周期钩子)
811
- * @param {any} dnd Dnd 实例(传给插件做初始化)
812
- */
813
- use(plugin, dnd) {
814
- if (!plugin) return;
815
- this.#plugins.push(plugin);
816
- this.#plugins.sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
817
- plugin.onAttach?.(dnd);
818
- }
819
- /**
820
- * root 容器变更通知(比如 dnd.root 被替换)
821
- * 插件可在此处重新绑定事件或做清理。
822
- *
823
- * @param {HTMLElement} nextRoot 新 root
824
- * @param {HTMLElement} prevRoot 旧 root
825
- * @param {AbortSignal} signal 用于自动解绑事件的 signal
826
- */
827
- onRootChange(nextRoot, prevRoot, signal) {
828
- for (const p of this.#plugins) p.onRootChange?.(nextRoot, prevRoot, signal);
829
- }
830
- /**
831
- * pointer/mouse/touch 按下阶段(拖拽尚未开始)
832
- * 通常用于:命中测试、准备 session、记录初始坐标等。
833
- *
834
- * @param {any} ctx 帧上下文/会话上下文
835
- * @param {Event} event 原始事件对象
836
- */
837
- onDown(ctx, event) {
838
- for (const p of this.#plugins) p.onDown?.(ctx, event);
839
- }
840
- /**
841
- * 真正开始拖拽(跨过 threshold / started=true)阶段
842
- * 通常用于:创建 mirror、创建 indicator、更新选中态等。
843
- *
844
- * @param {any} ctx 帧上下文/会话上下文
845
- */
846
- onStart(ctx) {
847
- for (const p of this.#plugins) p.onStart?.(ctx);
848
- }
849
- /**
850
- * Measure 阶段:只读测量(读 DOM)
851
- * 通常用于:读取 rect、计算命中 drop、记录布局信息等。
852
- *
853
- * @param {any} ctx 帧上下文/会话上下文
854
- */
855
- onMeasure(ctx) {
856
- for (const p of this.#plugins) p.onMeasure?.(ctx);
857
- }
858
- /**
859
- * Compute 阶段:纯计算(不写 DOM)
860
- * 通常用于:根据 measure 的结果计算 region、allowed、snap 等。
861
- *
862
- * @param {any} ctx 帧上下文/会话上下文
863
- */
864
- onCompute(ctx) {
865
- for (const p of this.#plugins) p.onCompute?.(ctx);
866
- }
867
- /**
868
- * Commit 阶段:写入(写 DOM)
869
- * 通常用于:更新 class/style、移动 mirror、更新 indicator 形态等。
870
- *
871
- * @param {any} ctx 帧上下文/会话上下文
872
- */
873
- onCommit(ctx) {
874
- for (const p of this.#plugins) p.onCommit?.(ctx);
875
- }
876
- /**
877
- * AfterDrag 阶段:拖拽过程中的后置处理(通常在 move 后)
878
- * 用途:自动滚动(auto scroll)、边缘滚动等。
879
- *
880
- * 返回值聚合规则:
881
- * - 任一插件返回 true 或 { scrolled: true } => 表示发生了滚动
882
- * - 最终返回 scrolled(boolean)供上层决定是否需要额外刷新/下一帧等
883
- *
884
- * @param {any} ctx 帧上下文/会话上下文
885
- * @returns {boolean} 是否发生滚动(或需要视为滚动)
886
- */
887
- onAfterDrag(ctx) {
888
- let scrolled = false;
889
- for (const p of this.#plugins) {
890
- const r = p.onAfterDrag?.(ctx);
891
- if (r === true || r?.scrolled) scrolled = true;
470
+ }, ee = class {
471
+ #e = [];
472
+ use(e, t) {
473
+ e && (this.#e.push(e), this.#e.sort((e, t) => (e.order ?? 0) - (t.order ?? 0)), e.onAttach?.(t));
474
+ }
475
+ onRootChange(e, t, n) {
476
+ for (let r of this.#e) r.onRootChange?.(e, t, n);
477
+ }
478
+ onDown(e, t) {
479
+ for (let n of this.#e) n.onDown?.(e, t);
480
+ }
481
+ onStart(e) {
482
+ for (let t of this.#e) t.onStart?.(e);
483
+ }
484
+ onMeasure(e) {
485
+ for (let t of this.#e) t.onMeasure?.(e);
486
+ }
487
+ onCompute(e) {
488
+ for (let t of this.#e) t.onCompute?.(e);
489
+ }
490
+ onCommit(e) {
491
+ for (let t of this.#e) t.onCommit?.(e);
492
+ }
493
+ onAfterDrag(e) {
494
+ let t = !1;
495
+ for (let n of this.#e) {
496
+ let r = n.onAfterDrag?.(e);
497
+ (r === !0 || r?.scrolled) && (t = !0);
892
498
  }
893
- return scrolled;
894
- }
895
- /**
896
- * 拖拽结束阶段
897
- * 通常用于:清理 DOM(mirror/indicator)、恢复样式、派发 drop 结果等。
898
- *
899
- * @param {any} ctx 帧上下文/会话上下文
900
- * @param {any} meta 结束元信息(比如 drop 成功/取消、原因等)
901
- */
902
- onEnd(ctx, meta) {
903
- for (const p of this.#plugins) p.onEnd?.(ctx, meta);
904
- }
905
- /**
906
- * Dnd 实例销毁阶段
907
- * 通常用于:解绑事件、释放引用、兜底清理(防止中途销毁导致残留)。
908
- *
909
- * @param {any} dnd Dnd 实例
910
- * @param {any} session 当前会话/monitor(用于清理残留 DOM)
911
- */
912
- onDestroy(dnd, session) {
913
- for (const p of this.#plugins) p.onDestroy?.(dnd, session);
914
- }
915
- /**
916
- * 释放插件强引用,断开 plugin <-> dnd 之间的循环引用,便于 GC。
917
- * 应该在 dnd.destroy() 末尾调用。
918
- */
499
+ return t;
500
+ }
501
+ onEnd(e, t) {
502
+ for (let n of this.#e) n.onEnd?.(e, t);
503
+ }
504
+ onDestroy(e, t) {
505
+ for (let n of this.#e) n.onDestroy?.(e, t);
506
+ }
919
507
  dispose() {
920
- this.#plugins.length = 0;
508
+ this.#e.length = 0;
921
509
  }
922
- };
923
- //#endregion
924
- //#region src/core/State.js
925
- var State = class {
926
- #store;
927
- #session;
928
- constructor({ store, session } = {}) {
929
- this.#store = store;
930
- this.#session = session;
510
+ }, te = class {
511
+ #e;
512
+ #t;
513
+ constructor({ store: e, session: t } = {}) {
514
+ this.#e = e, this.#t = t;
931
515
  }
932
516
  get session() {
933
- return this.#session;
517
+ return this.#t;
934
518
  }
935
519
  get store() {
936
- return this.#store;
937
- }
938
- /**
939
- * Dispatch an action to update session state.
940
- * Returns small effects flags for the facade.
941
- */
942
- dispatch(action) {
943
- if (!action || !this.#session) return { handled: false };
944
- switch (action.type) {
520
+ return this.#e;
521
+ }
522
+ dispatch(e) {
523
+ if (!e || !this.#t) return { handled: !1 };
524
+ switch (e.type) {
945
525
  case "DOWN": {
946
- if (this.#session.active) return { handled: false };
947
- Object.assign(this.#session, {
948
- active: true,
949
- started: false,
950
- dirty: false,
951
- pointerId: action.pointerId,
952
- startX: action.x,
953
- startY: action.y,
954
- x: action.x,
955
- y: action.y,
956
- prevX: action.x,
957
- prevY: action.y,
526
+ if (this.#t.active) return { handled: !1 };
527
+ Object.assign(this.#t, {
528
+ active: !0,
529
+ started: !1,
530
+ dirty: !1,
531
+ pointerId: e.pointerId,
532
+ startX: e.x,
533
+ startY: e.y,
534
+ x: e.x,
535
+ y: e.y,
536
+ prevX: e.x,
537
+ prevY: e.y,
958
538
  dx: 0,
959
539
  dy: 0,
960
- namespace: action.namespace,
961
- data: action.data,
962
- sourceEl: action.sourceEl,
963
- handleEl: action.handleEl,
964
- originDrop: action.originDrop,
540
+ namespace: e.namespace,
541
+ data: e.data,
542
+ sourceEl: e.sourceEl,
543
+ handleEl: e.handleEl,
544
+ originDrop: e.originDrop,
965
545
  currentDrop: void 0,
966
546
  currentDropRect: void 0,
967
- isDragScope: Boolean(action.isDragScope),
968
- isCopy: Boolean(action.isCopy),
969
- mirrorOffsetX: action.mirrorOffsetX ?? 0,
970
- mirrorOffsetY: action.mirrorOffsetY ?? 0,
547
+ isDragScope: !!e.isDragScope,
548
+ isCopy: !!e.isCopy,
549
+ mirrorOffsetX: e.mirrorOffsetX ?? 0,
550
+ mirrorOffsetY: e.mirrorOffsetY ?? 0,
971
551
  lastMoveTs: 0
972
- });
973
- this.#session.dragAbort = new AbortController();
974
- const { cache } = this.#session;
975
- if (cache) {
976
- cache.dropDataEl = void 0;
977
- cache.dropDataRaw = void 0;
978
- cache.dropDataParsed = void 0;
979
- cache.hitDropFn = void 0;
980
- cache.dropRectDirty = true;
981
- }
982
- return {
983
- handled: true,
984
- accepted: true,
985
- dragAbort: this.#session.dragAbort
552
+ }), this.#t.dragAbort = new AbortController();
553
+ let { cache: t } = this.#t;
554
+ return t && (t.dropDataEl = void 0, t.dropDataRaw = void 0, t.dropDataParsed = void 0, t.hitDropFn = void 0, t.dropRectDirty = !0), {
555
+ handled: !0,
556
+ accepted: !0,
557
+ dragAbort: this.#t.dragAbort
986
558
  };
987
559
  }
988
560
  case "MOVE": {
989
- if (!this.#session.active || action.pointerId !== this.#session.pointerId) return { handled: false };
990
- const nextX = action.x;
991
- const nextY = action.y;
992
- if (nextX === this.#session.x && nextY === this.#session.y) return {
993
- handled: true,
994
- moved: false
561
+ if (!this.#t.active || e.pointerId !== this.#t.pointerId) return { handled: !1 };
562
+ let t = e.x, n = e.y;
563
+ if (t === this.#t.x && n === this.#t.y) return {
564
+ handled: !0,
565
+ moved: !1
995
566
  };
996
- this.#session.prevX = this.#session.x;
997
- this.#session.prevY = this.#session.y;
998
- this.#session.x = nextX;
999
- this.#session.y = nextY;
1000
- this.#session.dx = nextX - this.#session.startX;
1001
- this.#session.dy = nextY - this.#session.startY;
1002
- this.#session.dirty = true;
1003
- let startedNow = false;
1004
- if (!this.#session.started) {
1005
- if (Math.hypot(this.#session.dx, this.#session.dy) >= this.#session.threshold) {
1006
- this.#session.started = true;
1007
- startedNow = true;
1008
- }
1009
- }
1010
- return {
1011
- handled: true,
1012
- moved: true,
1013
- startedNow,
1014
- started: this.#session.started
567
+ this.#t.prevX = this.#t.x, this.#t.prevY = this.#t.y, this.#t.x = t, this.#t.y = n, this.#t.dx = t - this.#t.startX, this.#t.dy = n - this.#t.startY, this.#t.dirty = !0;
568
+ let r = !1;
569
+ return this.#t.started || Math.hypot(this.#t.dx, this.#t.dy) >= this.#t.threshold && (this.#t.started = !0, r = !0), {
570
+ handled: !0,
571
+ moved: !0,
572
+ startedNow: r,
573
+ started: this.#t.started
1015
574
  };
1016
575
  }
1017
576
  case "END": {
1018
- if (!this.#session.active) return { handled: false };
1019
- if (action.pointerId !== void 0 && action.pointerId !== this.#session.pointerId) return { handled: false };
1020
- const ended = Boolean(this.#session.started);
1021
- this.#session.active = false;
1022
- return {
1023
- handled: true,
1024
- ended,
1025
- reason: action.reason
577
+ if (!this.#t.active || e.pointerId !== void 0 && e.pointerId !== this.#t.pointerId) return { handled: !1 };
578
+ let t = !!this.#t.started;
579
+ return this.#t.active = !1, {
580
+ handled: !0,
581
+ ended: t,
582
+ reason: e.reason
1026
583
  };
1027
584
  }
1028
- default: return { handled: false };
1029
- }
1030
- }
1031
- /** Reset session after end/destroy, preserving store references. */
1032
- resetSession({ ended } = { ended: false }) {
1033
- const store = this.#store;
1034
- const prev = this.#session;
1035
- const next = createSession(store);
1036
- next.adapter = prev?.adapter;
1037
- if (ended) {
1038
- next.suppressNextClick = true;
1039
- next.lastDragTs = performance.now();
1040
- }
1041
- this.#session = next;
1042
- return next;
1043
- }
1044
- };
1045
- //#endregion
1046
- //#region src/core/Dnd.js
1047
- /**
1048
- * Dnd Facade(对外门面)
1049
- *
1050
- * 设计目标:
1051
- * - 内部拆分职责:sensor(输入采集)/ engine(state)(状态机)/ runtime(插件调度)
1052
- * / adapter(DOM 适配)/ scheduler(rAF 驱动)
1053
- */
1054
- var Dnd = class extends EventDispatcher {
1055
- #abort = new AbortController();
1056
- #root;
1057
- #config;
1058
- #adapter = new DomAdapter();
1059
- #frame = new FrameContext();
1060
- #store = { selectedByNs: /* @__PURE__ */ new Map() };
1061
- #state;
1062
- #runtime = new PluginRuntime();
1063
- #scheduler;
1064
- #sensor;
1065
- #destroyed = false;
1066
- #frameCtx;
1067
- canDrop = () => true;
585
+ default: return { handled: !1 };
586
+ }
587
+ }
588
+ resetSession({ ended: e } = { ended: !1 }) {
589
+ let t = this.#e, n = this.#t, r = f(t);
590
+ return r.adapter = n?.adapter, e && (r.suppressNextClick = !0, r.lastDragTs = performance.now()), this.#t = r, r;
591
+ }
592
+ }, w = class extends e {
593
+ #e = new AbortController();
594
+ #t;
595
+ #n;
596
+ #r = new b();
597
+ #i = new C();
598
+ #a = { selectedByNs: /* @__PURE__ */ new Map() };
599
+ #o;
600
+ #s = new ee();
601
+ #c;
602
+ #l;
603
+ #u = !1;
604
+ #d;
605
+ canDrop = () => !0;
1068
606
  renderMirror = void 0;
1069
- /** 当前 root */
1070
607
  get root() {
1071
- return this.#root;
608
+ return this.#t;
1072
609
  }
1073
- /** 对外暴露 monitor(当前 session),用于观察拖拽状态 */
1074
610
  get monitor() {
1075
- if (this.#destroyed) return void 0;
1076
- return this.#state?.session;
611
+ if (!this.#u) return this.#o?.session;
1077
612
  }
1078
- /** 是否已销毁(destroy 后只读) */
1079
613
  get destroyed() {
1080
- return this.#destroyed;
1081
- }
1082
- constructor(config = {}) {
1083
- super();
1084
- this.#config = { threshold: config.threshold ?? THRESHOLDS.DRAG_START };
1085
- const session = createSession(this.#store);
1086
- session.threshold = this.#config.threshold;
1087
- session.adapter = this.#adapter;
1088
- this.#state = new State({
1089
- store: this.#store,
1090
- session
1091
- });
1092
- this.#scheduler = new RafScheduler(this.#onFrame);
1093
- this.#sensor = new PointerSensor({
1094
- onDown: this.#onPointerDown,
1095
- onMove: this.#onPointerMove,
1096
- onUp: this.#onPointerUp
1097
- });
1098
- this.setRoot(config.root);
1099
- }
1100
- /**
1101
- * 注册插件(按 order 升序执行)
1102
- */
1103
- use(plugin) {
1104
- if (!plugin) return this;
1105
- this.#runtime.use(plugin, this);
1106
- if (this.#root) plugin.onRootChange?.(this.#root, void 0, this.#abort.signal);
1107
- return this;
1108
- }
1109
- /**
1110
- * 设置/更换 root
1111
- * - 会 abort 旧 root 相关监听
1112
- * - 通知 sensor 绑定 root pointerdown
1113
- * - 通知 plugins root 变化
1114
- */
1115
- setRoot(root) {
1116
- const nextRoot = this.#adapter.resolveRoot(root);
1117
- if (nextRoot === this.#root) return;
1118
- const prevRoot = this.#root;
1119
- this.#abort.abort();
1120
- this.#abort = new AbortController();
1121
- this.#root = nextRoot;
1122
- this.#sensor.setRoot(this.#root);
1123
- if (!this.#root) return;
1124
- this.#runtime.onRootChange(this.#root, prevRoot, this.#abort.signal);
1125
- this.#root.addEventListener("click", this.#onClickCapture, {
1126
- capture: true,
1127
- passive: false,
1128
- signal: this.#abort.signal
1129
- });
614
+ return this.#u;
615
+ }
616
+ constructor(e = {}) {
617
+ super(), this.#n = { threshold: e.threshold ?? a.DRAG_START };
618
+ let t = f(this.#a);
619
+ t.threshold = this.#n.threshold, t.adapter = this.#r, this.#o = new te({
620
+ store: this.#a,
621
+ session: t
622
+ }), this.#c = new x(this.#g), this.#l = new S({
623
+ onDown: this.#p,
624
+ onMove: this.#m,
625
+ onUp: this.#h
626
+ }), this.setRoot(e.root);
627
+ }
628
+ use(e) {
629
+ return e ? (this.#s.use(e, this), this.#t && e.onRootChange?.(this.#t, void 0, this.#e.signal), this) : this;
630
+ }
631
+ setRoot(e) {
632
+ let t = this.#r.resolveRoot(e);
633
+ if (t === this.#t) return;
634
+ let n = this.#t;
635
+ this.#e.abort(), this.#e = new AbortController(), this.#t = t, this.#l.setRoot(this.#t), this.#t && (this.#s.onRootChange(this.#t, n, this.#e.signal), this.#t.addEventListener("click", this.#f, {
636
+ capture: !0,
637
+ passive: !1,
638
+ signal: this.#e.signal
639
+ }));
1130
640
  }
1131
- /**
1132
- * 销毁:
1133
- * - 解绑 root 事件、停止 sensor
1134
- * - 停止 rAF
1135
- * - 结束活跃 session(不触发 drop/cancel 事件)
1136
- * - 通知插件销毁
1137
- * - 重置 session
1138
- */
1139
641
  destroy() {
1140
- if (this.#destroyed) return;
1141
- this.#abort.abort();
1142
- this.#sensor.destroy();
1143
- this.#scheduler.cancel();
1144
- const monitor = this.#state.session;
1145
- if (monitor?.active) {
1146
- this.#runtime.onEnd(createContext({
1147
- dnd: this,
1148
- session: monitor,
1149
- store: this.#store,
1150
- frame: this.#frame,
1151
- adapter: this.#adapter
1152
- }), {
1153
- ended: false,
1154
- reason: "destroy"
1155
- });
1156
- monitor.dragAbort?.abort();
1157
- }
1158
- this.#runtime.onDestroy(this, monitor);
1159
- this.#runtime.dispose?.();
1160
- this.#frameCtx = void 0;
1161
- this.offAll();
1162
- this.#destroyed = true;
1163
- }
1164
- #onClickCapture = (e) => {
1165
- const m = this.#state?.session;
1166
- if (!m?.suppressNextClick) return;
1167
- const now = performance.now();
1168
- const withinWindow = !m.lastDragTs || now - m.lastDragTs < 800;
1169
- m.suppressNextClick = false;
1170
- if (!withinWindow) return;
1171
- e.preventDefault?.();
1172
- e.stopPropagation?.();
1173
- e.stopImmediatePropagation?.();
642
+ if (this.#u) return;
643
+ this.#e.abort(), this.#l.destroy(), this.#c.cancel();
644
+ let e = this.#o.session;
645
+ e?.active && (this.#s.onEnd(p({
646
+ dnd: this,
647
+ session: e,
648
+ store: this.#a,
649
+ frame: this.#i,
650
+ adapter: this.#r
651
+ }), {
652
+ ended: !1,
653
+ reason: "destroy"
654
+ }), e.dragAbort?.abort()), this.#s.onDestroy(this, e), this.#s.dispose?.(), this.#d = void 0, this.offAll(), this.#u = !0;
655
+ }
656
+ #f = (e) => {
657
+ let t = this.#o?.session;
658
+ if (!t?.suppressNextClick) return;
659
+ let n = performance.now(), r = !t.lastDragTs || n - t.lastDragTs < 800;
660
+ t.suppressNextClick = !1, r && (e.preventDefault?.(), e.stopPropagation?.(), e.stopImmediatePropagation?.());
1174
661
  };
1175
- /**
1176
- * pointerdown:
1177
- * - 校验 root、按键、handle、draggable
1178
- * - dispatch DOWN 到状态机
1179
- * - 执行插件 onDown(允许入队 DOM 写操作)
1180
- * - 返回给 sensor:accepted/pointerId/signal,用于建立会话监听
1181
- */
1182
- #onPointerDown = (event) => {
1183
- if (!this.#root) return { accepted: false };
1184
- if (event.button !== 0) return { accepted: false };
1185
- const handle = matchHandle(event.target, this.#adapter);
1186
- if (!handle) return { accepted: false };
1187
- const draggable = this.#adapter.closestDraggable(handle);
1188
- if (!draggable) return { accepted: false };
1189
- if (event.target?.closest?.("input, textarea, select, button, a[href], [contenteditable]")) return { accepted: false };
1190
- event.preventDefault();
1191
- event.target?.setPointerCapture?.(event.pointerId);
1192
- const ns = this.#adapter.getNamespace(draggable);
1193
- const originDrop = this.#adapter.closestDrop(draggable);
1194
- const rect = draggable.getBoundingClientRect();
1195
- const data = parseData(this.#adapter.getAttr(draggable, ATTR.dataAttr));
1196
- if (!this.#state.dispatch({
662
+ #p = (e) => {
663
+ if (!this.#t || e.button !== 0) return { accepted: !1 };
664
+ let n = h(e.target, this.#r);
665
+ if (!n) return { accepted: !1 };
666
+ let r = this.#r.closestDraggable(n);
667
+ if (!r || e.target?.closest?.("input, textarea, select, button, a[href], [contenteditable]")) return { accepted: !1 };
668
+ e.preventDefault(), e.target?.setPointerCapture?.(e.pointerId);
669
+ let i = this.#r.getNamespace(r), a = this.#r.closestDrop(r), o = r.getBoundingClientRect(), s = u(this.#r.getAttr(r, t.dataAttr));
670
+ if (!this.#o.dispatch({
1197
671
  type: "DOWN",
1198
- pointerId: event.pointerId,
1199
- x: event.clientX,
1200
- y: event.clientY,
1201
- namespace: ns,
1202
- data,
1203
- sourceEl: draggable,
1204
- handleEl: handle,
1205
- originDrop,
1206
- isDragScope: Boolean(this.#adapter.closestDragScope(draggable)),
1207
- isCopy: Boolean(this.#adapter.getAttr(draggable, ATTR.copyAttr)),
1208
- mirrorOffsetX: event.clientX - rect.left,
1209
- mirrorOffsetY: event.clientY - rect.top
1210
- })?.accepted) return { accepted: false };
1211
- const monitor = this.#state.session;
1212
- monitor.threshold = this.#config.threshold;
1213
- monitor.adapter = this.#adapter;
1214
- this.#frame.reset(performance.now());
1215
- this.#adapter.beginFrame();
1216
- monitor.cache.frameId = this.#adapter.frameId;
1217
- const ctx = createContext({
672
+ pointerId: e.pointerId,
673
+ x: e.clientX,
674
+ y: e.clientY,
675
+ namespace: i,
676
+ data: s,
677
+ sourceEl: r,
678
+ handleEl: n,
679
+ originDrop: a,
680
+ isDragScope: !!this.#r.closestDragScope(r),
681
+ isCopy: !!this.#r.getAttr(r, t.copyAttr),
682
+ mirrorOffsetX: e.clientX - o.left,
683
+ mirrorOffsetY: e.clientY - o.top
684
+ })?.accepted) return { accepted: !1 };
685
+ let c = this.#o.session;
686
+ c.threshold = this.#n.threshold, c.adapter = this.#r, this.#i.reset(performance.now()), this.#r.beginFrame(), c.cache.frameId = this.#r.frameId;
687
+ let l = p({
1218
688
  dnd: this,
1219
- session: monitor,
1220
- store: this.#store,
1221
- frame: this.#frame,
1222
- adapter: this.#adapter
689
+ session: c,
690
+ store: this.#a,
691
+ frame: this.#i,
692
+ adapter: this.#r
1223
693
  });
1224
- this.#runtime.onDown(ctx, event);
1225
- this.#frame.commit();
1226
- this.#adapter.endFrame();
1227
- return {
1228
- accepted: true,
1229
- pointerId: event.pointerId,
1230
- signal: monitor.dragAbort.signal
694
+ return this.#s.onDown(l, e), this.#i.commit(), this.#r.endFrame(), {
695
+ accepted: !0,
696
+ pointerId: e.pointerId,
697
+ signal: c.dragAbort.signal
1231
698
  };
1232
699
  };
1233
- /**
1234
- * pointermove:
1235
- * - dispatch MOVE 到状态机(更新坐标、started/dirty 等)
1236
- * - startedNow:触发 onStart + emit dragstart
1237
- * - started:请求 rAF 进入 per-frame 驱动
1238
- */
1239
- #onPointerMove = ({ pointerId, x, y }) => {
1240
- const effects = this.#state.dispatch({
700
+ #m = ({ pointerId: e, x: t, y: n }) => {
701
+ let r = this.#o.dispatch({
1241
702
  type: "MOVE",
1242
- pointerId,
1243
- x,
1244
- y
703
+ pointerId: e,
704
+ x: t,
705
+ y: n
1245
706
  });
1246
- if (!effects?.handled) return;
1247
- const monitor = this.#state.session;
1248
- if (effects.startedNow) {
1249
- const ctx = createContext({
707
+ if (!r?.handled) return;
708
+ let i = this.#o.session;
709
+ if (r.startedNow) {
710
+ let e = p({
1250
711
  dnd: this,
1251
- session: monitor,
1252
- store: this.#store,
1253
- frame: this.#frame,
1254
- adapter: this.#adapter
712
+ session: i,
713
+ store: this.#a,
714
+ frame: this.#i,
715
+ adapter: this.#r
1255
716
  });
1256
- this.#runtime.onStart(ctx);
1257
- this.emit("dragstart", createPayload("dragstart", monitor));
717
+ this.#s.onStart(e), this.emit("dragstart", d("dragstart", i));
1258
718
  }
1259
- if (effects.started) this.#scheduler.request();
719
+ r.started && this.#c.request();
1260
720
  };
1261
- /**
1262
- * pointerup / pointercancel / blur:
1263
- * - dispatch END 到状态机
1264
- * - 确保 drop 命中信息是最新的(避免最后一帧没跑)
1265
- * - 插件 onEnd 清理
1266
- * - 发出 drop/cancel 事件
1267
- * - abort 会话信号 & 重置 session
1268
- */
1269
- #onPointerUp = ({ event, pointerId, reason }) => {
1270
- const effects = this.#state.dispatch({
721
+ #h = ({ event: e, pointerId: t, reason: n }) => {
722
+ let r = this.#o.dispatch({
1271
723
  type: "END",
1272
- pointerId,
1273
- reason
724
+ pointerId: t,
725
+ reason: n
1274
726
  });
1275
- if (!effects?.handled) return;
1276
- const monitor = this.#state.session;
1277
- if ("pointerId" in event) event.target?.releasePointerCapture?.(event.pointerId);
1278
- const ended = Boolean(effects.ended);
1279
- this.#adapter.beginFrame();
1280
- monitor.cache.frameId = this.#adapter.frameId;
1281
- monitor.currentDrop = this.#adapter.hitDropForSource(monitor.x, monitor.y, monitor.namespace, monitor.sourceEl);
1282
- monitor.currentDropRect = monitor.currentDrop ? this.#adapter.measureRect(monitor.currentDrop) : void 0;
1283
- this.#adapter.endFrame();
1284
- const ctx = createContext({
727
+ if (!r?.handled) return;
728
+ let i = this.#o.session;
729
+ "pointerId" in e && e.target?.releasePointerCapture?.(e.pointerId);
730
+ let a = !!r.ended;
731
+ this.#r.beginFrame(), i.cache.frameId = this.#r.frameId, i.currentDrop = this.#r.hitDropForSource(i.x, i.y, i.namespace, i.sourceEl), i.currentDropRect = i.currentDrop ? this.#r.measureRect(i.currentDrop) : void 0, this.#r.endFrame();
732
+ let o = p({
1285
733
  dnd: this,
1286
- session: monitor,
1287
- store: this.#store,
1288
- frame: this.#frame,
1289
- adapter: this.#adapter
734
+ session: i,
735
+ store: this.#a,
736
+ frame: this.#i,
737
+ adapter: this.#r
1290
738
  });
1291
- this.#runtime.onEnd(ctx, {
1292
- ended,
1293
- reason: reason || "pointerup"
739
+ this.#s.onEnd(o, {
740
+ ended: a,
741
+ reason: n || "pointerup"
1294
742
  });
1295
- const payload = createPayload(ended ? "drop" : "cancel", monitor);
1296
- monitor.dragAbort?.abort();
1297
- monitor.dragAbort = void 0;
1298
- this.#scheduler.cancel();
1299
- this.#frameCtx = void 0;
1300
- const next = this.#state.resetSession({ ended });
1301
- next.adapter = this.#adapter;
1302
- ended ? this.emit("drop", payload) : this.emit("cancel", payload);
1303
- event.preventDefault?.();
743
+ let s = d(a ? "drop" : "cancel", i);
744
+ i.dragAbort?.abort(), i.dragAbort = void 0, this.#c.cancel(), this.#d = void 0;
745
+ let c = this.#o.resetSession({ ended: a });
746
+ c.adapter = this.#r, a ? this.emit("drop", s) : this.emit("cancel", s), e.preventDefault?.();
1304
747
  };
1305
- /**
1306
- * 单帧 rAF 回调:
1307
- * - started active 才会运行
1308
- * - 若 monitor.dirty:执行 measure/compute/commit,并 emit drag
1309
- * - afterDrag 钩子用于处理滚动/惯性等副作用
1310
- * - 返回 true 表示下一帧继续
1311
- */
1312
- #onFrame = (now) => {
1313
- const monitor = this.#state.session;
1314
- if (!monitor.active || !monitor.started) return false;
1315
- this.#frame.reset(now);
1316
- this.#adapter.beginFrame();
1317
- monitor.cache.frameId = this.#adapter.frameId;
1318
- let ctx = this.#frameCtx;
1319
- if (!ctx || ctx.session !== monitor) ctx = this.#frameCtx = createContext({
748
+ #g = (e) => {
749
+ let t = this.#o.session;
750
+ if (!t.active || !t.started) return !1;
751
+ this.#i.reset(e), this.#r.beginFrame(), t.cache.frameId = this.#r.frameId;
752
+ let n = this.#d;
753
+ !n || n.session !== t ? n = this.#d = p({
1320
754
  dnd: this,
1321
- session: monitor,
1322
- store: this.#store,
1323
- frame: this.#frame,
1324
- adapter: this.#adapter
1325
- });
1326
- else ctx.resetPayloadCache();
1327
- let scrolled = false;
1328
- if (monitor.dirty) {
1329
- this.#runtime.onMeasure(ctx);
1330
- this.#runtime.onCompute(ctx);
1331
- this.emit("drag", ctx.payload("drag"));
1332
- this.#runtime.onCommit(ctx);
1333
- this.#frame.commit();
1334
- if (this.#frame.scrolled) scrolled = true;
1335
- monitor.dirty = false;
1336
- }
1337
- if (this.#runtime.onAfterDrag(ctx)) scrolled = true;
1338
- if (scrolled) monitor.dirty = true;
1339
- this.#adapter.endFrame();
1340
- return monitor.dirty || scrolled;
755
+ session: t,
756
+ store: this.#a,
757
+ frame: this.#i,
758
+ adapter: this.#r
759
+ }) : n.resetPayloadCache();
760
+ let r = !1;
761
+ return t.dirty &&= (this.#s.onMeasure(n), this.#s.onCompute(n), this.emit("drag", n.payload("drag")), this.#s.onCommit(n), this.#i.commit(), this.#i.scrolled && (r = !0), !1), this.#s.onAfterDrag(n) && (r = !0), r && (t.dirty = !0), this.#r.endFrame(), t.dirty || r;
1341
762
  };
1342
- };
1343
- //#endregion
1344
- //#region src/services/DropService.js
1345
- /**
1346
- * DropService
1347
- *
1348
- * 目标:
1349
- * - 在每一帧(onMeasure 阶段)保证 drop 命中信息的”单一事实来源”(single source of truth)
1350
- * - 统一维护以下字段,避免多处重复计算/不一致:
1351
- * - monitor.currentDrop:当前命中的 drop 元素
1352
- * - monitor.currentDropRect:当前 drop 的测量矩形(DOMRect/自定义 rect)
1353
- * - monitor.currentAllowed:当前是否允许 drop(权威数据源)
1354
- * - 统一维护 canDrop/视觉反馈:
1355
- * - 给 currentDrop 添加/移除 CLASS_NAMES.canDrop / CLASS_NAMES.noDrop
1356
- *
1357
- * 注意:
1358
- * - order = 10,确保在其他依赖 drop 状态的服务(如 DropIndicatorService)之前执行
1359
- * - currentAllowed 由本服务在 onCompute 阶段计算,其他服务应直接使用该值
1360
- */
1361
- var DropService = class {
763
+ }, T = class {
1362
764
  order = 10;
1363
- /**
1364
- * onMeasure:
1365
- * - 只做 DOM 读取/测量相关工作(命中测试、measureRect)
1366
- * - 负责在每帧更新 currentDrop / currentDropRect
1367
- */
1368
- onMeasure(ctx) {
1369
- const m = ctx.session;
1370
- if (!m.active || !m.started) return;
1371
- const drop = ctx.adapter.hitDropForSource(m.x, m.y, m.namespace, m.sourceEl);
1372
- if (drop !== m.currentDrop) {
1373
- m.currentDrop = drop;
1374
- if (m.cache) m.cache.dropRectDirty = true;
1375
- }
1376
- if (!drop) {
1377
- m.currentDropRect = void 0;
1378
- if (m.cache) m.cache.dropRectDirty = false;
765
+ onMeasure(e) {
766
+ let t = e.session;
767
+ if (!t.active || !t.started) return;
768
+ let n = e.adapter.hitDropForSource(t.x, t.y, t.namespace, t.sourceEl);
769
+ if (n !== t.currentDrop && (t.currentDrop = n, t.cache && (t.cache.dropRectDirty = !0)), !n) {
770
+ t.currentDropRect = void 0, t.cache && (t.cache.dropRectDirty = !1);
1379
771
  return;
1380
772
  }
1381
- if (m.cache?.dropRectDirty || !m.currentDropRect) {
1382
- m.currentDropRect = ctx.adapter.measureRect(drop);
1383
- m.cache.dropRectDirty = false;
1384
- }
773
+ (t.cache?.dropRectDirty || !t.currentDropRect) && (t.currentDropRect = e.adapter.measureRect(n), t.cache.dropRectDirty = !1);
1385
774
  }
1386
- /**
1387
- * onCompute:
1388
- * - 计算当前 drop 是否允许(dnd.canDrop(payload)
1389
- * - 只写 session,不写 DOM
1390
- * - 这是 currentAllowed 的权威计算点,其他服务应直接使用该值
1391
- */
1392
- onCompute(ctx) {
1393
- const m = ctx.session;
1394
- if (!m.active || !m.started) return;
1395
- if (!m.currentDrop) {
1396
- m.currentAllowed = false;
775
+ onCompute(e) {
776
+ let t = e.session;
777
+ if (!t.active || !t.started) return;
778
+ if (!t.currentDrop) {
779
+ t.currentAllowed = !1;
1397
780
  return;
1398
781
  }
1399
- const fn = ctx.dnd?.canDrop;
1400
- if (typeof fn !== "function") {
1401
- m.currentAllowed = true;
782
+ let n = e.dnd?.canDrop;
783
+ if (typeof n != "function") {
784
+ t.currentAllowed = !0;
1402
785
  return;
1403
786
  }
1404
787
  try {
1405
- m.currentAllowed = !!fn(ctx.payload("drag"));
788
+ t.currentAllowed = !!n(e.payload("drag"));
1406
789
  } catch {
1407
- m.currentAllowed = false;
790
+ t.currentAllowed = !1;
1408
791
  }
1409
792
  }
1410
- /**
1411
- * onCommit:
1412
- * - 根据 currentDrop/currentAllowed 写入 drop 的 class
1413
- */
1414
- onCommit(ctx) {
1415
- const m = ctx.session;
1416
- if (!m?.active || !m?.started) return;
1417
- const cache = m.cache || (m.cache = {});
1418
- const prev = cache._dropClassEl;
1419
- const cur = m.currentDrop;
1420
- if (isHTMLElement(prev) && prev !== cur) {
1421
- ctx.frame.toggleClass(prev, CLASS_NAMES.canDrop, false);
1422
- ctx.frame.toggleClass(prev, CLASS_NAMES.noDrop, false);
1423
- }
1424
- if (isHTMLElement(cur)) {
1425
- ctx.frame.toggleClass(cur, CLASS_NAMES.canDrop, !!m.currentAllowed);
1426
- ctx.frame.toggleClass(cur, CLASS_NAMES.noDrop, !m.currentAllowed);
1427
- }
1428
- cache._dropClassEl = cur;
793
+ onCommit(e) {
794
+ let t = e.session;
795
+ if (!t?.active || !t?.started) return;
796
+ let r = t.cache ||= {}, i = r._dropClassEl, a = t.currentDrop;
797
+ g(i) && i !== a && (e.frame.toggleClass(i, n.canDrop, !1), e.frame.toggleClass(i, n.noDrop, !1)), g(a) && (e.frame.toggleClass(a, n.canDrop, !!t.currentAllowed), e.frame.toggleClass(a, n.noDrop, !t.currentAllowed)), r._dropClassEl = a;
1429
798
  }
1430
- onEnd(ctx) {
1431
- const m = ctx?.session;
1432
- if (!m) return;
1433
- const prev = m.cache?._dropClassEl;
1434
- if (isHTMLElement(prev)) prev.classList.remove(CLASS_NAMES.canDrop, CLASS_NAMES.noDrop);
1435
- if (m.cache) m.cache._dropClassEl = void 0;
799
+ onEnd(e) {
800
+ let t = e?.session;
801
+ if (!t) return;
802
+ let r = t.cache?._dropClassEl;
803
+ g(r) && r.classList.remove(n.canDrop, n.noDrop), t.cache && (t.cache._dropClassEl = void 0);
1436
804
  }
1437
- onDestroy(_dnd, session) {
1438
- this.onEnd({ session });
805
+ onDestroy(e, t) {
806
+ this.onEnd({ session: t });
1439
807
  }
1440
- };
1441
- //#endregion
1442
- //#region src/services/MirrorService.js
1443
- var MirrorService = class {
808
+ }, E = class {
1444
809
  order = 0;
1445
- onStart = (ctx) => {
1446
- const s = ctx?.session;
1447
- if (!s?.sourceEl || s.mirrorEl) return;
1448
- s.sourceEl.classList.add(CLASS_NAMES.dragging);
1449
- if (s.sourceEl.hasAttribute?.(ATTR.ignoreMirrorAttr)) return;
1450
- const rect = ctx.adapter.measureRect(s.sourceEl);
1451
- const m = typeof ctx?.dnd?.renderMirror === "function" ? ctx.dnd.renderMirror(ctx) : s.sourceEl.cloneNode(true);
1452
- if (!(m instanceof HTMLElement)) return;
1453
- m.setAttribute(ATTR.ignoreMirrorAttr, "");
1454
- m.classList.add(CLASS_NAMES.mirror);
1455
- Object.assign(m.style, {
1456
- width: `${rect.width}px`,
1457
- height: `${rect.height}px`,
810
+ onStart = (e) => {
811
+ let r = e?.session;
812
+ if (!r?.sourceEl || r.mirrorEl || (r.sourceEl.classList.add(n.dragging), r.sourceEl.hasAttribute?.(t.ignoreMirrorAttr))) return;
813
+ let i = e.adapter.measureRect(r.sourceEl), a = typeof e?.dnd?.renderMirror == "function" ? e.dnd.renderMirror(e) : r.sourceEl.cloneNode(!0);
814
+ a instanceof HTMLElement && (a.setAttribute(t.ignoreMirrorAttr, ""), a.classList.add(n.mirror), Object.assign(a.style, {
815
+ width: `${i.width}px`,
816
+ height: `${i.height}px`,
1458
817
  position: "fixed"
1459
- });
1460
- (ctx.dnd?.root || document.body).appendChild(m);
1461
- s.mirrorEl = m;
818
+ }), (e.dnd?.root || document.body).appendChild(a), r.mirrorEl = a);
1462
819
  };
1463
- onCommit = (ctx) => {
1464
- const s = ctx?.session;
1465
- if (!s?.active || !s.started) return;
1466
- if (s.mirrorEl) {
1467
- const x = s.x - (s.mirrorOffsetX || 0);
1468
- const y = s.y - (s.mirrorOffsetY || 0);
1469
- ctx.frame.setStyle(s.mirrorEl, "transform", `translate3d(${x}px, ${y}px, 0)`);
820
+ onCommit = (e) => {
821
+ let t = e?.session;
822
+ if (!(!t?.active || !t.started) && t.mirrorEl) {
823
+ let n = t.x - (t.mirrorOffsetX || 0), r = t.y - (t.mirrorOffsetY || 0);
824
+ e.frame.setStyle(t.mirrorEl, "transform", `translate3d(${n}px, ${r}px, 0)`);
1470
825
  }
1471
826
  };
1472
- onEnd = (ctx) => {
1473
- const s = ctx?.session;
1474
- if (!s) return;
1475
- if (s.mirrorEl) {
1476
- s.mirrorEl.remove();
1477
- s.mirrorEl = void 0;
1478
- }
1479
- s.sourceEl?.classList.remove(CLASS_NAMES.dragging);
827
+ onEnd = (e) => {
828
+ let t = e?.session;
829
+ t && (t.mirrorEl &&= (t.mirrorEl.remove(), void 0), t.sourceEl?.classList.remove(n.dragging));
1480
830
  };
1481
- onDestroy = (_dnd, session) => {
1482
- this.onEnd({ session });
831
+ onDestroy = (e, t) => {
832
+ this.onEnd({ session: t });
1483
833
  };
1484
- };
1485
- //#endregion
1486
- //#region src/services/AutoScrollService.js
1487
- var OVERFLOW_RE = /(auto|scroll|overlay)/i;
1488
- function isScrollable(el) {
1489
- if (!(el instanceof HTMLElement)) return false;
1490
- const s = getComputedStyle(el);
1491
- const oy = OVERFLOW_RE.test(s.overflowY) && el.scrollHeight > el.clientHeight + 1;
1492
- return OVERFLOW_RE.test(s.overflowX) && el.scrollWidth > el.clientWidth + 1 || oy;
834
+ }, D = /(auto|scroll|overlay)/i;
835
+ function ne(e) {
836
+ if (!(e instanceof HTMLElement)) return !1;
837
+ let t = getComputedStyle(e), n = D.test(t.overflowY) && e.scrollHeight > e.clientHeight + 1;
838
+ return D.test(t.overflowX) && e.scrollWidth > e.clientWidth + 1 || n;
1493
839
  }
1494
- function findScrollTarget(fromEl) {
1495
- let el = fromEl;
1496
- while (el) {
1497
- if (isScrollable(el)) return el;
1498
- el = el.parentElement;
840
+ function re(e) {
841
+ let t = e;
842
+ for (; t;) {
843
+ if (ne(t)) return t;
844
+ t = t.parentElement;
1499
845
  }
1500
846
  }
1501
- function edgePlan(p, start, end, edge) {
1502
- if (p < start + edge) return {
847
+ function O(e, t, n, r) {
848
+ return e < t + r ? {
1503
849
  dir: -1,
1504
- k: (start + edge - p) / edge
1505
- };
1506
- if (p > end - edge) return {
850
+ k: (t + r - e) / r
851
+ } : e > n - r ? {
1507
852
  dir: 1,
1508
- k: (p - (end - edge)) / edge
1509
- };
1510
- return {
853
+ k: (e - (n - r)) / r
854
+ } : {
1511
855
  dir: 0,
1512
856
  k: 0
1513
857
  };
1514
858
  }
1515
- var AutoScrollService = class {
859
+ var ie = class {
1516
860
  order = 1e4;
1517
- constructor(opts = {}) {
1518
- this.edge = opts.edge ?? AUTO_SCROLL.EDGE;
1519
- this.minSpeed = opts.minSpeed ?? AUTO_SCROLL.MIN_SPEED;
1520
- this.maxSpeed = opts.maxSpeed ?? AUTO_SCROLL.MAX_SPEED;
1521
- this.allowWindowScroll = opts.allowWindowScroll ?? true;
1522
- }
1523
- onAfterDrag = (ctx) => {
1524
- const s = ctx.session;
1525
- if (!s.active || !s.started) return false;
1526
- const cache = s.cache;
1527
- let targetEl;
1528
- let useWindow;
1529
- if (cache && cache.autoScrollTargetDrop === s.currentDrop) {
1530
- targetEl = cache.autoScrollTarget;
1531
- useWindow = cache.autoScrollUseWindow;
1532
- } else {
1533
- targetEl = s.currentDrop ? findScrollTarget(s.currentDrop) : void 0;
1534
- useWindow = false;
1535
- if (!targetEl && this.allowWindowScroll) {
1536
- targetEl = document.scrollingElement || document.documentElement;
1537
- useWindow = !!targetEl;
1538
- }
1539
- if (cache) {
1540
- cache.autoScrollTargetDrop = s.currentDrop;
1541
- cache.autoScrollTarget = targetEl;
1542
- cache.autoScrollUseWindow = useWindow;
1543
- }
1544
- }
1545
- if (!targetEl) return false;
1546
- const now = ctx.frame.now;
1547
- const last = s.cache.autoScrollLastTs || 0;
1548
- const dt = last ? Math.max(AUTO_SCROLL.MIN_DT, Math.min(AUTO_SCROLL.MAX_DT, now - last)) : AUTO_SCROLL.DEFAULT_DT;
1549
- if (s.cache) s.cache.autoScrollLastTs = now;
1550
- const rect = useWindow ? {
861
+ constructor(e = {}) {
862
+ this.edge = e.edge ?? o.EDGE, this.minSpeed = e.minSpeed ?? o.MIN_SPEED, this.maxSpeed = e.maxSpeed ?? o.MAX_SPEED, this.allowWindowScroll = e.allowWindowScroll ?? !0;
863
+ }
864
+ onAfterDrag = (e) => {
865
+ let t = e.session;
866
+ if (!t.active || !t.started) return !1;
867
+ let n = t.cache, r, i;
868
+ if (n && n.autoScrollTargetDrop === t.currentDrop ? (r = n.autoScrollTarget, i = n.autoScrollUseWindow) : (r = t.currentDrop ? re(t.currentDrop) : void 0, i = !1, !r && this.allowWindowScroll && (r = document.scrollingElement || document.documentElement, i = !!r), n && (n.autoScrollTargetDrop = t.currentDrop, n.autoScrollTarget = r, n.autoScrollUseWindow = i)), !r) return !1;
869
+ let a = e.frame.now, s = t.cache.autoScrollLastTs || 0, c = s ? Math.max(o.MIN_DT, Math.min(o.MAX_DT, a - s)) : o.DEFAULT_DT;
870
+ t.cache && (t.cache.autoScrollLastTs = a);
871
+ let l = i ? {
1551
872
  left: 0,
1552
873
  top: 0,
1553
874
  right: innerWidth,
1554
875
  bottom: innerHeight
1555
- } : ctx.adapter.measureRect(targetEl);
1556
- const px = s.x, py = s.y;
1557
- const ex = edgePlan(px, rect.left, rect.right, this.edge);
1558
- const ey = edgePlan(py, rect.top, rect.bottom, this.edge);
1559
- const speed = (k) => this.minSpeed + (this.maxSpeed - this.minSpeed) * k;
1560
- const dx = ex.dir ? ex.dir * speed(ex.k) * dt / 1e3 : 0;
1561
- const dy = ey.dir ? ey.dir * speed(ey.k) * dt / 1e3 : 0;
1562
- if (!dx && !dy) return false;
1563
- const beforeTop = targetEl.scrollTop, beforeLeft = targetEl.scrollLeft;
1564
- if (useWindow) window.scrollBy(dx, dy);
1565
- else targetEl.scrollBy({
1566
- left: dx,
1567
- top: dy,
876
+ } : e.adapter.measureRect(r), u = t.x, d = t.y, f = O(u, l.left, l.right, this.edge), p = O(d, l.top, l.bottom, this.edge), m = (e) => this.minSpeed + (this.maxSpeed - this.minSpeed) * e, h = f.dir ? f.dir * m(f.k) * c / 1e3 : 0, g = p.dir ? p.dir * m(p.k) * c / 1e3 : 0;
877
+ if (!h && !g) return !1;
878
+ let _ = r.scrollTop, v = r.scrollLeft;
879
+ i ? window.scrollBy(h, g) : r.scrollBy({
880
+ left: h,
881
+ top: g,
1568
882
  behavior: "auto"
1569
883
  });
1570
- const scrolled = beforeTop !== targetEl.scrollTop || beforeLeft !== targetEl.scrollLeft;
1571
- if (scrolled && ctx.frame) ctx.frame.scrolled = true;
1572
- return scrolled;
884
+ let y = _ !== r.scrollTop || v !== r.scrollLeft;
885
+ return y && e.frame && (e.frame.scrolled = !0), y;
1573
886
  };
1574
- onEnd = (ctx) => {
1575
- const s = ctx?.session;
1576
- if (s?.cache) {
1577
- s.cache.autoScrollLastTs = 0;
1578
- s.cache.autoScrollTargetDrop = void 0;
1579
- s.cache.autoScrollTarget = void 0;
1580
- s.cache.autoScrollUseWindow = false;
1581
- }
887
+ onEnd = (e) => {
888
+ let t = e?.session;
889
+ t?.cache && (t.cache.autoScrollLastTs = 0, t.cache.autoScrollTargetDrop = void 0, t.cache.autoScrollTarget = void 0, t.cache.autoScrollUseWindow = !1);
1582
890
  };
1583
- };
1584
- //#endregion
1585
- //#region src/services/DropIndicatorService.js
1586
- var REGION_CLS = {
1587
- top: CLASS_NAMES.indicatorTop,
1588
- right: CLASS_NAMES.indicatorRight,
1589
- bottom: CLASS_NAMES.indicatorBottom,
1590
- left: CLASS_NAMES.indicatorLeft
1591
- };
1592
- var REGION_LIST = Object.values(REGION_CLS);
1593
- var VALID = /* @__PURE__ */ new Set([
891
+ }, k = {
892
+ top: n.indicatorTop,
893
+ right: n.indicatorRight,
894
+ bottom: n.indicatorBottom,
895
+ left: n.indicatorLeft
896
+ }, A = Object.values(k), j = /* @__PURE__ */ new Set([
1594
897
  "top",
1595
898
  "right",
1596
899
  "bottom",
1597
900
  "left"
1598
901
  ]);
1599
- function toggle(ctx, el, cls, on) {
1600
- if (!isHTMLElement(el)) return;
1601
- ctx.frame.toggleClass(el, cls, !!on);
902
+ function M(e, t, n, r) {
903
+ g(t) && e.frame.toggleClass(t, n, !!r);
1602
904
  }
1603
- function parseSupport(dropEl) {
1604
- if (!isHTMLElement(dropEl)) return;
1605
- const name = ATTR.dropIndicatorAttr || "drop-indicator";
1606
- const dataName = `data-${name}`;
1607
- let raw = void 0;
1608
- if (dropEl.hasAttribute?.(name)) raw = dropEl.getAttribute?.(name);
1609
- else if (dropEl.hasAttribute?.(dataName)) raw = dropEl.getAttribute?.(dataName);
905
+ function N(e) {
906
+ if (!g(e)) return;
907
+ let n = t.dropIndicatorAttr || "drop-indicator", r = `data-${n}`, i;
908
+ if (e.hasAttribute?.(n)) i = e.getAttribute?.(n);
909
+ else if (e.hasAttribute?.(r)) i = e.getAttribute?.(r);
1610
910
  else return;
1611
- const text = (raw ?? "").trim();
1612
- if (!text) return "all";
1613
- const set = /* @__PURE__ */ new Set();
1614
- for (const p of text.split(/[,\s]+/)) {
1615
- const k = (p || "").trim().toLowerCase();
1616
- if (VALID.has(k)) set.add(k);
1617
- }
1618
- return set.size ? set : void 0;
911
+ let a = (i ?? "").trim();
912
+ if (!a) return "all";
913
+ let o = /* @__PURE__ */ new Set();
914
+ for (let e of a.split(/[,\s]+/)) {
915
+ let t = (e || "").trim().toLowerCase();
916
+ j.has(t) && o.add(t);
917
+ }
918
+ return o.size ? o : void 0;
1619
919
  }
1620
- function getSupport(ctx, dropEl) {
1621
- const cache = ctx.session?.cache;
1622
- if (!cache) return parseSupport(dropEl);
1623
- if (cache.indicatorSupportEl === dropEl) return cache.indicatorSupport;
1624
- const support = parseSupport(dropEl);
1625
- cache.indicatorSupportEl = dropEl;
1626
- cache.indicatorSupport = support;
1627
- return support;
920
+ function ae(e, t) {
921
+ let n = e.session?.cache;
922
+ if (!n) return N(t);
923
+ if (n.indicatorSupportEl === t) return n.indicatorSupport;
924
+ let r = N(t);
925
+ return n.indicatorSupportEl = t, n.indicatorSupport = r, r;
1628
926
  }
1629
- function ensureIndicator(ctx) {
1630
- const m = ctx.session;
1631
- const doc = ctx.dnd?.root?.ownerDocument || document;
1632
- let el = m.indicatorEl;
1633
- if (!isHTMLElement(el)) {
1634
- el = doc.createElement("div");
1635
- el.classList.add(CLASS_NAMES.dropIndicator);
1636
- m.indicatorEl = el;
1637
- }
1638
- const parent = m.currentDrop || ctx.dnd?.root || doc.body;
1639
- if (isHTMLElement(parent) && el.parentNode !== parent) parent.appendChild(el);
1640
- return el;
927
+ function oe(e) {
928
+ let t = e.session, r = e.dnd?.root?.ownerDocument || document, i = t.indicatorEl;
929
+ g(i) || (i = r.createElement("div"), i.classList.add(n.dropIndicator), t.indicatorEl = i);
930
+ let a = t.currentDrop || e.dnd?.root || r.body;
931
+ return g(a) && i.parentNode !== a && a.appendChild(i), i;
1641
932
  }
1642
- function computeRegion(m, support) {
1643
- if (!m.currentDrop || !m.currentDropRect) return;
1644
- const f = computeDropRegion(m, support);
1645
- if (f.isOverLeft()) return "left";
1646
- if (f.isOverRight()) return "right";
1647
- if (f.isOverTop()) return "top";
1648
- if (f.isOverBottom()) return "bottom";
933
+ function se(e, t) {
934
+ if (!e.currentDrop || !e.currentDropRect) return;
935
+ let n = l(e, t);
936
+ if (n.isOverLeft()) return "left";
937
+ if (n.isOverRight()) return "right";
938
+ if (n.isOverTop()) return "top";
939
+ if (n.isOverBottom()) return "bottom";
1649
940
  }
1650
- /**
1651
- * 获取当前 drop 是否允许
1652
- * 优先使用 DropService 已计算的 currentAllowed
1653
- * 这样避免重复计算,保持单一数据源
1654
- */
1655
- function resolveAllowed(ctx) {
1656
- const m = ctx.session;
1657
- if (!m.currentDrop) return false;
1658
- if (typeof m.currentAllowed === "boolean") return m.currentAllowed;
1659
- return true;
941
+ function ce(e) {
942
+ let t = e.session;
943
+ return t.currentDrop ? typeof t.currentAllowed == "boolean" ? t.currentAllowed : !0 : !1;
1660
944
  }
1661
- var DropIndicatorService = class {
945
+ var le = class {
1662
946
  order = 40;
1663
- onCommit(ctx) {
1664
- const m = ctx.session;
1665
- if (!m?.active || !m?.started) return;
1666
- const drop = m.currentDrop;
1667
- const support = getSupport(ctx, drop);
1668
- if (!support) {
1669
- const ind = m.indicatorEl;
1670
- if (isHTMLElement(ind)) {
1671
- toggle(ctx, ind, CLASS_NAMES.dropIndicatorActive, false);
1672
- for (const c of REGION_LIST) toggle(ctx, ind, c, false);
947
+ onCommit(e) {
948
+ let t = e.session;
949
+ if (!t?.active || !t?.started) return;
950
+ let r = t.currentDrop, i = ae(e, r);
951
+ if (!i) {
952
+ let r = t.indicatorEl;
953
+ if (g(r)) {
954
+ M(e, r, n.dropIndicatorActive, !1);
955
+ for (let t of A) M(e, r, t, !1);
1673
956
  }
1674
- m.indicatorRegion = void 0;
957
+ t.indicatorRegion = void 0;
1675
958
  return;
1676
959
  }
1677
- const ind = ensureIndicator(ctx);
1678
- const allowed = resolveAllowed(ctx);
1679
- const region = computeRegion(m, support);
1680
- const okRegion = support === "all" ? region : region && support.has(region) ? region : void 0;
1681
- const show = !!(drop && m.currentDropRect && allowed && okRegion);
1682
- toggle(ctx, ind, CLASS_NAMES.dropIndicatorActive, show);
1683
- m.indicatorRegion = show ? okRegion : void 0;
1684
- if (!show) for (const c of REGION_LIST) toggle(ctx, ind, c, false);
1685
- else for (const [r, c] of Object.entries(REGION_CLS)) toggle(ctx, ind, c, r === okRegion);
1686
- }
1687
- onEnd(ctx) {
1688
- const m = ctx.session;
1689
- if (!m) return;
1690
- m.lastIndicatorRegion = m.indicatorRegion ?? "inside";
1691
- if (isHTMLElement(m.indicatorEl)) m.indicatorEl.remove();
1692
- m.indicatorEl = void 0;
1693
- m.indicatorRegion = void 0;
1694
- }
1695
- onDestroy(_dnd, session) {
1696
- this.onEnd({ session });
960
+ let a = oe(e), o = ce(e), s = se(t, i), c = i === "all" || s && i.has(s) ? s : void 0, l = !!(r && t.currentDropRect && o && c);
961
+ if (M(e, a, n.dropIndicatorActive, l), t.indicatorRegion = l ? c : void 0, l) for (let [t, n] of Object.entries(k)) M(e, a, n, t === c);
962
+ else for (let t of A) M(e, a, t, !1);
1697
963
  }
1698
- };
1699
- //#endregion
1700
- //#region src/services/ActiveSelectionService.js
1701
- var ACTIVE_WRAP_CLASS = "draggable-dot-wrap";
1702
- var DOT_CLASS = "draggable-dot";
1703
- var ROTATE_CLASS = "draggable-rotate";
1704
- function buildWrap(doc, opt = {}) {
1705
- const { resizable = true, rotatable = true } = opt;
1706
- const wrap = doc.createElement("div");
1707
- wrap.classList.add(ACTIVE_WRAP_CLASS);
1708
- wrap.dataset.resizable = String(resizable);
1709
- wrap.dataset.rotatable = String(rotatable);
1710
- if (resizable) for (const [dir, pos] of [
964
+ onEnd(e) {
965
+ let t = e.session;
966
+ t && (t.lastIndicatorRegion = t.indicatorRegion ?? "inside", g(t.indicatorEl) && t.indicatorEl.remove(), t.indicatorEl = void 0, t.indicatorRegion = void 0);
967
+ }
968
+ onDestroy(e, t) {
969
+ this.onEnd({ session: t });
970
+ }
971
+ }, P = "draggable-dot-wrap", F = "draggable-dot", I = "draggable-rotate";
972
+ function ue(e, n = {}) {
973
+ let { resizable: r = !0, rotatable: i = !0 } = n, a = e.createElement("div");
974
+ if (a.classList.add(P), a.dataset.resizable = String(r), a.dataset.rotatable = String(i), r) for (let [n, r] of [
1711
975
  ["nw", "tl"],
1712
976
  ["n", "tm"],
1713
977
  ["ne", "tr"],
@@ -1717,394 +981,255 @@ function buildWrap(doc, opt = {}) {
1717
981
  ["sw", "bl"],
1718
982
  ["w", "lm"]
1719
983
  ]) {
1720
- const dot = doc.createElement("div");
1721
- dot.classList.add(DOT_CLASS);
1722
- dot.setAttribute(ATTR.handleResizeAttr, "");
1723
- dot.dataset.dir = dir;
1724
- dot.dataset.pos = pos;
1725
- wrap.appendChild(dot);
1726
- }
1727
- if (rotatable) {
1728
- const rotate = doc.createElement("div");
1729
- rotate.classList.add(ROTATE_CLASS);
1730
- rotate.setAttribute(ATTR.handleRotateAttr, "");
1731
- rotate.dataset.dir = "rotate";
1732
- wrap.appendChild(rotate);
1733
- }
1734
- return wrap;
984
+ let i = e.createElement("div");
985
+ i.classList.add(F), i.setAttribute(t.handleResizeAttr, ""), i.dataset.dir = n, i.dataset.pos = r, a.appendChild(i);
986
+ }
987
+ if (i) {
988
+ let n = e.createElement("div");
989
+ n.classList.add(I), n.setAttribute(t.handleRotateAttr, ""), n.dataset.dir = "rotate", a.appendChild(n);
990
+ }
991
+ return a;
1735
992
  }
1736
- function removeWrap(el) {
1737
- if (!isHTMLElement(el)) return;
1738
- el.querySelector?.(`.${ACTIVE_WRAP_CLASS}`)?.remove();
993
+ function L(e) {
994
+ g(e) && e.querySelector?.(`.${P}`)?.remove();
1739
995
  }
1740
- function ensureWrapIfScoped(el) {
1741
- if (!isHTMLElement(el)) return;
1742
- const scoped = !!el.closest?.(SCOPE_SEL);
1743
- let existedWrap = el.querySelector?.(`.draggable-dot-wrap`) || null;
1744
- let hasWrap = !!existedWrap;
1745
- const resizable = isToggleEnabled(el, ATTR.resizableAttr, true);
1746
- const rotatable = isToggleEnabled(el, ATTR.rotatableAttr, true);
1747
- const needWrap = resizable || rotatable;
1748
- if (!scoped) {
1749
- if (hasWrap) removeWrap(el);
996
+ function R(e) {
997
+ if (!g(e)) return;
998
+ let n = !!e.closest?.(y), r = e.querySelector?.(".draggable-dot-wrap") || null, i = !!r, a = m(e, t.resizableAttr, !0), o = m(e, t.rotatableAttr, !0), s = a || o;
999
+ if (!n) {
1000
+ i && L(e);
1750
1001
  return;
1751
1002
  }
1752
- if (!needWrap) {
1753
- if (hasWrap) removeWrap(el);
1003
+ if (!s) {
1004
+ i && L(e);
1754
1005
  return;
1755
1006
  }
1756
- if (!!existedWrap && (String(existedWrap.dataset?.resizable) !== String(resizable) || String(existedWrap.dataset?.rotatable) !== String(rotatable))) {
1757
- existedWrap.remove();
1758
- existedWrap = null;
1759
- hasWrap = false;
1760
- }
1761
- if (!hasWrap) {
1762
- const pos = getComputedStyle(el).position;
1763
- if (pos === "static" || !pos) el.style.position = "relative";
1764
- el.appendChild(buildWrap(el.ownerDocument || document, {
1765
- resizable,
1766
- rotatable
1007
+ if (r && (String(r.dataset?.resizable) !== String(a) || String(r.dataset?.rotatable) !== String(o)) && (r.remove(), r = null, i = !1), !i) {
1008
+ let t = getComputedStyle(e).position;
1009
+ (t === "static" || !t) && (e.style.position = "relative"), e.appendChild(ue(e.ownerDocument || document, {
1010
+ resizable: a,
1011
+ rotatable: o
1767
1012
  }));
1768
1013
  }
1769
1014
  }
1770
- /**
1771
- * 清理一个选中值(可能是数组[多选]或单个元素):移除 active class + wrap。
1772
- * toggleFn 可选:若传入则走帧队列(ctx.frame.toggleClass),否则直接 classList。
1773
- */
1774
- function clearSelectionValue(value, toggleFn) {
1775
- if (!value) return;
1776
- const els = Array.isArray(value) ? value : [value];
1777
- for (const el of els) {
1778
- if (toggleFn) toggleFn(el, CLASS_NAMES.active, false);
1779
- else el?.classList?.remove?.(CLASS_NAMES.active);
1780
- removeWrap(el);
1781
- }
1015
+ function z(e, t) {
1016
+ if (!e) return;
1017
+ let r = Array.isArray(e) ? e : [e];
1018
+ for (let e of r) t ? t(e, n.active, !1) : e?.classList?.remove?.(n.active), L(e);
1782
1019
  }
1783
- function setActiveWithWrap(ctx, map, dragEl, ns) {
1784
- const prev = map.get(ns);
1785
- if (prev && prev !== dragEl) clearSelectionValue(prev);
1786
- dragEl.classList.add(CLASS_NAMES.active);
1787
- ensureWrapIfScoped(dragEl);
1788
- map.set(ns, dragEl);
1020
+ function B(e, t, r, i) {
1021
+ let a = t.get(i);
1022
+ a && a !== r && z(a), r.classList.add(n.active), R(r), t.set(i, r);
1789
1023
  }
1790
- function setMultipleActive(map, elements, ns) {
1791
- clearSelectionValue(map.get(ns));
1792
- for (const el of elements) {
1793
- el.classList.add(CLASS_NAMES.active);
1794
- ensureWrapIfScoped(el);
1795
- }
1796
- map.set(ns, elements);
1024
+ function V(e, t, r) {
1025
+ z(e.get(r));
1026
+ for (let e of t) e.classList.add(n.active), R(e);
1027
+ e.set(r, t);
1797
1028
  }
1798
- function clearAll(map, namespace) {
1799
- if (namespace !== void 0) {
1800
- const val = map.get(namespace);
1801
- if (val) {
1802
- clearSelectionValue(val);
1803
- map.delete(namespace);
1804
- }
1029
+ function H(e, t) {
1030
+ if (t !== void 0) {
1031
+ let n = e.get(t);
1032
+ n && (z(n), e.delete(t));
1805
1033
  return;
1806
1034
  }
1807
- for (const val of map.values()) clearSelectionValue(val);
1808
- map.clear();
1035
+ for (let t of e.values()) z(t);
1036
+ e.clear();
1809
1037
  }
1810
- var ActiveSelectionService = class {
1038
+ var U = class {
1811
1039
  order = -50;
1812
- #dnd;
1813
- onAttach(dnd) {
1814
- this.#dnd = dnd;
1815
- }
1816
- onRootChange(nextRoot, _prevRoot, signal) {
1817
- if (!isHTMLElement(nextRoot)) return;
1818
- const monitor = this.#dnd.monitor;
1819
- nextRoot.addEventListener("pointerdown", (e) => {
1820
- if (e.button !== 0) return;
1821
- if (isIgnoreClick(e.target)) return;
1822
- const map = monitor.selectedByNs;
1823
- if (!map) return;
1824
- const drag = monitor.adapter.closestDraggable(e.target);
1825
- if (!drag) {
1826
- clearAll(map);
1040
+ #e;
1041
+ onAttach(e) {
1042
+ this.#e = e;
1043
+ }
1044
+ onRootChange(e, t, n) {
1045
+ if (!g(e)) return;
1046
+ let r = this.#e.monitor;
1047
+ e.addEventListener("pointerdown", (e) => {
1048
+ if (e.button !== 0 || _(e.target)) return;
1049
+ let t = r.selectedByNs;
1050
+ if (!t) return;
1051
+ let n = r.adapter.closestDraggable(e.target);
1052
+ if (!n) {
1053
+ H(t);
1827
1054
  return;
1828
1055
  }
1829
- const ns = monitor.adapter.getNamespace(drag);
1830
- const prev = map.get(ns);
1831
- if (Array.isArray(prev) && prev.length > 1 && prev.includes(drag)) return;
1832
- setActiveWithWrap(null, map, drag, ns);
1056
+ let i = r.adapter.getNamespace(n), a = t.get(i);
1057
+ Array.isArray(a) && a.length > 1 && a.includes(n) || B(null, t, n, i);
1833
1058
  }, {
1834
- capture: true,
1835
- signal
1059
+ capture: !0,
1060
+ signal: n
1836
1061
  });
1837
1062
  }
1838
- onDown(ctx, event) {
1839
- const m = ctx?.session;
1840
- if (!m?.sourceEl || event?.button !== 0) return;
1841
- if (isIgnoreClick(event.target)) return;
1842
- const map = ctx.store?.selectedByNs || m.selectedByNs;
1843
- if (!map) return;
1844
- const ns = m.namespace || ctx.adapter.getNamespace(m.sourceEl);
1845
- const prev = map.get(ns);
1846
- if (Array.isArray(prev) && prev.length > 1 && prev.includes(m.sourceEl)) return;
1847
- if (prev && prev !== m.sourceEl) clearSelectionValue(prev, (el, cls, on) => ctx.frame.toggleClass(el, cls, on));
1848
- ctx.frame.toggleClass(m.sourceEl, CLASS_NAMES.active, true);
1849
- ensureWrapIfScoped(m.sourceEl);
1850
- map.set(ns, m.sourceEl);
1851
- }
1852
- onDestroy(_dnd, session) {
1853
- const map = session?.selectedByNs;
1854
- if (!map) return;
1855
- clearAll(map);
1063
+ onDown(e, t) {
1064
+ let r = e?.session;
1065
+ if (!r?.sourceEl || t?.button !== 0 || _(t.target)) return;
1066
+ let i = e.store?.selectedByNs || r.selectedByNs;
1067
+ if (!i) return;
1068
+ let a = r.namespace || e.adapter.getNamespace(r.sourceEl), o = i.get(a);
1069
+ Array.isArray(o) && o.length > 1 && o.includes(r.sourceEl) || (o && o !== r.sourceEl && z(o, (t, n, r) => e.frame.toggleClass(t, n, r)), e.frame.toggleClass(r.sourceEl, n.active, !0), R(r.sourceEl), i.set(a, r.sourceEl));
1070
+ }
1071
+ onDestroy(e, t) {
1072
+ let n = t?.selectedByNs;
1073
+ n && H(n);
1856
1074
  }
1857
1075
  };
1858
1076
  //#endregion
1859
1077
  //#region src/services/MarqueeSelectionService.js
1860
- function normalizeRect(x1, y1, x2, y2) {
1078
+ function de(e, t, n, r) {
1861
1079
  return {
1862
- left: Math.min(x1, x2),
1863
- right: Math.max(x1, x2),
1864
- top: Math.min(y1, y2),
1865
- bottom: Math.max(y1, y2),
1866
- width: Math.abs(x2 - x1),
1867
- height: Math.abs(y2 - y1)
1080
+ left: Math.min(e, n),
1081
+ right: Math.max(e, n),
1082
+ top: Math.min(t, r),
1083
+ bottom: Math.max(t, r),
1084
+ width: Math.abs(n - e),
1085
+ height: Math.abs(r - t)
1868
1086
  };
1869
1087
  }
1870
- function isHalfOverlap(selectRect, elementRect) {
1871
- const overlapLeft = Math.max(selectRect.left, elementRect.left);
1872
- const overlapRight = Math.min(selectRect.right, elementRect.right);
1873
- const overlapTop = Math.max(selectRect.top, elementRect.top);
1874
- const overlapBottom = Math.min(selectRect.bottom, elementRect.bottom);
1875
- const overlapW = overlapRight - overlapLeft;
1876
- const overlapH = overlapBottom - overlapTop;
1877
- if (overlapW <= 0 || overlapH <= 0) return false;
1878
- return overlapW * overlapH > (elementRect.right - elementRect.left) * (elementRect.bottom - elementRect.top) * MARQUEE_OVERLAP_RATIO;
1088
+ function fe(e, t) {
1089
+ let n = Math.max(e.left, t.left), r = Math.min(e.right, t.right), i = Math.max(e.top, t.top), a = Math.min(e.bottom, t.bottom), o = r - n, c = a - i;
1090
+ return o <= 0 || c <= 0 ? !1 : o * c > (t.right - t.left) * (t.bottom - t.top) * s;
1879
1091
  }
1880
- var MarqueeSelectionService = class {
1092
+ var pe = class {
1881
1093
  order = -40;
1882
- #dnd;
1883
- #rootSignal;
1884
- onAttach(dnd) {
1885
- this.#dnd = dnd;
1886
- }
1887
- onRootChange(nextRoot, _prevRoot, signal) {
1888
- this.#rootSignal = signal;
1889
- if (!isHTMLElement(nextRoot)) return;
1890
- nextRoot.addEventListener("pointerdown", (e) => {
1891
- if (e.button !== 0) return;
1892
- if (isIgnoreClick(e.target)) return;
1893
- const scope = e.target.closest(SCOPE_SEL);
1894
- if (!scope) return;
1895
- if (this.#dnd.monitor.adapter.closestDraggable(e.target)) return;
1896
- this.#startMarquee(scope, e);
1094
+ #e;
1095
+ #t;
1096
+ onAttach(e) {
1097
+ this.#e = e;
1098
+ }
1099
+ onRootChange(e, t, n) {
1100
+ this.#t = n, g(e) && e.addEventListener("pointerdown", (e) => {
1101
+ if (e.button !== 0 || _(e.target)) return;
1102
+ let t = e.target.closest(y);
1103
+ t && (this.#e.monitor.adapter.closestDraggable(e.target) || this.#n(t, e));
1897
1104
  }, {
1898
- capture: true,
1899
- signal
1105
+ capture: !0,
1106
+ signal: n
1900
1107
  });
1901
1108
  }
1902
- #startMarquee(scope, startEvent) {
1903
- const startX = startEvent.clientX;
1904
- const startY = startEvent.clientY;
1905
- const adapter = this.#dnd.monitor.adapter;
1906
- const namespace = adapter.getNamespace(scope);
1907
- const scaleRatio = parseFloat(scope.getAttribute(ATTR.scaleRatioAttr) || "1");
1908
- const marquee = document.createElement("div");
1909
- marquee.classList.add(CLASS_NAMES.marquee);
1910
- scope.appendChild(marquee);
1911
- const scopeRect = scope.getBoundingClientRect();
1912
- const candidates = [];
1913
- for (const el of scope.querySelectorAll(`[${ATTR.dragAttr}], [${ATTR.dragdropAttr}]`)) if (adapter.getNamespace(el) === namespace) candidates.push(el);
1914
- let hasMoved = false;
1915
- let rafId = 0;
1916
- let lastEvent = null;
1917
- const rootSignal = this.#rootSignal;
1918
- const sessionAbort = new AbortController();
1919
- const onRootAbort = () => cleanup();
1920
- const cleanup = () => {
1921
- if (sessionAbort.signal.aborted) return;
1922
- if (rafId) {
1923
- cancelAnimationFrame(rafId);
1924
- rafId = 0;
1109
+ #n(e, r) {
1110
+ let i = r.clientX, o = r.clientY, s = this.#e.monitor.adapter, c = s.getNamespace(e), l = parseFloat(e.getAttribute(t.scaleRatioAttr) || "1"), u = document.createElement("div");
1111
+ u.classList.add(n.marquee), e.appendChild(u);
1112
+ let d = e.getBoundingClientRect(), f = [];
1113
+ for (let n of e.querySelectorAll(`[${t.dragAttr}], [${t.dragdropAttr}]`)) s.getNamespace(n) === c && f.push(n);
1114
+ let p = !1, m = 0, h = null, g = this.#t, _ = new AbortController(), v = () => y(), y = () => {
1115
+ if (!_.signal.aborted) {
1116
+ m &&= (cancelAnimationFrame(m), 0), g?.removeEventListener?.("abort", v);
1117
+ try {
1118
+ u.remove();
1119
+ } catch {}
1120
+ _.abort();
1925
1121
  }
1926
- rootSignal?.removeEventListener?.("abort", onRootAbort);
1927
- try {
1928
- marquee.remove();
1929
- } catch (_) {}
1930
- sessionAbort.abort();
1931
- };
1932
- const processMove = () => {
1933
- rafId = 0;
1934
- const e = lastEvent;
1122
+ }, b = () => {
1123
+ m = 0;
1124
+ let e = h;
1935
1125
  if (!e) return;
1936
- const rect = normalizeRect(startX, startY, e.clientX, e.clientY);
1937
- this.#updateMarqueeDOM(marquee, rect, scopeRect, scaleRatio);
1938
- const selected = this.#detectCollisions(candidates, adapter, rect);
1939
- const map = this.#dnd.monitor.selectedByNs;
1940
- if (map) {
1941
- clearAll(map, namespace);
1942
- if (selected.length > 0) setMultipleActive(map, selected, namespace);
1943
- }
1944
- };
1945
- const onMove = (e) => {
1946
- const dx = e.clientX - startX;
1947
- const dy = e.clientY - startY;
1948
- if (!hasMoved && Math.abs(dx) < THRESHOLDS.MARQUEE_MOVE && Math.abs(dy) < THRESHOLDS.MARQUEE_MOVE) return;
1949
- hasMoved = true;
1950
- lastEvent = e;
1951
- if (!rafId) rafId = requestAnimationFrame(processMove);
1952
- };
1953
- const onUp = () => {
1954
- if (!hasMoved) {
1955
- const map = this.#dnd.monitor?.selectedByNs;
1956
- if (map) clearAll(map, namespace);
1126
+ let t = de(i, o, e.clientX, e.clientY);
1127
+ this.#r(u, t, d, l);
1128
+ let n = this.#i(f, s, t), r = this.#e.monitor.selectedByNs;
1129
+ r && (H(r, c), n.length > 0 && V(r, n, c));
1130
+ }, x = (e) => {
1131
+ let t = e.clientX - i, n = e.clientY - o;
1132
+ !p && Math.abs(t) < a.MARQUEE_MOVE && Math.abs(n) < a.MARQUEE_MOVE || (p = !0, h = e, m ||= requestAnimationFrame(b));
1133
+ }, S = () => {
1134
+ if (!p) {
1135
+ let e = this.#e.monitor?.selectedByNs;
1136
+ e && H(e, c);
1957
1137
  }
1958
- cleanup();
1138
+ y();
1959
1139
  };
1960
- if (rootSignal?.aborted) {
1961
- cleanup();
1140
+ if (g?.aborted) {
1141
+ y();
1962
1142
  return;
1963
1143
  }
1964
- rootSignal?.addEventListener?.("abort", onRootAbort, { once: true });
1965
- const opts = { signal: sessionAbort.signal };
1966
- document.addEventListener("pointermove", onMove, opts);
1967
- document.addEventListener("pointerup", onUp, opts);
1968
- document.addEventListener("pointercancel", cleanup, opts);
1969
- window.addEventListener("blur", cleanup, opts);
1970
- }
1971
- #updateMarqueeDOM(marquee, rect, scopeRect, scaleRatio) {
1972
- const left = (rect.left - scopeRect.left) / scaleRatio;
1973
- const top = (rect.top - scopeRect.top) / scaleRatio;
1974
- const width = rect.width / scaleRatio;
1975
- const height = rect.height / scaleRatio;
1976
- marquee.style.left = `${left}px`;
1977
- marquee.style.top = `${top}px`;
1978
- marquee.style.width = `${width}px`;
1979
- marquee.style.height = `${height}px`;
1980
- }
1981
- #detectCollisions(candidates, adapter, selectRect) {
1982
- const selected = [];
1983
- for (const el of candidates) {
1984
- const elRect = adapter.measureRect(el);
1985
- if (elRect && isHalfOverlap(selectRect, elRect)) selected.push(el);
1144
+ g?.addEventListener?.("abort", v, { once: !0 });
1145
+ let C = { signal: _.signal };
1146
+ document.addEventListener("pointermove", x, C), document.addEventListener("pointerup", S, C), document.addEventListener("pointercancel", y, C), window.addEventListener("blur", y, C);
1147
+ }
1148
+ #r(e, t, n, r) {
1149
+ let i = (t.left - n.left) / r, a = (t.top - n.top) / r, o = t.width / r, s = t.height / r;
1150
+ e.style.left = `${i}px`, e.style.top = `${a}px`, e.style.width = `${o}px`, e.style.height = `${s}px`;
1151
+ }
1152
+ #i(e, t, n) {
1153
+ let r = [];
1154
+ for (let i of e) {
1155
+ let e = t.measureRect(i);
1156
+ e && fe(n, e) && r.push(i);
1986
1157
  }
1987
- return selected;
1158
+ return r;
1988
1159
  }
1989
1160
  };
1990
1161
  //#endregion
1991
1162
  //#region src/services/transform/utils/geometry.js
1992
- /**
1993
- * 几何计算工具函数
1994
- */
1995
- /**
1996
- * 添加单位(px),保留亚像素精度(四舍五入到 2 位小数去除浮点噪声)
1997
- */
1998
- function withUnit(v = 0) {
1999
- const n = Number(v);
2000
- if (!Number.isFinite(n)) return "0px";
2001
- return `${Math.round(n * 100) / 100}px`;
1163
+ function W(e = 0) {
1164
+ let t = Number(e);
1165
+ return Number.isFinite(t) ? `${Math.round(t * 100) / 100}px` : "0px";
2002
1166
  }
2003
- /**
2004
- * 角度转弧度
2005
- */
2006
- function toRad(deg) {
2007
- return deg * Math.PI / 180;
1167
+ function G(e) {
1168
+ return e * Math.PI / 180;
2008
1169
  }
2009
- /**
2010
- * 计算向量长度
2011
- */
2012
- function getLength(x, y) {
2013
- return Math.sqrt(x * x + y * y);
1170
+ function me(e, t) {
1171
+ return Math.sqrt(e * e + t * t);
2014
1172
  }
2015
- /**
2016
- * 网格吸附计算
2017
- */
2018
- function calcGrid(diff, grid) {
2019
- const g = Math.max(1, Number(grid) || 1);
2020
- const r = Math.abs(diff) % g;
2021
- const mul = diff > 0 ? g : -g;
2022
- if (r > g / 2) return mul * Math.ceil(Math.abs(diff) / g);
2023
- return mul * Math.floor(Math.abs(diff) / g);
1173
+ function K(e, t) {
1174
+ let n = Math.max(1, Number(t) || 1), r = Math.abs(e) % n, i = e > 0 ? n : -n;
1175
+ return r > n / 2 ? i * Math.ceil(Math.abs(e) / n) : i * Math.floor(Math.abs(e) / n);
2024
1176
  }
2025
- /**
2026
- * 根据缩放比例获取元素矩形
2027
- */
2028
- function getRectByScale(el, scale = 1, adapter) {
2029
- const r = adapter.measureRect(el);
2030
- const s = Number(scale) || 1;
1177
+ function q(e, t = 1, n) {
1178
+ let r = n.measureRect(e), i = Number(t) || 1;
2031
1179
  return {
2032
- bottom: r.bottom / s,
2033
- height: r.height / s,
2034
- left: r.left / s,
2035
- right: r.right / s,
2036
- top: r.top / s,
2037
- width: r.width / s
1180
+ bottom: r.bottom / i,
1181
+ height: r.height / i,
1182
+ left: r.left / i,
1183
+ right: r.right / i,
1184
+ top: r.top / i,
1185
+ width: r.width / i
2038
1186
  };
2039
1187
  }
2040
- /**
2041
- * 计算指针相对中心点的角度
2042
- */
2043
- function angleToPointer(cx, cy, px, py) {
2044
- const dx = px - cx;
2045
- const dy = py - cy;
2046
- let deg = Math.atan2(dy, dx) * 180 / Math.PI + 90;
2047
- deg = (deg % 360 + 360) % 360;
2048
- return deg;
1188
+ function J(e, t, n, r) {
1189
+ let i = n - e, a = r - t, o = Math.atan2(a, i) * 180 / Math.PI + 90;
1190
+ return o = (o % 360 + 360) % 360, o;
2049
1191
  }
2050
- /**
2051
- * 格式化变换数据(中心点坐标系)
2052
- */
2053
- function formatData(data, cx, cy) {
2054
- const { width, height } = data;
1192
+ function he(e, t, n) {
1193
+ let { width: r, height: i } = e;
2055
1194
  return {
2056
- height: Math.abs(height),
2057
- width: Math.abs(width),
2058
- x: cx - Math.abs(width) / 2,
2059
- y: cy - Math.abs(height) / 2
1195
+ height: Math.abs(i),
1196
+ width: Math.abs(r),
1197
+ x: t - Math.abs(r) / 2,
1198
+ y: n - Math.abs(i) / 2
2060
1199
  };
2061
1200
  }
2062
- /**
2063
- * 中心点坐标转左上角坐标
2064
- */
2065
- function centerToTL({ centerX, centerY, width, height, angle }) {
1201
+ function ge({ centerX: e, centerY: t, width: n, height: r, angle: i }) {
2066
1202
  return {
2067
- angle,
2068
- height,
2069
- width,
2070
- x: centerX - width / 2,
2071
- y: centerY - height / 2
1203
+ angle: i,
1204
+ height: r,
1205
+ width: n,
1206
+ x: e - n / 2,
1207
+ y: t - r / 2
2072
1208
  };
2073
1209
  }
2074
- /**
2075
- * 获取元素的 transform 信息
2076
- */
2077
- function getElementTransformInfo(el) {
2078
- const style = getComputedStyle(el);
2079
- let matrix = {};
1210
+ function Y(e) {
1211
+ let t = getComputedStyle(e), n = {};
2080
1212
  try {
2081
- matrix = new DOMMatrixReadOnly(style.transform);
1213
+ n = new DOMMatrixReadOnly(t.transform);
2082
1214
  } catch {
2083
- matrix = new DOMMatrixReadOnly();
1215
+ n = new DOMMatrixReadOnly();
2084
1216
  }
2085
- const x = matrix.m41;
2086
- const y = matrix.m42;
2087
- let width = Number.parseFloat(style.width);
2088
- let height = Number.parseFloat(style.height);
2089
- if (!Number.isFinite(width) || !Number.isFinite(height)) {
2090
- const r = el.getBoundingClientRect();
2091
- width = r.width;
2092
- height = r.height;
1217
+ let r = n.m41, i = n.m42, a = Number.parseFloat(t.width), o = Number.parseFloat(t.height);
1218
+ if (!Number.isFinite(a) || !Number.isFinite(o)) {
1219
+ let t = e.getBoundingClientRect();
1220
+ a = t.width, o = t.height;
2093
1221
  }
2094
1222
  return {
2095
- angle: -Math.atan2(matrix.m21, matrix.m11) * (180 / Math.PI),
2096
- height,
2097
- width,
2098
- x,
2099
- y
1223
+ angle: -Math.atan2(n.m21, n.m11) * (180 / Math.PI),
1224
+ height: o,
1225
+ width: a,
1226
+ x: r,
1227
+ y: i
2100
1228
  };
2101
1229
  }
2102
1230
  //#endregion
2103
1231
  //#region src/services/transform/utils/cursor.js
2104
- /**
2105
- * 光标映射工具
2106
- */
2107
- var resizableMap = {
1232
+ var _e = {
2108
1233
  e: "right",
2109
1234
  n: "top",
2110
1235
  ne: "top-right",
@@ -2113,8 +1238,7 @@ var resizableMap = {
2113
1238
  se: "bottom-right",
2114
1239
  sw: "bottom-left",
2115
1240
  w: "left"
2116
- };
2117
- var cursorDir = [
1241
+ }, ve = [
2118
1242
  "n",
2119
1243
  "ne",
2120
1244
  "e",
@@ -2123,8 +1247,7 @@ var cursorDir = [
2123
1247
  "sw",
2124
1248
  "w",
2125
1249
  "nw"
2126
- ];
2127
- var cursorMap = {
1250
+ ], ye = {
2128
1251
  0: 0,
2129
1252
  1: 1,
2130
1253
  2: 1,
@@ -2137,8 +1260,7 @@ var cursorMap = {
2137
1260
  9: 6,
2138
1261
  10: 7,
2139
1262
  11: 7
2140
- };
2141
- var cursorStartMap = {
1263
+ }, be = {
2142
1264
  e: 2,
2143
1265
  n: 0,
2144
1266
  ne: 1,
@@ -2148,445 +1270,251 @@ var cursorStartMap = {
2148
1270
  sw: 5,
2149
1271
  w: 6
2150
1272
  };
2151
- /**
2152
- * 根据旋转角度和方向获取光标样式
2153
- */
2154
- function getCursor(angle, d) {
2155
- const inc = cursorMap[Math.floor((angle % 360 + 360) % 360 / 30)];
2156
- return cursorDir[(cursorStartMap[d] + inc) % 8];
1273
+ function xe(e, t) {
1274
+ let n = ye[Math.floor((e % 360 + 360) % 360 / 30)];
1275
+ return ve[(be[t] + n) % 8];
2157
1276
  }
2158
1277
  //#endregion
2159
1278
  //#region src/services/transform/utils/markline.js
2160
- /**
2161
- * Markline(对齐辅助线)工具
2162
- */
2163
- /**
2164
- * 计算对齐线
2165
- * @param {Array} list - 其他元素的位置信息列表
2166
- * @param {Object} current - 当前元素的位置信息
2167
- * @returns {Object} 对齐线信息
2168
- */
2169
- function calcLines(list, current) {
2170
- const lines = {
1279
+ function Se(e, t) {
1280
+ let n = {
2171
1281
  x: [],
2172
1282
  y: []
2173
- };
2174
- const { width = 0, height = 0 } = current;
2175
- list.forEach((b) => {
2176
- const { top: ATop, left: ALeft, width: AWidth, height: AHeight } = b;
2177
- lines.y.push({
2178
- showTop: ATop,
2179
- top: ATop
2180
- });
2181
- lines.y.push({
2182
- showTop: ATop,
2183
- top: ATop - height
1283
+ }, { width: r = 0, height: i = 0 } = t;
1284
+ return e.forEach((e) => {
1285
+ let { top: t, left: a, width: o, height: s } = e;
1286
+ n.y.push({
1287
+ showTop: t,
1288
+ top: t
1289
+ }), n.y.push({
1290
+ showTop: t,
1291
+ top: t - i
1292
+ }), n.y.push({
1293
+ showTop: t + s / 2,
1294
+ top: t + s / 2 - i / 2
1295
+ }), n.y.push({
1296
+ showTop: t + s,
1297
+ top: t + s
1298
+ }), n.y.push({
1299
+ showTop: t + s,
1300
+ top: t + s - i
1301
+ }), n.x.push({
1302
+ left: a,
1303
+ showLeft: a
1304
+ }), n.x.push({
1305
+ left: a + o,
1306
+ showLeft: a + o
1307
+ }), n.x.push({
1308
+ left: a + o / 2 - r / 2,
1309
+ showLeft: a + o / 2
1310
+ }), n.x.push({
1311
+ left: a + o - r,
1312
+ showLeft: a + o
1313
+ }), n.x.push({
1314
+ left: a - r,
1315
+ showLeft: a
2184
1316
  });
2185
- lines.y.push({
2186
- showTop: ATop + AHeight / 2,
2187
- top: ATop + AHeight / 2 - height / 2
2188
- });
2189
- lines.y.push({
2190
- showTop: ATop + AHeight,
2191
- top: ATop + AHeight
2192
- });
2193
- lines.y.push({
2194
- showTop: ATop + AHeight,
2195
- top: ATop + AHeight - height
2196
- });
2197
- lines.x.push({
2198
- left: ALeft,
2199
- showLeft: ALeft
2200
- });
2201
- lines.x.push({
2202
- left: ALeft + AWidth,
2203
- showLeft: ALeft + AWidth
2204
- });
2205
- lines.x.push({
2206
- left: ALeft + AWidth / 2 - width / 2,
2207
- showLeft: ALeft + AWidth / 2
2208
- });
2209
- lines.x.push({
2210
- left: ALeft + AWidth - width,
2211
- showLeft: ALeft + AWidth
2212
- });
2213
- lines.x.push({
2214
- left: ALeft - width,
2215
- showLeft: ALeft
2216
- });
2217
- });
2218
- return lines;
1317
+ }), n;
2219
1318
  }
2220
- /**
2221
- * Resize 专用吸附解算(纯函数)
2222
- *
2223
- * 与 calcLines(为 move 设计、把当前 width/height 烘进候选线)不同:
2224
- * resize 只把「正在拖动的那条边」吸附到邻居的裸边(left/中线/right,top/中线/bottom),
2225
- * 对侧边保持锚定。返回移动边需要的位移 diff 与命中线在 viewport 坐标的位置 guide。
2226
- *
2227
- * @param {Object} arg
2228
- * @param {string} arg.side - left/right/top/bottom/top-left/top-right/bottom-left/bottom-right
2229
- * @param {Object} arg.source - 当前盒子矩形(viewport-scaled,含 left/right/top/bottom)
2230
- * @param {Array} arg.targetRects - 邻居元素矩形列表(viewport-scaled,含 left/top/width/height)
2231
- * @param {number} arg.threshold - 吸附阈值(viewport-scaled 像素)
2232
- * @returns {{diffX:number, diffY:number, guideLeft:(number|undefined), guideTop:(number|undefined)}}
2233
- */
2234
- function resolveResizeSnap({ side = "", source, targetRects = [], threshold = 10 }) {
2235
- const result = {
1319
+ function Ce({ side: e = "", source: t, targetRects: n = [], threshold: r = 10 }) {
1320
+ let i = {
2236
1321
  diffX: 0,
2237
1322
  diffY: 0,
2238
1323
  guideLeft: void 0,
2239
1324
  guideTop: void 0
2240
1325
  };
2241
- if (!source) return result;
2242
- const movesLeft = side.includes("left");
2243
- const movesRight = side.includes("right");
2244
- const movesTop = side.includes("top");
2245
- const movesBottom = side.includes("bottom");
2246
- if (movesLeft || movesRight) {
2247
- const edge = movesLeft ? source.left : source.right;
2248
- for (const t of targetRects) {
2249
- const candidates = [
1326
+ if (!t) return i;
1327
+ let a = e.includes("left"), o = e.includes("right"), s = e.includes("top"), c = e.includes("bottom");
1328
+ if (a || o) {
1329
+ let e = a ? t.left : t.right;
1330
+ for (let t of n) {
1331
+ let n = [
2250
1332
  t.left,
2251
1333
  t.left + t.width / 2,
2252
1334
  t.left + t.width
2253
- ];
2254
- let hit;
2255
- for (const c of candidates) if (Math.abs(c - edge) < threshold) {
2256
- hit = c;
1335
+ ], a;
1336
+ for (let t of n) if (Math.abs(t - e) < r) {
1337
+ a = t;
2257
1338
  break;
2258
1339
  }
2259
- if (hit !== void 0) {
2260
- result.diffX = hit - edge;
2261
- result.guideLeft = hit;
1340
+ if (a !== void 0) {
1341
+ i.diffX = a - e, i.guideLeft = a;
2262
1342
  break;
2263
1343
  }
2264
1344
  }
2265
1345
  }
2266
- if (movesTop || movesBottom) {
2267
- const edge = movesTop ? source.top : source.bottom;
2268
- for (const t of targetRects) {
2269
- const candidates = [
1346
+ if (s || c) {
1347
+ let e = s ? t.top : t.bottom;
1348
+ for (let t of n) {
1349
+ let n = [
2270
1350
  t.top,
2271
1351
  t.top + t.height / 2,
2272
1352
  t.top + t.height
2273
- ];
2274
- let hit;
2275
- for (const c of candidates) if (Math.abs(c - edge) < threshold) {
2276
- hit = c;
1353
+ ], a;
1354
+ for (let t of n) if (Math.abs(t - e) < r) {
1355
+ a = t;
2277
1356
  break;
2278
1357
  }
2279
- if (hit !== void 0) {
2280
- result.diffY = hit - edge;
2281
- result.guideTop = hit;
1358
+ if (a !== void 0) {
1359
+ i.diffY = a - e, i.guideTop = a;
2282
1360
  break;
2283
1361
  }
2284
1362
  }
2285
1363
  }
2286
- return result;
1364
+ return i;
2287
1365
  }
2288
- /**
2289
- * 创建临时对齐线容器
2290
- */
2291
- function createTempMarklines(container) {
2292
- let x = container.querySelector(".draggable-markline-x");
2293
- let y = container.querySelector(".draggable-markline-y");
2294
- if (!x) {
2295
- x = document.createElement("div");
2296
- x.className = "draggable-markline-x";
2297
- container.appendChild(x);
2298
- }
2299
- if (!y) {
2300
- y = document.createElement("div");
2301
- y.className = "draggable-markline-y";
2302
- container.appendChild(y);
2303
- }
2304
- return {
2305
- x,
2306
- y
1366
+ function X(e) {
1367
+ let t = e.querySelector(".draggable-markline-x"), n = e.querySelector(".draggable-markline-y");
1368
+ return t || (t = document.createElement("div"), t.className = "draggable-markline-x", e.appendChild(t)), n || (n = document.createElement("div"), n.className = "draggable-markline-y", e.appendChild(n)), {
1369
+ x: t,
1370
+ y: n
2307
1371
  };
2308
1372
  }
2309
- /**
2310
- * 隐藏对齐线
2311
- */
2312
- function hideMarkline(el) {
2313
- if (!el) return;
2314
- el.style.display = "none";
1373
+ function Z(e) {
1374
+ e && (e.style.display = "none");
2315
1375
  }
2316
1376
  //#endregion
2317
1377
  //#region src/services/transform/utils/resize.js
2318
- /**
2319
- * Resize 尺寸计算工具
2320
- */
2321
- /**
2322
- * 设置宽度和增量,考虑最小宽度限制
2323
- */
2324
- function setWidthAndDeltaW(width, deltaW, minWidth) {
2325
- const expected = width + deltaW;
2326
- if (expected > minWidth) width = expected;
2327
- else {
2328
- deltaW = minWidth - width;
2329
- width = minWidth;
2330
- }
2331
- return {
2332
- deltaW,
2333
- width
1378
+ function Q(e, t, n) {
1379
+ let r = e + t;
1380
+ return r > n ? e = r : (t = n - e, e = n), {
1381
+ deltaW: t,
1382
+ width: e
2334
1383
  };
2335
1384
  }
2336
- /**
2337
- * 设置高度和增量,考虑最小高度限制
2338
- */
2339
- function setHeightAndDeltaH(height, deltaH, minHeight) {
2340
- const expected = height + deltaH;
2341
- if (expected > minHeight) height = expected;
2342
- else {
2343
- deltaH = minHeight - height;
2344
- height = minHeight;
2345
- }
2346
- return {
2347
- deltaH,
2348
- height
1385
+ function $(e, t, n) {
1386
+ let r = e + t;
1387
+ return r > n ? e = r : (t = n - e, e = n), {
1388
+ deltaH: t,
1389
+ height: e
2349
1390
  };
2350
1391
  }
2351
- /**
2352
- * 根据 resize 类型计算新的样式
2353
- * @param {string} type - resize 方向(top/right/bottom/left/top-right/...)
2354
- * @param {Object} rect - 当前矩形信息
2355
- * @param {number} deltaW - 宽度变化量
2356
- * @param {number} deltaH - 高度变化量
2357
- * @param {number} ratio - 宽高比(可选)
2358
- * @param {number} minWidth - 最小宽度
2359
- * @param {number} minHeight - 最小高度
2360
- * @returns {Object} 新的样式信息
2361
- */
2362
- function getNewStyle(type, rect, deltaW, deltaH, ratio, minWidth, minHeight) {
2363
- let { width, height, centerX, centerY, rotateAngle } = rect;
2364
- const wf = width < 0 ? -1 : 1;
2365
- const hf = height < 0 ? -1 : 1;
2366
- width = Math.abs(width);
2367
- height = Math.abs(height);
2368
- const rad = toRad(rotateAngle);
2369
- const cos = Math.cos(rad);
2370
- const sin = Math.sin(rad);
2371
- if ([
1392
+ function we(e, t, n, r, i, a, o) {
1393
+ let { width: s, height: c, centerX: l, centerY: u, rotateAngle: d } = t, f = s < 0 ? -1 : 1, p = c < 0 ? -1 : 1;
1394
+ s = Math.abs(s), c = Math.abs(c);
1395
+ let m = G(d), h = Math.cos(m), g = Math.sin(m);
1396
+ switch ([
2372
1397
  "top-left",
2373
1398
  "top-right",
2374
1399
  "bottom-left",
2375
1400
  "bottom-right"
2376
- ].includes(type)) {
2377
- if (type === "top-right") deltaH = -deltaH;
2378
- else if (type === "bottom-left") deltaW = -deltaW;
2379
- else if (type === "top-left") {
2380
- deltaW = -deltaW;
2381
- deltaH = -deltaH;
2382
- }
2383
- ({width, deltaW} = setWidthAndDeltaW(width, deltaW, minWidth));
2384
- ({height, deltaH} = setHeightAndDeltaH(height, deltaH, minHeight));
2385
- if (ratio) {
2386
- deltaH = deltaW / ratio;
2387
- height = width / ratio;
2388
- }
2389
- }
2390
- switch (type) {
1401
+ ].includes(e) && (e === "top-right" ? r = -r : e === "bottom-left" ? n = -n : e === "top-left" && (n = -n, r = -r), {width: s, deltaW: n} = Q(s, n, a), {height: c, deltaH: r} = $(c, r, o), i && (r = n / i, c = s / i)), e) {
2391
1402
  case "right":
2392
- ({width, deltaW} = setWidthAndDeltaW(width, deltaW, minWidth));
2393
- if (ratio) {
2394
- deltaH = deltaW / ratio;
2395
- height = width / ratio;
2396
- centerX += deltaW / 2 * cos - deltaH / 2 * sin;
2397
- centerY += deltaW / 2 * sin + deltaH / 2 * cos;
2398
- } else {
2399
- centerX += deltaW / 2 * cos;
2400
- centerY += deltaW / 2 * sin;
2401
- }
1403
+ ({width: s, deltaW: n} = Q(s, n, a)), i ? (r = n / i, c = s / i, l += n / 2 * h - r / 2 * g, u += n / 2 * g + r / 2 * h) : (l += n / 2 * h, u += n / 2 * g);
2402
1404
  break;
2403
1405
  case "top-right":
2404
- centerX += deltaW / 2 * cos + deltaH / 2 * sin;
2405
- centerY += deltaW / 2 * sin - deltaH / 2 * cos;
1406
+ l += n / 2 * h + r / 2 * g, u += n / 2 * g - r / 2 * h;
2406
1407
  break;
2407
1408
  case "bottom-right":
2408
- centerX += deltaW / 2 * cos - deltaH / 2 * sin;
2409
- centerY += deltaW / 2 * sin + deltaH / 2 * cos;
1409
+ l += n / 2 * h - r / 2 * g, u += n / 2 * g + r / 2 * h;
2410
1410
  break;
2411
1411
  case "bottom":
2412
- ({height, deltaH} = setHeightAndDeltaH(height, deltaH, minHeight));
2413
- if (ratio) {
2414
- deltaW = deltaH * ratio;
2415
- width = height * ratio;
2416
- centerX += deltaW / 2 * cos - deltaH / 2 * sin;
2417
- centerY += deltaW / 2 * sin + deltaH / 2 * cos;
2418
- } else {
2419
- centerX -= deltaH / 2 * sin;
2420
- centerY += deltaH / 2 * cos;
2421
- }
1412
+ ({height: c, deltaH: r} = $(c, r, o)), i ? (n = r * i, s = c * i, l += n / 2 * h - r / 2 * g, u += n / 2 * g + r / 2 * h) : (l -= r / 2 * g, u += r / 2 * h);
2422
1413
  break;
2423
1414
  case "bottom-left":
2424
- centerX -= deltaW / 2 * cos + deltaH / 2 * sin;
2425
- centerY -= deltaW / 2 * sin - deltaH / 2 * cos;
1415
+ l -= n / 2 * h + r / 2 * g, u -= n / 2 * g - r / 2 * h;
2426
1416
  break;
2427
1417
  case "left":
2428
- deltaW = -deltaW;
2429
- ({width, deltaW} = setWidthAndDeltaW(width, deltaW, minWidth));
2430
- if (ratio) {
2431
- height = width / ratio;
2432
- deltaH = deltaW / ratio;
2433
- centerX -= deltaW / 2 * cos + deltaH / 2 * sin;
2434
- centerY -= deltaW / 2 * sin - deltaH / 2 * cos;
2435
- } else {
2436
- centerX -= deltaW / 2 * cos;
2437
- centerY -= deltaW / 2 * sin;
2438
- }
1418
+ n = -n, {width: s, deltaW: n} = Q(s, n, a), i ? (c = s / i, r = n / i, l -= n / 2 * h + r / 2 * g, u -= n / 2 * g - r / 2 * h) : (l -= n / 2 * h, u -= n / 2 * g);
2439
1419
  break;
2440
1420
  case "top-left":
2441
- centerX -= deltaW / 2 * cos - deltaH / 2 * sin;
2442
- centerY -= deltaW / 2 * sin + deltaH / 2 * cos;
1421
+ l -= n / 2 * h - r / 2 * g, u -= n / 2 * g + r / 2 * h;
2443
1422
  break;
2444
1423
  case "top":
2445
- deltaH = -deltaH;
2446
- ({height, deltaH} = setHeightAndDeltaH(height, deltaH, minHeight));
2447
- if (ratio) {
2448
- width = height * ratio;
2449
- deltaW = deltaH * ratio;
2450
- centerX += deltaW / 2 * cos + deltaH / 2 * sin;
2451
- centerY += deltaW / 2 * sin - deltaH / 2 * cos;
2452
- } else {
2453
- centerX += deltaH / 2 * sin;
2454
- centerY -= deltaH / 2 * cos;
2455
- }
1424
+ r = -r, {height: c, deltaH: r} = $(c, r, o), i ? (s = c * i, n = r * i, l += n / 2 * h + r / 2 * g, u += n / 2 * g - r / 2 * h) : (l += r / 2 * g, u -= r / 2 * h);
2456
1425
  break;
2457
1426
  default: break;
2458
1427
  }
2459
1428
  return {
2460
1429
  position: {
2461
- centerX,
2462
- centerY
1430
+ centerX: l,
1431
+ centerY: u
2463
1432
  },
2464
1433
  size: {
2465
- height: height * hf,
2466
- width: width * wf
1434
+ height: c * p,
1435
+ width: s * f
2467
1436
  }
2468
1437
  };
2469
1438
  }
2470
1439
  //#endregion
2471
1440
  //#region src/services/transform/utils/handles.js
2472
- /**
2473
- * Handle(控制点)管理工具
2474
- */
2475
- /**
2476
- * 查找元素内的所有 resize 控制点
2477
- */
2478
- function findDots(el) {
2479
- const wrap = el?.querySelector?.(`:scope > .draggable-dot-wrap`);
2480
- return wrap ? [...wrap.querySelectorAll?.(`.draggable-dot`) || []] : [];
1441
+ function Te(e) {
1442
+ let t = e?.querySelector?.(":scope > .draggable-dot-wrap");
1443
+ return t ? [...t.querySelectorAll?.(".draggable-dot") || []] : [];
2481
1444
  }
2482
- /**
2483
- * handle 元素获取 resize 方向
2484
- */
2485
- function getResizeSideFromHandle(handleEl) {
2486
- const dir = handleEl?.dataset?.dir;
2487
- return dir && resizableMap[dir] || "right";
1445
+ function Ee(e) {
1446
+ let t = e?.dataset?.dir;
1447
+ return t && _e[t] || "right";
2488
1448
  }
2489
- /**
2490
- * 判断是否为 rotate handle
2491
- */
2492
- function isRotateHandle(handleEl) {
2493
- return Boolean(handleEl?.hasAttribute?.(ATTR.handleRotateAttr));
1449
+ function De(e) {
1450
+ return !!e?.hasAttribute?.(t.handleRotateAttr);
2494
1451
  }
2495
- /**
2496
- * 判断是否为 resize handle
2497
- */
2498
- function isResizeHandle(handleEl) {
2499
- return Boolean(handleEl?.hasAttribute?.(ATTR.handleResizeAttr));
1452
+ function Oe(e) {
1453
+ return !!e?.hasAttribute?.(t.handleResizeAttr);
2500
1454
  }
2501
1455
  //#endregion
2502
1456
  //#region src/services/TransformControllerService.js
2503
- var TransformControllerService = class {
1457
+ var ke = class {
2504
1458
  order = 25;
2505
- #opt;
2506
- constructor(options = {}) {
2507
- this.#opt = {
2508
- resizable: true,
2509
- rotatable: true,
2510
- /** 是否限制在 drag-scope 容器内 */
2511
- boundary: true,
2512
- /** 外层缩放比例(画布缩放) */
1459
+ #e;
1460
+ constructor(e = {}) {
1461
+ this.#e = {
1462
+ resizable: !0,
1463
+ rotatable: !0,
1464
+ boundary: !0,
2513
1465
  scaleRatio: 1,
2514
- /** 吸附到网格 */
2515
- snapToGrid: false,
1466
+ snapToGrid: !1,
2516
1467
  gridX: 10,
2517
1468
  gridY: 10,
2518
- /** resize 约束 */
2519
1469
  aspectRatio: void 0,
2520
1470
  minWidth: 10,
2521
1471
  minHeight: 10,
2522
1472
  maxWidth: 0,
2523
1473
  maxHeight: 0,
2524
- /** rotate 吸附 */
2525
- rotateSnap: false,
1474
+ rotateSnap: !1,
2526
1475
  rotateStep: 15,
2527
- /** markline + snap */
2528
- snap: true,
1476
+ snap: !0,
2529
1477
  snapThreshold: 10,
2530
- markline: true,
2531
- /** 在 drag-scope 内默认关闭镜像与 drop 指示器 */
2532
- disableMirrorInScope: true,
2533
- disableDropIndicatorInScope: true,
2534
- /** 是否允许 transform(业务可覆写) */
2535
- canTransform: () => true,
2536
- ...options
1478
+ markline: !0,
1479
+ disableMirrorInScope: !0,
1480
+ disableDropIndicatorInScope: !0,
1481
+ canTransform: () => !0,
1482
+ ...e
2537
1483
  };
2538
1484
  }
2539
- /**
2540
- * 获取当前 drag-scope/drop 容器的缩放比例:
2541
- * - 优先读取容器上的 [scale-ratio](或 [data-scale-ratio])
2542
- * - 若未设置/非法,则回退到 options.scaleRatio
2543
- */
2544
- #resolveScaleRatio(container, adapter) {
2545
- const name = ATTR.scaleRatioAttr || "scale-ratio";
2546
- const v = adapter?.getAttr?.(container, name) ?? adapter?.getAttr?.(container, `data-${name}`) ?? container?.getAttribute?.(name) ?? container?.getAttribute?.(`data-${name}`);
2547
- const n = Number.parseFloat(String(v ?? ""));
2548
- if (Number.isFinite(n) && n > 0) return n;
2549
- const opt = Number(this.#opt.scaleRatio);
2550
- return Number.isFinite(opt) && opt > 0 ? opt : 1;
2551
- }
2552
- #getScaleRatio(st) {
2553
- const n = Number(st?.scaleRatio);
2554
- if (Number.isFinite(n) && n > 0) return n;
2555
- const opt = Number(this.#opt.scaleRatio);
2556
- return Number.isFinite(opt) && opt > 0 ? opt : 1;
2557
- }
2558
- onDown(ctx) {
2559
- const m = ctx?.session;
2560
- if (!m?.isDragScope || !isHTMLElement(m.sourceEl)) return;
2561
- if (!this.#opt.resizable) return;
2562
- const { angle } = getElementTransformInfo(m.sourceEl);
2563
- if (angle) this.#updateDotCursors(m.sourceEl, angle);
2564
- }
2565
- onStart(ctx) {
2566
- const m = ctx.session;
2567
- if (!m?.active || !m?.started || !m.isDragScope) return;
2568
- if (!isHTMLElement(m.sourceEl)) return;
2569
- if (typeof this.#opt.canTransform === "function" && !this.#opt.canTransform(m.sourceEl)) return;
2570
- const selectedValue = m.selectedByNs?.get(m.namespace);
2571
- const isMultiSelect = Array.isArray(selectedValue) && selectedValue.length > 1;
2572
- let type = "move";
2573
- let side = "";
2574
- const canRotate = this.#opt.rotatable && isToggleEnabled(m.sourceEl, ATTR.rotatableAttr, true);
2575
- const canResize = this.#opt.resizable && isToggleEnabled(m.sourceEl, ATTR.resizableAttr, true);
2576
- if (isRotateHandle(m.handleEl) && canRotate) {
2577
- if (isMultiSelect) return;
2578
- type = "rotate";
2579
- } else if (isResizeHandle(m.handleEl) && canResize) {
2580
- if (isMultiSelect) return;
2581
- type = "resize";
2582
- side = getResizeSideFromHandle(m.handleEl);
2583
- }
2584
- if (this.#opt.disableMirrorInScope) this.#disableMirrorNow(m);
2585
- if (this.#opt.disableDropIndicatorInScope) this.#disableIndicatorNow(m);
2586
- m.cache.__transform = {
1485
+ #t(e, n) {
1486
+ let r = t.scaleRatioAttr || "scale-ratio", i = n?.getAttr?.(e, r) ?? n?.getAttr?.(e, `data-${r}`) ?? e?.getAttribute?.(r) ?? e?.getAttribute?.(`data-${r}`), a = Number.parseFloat(String(i ?? ""));
1487
+ if (Number.isFinite(a) && a > 0) return a;
1488
+ let o = Number(this.#e.scaleRatio);
1489
+ return Number.isFinite(o) && o > 0 ? o : 1;
1490
+ }
1491
+ #n(e) {
1492
+ let t = Number(e?.scaleRatio);
1493
+ if (Number.isFinite(t) && t > 0) return t;
1494
+ let n = Number(this.#e.scaleRatio);
1495
+ return Number.isFinite(n) && n > 0 ? n : 1;
1496
+ }
1497
+ onDown(e) {
1498
+ let t = e?.session;
1499
+ if (!t?.isDragScope || !g(t.sourceEl) || !this.#e.resizable) return;
1500
+ let { angle: n } = Y(t.sourceEl);
1501
+ n && this.#u(t.sourceEl, n);
1502
+ }
1503
+ onStart(e) {
1504
+ let n = e.session;
1505
+ if (!n?.active || !n?.started || !n.isDragScope || !g(n.sourceEl) || typeof this.#e.canTransform == "function" && !this.#e.canTransform(n.sourceEl)) return;
1506
+ let r = n.selectedByNs?.get(n.namespace), i = Array.isArray(r) && r.length > 1, a = "move", o = "", s = this.#e.rotatable && m(n.sourceEl, t.rotatableAttr, !0), c = this.#e.resizable && m(n.sourceEl, t.resizableAttr, !0);
1507
+ if (De(n.handleEl) && s) {
1508
+ if (i) return;
1509
+ a = "rotate";
1510
+ } else if (Oe(n.handleEl) && c) {
1511
+ if (i) return;
1512
+ a = "resize", o = Ee(n.handleEl);
1513
+ }
1514
+ this.#e.disableMirrorInScope && this.#h(n), this.#e.disableDropIndicatorInScope && this.#g(n), n.cache.__transform = {
2587
1515
  phase: 0,
2588
- type,
2589
- side,
1516
+ type: a,
1517
+ side: o,
2590
1518
  scaleRatio: void 0,
2591
1519
  container: void 0,
2592
1520
  containerRect: void 0,
@@ -2607,7 +1535,7 @@ var TransformControllerService = class {
2607
1535
  left: void 0,
2608
1536
  top: void 0
2609
1537
  },
2610
- didCompute: false,
1538
+ didCompute: !1,
2611
1539
  lastValidData: void 0,
2612
1540
  lastAppliedX: void 0,
2613
1541
  lastAppliedY: void 0,
@@ -2615,500 +1543,299 @@ var TransformControllerService = class {
2615
1543
  lastAppliedH: void 0,
2616
1544
  lastAppliedAngle: void 0,
2617
1545
  multiSelection: {
2618
- enabled: isMultiSelect,
1546
+ enabled: i,
2619
1547
  elements: [],
2620
1548
  initialTransforms: []
2621
1549
  }
2622
1550
  };
2623
1551
  }
2624
- onMeasure(ctx) {
2625
- const m = ctx.session;
2626
- const st = m?.cache?.__transform;
2627
- if (!m?.active || !m?.started || !m.isDragScope || !st || st.phase !== 0) return;
2628
- if (!isHTMLElement(m.sourceEl)) {
2629
- m.cache.__transform = void 0;
1552
+ onMeasure(e) {
1553
+ let n = e.session, r = n?.cache?.__transform;
1554
+ if (!n?.active || !n?.started || !n.isDragScope || !r || r.phase !== 0) return;
1555
+ if (!g(n.sourceEl)) {
1556
+ n.cache.__transform = void 0;
2630
1557
  return;
2631
1558
  }
2632
- const container = ctx.adapter.closestDragScope(m.sourceEl);
2633
- if (!isHTMLElement(container)) {
2634
- m.cache.__transform = void 0;
1559
+ let i = e.adapter.closestDragScope(n.sourceEl);
1560
+ if (!g(i)) {
1561
+ n.cache.__transform = void 0;
2635
1562
  return;
2636
1563
  }
2637
- const scale = this.#resolveScaleRatio(container, ctx.adapter);
2638
- const info = getElementTransformInfo(m.sourceEl);
2639
- const cRect = ctx.adapter.measureRect(container);
2640
- const cRectScaled = {
2641
- height: cRect.height / scale,
2642
- left: cRect.left / scale,
2643
- top: cRect.top / scale,
2644
- width: cRect.width / scale
2645
- };
2646
- st.container = container;
2647
- st.scaleRatio = scale;
2648
- st.containerRect = cRect;
2649
- st.containerRectScaled = cRectScaled;
2650
- st.start = { ...info };
2651
- st.data = { ...info };
2652
- st.center = {
2653
- x: info.x + info.width / 2,
2654
- y: info.y + info.height / 2
1564
+ let a = this.#t(i, e.adapter), o = Y(n.sourceEl), s = e.adapter.measureRect(i), c = {
1565
+ height: s.height / a,
1566
+ left: s.left / a,
1567
+ top: s.top / a,
1568
+ width: s.width / a
2655
1569
  };
2656
- if (this.#opt.boundary) st.boundary = {
2657
- w: Math.max(0, container.clientWidth),
2658
- h: Math.max(0, container.clientHeight)
2659
- };
2660
- if (st.type === "rotate") {
2661
- const mx = (m.x - cRect.left) / scale;
2662
- const my = (m.y - cRect.top) / scale;
2663
- st.rotateOffset = angleToPointer(st.center.x, st.center.y, mx, my) - st.data.angle;
2664
- }
2665
- if (this.#opt.snap || this.#opt.markline) {
2666
- const startRect = getRectByScale(m.sourceEl, scale, ctx.adapter);
2667
- st.startRect = startRect;
2668
- st.viewportCenterOffset = {
2669
- x: startRect.left + startRect.width / 2 - st.center.x,
2670
- y: startRect.top + startRect.height / 2 - st.center.y
1570
+ if (r.container = i, r.scaleRatio = a, r.containerRect = s, r.containerRectScaled = c, r.start = { ...o }, r.data = { ...o }, r.center = {
1571
+ x: o.x + o.width / 2,
1572
+ y: o.y + o.height / 2
1573
+ }, this.#e.boundary && (r.boundary = {
1574
+ w: Math.max(0, i.clientWidth),
1575
+ h: Math.max(0, i.clientHeight)
1576
+ }), r.type === "rotate") {
1577
+ let e = (n.x - s.left) / a, t = (n.y - s.top) / a;
1578
+ r.rotateOffset = J(r.center.x, r.center.y, e, t) - r.data.angle;
1579
+ }
1580
+ if (this.#e.snap || this.#e.markline) {
1581
+ let o = q(n.sourceEl, a, e.adapter);
1582
+ r.startRect = o, r.viewportCenterOffset = {
1583
+ x: o.left + o.width / 2 - r.center.x,
1584
+ y: o.top + o.height / 2 - r.center.y
2671
1585
  };
2672
- const els = [...container.querySelectorAll?.(`[${ATTR.dragAttr}]`) || []];
2673
- const targets = [];
2674
- for (const node of els) {
2675
- if (node === m.sourceEl) continue;
2676
- if (!isHTMLElement(node)) continue;
2677
- targets.push(getRectByScale(node, scale, ctx.adapter));
2678
- }
2679
- st.lines = calcLines(targets, startRect);
2680
- st.targetRects = targets;
2681
- if (this.#opt.markline) {
2682
- const guides = createTempMarklines(container);
2683
- st.guideX = guides.x;
2684
- st.guideY = guides.y;
1586
+ let s = [...i.querySelectorAll?.(`[${t.dragAttr}]`) || []], c = [];
1587
+ for (let t of s) t !== n.sourceEl && g(t) && c.push(q(t, a, e.adapter));
1588
+ if (r.lines = Se(c, o), r.targetRects = c, this.#e.markline) {
1589
+ let e = X(i);
1590
+ r.guideX = e.x, r.guideY = e.y;
2685
1591
  }
2686
1592
  }
2687
- if (st.multiSelection.enabled) {
2688
- const selectedValue = m.selectedByNs?.get(m.namespace);
2689
- if (Array.isArray(selectedValue)) {
2690
- for (const el of selectedValue) if (el !== m.sourceEl && isHTMLElement(el)) {
2691
- st.multiSelection.elements.push(el);
2692
- st.multiSelection.initialTransforms.push(getElementTransformInfo(el));
2693
- }
2694
- }
2695
- }
2696
- st.phase = 1;
2697
- }
2698
- onCompute(ctx) {
2699
- const m = ctx.session;
2700
- const st = m?.cache?.__transform;
2701
- if (!m?.active || !m?.started || !m.isDragScope || !st || st.phase !== 1) return;
2702
- if (!isHTMLElement(m.sourceEl)) return;
2703
- st.didCompute = true;
2704
- if (st.type === "move") this.#computeMove(m, st);
2705
- else if (st.type === "rotate") this.#computeRotate(m, st);
2706
- else if (st.type === "resize") this.#computeResize(m, st);
2707
- }
2708
- onCommit(ctx) {
2709
- const m = ctx.session;
2710
- const st = m?.cache?.__transform;
2711
- if (!m?.active || !m?.started || !m.isDragScope || !st || st.phase !== 1) return;
2712
- if (!st.didCompute || !isHTMLElement(m.sourceEl)) return;
2713
- this.#apply(ctx, m.sourceEl, st);
2714
- if (st.multiSelection.enabled && st.type === "move") {
2715
- const deltaX = st.data.x - st.start.x;
2716
- const deltaY = st.data.y - st.start.y;
2717
- for (let i = 0; i < st.multiSelection.elements.length; i++) {
2718
- const el = st.multiSelection.elements[i];
2719
- const initialInfo = st.multiSelection.initialTransforms[i];
2720
- const newData = {
2721
- x: initialInfo.x + deltaX,
2722
- y: initialInfo.y + deltaY,
2723
- width: initialInfo.width,
2724
- height: initialInfo.height,
2725
- angle: initialInfo.angle
1593
+ if (r.multiSelection.enabled) {
1594
+ let e = n.selectedByNs?.get(n.namespace);
1595
+ if (Array.isArray(e)) for (let t of e) t !== n.sourceEl && g(t) && (r.multiSelection.elements.push(t), r.multiSelection.initialTransforms.push(Y(t)));
1596
+ }
1597
+ r.phase = 1;
1598
+ }
1599
+ onCompute(e) {
1600
+ let t = e.session, n = t?.cache?.__transform;
1601
+ !t?.active || !t?.started || !t.isDragScope || !n || n.phase !== 1 || g(t.sourceEl) && (n.didCompute = !0, n.type === "move" ? this.#r(t, n) : n.type === "rotate" ? this.#i(t, n) : n.type === "resize" && this.#a(t, n));
1602
+ }
1603
+ onCommit(e) {
1604
+ let t = e.session, n = t?.cache?.__transform;
1605
+ if (!t?.active || !t?.started || !t.isDragScope || !n || n.phase !== 1 || !n.didCompute || !g(t.sourceEl)) return;
1606
+ if (this.#f(e, t.sourceEl, n), n.multiSelection.enabled && n.type === "move") {
1607
+ let t = n.data.x - n.start.x, r = n.data.y - n.start.y;
1608
+ for (let i = 0; i < n.multiSelection.elements.length; i++) {
1609
+ let a = n.multiSelection.elements[i], o = n.multiSelection.initialTransforms[i], s = {
1610
+ x: o.x + t,
1611
+ y: o.y + r,
1612
+ width: o.width,
1613
+ height: o.height,
1614
+ angle: o.angle
2726
1615
  };
2727
- this.#applyTransform(ctx, el, newData);
1616
+ this.#d(e, a, s);
2728
1617
  }
2729
1618
  }
2730
- if (st.type === "rotate" && this.#opt.resizable && st.lastCursorAngle !== st.data?.angle) {
2731
- st.lastCursorAngle = st.data?.angle;
2732
- ctx.frame?.run?.(() => {
2733
- this.#updateDotCursors(m.sourceEl, st.lastCursorAngle || 0);
2734
- });
2735
- }
2736
- if (this.#opt.markline) this.#commitMarkline(ctx, st);
2737
- const dnd = ctx.dnd;
2738
- if (dnd?.emit && st?.data) {
2739
- let payload = st.__emitPayload;
2740
- if (!payload) {
2741
- payload = st.__emitPayload = {
2742
- type: st.type,
2743
- el: m.sourceEl
2744
- };
2745
- st.__emitEvt = st.type === "move" ? "draggable:drag" : st.type === "rotate" ? "draggable:rotate" : "draggable:resize";
2746
- st.__emitRun = () => dnd.emit(st.__emitEvt, st.__emitPayload);
2747
- }
2748
- payload.el = m.sourceEl;
2749
- payload.x = st.data.x;
2750
- payload.y = st.data.y;
2751
- payload.width = st.data.width;
2752
- payload.height = st.data.height;
2753
- payload.angle = st.data.angle;
2754
- ctx.frame?.run?.(st.__emitRun);
2755
- }
2756
- st.didCompute = false;
2757
- }
2758
- onEnd(ctx, meta) {
2759
- const m = ctx.session;
2760
- const st = m?.cache?.__transform;
2761
- if (!st) return;
2762
- hideMarkline(st.guideX);
2763
- hideMarkline(st.guideY);
2764
- if (meta?.ended && isHTMLElement(m?.sourceEl) && st?.data) {
2765
- ctx.dnd?.emit?.("draggable:drop", {
2766
- type: st.type,
2767
- el: m.sourceEl,
2768
- data: m.data,
2769
- ...st.data
2770
- });
2771
- if (st.multiSelection?.enabled && st.type === "move") {
2772
- const deltaX = st.data.x - st.start.x;
2773
- const deltaY = st.data.y - st.start.y;
2774
- const elements = [{
2775
- el: m.sourceEl,
2776
- x: st.data.x,
2777
- y: st.data.y,
2778
- width: st.data.width,
2779
- height: st.data.height,
2780
- angle: st.data.angle,
2781
- data: m.data
2782
- }, ...st.multiSelection.elements.map((el, i) => {
2783
- const init = st.multiSelection.initialTransforms[i];
1619
+ n.type === "rotate" && this.#e.resizable && n.lastCursorAngle !== n.data?.angle && (n.lastCursorAngle = n.data?.angle, e.frame?.run?.(() => {
1620
+ this.#u(t.sourceEl, n.lastCursorAngle || 0);
1621
+ })), this.#e.markline && this.#l(e, n);
1622
+ let r = e.dnd;
1623
+ if (r?.emit && n?.data) {
1624
+ let i = n.__emitPayload;
1625
+ i || (i = n.__emitPayload = {
1626
+ type: n.type,
1627
+ el: t.sourceEl
1628
+ }, n.__emitEvt = n.type === "move" ? "draggable:drag" : n.type === "rotate" ? "draggable:rotate" : "draggable:resize", n.__emitRun = () => r.emit(n.__emitEvt, n.__emitPayload)), i.el = t.sourceEl, i.x = n.data.x, i.y = n.data.y, i.width = n.data.width, i.height = n.data.height, i.angle = n.data.angle, e.frame?.run?.(n.__emitRun);
1629
+ }
1630
+ n.didCompute = !1;
1631
+ }
1632
+ onEnd(e, n) {
1633
+ let r = e.session, i = r?.cache?.__transform;
1634
+ if (i) {
1635
+ if (Z(i.guideX), Z(i.guideY), n?.ended && g(r?.sourceEl) && i?.data && (e.dnd?.emit?.("draggable:drop", {
1636
+ type: i.type,
1637
+ el: r.sourceEl,
1638
+ data: r.data,
1639
+ ...i.data
1640
+ }), i.multiSelection?.enabled && i.type === "move")) {
1641
+ let n = i.data.x - i.start.x, a = i.data.y - i.start.y, o = [{
1642
+ el: r.sourceEl,
1643
+ x: i.data.x,
1644
+ y: i.data.y,
1645
+ width: i.data.width,
1646
+ height: i.data.height,
1647
+ angle: i.data.angle,
1648
+ data: r.data
1649
+ }, ...i.multiSelection.elements.map((r, o) => {
1650
+ let s = i.multiSelection.initialTransforms[o];
2784
1651
  return {
2785
- el,
2786
- x: init.x + deltaX,
2787
- y: init.y + deltaY,
2788
- width: init.width,
2789
- height: init.height,
2790
- angle: init.angle,
2791
- data: parseData(ctx.adapter?.getAttr?.(el, ATTR.dataAttr))
1652
+ el: r,
1653
+ x: s.x + n,
1654
+ y: s.y + a,
1655
+ width: s.width,
1656
+ height: s.height,
1657
+ angle: s.angle,
1658
+ data: u(e.adapter?.getAttr?.(r, t.dataAttr))
2792
1659
  };
2793
1660
  })];
2794
- ctx.dnd?.emit?.("draggable:multi-drop", elements);
1661
+ e.dnd?.emit?.("draggable:multi-drop", o);
2795
1662
  }
2796
- }
2797
- if (meta?.ended && st.type === "rotate" && this.#opt.resizable && isHTMLElement(m?.sourceEl)) this.#updateDotCursors(m.sourceEl, st.data?.angle || 0);
2798
- m.cache.__transform = void 0;
2799
- }
2800
- onDestroy(_dnd, session) {
2801
- const st = session?.cache?.__transform;
2802
- if (st) {
2803
- hideMarkline(st.guideX);
2804
- hideMarkline(st.guideY);
2805
- session.cache.__transform = void 0;
2806
- }
2807
- }
2808
- #computeMove(m, st) {
2809
- const scale = this.#getScaleRatio(st);
2810
- let x = st.start.x + m.dx / scale;
2811
- let y = st.start.y + m.dy / scale;
2812
- if (this.#opt.snapToGrid) {
2813
- x = st.start.x + calcGrid(x - st.start.x, this.#opt.gridX);
2814
- y = st.start.y + calcGrid(y - st.start.y, this.#opt.gridY);
2815
- }
2816
- st.data = {
2817
- ...st.data,
2818
- x,
2819
- y
2820
- };
2821
- this.#markline(st);
2822
- this.#clampMove(st.data, st.boundary);
2823
- }
2824
- #computeRotate(m, st) {
2825
- const scale = this.#getScaleRatio(st);
2826
- const cRect = st.containerRect;
2827
- if (!cRect) return;
2828
- const mx = (m.x - cRect.left) / scale;
2829
- const my = (m.y - cRect.top) / scale;
2830
- let deg = angleToPointer(st.center.x, st.center.y, mx, my) - (st.rotateOffset ?? 0);
2831
- deg = (deg % 360 + 360) % 360;
2832
- if (this.#opt.rotateSnap) {
2833
- const step = Number(this.#opt.rotateStep) || 15;
2834
- deg = Math.round(deg / step) * step;
2835
- }
2836
- st.data = {
2837
- ...st.data,
2838
- angle: deg
1663
+ n?.ended && i.type === "rotate" && this.#e.resizable && g(r?.sourceEl) && this.#u(r.sourceEl, i.data?.angle || 0), r.cache.__transform = void 0;
1664
+ }
1665
+ }
1666
+ onDestroy(e, t) {
1667
+ let n = t?.cache?.__transform;
1668
+ n && (Z(n.guideX), Z(n.guideY), t.cache.__transform = void 0);
1669
+ }
1670
+ #r(e, t) {
1671
+ let n = this.#n(t), r = t.start.x + e.dx / n, i = t.start.y + e.dy / n;
1672
+ this.#e.snapToGrid && (r = t.start.x + K(r - t.start.x, this.#e.gridX), i = t.start.y + K(i - t.start.y, this.#e.gridY)), t.data = {
1673
+ ...t.data,
1674
+ x: r,
1675
+ y: i
1676
+ }, this.#s(t), this.#p(t.data, t.boundary);
1677
+ }
1678
+ #i(e, t) {
1679
+ let n = this.#n(t), r = t.containerRect;
1680
+ if (!r) return;
1681
+ let i = (e.x - r.left) / n, a = (e.y - r.top) / n, o = J(t.center.x, t.center.y, i, a) - (t.rotateOffset ?? 0);
1682
+ if (o = (o % 360 + 360) % 360, this.#e.rotateSnap) {
1683
+ let e = Number(this.#e.rotateStep) || 15;
1684
+ o = Math.round(o / e) * e;
1685
+ }
1686
+ t.data = {
1687
+ ...t.data,
1688
+ angle: o
2839
1689
  };
2840
1690
  }
2841
- #computeResize(m, st) {
2842
- const scale = this.#getScaleRatio(st);
2843
- const ratio = this.#opt.aspectRatio;
2844
- const dx = m.dx / scale;
2845
- const dy = m.dy / scale;
2846
- const alpha = Math.atan2(dy, dx);
2847
- const deltaL = getLength(dx, dy);
2848
- const beta = alpha - toRad(st.start.angle);
2849
- const deltaW = deltaL * Math.cos(beta);
2850
- const deltaH = deltaL * Math.sin(beta);
2851
- const rect = {
2852
- centerX: st.start.x + st.start.width / 2,
2853
- centerY: st.start.y + st.start.height / 2,
2854
- height: st.start.height,
2855
- rotateAngle: st.start.angle,
2856
- width: st.start.width
1691
+ #a(e, t) {
1692
+ let n = this.#n(t), r = this.#e.aspectRatio, i = e.dx / n, a = e.dy / n, o = Math.atan2(a, i), s = me(i, a), c = o - G(t.start.angle), l = s * Math.cos(c), u = s * Math.sin(c), d = {
1693
+ centerX: t.start.x + t.start.width / 2,
1694
+ centerY: t.start.y + t.start.height / 2,
1695
+ height: t.start.height,
1696
+ rotateAngle: t.start.angle,
1697
+ width: t.start.width
1698
+ }, { position: { centerX: f, centerY: p }, size: { width: m, height: h } } = we(t.side, d, l, u, r, this.#e.minWidth, this.#e.minHeight), g = ge({
1699
+ angle: t.data.angle,
1700
+ centerX: f,
1701
+ centerY: p,
1702
+ height: h,
1703
+ width: m
1704
+ }), _ = {
1705
+ ...t.data,
1706
+ ...he(g, f, p)
2857
1707
  };
2858
- const { position: { centerX, centerY }, size: { width: nw, height: nh } } = getNewStyle(st.side, rect, deltaW, deltaH, ratio, this.#opt.minWidth, this.#opt.minHeight);
2859
- const tl = centerToTL({
2860
- angle: st.data.angle,
2861
- centerX,
2862
- centerY,
2863
- height: nh,
2864
- width: nw
2865
- });
2866
- const next = {
2867
- ...st.data,
2868
- ...formatData(tl, centerX, centerY)
2869
- };
2870
- if (this.#opt.maxWidth > 0) next.width = Math.min(next.width, this.#opt.maxWidth);
2871
- if (this.#opt.maxHeight > 0) next.height = Math.min(next.height, this.#opt.maxHeight);
2872
- if (this.#opt.snapToGrid) {
2873
- const cx = next.x + next.width / 2;
2874
- const cy = next.y + next.height / 2;
2875
- const gx = this.#opt.gridX;
2876
- const gy = this.#opt.gridY;
2877
- let w = st.start.width + calcGrid(next.width - st.start.width, gx);
2878
- let h;
2879
- if (ratio) h = w / ratio;
2880
- else h = st.start.height + calcGrid(next.height - st.start.height, gy);
2881
- next.width = Math.abs(w);
2882
- next.height = Math.abs(h);
2883
- next.x = cx - next.width / 2;
2884
- next.y = cy - next.height / 2;
1708
+ if (this.#e.maxWidth > 0 && (_.width = Math.min(_.width, this.#e.maxWidth)), this.#e.maxHeight > 0 && (_.height = Math.min(_.height, this.#e.maxHeight)), this.#e.snapToGrid) {
1709
+ let e = _.x + _.width / 2, n = _.y + _.height / 2, i = this.#e.gridX, a = this.#e.gridY, o = t.start.width + K(_.width - t.start.width, i), s;
1710
+ s = r ? o / r : t.start.height + K(_.height - t.start.height, a), _.width = Math.abs(o), _.height = Math.abs(s), _.x = e - _.width / 2, _.y = n - _.height / 2;
2885
1711
  }
2886
- const tentativeData = next;
2887
- if (this.#clampResize(tentativeData, st.boundary)) {
2888
- st.data = tentativeData;
2889
- st.lastValidData = { ...tentativeData };
2890
- } else st.data = st.lastValidData ? { ...st.lastValidData } : { ...st.start };
2891
- this.#marklineResize(st);
2892
- }
2893
- #calcViewportRect(st) {
2894
- const d = st?.data;
2895
- const off = st?.viewportCenterOffset;
2896
- if (!d || !off) return st.startRect;
2897
- const rad = toRad(d.angle || 0);
2898
- const cos = Math.cos(rad);
2899
- const sin = Math.sin(rad);
2900
- const aabbW = Math.abs(d.width * cos) + Math.abs(d.height * sin);
2901
- const aabbH = Math.abs(d.width * sin) + Math.abs(d.height * cos);
2902
- const cx = d.x + d.width / 2 + off.x;
2903
- const cy = d.y + d.height / 2 + off.y;
2904
- const left = cx - aabbW / 2;
2905
- const top = cy - aabbH / 2;
1712
+ let v = _;
1713
+ this.#m(v, t.boundary) ? (t.data = v, t.lastValidData = { ...v }) : t.data = t.lastValidData ? { ...t.lastValidData } : { ...t.start }, this.#c(t);
1714
+ }
1715
+ #o(e) {
1716
+ let t = e?.data, n = e?.viewportCenterOffset;
1717
+ if (!t || !n) return e.startRect;
1718
+ let r = G(t.angle || 0), i = Math.cos(r), a = Math.sin(r), o = Math.abs(t.width * i) + Math.abs(t.height * a), s = Math.abs(t.width * a) + Math.abs(t.height * i), c = t.x + t.width / 2 + n.x, l = t.y + t.height / 2 + n.y, u = c - o / 2, d = l - s / 2;
2906
1719
  return {
2907
- bottom: top + aabbH,
2908
- height: aabbH,
2909
- left,
2910
- right: left + aabbW,
2911
- top,
2912
- width: aabbW
1720
+ bottom: d + s,
1721
+ height: s,
1722
+ left: u,
1723
+ right: u + o,
1724
+ top: d,
1725
+ width: o
2913
1726
  };
2914
1727
  }
2915
- #markline(st) {
2916
- if (!this.#opt.snap && !this.#opt.markline) return;
2917
- if (!st?.lines || !st.containerRectScaled) return;
2918
- const source = this.#calcViewportRect(st);
2919
- const lines = st.lines || {
1728
+ #s(e) {
1729
+ if (!this.#e.snap && !this.#e.markline || !e?.lines || !e.containerRectScaled) return;
1730
+ let t = this.#o(e), n = e.lines || {
2920
1731
  x: [],
2921
1732
  y: []
2922
- };
2923
- const mark = {
1733
+ }, r = {
2924
1734
  diffX: 0,
2925
1735
  diffY: 0,
2926
1736
  left: void 0,
2927
1737
  top: void 0
2928
1738
  };
2929
- for (let i = 0; i < (lines.y.length || 0); i++) {
2930
- const { top, showTop } = lines.y[i];
2931
- const diff = top - source.top;
2932
- if (Math.abs(diff) < this.#opt.snapThreshold) {
2933
- mark.diffY = diff;
2934
- mark.top = showTop - st.containerRectScaled.top;
1739
+ for (let i = 0; i < (n.y.length || 0); i++) {
1740
+ let { top: a, showTop: o } = n.y[i], s = a - t.top;
1741
+ if (Math.abs(s) < this.#e.snapThreshold) {
1742
+ r.diffY = s, r.top = o - e.containerRectScaled.top;
2935
1743
  break;
2936
1744
  }
2937
1745
  }
2938
- for (let i = 0; i < (lines.x.length || 0); i++) {
2939
- const { left, showLeft } = lines.x[i];
2940
- const diff = left - source.left;
2941
- if (Math.abs(diff) < this.#opt.snapThreshold) {
2942
- mark.diffX = diff;
2943
- mark.left = showLeft - st.containerRectScaled.left;
1746
+ for (let i = 0; i < (n.x.length || 0); i++) {
1747
+ let { left: a, showLeft: o } = n.x[i], s = a - t.left;
1748
+ if (Math.abs(s) < this.#e.snapThreshold) {
1749
+ r.diffX = s, r.left = o - e.containerRectScaled.left;
2944
1750
  break;
2945
1751
  }
2946
1752
  }
2947
- if (this.#opt.snap) {
2948
- if (mark.diffX) st.data.x += mark.diffX;
2949
- if (mark.diffY) st.data.y += mark.diffY;
2950
- }
2951
- st.mark = mark;
1753
+ this.#e.snap && (r.diffX && (e.data.x += r.diffX), r.diffY && (e.data.y += r.diffY)), e.mark = r;
2952
1754
  }
2953
- #marklineResize(st) {
2954
- if (!this.#opt.snap && !this.#opt.markline) return;
2955
- if (!st?.targetRects || !st.containerRectScaled) return;
2956
- const mark = {
1755
+ #c(e) {
1756
+ if (!this.#e.snap && !this.#e.markline || !e?.targetRects || !e.containerRectScaled) return;
1757
+ let t = {
2957
1758
  diffX: 0,
2958
1759
  diffY: 0,
2959
1760
  left: void 0,
2960
1761
  top: void 0
2961
1762
  };
2962
- if ((st.data.angle || 0) !== 0 || this.#opt.aspectRatio) {
2963
- st.mark = mark;
1763
+ if ((e.data.angle || 0) !== 0 || this.#e.aspectRatio) {
1764
+ e.mark = t;
2964
1765
  return;
2965
1766
  }
2966
- const source = this.#calcViewportRect(st);
2967
- const { diffX, diffY, guideLeft, guideTop } = resolveResizeSnap({
2968
- side: st.side,
2969
- source,
2970
- targetRects: st.targetRects,
2971
- threshold: this.#opt.snapThreshold
1767
+ let n = this.#o(e), { diffX: r, diffY: i, guideLeft: a, guideTop: o } = Ce({
1768
+ side: e.side,
1769
+ source: n,
1770
+ targetRects: e.targetRects,
1771
+ threshold: this.#e.snapThreshold
2972
1772
  });
2973
- mark.diffX = diffX;
2974
- mark.diffY = diffY;
2975
- mark.left = guideLeft === void 0 ? void 0 : guideLeft - st.containerRectScaled.left;
2976
- mark.top = guideTop === void 0 ? void 0 : guideTop - st.containerRectScaled.top;
2977
- if (this.#opt.snap && (diffX || diffY)) {
2978
- const scale = this.#getScaleRatio(st);
2979
- const snapshot = { ...st.data };
2980
- const next = { ...st.data };
2981
- const side = st.side || "";
2982
- if (diffX) {
2983
- const dx = diffX / scale;
2984
- if (side.includes("left")) {
2985
- next.x += dx;
2986
- next.width -= dx;
2987
- } else if (side.includes("right")) next.width += dx;
1773
+ if (t.diffX = r, t.diffY = i, t.left = a === void 0 ? void 0 : a - e.containerRectScaled.left, t.top = o === void 0 ? void 0 : o - e.containerRectScaled.top, this.#e.snap && (r || i)) {
1774
+ let n = this.#n(e), a = { ...e.data }, o = { ...e.data }, s = e.side || "";
1775
+ if (r) {
1776
+ let e = r / n;
1777
+ s.includes("left") ? (o.x += e, o.width -= e) : s.includes("right") && (o.width += e);
2988
1778
  }
2989
- if (diffY) {
2990
- const dy = diffY / scale;
2991
- if (side.includes("top")) {
2992
- next.y += dy;
2993
- next.height -= dy;
2994
- } else if (side.includes("bottom")) next.height += dy;
1779
+ if (i) {
1780
+ let e = i / n;
1781
+ s.includes("top") ? (o.y += e, o.height -= e) : s.includes("bottom") && (o.height += e);
2995
1782
  }
2996
- let valid = next.width >= this.#opt.minWidth && next.height >= this.#opt.minHeight;
2997
- if (valid && this.#opt.maxWidth > 0 && next.width > this.#opt.maxWidth) valid = false;
2998
- if (valid && this.#opt.maxHeight > 0 && next.height > this.#opt.maxHeight) valid = false;
2999
- if (valid && !this.#clampResize(next, st.boundary)) valid = false;
3000
- if (valid) {
3001
- st.data = next;
3002
- st.lastValidData = { ...next };
3003
- } else {
3004
- st.data = snapshot;
3005
- mark.left = void 0;
3006
- mark.top = void 0;
3007
- }
3008
- }
3009
- st.mark = mark;
3010
- }
3011
- #commitMarkline(ctx, st) {
3012
- const { guideX, guideY } = st;
3013
- const mark = st.mark || {};
3014
- if (guideX) if (mark.left === void 0) ctx.frame?.setStyle?.(guideX, "display", "none");
3015
- else {
3016
- ctx.frame?.setStyle?.(guideX, "display", "block");
3017
- ctx.frame?.setStyle?.(guideX, "transform", `translate(${withUnit(mark.left)}, 0)`);
3018
- }
3019
- if (guideY) if (mark.top === void 0) ctx.frame?.setStyle?.(guideY, "display", "none");
3020
- else {
3021
- ctx.frame?.setStyle?.(guideY, "display", "block");
3022
- ctx.frame?.setStyle?.(guideY, "transform", `translate(0, ${withUnit(mark.top)})`);
1783
+ let c = o.width >= this.#e.minWidth && o.height >= this.#e.minHeight;
1784
+ c && this.#e.maxWidth > 0 && o.width > this.#e.maxWidth && (c = !1), c && this.#e.maxHeight > 0 && o.height > this.#e.maxHeight && (c = !1), c && !this.#m(o, e.boundary) && (c = !1), c ? (e.data = o, e.lastValidData = { ...o }) : (e.data = a, t.left = void 0, t.top = void 0);
3023
1785
  }
1786
+ e.mark = t;
3024
1787
  }
3025
- #updateDotCursors(el, angle) {
3026
- const dots = findDots(el);
3027
- for (const dot of dots) {
3028
- const dir = dot?.dataset?.dir;
3029
- if (dir) dot.style.cursor = `${getCursor(angle, dir)}-resize`;
1788
+ #l(e, t) {
1789
+ let { guideX: n, guideY: r } = t, i = t.mark || {};
1790
+ n && (i.left === void 0 ? e.frame?.setStyle?.(n, "display", "none") : (e.frame?.setStyle?.(n, "display", "block"), e.frame?.setStyle?.(n, "transform", `translate(${W(i.left)}, 0)`))), r && (i.top === void 0 ? e.frame?.setStyle?.(r, "display", "none") : (e.frame?.setStyle?.(r, "display", "block"), e.frame?.setStyle?.(r, "transform", `translate(0, ${W(i.top)})`)));
1791
+ }
1792
+ #u(e, t) {
1793
+ let n = Te(e);
1794
+ for (let e of n) {
1795
+ let n = e?.dataset?.dir;
1796
+ n && (e.style.cursor = `${xe(t, n)}-resize`);
3030
1797
  }
3031
1798
  }
3032
- #applyTransform(ctx, el, data) {
3033
- ctx.frame?.setStyle?.(el, "transform", `translate(${withUnit(data.x)}, ${withUnit(data.y)}) rotate(${data.angle}deg)`);
1799
+ #d(e, t, n) {
1800
+ e.frame?.setStyle?.(t, "transform", `translate(${W(n.x)}, ${W(n.y)}) rotate(${n.angle}deg)`);
3034
1801
  }
3035
- #apply(ctx, el, st) {
3036
- const d = st.data;
3037
- if (st.lastAppliedW !== d.width) {
3038
- ctx.frame?.setStyle?.(el, "width", withUnit(d.width));
3039
- st.lastAppliedW = d.width;
3040
- }
3041
- if (st.lastAppliedH !== d.height) {
3042
- ctx.frame?.setStyle?.(el, "height", withUnit(d.height));
3043
- st.lastAppliedH = d.height;
3044
- }
3045
- if (st.lastAppliedX !== d.x || st.lastAppliedY !== d.y || st.lastAppliedAngle !== d.angle) {
3046
- this.#applyTransform(ctx, el, d);
3047
- st.lastAppliedX = d.x;
3048
- st.lastAppliedY = d.y;
3049
- st.lastAppliedAngle = d.angle;
3050
- }
1802
+ #f(e, t, n) {
1803
+ let r = n.data;
1804
+ n.lastAppliedW !== r.width && (e.frame?.setStyle?.(t, "width", W(r.width)), n.lastAppliedW = r.width), n.lastAppliedH !== r.height && (e.frame?.setStyle?.(t, "height", W(r.height)), n.lastAppliedH = r.height), (n.lastAppliedX !== r.x || n.lastAppliedY !== r.y || n.lastAppliedAngle !== r.angle) && (this.#d(e, t, r), n.lastAppliedX = r.x, n.lastAppliedY = r.y, n.lastAppliedAngle = r.angle);
1805
+ }
1806
+ #p(e, t) {
1807
+ if (!t) return;
1808
+ let n = G(e.angle || 0), r = Math.abs(Math.cos(n)), i = Math.abs(Math.sin(n)), a = e.width * r + e.height * i, o = e.width * i + e.height * r, s = (a - e.width) / 2, c = t.w - a / 2 - e.width / 2, l = (o - e.height) / 2, u = t.h - o / 2 - e.height / 2;
1809
+ e.x = Math.max(Math.min(s, c), Math.min(e.x, Math.max(s, c))), e.y = Math.max(Math.min(l, u), Math.min(e.y, Math.max(l, u)));
1810
+ }
1811
+ #m(e, t) {
1812
+ if (!t) return !0;
1813
+ let n = G(e.angle || 0), r = Math.abs(Math.cos(n)), i = Math.abs(Math.sin(n)), a = e.width * r + e.height * i, o = e.width * i + e.height * r, s = e.x + e.width / 2, l = e.y + e.height / 2, u = s - a / 2, d = s + a / 2, f = l - o / 2, p = l + o / 2, m = c;
1814
+ return !(u < -m || f < -m || d > t.w + m || p > t.h + m);
3051
1815
  }
3052
- #clampMove(d, boundary) {
3053
- if (!boundary) return;
3054
- const rad = toRad(d.angle || 0);
3055
- const cos = Math.abs(Math.cos(rad));
3056
- const sin = Math.abs(Math.sin(rad));
3057
- const aabbW = d.width * cos + d.height * sin;
3058
- const aabbH = d.width * sin + d.height * cos;
3059
- const minX = (aabbW - d.width) / 2;
3060
- const maxX = boundary.w - aabbW / 2 - d.width / 2;
3061
- const minY = (aabbH - d.height) / 2;
3062
- const maxY = boundary.h - aabbH / 2 - d.height / 2;
3063
- d.x = Math.max(Math.min(minX, maxX), Math.min(d.x, Math.max(minX, maxX)));
3064
- d.y = Math.max(Math.min(minY, maxY), Math.min(d.y, Math.max(minY, maxY)));
3065
- }
3066
- #clampResize(d, boundary) {
3067
- if (!boundary) return true;
3068
- const rad = toRad(d.angle || 0);
3069
- const cos = Math.abs(Math.cos(rad));
3070
- const sin = Math.abs(Math.sin(rad));
3071
- const aabbW = d.width * cos + d.height * sin;
3072
- const aabbH = d.width * sin + d.height * cos;
3073
- const cx = d.x + d.width / 2;
3074
- const cy = d.y + d.height / 2;
3075
- const left = cx - aabbW / 2;
3076
- const right = cx + aabbW / 2;
3077
- const top = cy - aabbH / 2;
3078
- const bottom = cy + aabbH / 2;
3079
- const t = CLAMP_TOLERANCE;
3080
- if (left < -t || top < -t || right > boundary.w + t || bottom > boundary.h + t) return false;
3081
- return true;
3082
- }
3083
- #disableMirrorNow(m) {
3084
- if (m?.mirrorEl) {
1816
+ #h(e) {
1817
+ if (e?.mirrorEl) {
3085
1818
  try {
3086
- m.mirrorEl.parentNode?.removeChild?.(m.mirrorEl);
1819
+ e.mirrorEl.parentNode?.removeChild?.(e.mirrorEl);
3087
1820
  } catch {}
3088
- m.mirrorEl = void 0;
1821
+ e.mirrorEl = void 0;
3089
1822
  }
3090
- if (isHTMLElement(m?.sourceEl)) try {
3091
- m.sourceEl.style.visibility = "";
1823
+ if (g(e?.sourceEl)) try {
1824
+ e.sourceEl.style.visibility = "";
3092
1825
  } catch {}
3093
1826
  }
3094
- #disableIndicatorNow(m) {
3095
- if (m?.indicatorEl) {
1827
+ #g(e) {
1828
+ if (e?.indicatorEl) {
3096
1829
  try {
3097
- m.indicatorEl.parentNode?.removeChild?.(m.indicatorEl);
1830
+ e.indicatorEl.parentNode?.removeChild?.(e.indicatorEl);
3098
1831
  } catch {}
3099
- m.indicatorEl = void 0;
3100
- m.indicatorRegion = void 0;
1832
+ e.indicatorEl = void 0, e.indicatorRegion = void 0;
3101
1833
  }
3102
- m.currentDrop = void 0;
3103
- m.currentDropRect = void 0;
3104
- m.currentAllowed = false;
1834
+ e.currentDrop = void 0, e.currentDropRect = void 0, e.currentAllowed = !1;
3105
1835
  }
3106
- };
3107
- //#endregion
3108
- //#region src/version.js
3109
- var DndVersion = {
1836
+ }, Ae = {
3110
1837
  name: "@ptahjs/dnd",
3111
- version: "0.1.2"
1838
+ version: "0.1.3"
3112
1839
  };
3113
1840
  //#endregion
3114
- export { ACTIVE_WRAP_CLASS, ActiveSelectionService, AutoScrollService, DOT_CLASS, Dnd, DndVersion, DropIndicatorService, DropService, MarqueeSelectionService, MirrorService, ROTATE_CLASS, TransformControllerService, clearAll, setMultipleActive };
1841
+ export { P as ACTIVE_WRAP_CLASS, U as ActiveSelectionService, ie as AutoScrollService, F as DOT_CLASS, w as Dnd, Ae as DndVersion, le as DropIndicatorService, T as DropService, pe as MarqueeSelectionService, E as MirrorService, I as ROTATE_CLASS, ke as TransformControllerService, H as clearAll, V as setMultipleActive };