uiik 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js ADDED
@@ -0,0 +1,1995 @@
1
+ /**
2
+ * uiik v1.0.0
3
+ * A UI interaction kit includes draggable, splittable, rotatable, selectable, etc.
4
+ * https://github.com/holyhigh2/uii
5
+ * c) 2021-2023 @holyhigh2 may be freely distributed under the MIT license
6
+ */
7
+ (function (global, factory) {
8
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@holyhigh/func.js')) :
9
+ typeof define === 'function' && define.amd ? define(['exports', '@holyhigh/func.js'], factory) :
10
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.uii = {}, global.func_js));
11
+ })(this, (function (exports, func_js) { 'use strict';
12
+
13
+ /******************************************************************************
14
+ Copyright (c) Microsoft Corporation.
15
+
16
+ Permission to use, copy, modify, and/or distribute this software for any
17
+ purpose with or without fee is hereby granted.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
20
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
21
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
22
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
23
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
24
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
25
+ PERFORMANCE OF THIS SOFTWARE.
26
+ ***************************************************************************** */
27
+
28
+ function __classPrivateFieldGet(receiver, state, kind, f) {
29
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
30
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
31
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
32
+ }
33
+
34
+ function __classPrivateFieldSet(receiver, state, value, kind, f) {
35
+ if (kind === "m") throw new TypeError("Private method is not writable");
36
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
37
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
38
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
39
+ }
40
+
41
+ var _Uii_listeners;
42
+ /**
43
+ * A Base class for all Uii classes
44
+ */
45
+ class Uii {
46
+ constructor(ele, opts) {
47
+ this.enabled = true;
48
+ _Uii_listeners.set(this, []);
49
+ this.opts = opts || {};
50
+ if (func_js.isArrayLike(ele) && !func_js.isString(ele)) {
51
+ this.ele = func_js.map(ele, (el) => {
52
+ let e = func_js.isString(el) ? document.querySelector(el) : el;
53
+ if (!func_js.isElement(e)) {
54
+ console.error('Invalid element "' + el + '"');
55
+ return false;
56
+ }
57
+ return e;
58
+ });
59
+ }
60
+ else {
61
+ const el = func_js.isString(ele) ? document.querySelectorAll(ele) : ele;
62
+ if (!func_js.isElement(el) && !func_js.isArrayLike(el)) {
63
+ console.error('Invalid element "' + ele + '"');
64
+ return;
65
+ }
66
+ this.ele = func_js.isArrayLike(el) ? func_js.toArray(el) : [el];
67
+ }
68
+ }
69
+ /**
70
+ * 销毁uii对象,包括卸载事件、清空元素等
71
+ */
72
+ destroy() {
73
+ func_js.each(__classPrivateFieldGet(this, _Uii_listeners, "f"), ev => {
74
+ ev[0].removeEventListener(ev[1], ev[2], ev[3]);
75
+ });
76
+ __classPrivateFieldSet(this, _Uii_listeners, [], "f");
77
+ }
78
+ /**
79
+ * 注册事件,以便在{@link destroy}方法中卸载
80
+ * @param el dom元素
81
+ * @param event 事件名
82
+ * @param hook 回调函数
83
+ * @param useCapture 默认false
84
+ */
85
+ registerEvent(el, event, hook, useCapture = false) {
86
+ const wrapper = ((ev) => {
87
+ if (!this.enabled)
88
+ return;
89
+ hook(ev);
90
+ }).bind(this);
91
+ el.addEventListener(event, wrapper, useCapture);
92
+ __classPrivateFieldGet(this, _Uii_listeners, "f").push([el, event, wrapper, useCapture]);
93
+ }
94
+ /**
95
+ * 禁用uii实例,禁用后的dom不会响应事件
96
+ */
97
+ disable() {
98
+ this.enabled = false;
99
+ }
100
+ /**
101
+ * 启用uii实例
102
+ */
103
+ enable() {
104
+ this.enabled = true;
105
+ }
106
+ /**
107
+ * 获取指定名称的选项值
108
+ * @param name
109
+ * @returns
110
+ */
111
+ getOption(name) {
112
+ return name ? this.opts[name] : this.opts;
113
+ }
114
+ /**
115
+ * 一次设置多个选项值。触发`onOptionChanged`
116
+ * @param options
117
+ */
118
+ setOptions(options) {
119
+ func_js.assign(this.opts, options);
120
+ this.onOptionChanged(this.opts);
121
+ }
122
+ /**
123
+ * 设置指定name的选项值。触发`onOptionChanged`
124
+ * @param name
125
+ * @param value
126
+ */
127
+ setOption(name, value) {
128
+ this.opts[name] = value;
129
+ this.onOptionChanged(this.opts);
130
+ }
131
+ /**
132
+ * @internal
133
+ */
134
+ onOptionChanged(opts) {
135
+ }
136
+ }
137
+ _Uii_listeners = new WeakMap();
138
+
139
+ /* eslint-disable max-len */
140
+ /**
141
+ * 工具包
142
+ * @author holyhigh2
143
+ */
144
+ /**
145
+ * 获取child相对于parent的offset信息。含border宽度
146
+ * @returns
147
+ */
148
+ function getOffset(child, parent) {
149
+ const rs = { x: 0, y: 0 };
150
+ let op = child.offsetParent;
151
+ while (op && parent && op !== parent) {
152
+ const style = window.getComputedStyle(op);
153
+ rs.x += op.offsetLeft + parseFloat(style.borderLeftWidth);
154
+ rs.y += op.offsetTop + parseFloat(style.borderTopWidth);
155
+ op = op.offsetParent;
156
+ }
157
+ rs.x += child.offsetLeft;
158
+ rs.y += child.offsetTop;
159
+ return rs;
160
+ }
161
+ /**
162
+ * 边缘检测最小内部边距
163
+ */
164
+ const EDGE_THRESHOLD = 5;
165
+ const DRAGGING_RULE = "body * { pointer-events: none; }";
166
+ function lockPage() {
167
+ document.styleSheets[0].insertRule(DRAGGING_RULE, 0);
168
+ }
169
+ function unlockPage() {
170
+ document.styleSheets[0].deleteRule(0);
171
+ }
172
+
173
+ var _Splittable_instances, _Splittable_checkDirection, _Splittable_bindHandle;
174
+ const THRESHOLD$3 = 1;
175
+ const CLASS_SPLITTABLE = "uii-splittable";
176
+ const CLASS_SPLITTABLE_HANDLE = "uii-splittable-handle";
177
+ const CLASS_SPLITTABLE_HANDLE_GHOST = "uii-splittable-handle-ghost";
178
+ const CLASS_SPLITTABLE_HANDLE_ACTIVE = "uii-splittable-handle-active";
179
+ const CLASS_SPLITTABLE_V = "uii-splittable-v";
180
+ const CLASS_SPLITTABLE_H = "uii-splittable-h";
181
+ function getRootEl(el, root) {
182
+ let rs = el.parentNode;
183
+ while (rs && rs.parentNode !== root) {
184
+ rs = rs.parentNode;
185
+ }
186
+ return rs;
187
+ }
188
+ /**
189
+ * 用于表示一个或多个分割器的定义
190
+ * > 可用CSS接口
191
+ * - .uii-splittable
192
+ * - .uii-splittable-handle
193
+ * - .uii-splittable-handle-ghost
194
+ * - .uii-splittable-handle-active
195
+ * - .uii-splittable-v
196
+ * - .uii-splittable-h
197
+ * @public
198
+ */
199
+ class Splittable extends Uii {
200
+ constructor(container, opts) {
201
+ super(container, func_js.assign({
202
+ handleSize: 10,
203
+ minSize: 0,
204
+ sticky: false,
205
+ inside: false,
206
+ ghost: false
207
+ }, opts));
208
+ _Splittable_instances.add(this);
209
+ const con = this.ele[0];
210
+ //detect container position
211
+ const pos = window.getComputedStyle(con).position;
212
+ if (pos === "static") {
213
+ con.style.position = "relative";
214
+ }
215
+ con.classList.toggle(CLASS_SPLITTABLE, true);
216
+ const handleDoms = con.querySelectorAll(this.opts.handle);
217
+ const children = func_js.reject(con.children, c => {
218
+ if (func_js.includes(handleDoms, c))
219
+ return true;
220
+ return false;
221
+ });
222
+ const dir = __classPrivateFieldGet(this, _Splittable_instances, "m", _Splittable_checkDirection).call(this, con);
223
+ con.classList.toggle(dir === 'v' ? CLASS_SPLITTABLE_V : CLASS_SPLITTABLE_H, true);
224
+ const minSizeAry = func_js.map(children, (c, i) => {
225
+ if (func_js.isArray(this.opts.minSize)) {
226
+ return this.opts.minSize[i] || 0;
227
+ }
228
+ else {
229
+ return this.opts.minSize;
230
+ }
231
+ });
232
+ const stickyAry = func_js.map(children, (c, i) => {
233
+ if (func_js.isArray(this.opts.sticky)) {
234
+ return this.opts.sticky[i] || false;
235
+ }
236
+ else {
237
+ return this.opts.sticky;
238
+ }
239
+ });
240
+ if (func_js.isEmpty(handleDoms)) {
241
+ const len = children.length - 1;
242
+ for (let i = 0; i < len; i++) {
243
+ __classPrivateFieldGet(this, _Splittable_instances, "m", _Splittable_bindHandle).call(this, minSizeAry.slice(i, i + 2), stickyAry.slice(i, i + 2), this.opts, dir, children[i], children[i + 1]);
244
+ }
245
+ }
246
+ else {
247
+ func_js.each(handleDoms, (h, i) => {
248
+ const isRoot = h.parentNode.classList.contains(CLASS_SPLITTABLE);
249
+ let dom1, dom2;
250
+ if (isRoot) {
251
+ dom1 = h.previousElementSibling;
252
+ dom2 = h.nextElementSibling;
253
+ }
254
+ else {
255
+ dom2 = getRootEl(h, con);
256
+ dom1 = dom2.previousElementSibling;
257
+ }
258
+ __classPrivateFieldGet(this, _Splittable_instances, "m", _Splittable_bindHandle).call(this, minSizeAry.slice(i, i + 2), stickyAry.slice(i, i + 2), this.opts, dir, dom1, dom2, h);
259
+ });
260
+ }
261
+ }
262
+ }
263
+ _Splittable_instances = new WeakSet(), _Splittable_checkDirection = function _Splittable_checkDirection(container) {
264
+ let dir = 'h';
265
+ const child = container.children[0];
266
+ let lastY = child.offsetTop;
267
+ func_js.each(container.children, c => {
268
+ if (c.offsetTop != lastY) {
269
+ dir = 'v';
270
+ return false;
271
+ }
272
+ });
273
+ return dir;
274
+ }, _Splittable_bindHandle = function _Splittable_bindHandle(minSizeAry, stickyAry, opts, dir, dom1, dom2, handle) {
275
+ var _a;
276
+ const handleSize = opts.handleSize;
277
+ if (!handle) {
278
+ handle = document.createElement('div');
279
+ let initPos = 0;
280
+ if (!opts.inside) {
281
+ initPos = (dir === 'v' ? dom2.offsetTop : dom2.offsetLeft);
282
+ }
283
+ const sensorHCss = `width:${handleSize}px;height:100%;top:0;left:${initPos - handleSize / 2}px;z-index:9;`;
284
+ const sensorVCss = `height:${handleSize}px;width:100%;left:0;top:${initPos - handleSize / 2}px;z-index:9;`;
285
+ handle.style.cssText =
286
+ 'position: absolute;' + (dir === 'v' ? sensorVCss : sensorHCss);
287
+ if (opts.inside) {
288
+ dom2.appendChild(handle);
289
+ }
290
+ (_a = dom2.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(handle, dom2);
291
+ }
292
+ handle.style.cursor = dir === 'v' ? 's-resize' : 'e-resize';
293
+ handle.dataset.cursor = handle.style.cursor;
294
+ handle.classList.add(CLASS_SPLITTABLE_HANDLE);
295
+ const minSize1 = minSizeAry[0];
296
+ const minSize2 = minSizeAry[1];
297
+ let sticky1 = stickyAry[0];
298
+ let sticky2 = stickyAry[1];
299
+ const onStart = opts.onStart;
300
+ const onSplit = opts.onSplit;
301
+ const onEnd = opts.onEnd;
302
+ const onSticky = opts.onSticky;
303
+ const onClone = opts.onClone;
304
+ const oneSideMode = opts.oneSideMode;
305
+ const updateStart = !oneSideMode || oneSideMode === 'start';
306
+ const updateEnd = !oneSideMode || oneSideMode === 'end';
307
+ handle.onmousedown = function (e) {
308
+ // 1. 获取原始高度/宽度;设置宽度/高度
309
+ let originSize = 0;
310
+ let originSize1 = 0;
311
+ const originPosX = e.clientX;
312
+ const originPosY = e.clientY;
313
+ let splitterSize = 1;
314
+ let blockSize = 0; // 分割区size
315
+ switch (dir) {
316
+ case 'v':
317
+ originSize = dom1.offsetHeight;
318
+ originSize1 = dom2.offsetHeight;
319
+ splitterSize = handle.offsetHeight;
320
+ break;
321
+ case 'h':
322
+ originSize = dom1.offsetWidth;
323
+ originSize1 = dom2.offsetWidth;
324
+ splitterSize = handle.offsetWidth;
325
+ break;
326
+ }
327
+ blockSize = splitterSize + originSize + originSize1;
328
+ const dom1Style = dom1.style;
329
+ const dom2Style = dom2.style;
330
+ //ghost
331
+ const ghost = opts.ghost;
332
+ const ghostClass = opts.ghostClass;
333
+ let ghostNode = null;
334
+ // 初始化sticked位置
335
+ let sticked = 'none';
336
+ if (originSize < minSize1 / 2) {
337
+ sticked = 'start';
338
+ }
339
+ else if (blockSize - originSize - splitterSize < minSize2 / 2) {
340
+ sticked = 'end';
341
+ }
342
+ let dragging = false;
343
+ let bodyCursor = document.body.style.cursor;
344
+ let startPos = dir === 'v' ? dom1.offsetTop : dom1.offsetLeft;
345
+ let ds1, anotherSize;
346
+ const dragListener = (ev) => {
347
+ var _a;
348
+ const offsetx = ev.clientX - originPosX;
349
+ const offsety = ev.clientY - originPosY;
350
+ if (!dragging) {
351
+ if (Math.abs(offsetx) > THRESHOLD$3 || Math.abs(offsety) > THRESHOLD$3) {
352
+ dragging = true;
353
+ handle === null || handle === void 0 ? void 0 : handle.classList.add(CLASS_SPLITTABLE_HANDLE_ACTIVE);
354
+ if (ghost) {
355
+ ghostNode = handle.cloneNode(true);
356
+ ghostNode.style.opacity = '0.3';
357
+ ghostNode.style.pointerEvents = 'none';
358
+ ghostNode.classList.add(CLASS_SPLITTABLE_HANDLE_GHOST);
359
+ if (ghostNode) {
360
+ if (ghostClass) {
361
+ ghostNode.className =
362
+ ghostNode.className.replace(ghostClass, '') + ' ' + ghostClass;
363
+ }
364
+ (_a = handle === null || handle === void 0 ? void 0 : handle.parentNode) === null || _a === void 0 ? void 0 : _a.appendChild(ghostNode);
365
+ func_js.call(onClone, ghostNode, e);
366
+ }
367
+ }
368
+ lockPage();
369
+ document.body.style.cursor = (handle === null || handle === void 0 ? void 0 : handle.dataset.cursor) || '';
370
+ func_js.call(onStart, originSize, originSize1);
371
+ }
372
+ else {
373
+ ev.preventDefault();
374
+ return false;
375
+ }
376
+ }
377
+ let doSticky = false;
378
+ ds1 = dir === 'v' ? originSize + offsety : originSize + offsetx;
379
+ if (ds1 < minSize1 / 2 && sticky1 && minSize1 > 0) {
380
+ if (sticked == 'none') {
381
+ doSticky = true;
382
+ sticked = 'start';
383
+ }
384
+ ds1 = 0;
385
+ }
386
+ else if (ds1 < minSize1) {
387
+ ds1 = minSize1;
388
+ if (sticked == 'start' && sticky1) {
389
+ // 重置状态
390
+ doSticky = true;
391
+ sticked = 'none';
392
+ }
393
+ }
394
+ else if (blockSize - ds1 - splitterSize < minSize2 / 2 &&
395
+ sticky2) {
396
+ if (sticked == 'none') {
397
+ doSticky = true;
398
+ sticked = 'end';
399
+ }
400
+ ds1 = blockSize - splitterSize;
401
+ }
402
+ else if (blockSize - ds1 - splitterSize < minSize2) {
403
+ ds1 = blockSize - minSize2 - splitterSize;
404
+ if (sticked == 'end' && sticky2) {
405
+ // 重置状态
406
+ doSticky = true;
407
+ sticked = 'none';
408
+ }
409
+ }
410
+ anotherSize = blockSize - ds1 - splitterSize;
411
+ if (ghostNode) {
412
+ if (dir === 'v') {
413
+ ghostNode.style.top = startPos + ds1 - handleSize / 2 + 'px';
414
+ }
415
+ else {
416
+ ghostNode.style.left = startPos + ds1 - handleSize / 2 + 'px';
417
+ }
418
+ }
419
+ else {
420
+ const updateProp = dir === 'v' ? 'height' : 'width';
421
+ if (updateStart) {
422
+ dom1Style.setProperty(updateProp, ds1 + 'px', 'important');
423
+ }
424
+ if (updateEnd) {
425
+ dom2Style.setProperty(updateProp, anotherSize + 'px', 'important');
426
+ }
427
+ if (doSticky) {
428
+ func_js.call(onSticky, ds1, anotherSize, sticked);
429
+ }
430
+ //update handle
431
+ if (dir === 'v') {
432
+ handle.style.top = dom2.offsetTop - handleSize / 2 + 'px';
433
+ }
434
+ else {
435
+ handle.style.left = dom2.offsetLeft - handleSize / 2 + 'px';
436
+ }
437
+ }
438
+ func_js.call(onSplit, ds1, anotherSize);
439
+ ev.preventDefault();
440
+ return false;
441
+ };
442
+ const dragEndListener = (ev) => {
443
+ var _a;
444
+ document.removeEventListener('mousemove', dragListener, false);
445
+ document.removeEventListener('mouseup', dragEndListener, false);
446
+ window.removeEventListener('blur', dragEndListener, false);
447
+ if (dragging) {
448
+ switch (dir) {
449
+ case 'v':
450
+ originSize = (dom1 === null || dom1 === void 0 ? void 0 : dom1.offsetHeight) || -1;
451
+ originSize1 = (dom2 === null || dom2 === void 0 ? void 0 : dom2.offsetHeight) || -1;
452
+ break;
453
+ case 'h':
454
+ originSize = (dom1 === null || dom1 === void 0 ? void 0 : dom1.offsetWidth) || -1;
455
+ originSize1 = (dom2 === null || dom2 === void 0 ? void 0 : dom2.offsetWidth) || -1;
456
+ break;
457
+ }
458
+ handle === null || handle === void 0 ? void 0 : handle.classList.remove(CLASS_SPLITTABLE_HANDLE_ACTIVE);
459
+ if (ghostNode) {
460
+ const updateProp = dir === 'v' ? 'height' : 'width';
461
+ if (updateStart) {
462
+ dom1Style.setProperty(updateProp, ds1 + 'px', 'important');
463
+ }
464
+ if (updateEnd) {
465
+ dom2Style.setProperty(updateProp, anotherSize + 'px', 'important');
466
+ }
467
+ //update handle
468
+ if (dir === 'v') {
469
+ handle.style.top = startPos + ds1 - handleSize / 2 + 'px';
470
+ }
471
+ else {
472
+ handle.style.left = startPos + ds1 - handleSize / 2 + 'px';
473
+ }
474
+ (_a = ghostNode.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(ghostNode);
475
+ }
476
+ unlockPage();
477
+ document.body.style.cursor = bodyCursor;
478
+ func_js.call(onEnd, originSize, originSize1);
479
+ }
480
+ };
481
+ document.addEventListener('mousemove', dragListener, false);
482
+ document.addEventListener('mouseup', dragEndListener, false);
483
+ window.addEventListener('blur', dragEndListener, false);
484
+ e.preventDefault();
485
+ return false;
486
+ };
487
+ };
488
+ /**
489
+ * Add one or more splittors into the container
490
+ * @param container css selector or html element
491
+ * @param opts SplittableOptions
492
+ * @returns
493
+ */
494
+ function newSplittable(container, opts) {
495
+ return new Splittable(container, opts);
496
+ }
497
+
498
+ /* eslint-disable max-len */
499
+ const THRESHOLD$2 = 2;
500
+ const CLASS_RESIZABLE_HANDLE = "uii-resizable-handle";
501
+ const CLASS_RESIZABLE_HANDLE_DIR = "uii-resizable-handle-";
502
+ const CLASS_RESIZABLE_HANDLE_ACTIVE = "uii-resizable-handle-active";
503
+ /**
504
+ * 用于表示一个或多个可改变尺寸元素的定义
505
+ * > 可用CSS接口
506
+ * - .uii-resizable-handle
507
+ * - .uii-resizable-handle-[n/s/e/w/ne/nw/se/sw]
508
+ * - .uii-resizable-handle-active
509
+ * @public
510
+ */
511
+ class Resizable extends Uii {
512
+ constructor(els, opts) {
513
+ super(els, func_js.assign({
514
+ handleSize: 8,
515
+ minSize: 50,
516
+ dir: ['n', 's', 'e', 'w', 'ne', 'nw', 'se', 'sw'],
517
+ ghost: false,
518
+ offset: 0
519
+ }, opts));
520
+ func_js.each(this.ele, (el) => {
521
+ initHandle$1(el, this.opts);
522
+ });
523
+ }
524
+ }
525
+ function bindHandle$1(handle, dir, panel, opts) {
526
+ const onStart = opts.onStart;
527
+ const onResize = opts.onResize;
528
+ const onEnd = opts.onEnd;
529
+ const onClone = opts.onClone;
530
+ handle.onmousedown = function (e) {
531
+ // 获取panel当前信息
532
+ const originW = panel.offsetWidth;
533
+ const originH = panel.offsetHeight;
534
+ const originX = panel.offsetLeft;
535
+ const originY = panel.offsetTop;
536
+ let changeW = false;
537
+ let changeH = false;
538
+ let changeX = false;
539
+ let changeY = false;
540
+ switch (dir) {
541
+ case 's':
542
+ changeH = true;
543
+ break;
544
+ case 'e':
545
+ changeW = true;
546
+ break;
547
+ case 'n':
548
+ changeY = true;
549
+ changeH = true;
550
+ break;
551
+ case 'w':
552
+ changeX = true;
553
+ changeW = true;
554
+ break;
555
+ case 'se':
556
+ changeW = true;
557
+ changeH = true;
558
+ break;
559
+ case 'sw':
560
+ changeX = true;
561
+ changeW = true;
562
+ changeH = true;
563
+ break;
564
+ case 'ne':
565
+ changeY = true;
566
+ changeW = true;
567
+ changeH = true;
568
+ break;
569
+ case 'nw':
570
+ changeX = true;
571
+ changeY = true;
572
+ changeW = true;
573
+ changeH = true;
574
+ break;
575
+ }
576
+ const originPosX = e.clientX;
577
+ const originPosY = e.clientY;
578
+ // boundary
579
+ let minWidth;
580
+ let minHeight;
581
+ let maxWidth;
582
+ let maxHeight;
583
+ if (func_js.isArray(opts.minSize)) {
584
+ minWidth = opts.minSize[0];
585
+ minHeight = opts.minSize[1];
586
+ }
587
+ else if (func_js.isNumber(opts.minSize)) {
588
+ minWidth = opts.minSize;
589
+ minHeight = opts.minSize;
590
+ }
591
+ if (func_js.isArray(opts.maxSize)) {
592
+ maxWidth = opts.maxSize[0];
593
+ maxHeight = opts.maxSize[1];
594
+ }
595
+ else if (func_js.isNumber(opts.maxSize)) {
596
+ maxWidth = opts.maxSize;
597
+ maxHeight = opts.maxSize;
598
+ }
599
+ const minX = maxWidth ? originX - maxWidth + originW : null;
600
+ const minY = maxHeight ? originY - maxHeight + originH : null;
601
+ const maxX = minWidth ? originX + originW - minWidth : null;
602
+ const maxY = minHeight ? originY + originH - minHeight : null;
603
+ //ghost
604
+ const ghost = opts.ghost;
605
+ const ghostClass = opts.ghostClass;
606
+ let ghostNode = null;
607
+ //aspectRatio
608
+ const aspectRatio = opts.aspectRatio;
609
+ const panelStyle = panel.style;
610
+ let style = panelStyle;
611
+ let currentW = originW;
612
+ let currentH = originH;
613
+ let dragging = false;
614
+ let bodyCursor = document.body.style.cursor;
615
+ const dragListener = (ev) => {
616
+ var _a;
617
+ const offsetx = ev.clientX - originPosX;
618
+ const offsety = ev.clientY - originPosY;
619
+ if (!dragging) {
620
+ if (Math.abs(offsetx) > THRESHOLD$2 || Math.abs(offsety) > THRESHOLD$2) {
621
+ dragging = true;
622
+ handle.classList.add(CLASS_RESIZABLE_HANDLE_ACTIVE);
623
+ if (ghost) {
624
+ if (func_js.isFunction(ghost)) {
625
+ ghostNode = ghost();
626
+ }
627
+ else {
628
+ ghostNode = panel.cloneNode(true);
629
+ ghostNode.style.opacity = '0.3';
630
+ ghostNode.style.pointerEvents = 'none';
631
+ }
632
+ if (ghostNode) {
633
+ if (ghostClass) {
634
+ ghostNode.className =
635
+ ghostNode.className.replace(ghostClass, '') + ' ' + ghostClass;
636
+ }
637
+ (_a = panel.parentNode) === null || _a === void 0 ? void 0 : _a.appendChild(ghostNode);
638
+ func_js.call(onClone, ghostNode, e);
639
+ }
640
+ style = ghostNode === null || ghostNode === void 0 ? void 0 : ghostNode.style;
641
+ }
642
+ lockPage();
643
+ document.body.style.cursor = handle.dataset.cursor || '';
644
+ func_js.call(onStart, originW, originH);
645
+ }
646
+ else {
647
+ ev.preventDefault();
648
+ return false;
649
+ }
650
+ }
651
+ let w = originW;
652
+ let h = originH;
653
+ let y = originY;
654
+ let x = originX;
655
+ if (changeW) {
656
+ w = originW + offsetx * (changeX ? -1 : 1);
657
+ if (minWidth && w < minWidth)
658
+ w = minWidth;
659
+ if (maxWidth && w > maxWidth)
660
+ w = maxWidth;
661
+ }
662
+ if (changeH) {
663
+ h = originH + offsety * (changeY ? -1 : 1);
664
+ if (minHeight && h < minHeight)
665
+ h = minHeight;
666
+ if (maxHeight && h > maxHeight)
667
+ h = maxHeight;
668
+ }
669
+ if (changeY) {
670
+ y = originY + offsety;
671
+ if (minY && y < minY)
672
+ y = minY;
673
+ if (maxY && y > maxY)
674
+ y = maxY;
675
+ }
676
+ if (changeX) {
677
+ x = originX + offsetx;
678
+ if (minX && x < minX)
679
+ x = minX;
680
+ if (maxX && x > maxX)
681
+ x = maxX;
682
+ }
683
+ if (aspectRatio) {
684
+ if (changeW) {
685
+ style.width = w + 'px';
686
+ style.height = w / aspectRatio + 'px';
687
+ }
688
+ if (changeH && dir !== 'sw') {
689
+ if (dir === 'nw') {
690
+ y = originY - w / aspectRatio + originH;
691
+ }
692
+ else {
693
+ style.width = h * aspectRatio + 'px';
694
+ style.height = h + 'px';
695
+ }
696
+ }
697
+ }
698
+ else {
699
+ if (changeW) {
700
+ style.width = w + 'px';
701
+ }
702
+ if (changeH) {
703
+ style.height = h + 'px';
704
+ }
705
+ }
706
+ if (changeY) {
707
+ style.top = y + 'px';
708
+ }
709
+ if (changeX) {
710
+ style.left = x + 'px';
711
+ }
712
+ currentW = w;
713
+ currentH = h;
714
+ func_js.call(onResize, w, h);
715
+ ev.preventDefault();
716
+ return false;
717
+ };
718
+ const dragEndListener = (ev) => {
719
+ var _a;
720
+ document.removeEventListener('mousemove', dragListener, false);
721
+ document.removeEventListener('mouseup', dragEndListener, false);
722
+ window.removeEventListener('blur', dragEndListener, false);
723
+ if (ghost && ghostNode) {
724
+ (_a = panel.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(ghostNode);
725
+ panelStyle.left = ghostNode.style.left;
726
+ panelStyle.top = ghostNode.style.top;
727
+ panelStyle.width = ghostNode.style.width;
728
+ panelStyle.height = ghostNode.style.height;
729
+ }
730
+ handle.classList.remove(CLASS_RESIZABLE_HANDLE_ACTIVE);
731
+ unlockPage();
732
+ document.body.style.cursor = bodyCursor;
733
+ func_js.call(onEnd, currentW, currentH);
734
+ };
735
+ document.addEventListener('mousemove', dragListener, false);
736
+ document.addEventListener('mouseup', dragEndListener, false);
737
+ window.addEventListener('blur', dragEndListener, false);
738
+ e.preventDefault();
739
+ return false;
740
+ };
741
+ }
742
+ function initHandle$1(panel, opts) {
743
+ // create handles
744
+ const handleSize = opts.handleSize;
745
+ const offset = opts.offset || 0;
746
+ func_js.each(opts.dir || ['n', 's', 'e', 'w', 'ne', 'nw', 'se', 'sw'], (dir) => {
747
+ const handle = document.createElement('div');
748
+ handle.classList.add(CLASS_RESIZABLE_HANDLE, CLASS_RESIZABLE_HANDLE_DIR + dir);
749
+ handle.setAttribute('name', 'handle');
750
+ let css = '';
751
+ switch (dir) {
752
+ case 'n':
753
+ css = `left:0px;top:${-offset}px;width:100%;height:${handleSize}px;`;
754
+ break;
755
+ case 's':
756
+ css = `left:0px;bottom:${-offset}px;width:100%;height:${handleSize}px;`;
757
+ break;
758
+ case 'w':
759
+ css = `top:0px;left:${-offset}px;width:${handleSize}px;height:100%;`;
760
+ break;
761
+ case 'e':
762
+ css = `top:0px;right:${-offset}px;width:${handleSize}px;height:100%;`;
763
+ break;
764
+ default:
765
+ css = `width:${handleSize}px;height:${handleSize}px;z-index:9;`;
766
+ switch (dir) {
767
+ case 'ne':
768
+ css += `top:${-offset}px;right:${-offset}px;`;
769
+ break;
770
+ case 'nw':
771
+ css += `top:${-offset}px;left:${-offset}px;`;
772
+ break;
773
+ case 'se':
774
+ css += `bottom:${-offset}px;right:${-offset}px;`;
775
+ break;
776
+ case 'sw':
777
+ css += `bottom:${-offset}px;left:${-offset}px;`;
778
+ }
779
+ }
780
+ bindHandle$1(handle, dir, panel, opts);
781
+ handle.style.cssText = `position: absolute;cursor: ${dir}-resize;` + css;
782
+ handle.dataset.cursor = `${dir}-resize`;
783
+ panel.appendChild(handle);
784
+ });
785
+ }
786
+ /**
787
+ * Make els resizable
788
+ * @param els selector string / html element
789
+ * @param opts
790
+ * @returns
791
+ */
792
+ function newResizable(els, opts) {
793
+ return new Resizable(els, opts);
794
+ }
795
+
796
+ var _Draggable_handleMap;
797
+ const DRAGGER_GROUPS = {};
798
+ const CLASS_DRAGGABLE = "uii-draggable";
799
+ const CLASS_DRAGGABLE_HANDLE = "uii-draggable-handle";
800
+ const CLASS_DRAGGABLE_ACTIVE = "uii-draggable-active";
801
+ const CLASS_DRAGGABLE_GHOST = "uii-draggable-ghost";
802
+ /**
803
+ * 用于表示一个或多个可拖动元素的定义
804
+ * > 可用CSS接口
805
+ * - .uii-draggable
806
+ * - .uii-draggable-handle
807
+ * - .uii-draggable-active
808
+ * - .uii-draggable-ghost
809
+ * @public
810
+ */
811
+ class Draggable extends Uii {
812
+ constructor(els, opts) {
813
+ super(els, func_js.assign({
814
+ container: false,
815
+ threshold: 0,
816
+ ghost: false,
817
+ direction: "",
818
+ scroll: true,
819
+ snapOptions: {
820
+ tolerance: 10,
821
+ }
822
+ }, opts));
823
+ _Draggable_handleMap.set(this, new WeakMap());
824
+ if (this.opts.handle) {
825
+ func_js.each(this.ele, (el) => {
826
+ const h = el.querySelector(this.opts.handle);
827
+ if (!h) {
828
+ console.error('No handle found "' + this.opts.handle + '"');
829
+ return false;
830
+ }
831
+ __classPrivateFieldGet(this, _Draggable_handleMap, "f").set(el, h);
832
+ });
833
+ }
834
+ this.onOptionChanged(this.opts);
835
+ //put into group
836
+ if (this.opts.group) {
837
+ if (!DRAGGER_GROUPS[this.opts.group]) {
838
+ DRAGGER_GROUPS[this.opts.group] = [];
839
+ }
840
+ DRAGGER_GROUPS[this.opts.group].push(...this.ele);
841
+ }
842
+ func_js.each(this.ele, (el) => {
843
+ bindEvent(this.registerEvent.bind(this), el, this.opts, __classPrivateFieldGet(this, _Draggable_handleMap, "f"));
844
+ if (func_js.isDefined(this.opts.type))
845
+ el.dataset.dropType = this.opts.type;
846
+ el.classList.toggle(CLASS_DRAGGABLE, true);
847
+ const ee = __classPrivateFieldGet(this, _Draggable_handleMap, "f").get(el) || el;
848
+ ee.classList.toggle(CLASS_DRAGGABLE_HANDLE, true);
849
+ if (func_js.isDefined(this.opts.cursor)) {
850
+ el.style.cursor = this.opts.cursor.default || 'move';
851
+ if (func_js.isDefined(this.opts.cursor.over)) {
852
+ el.dataset.cursorOver = this.opts.cursor.over;
853
+ el.dataset.cursorActive = this.opts.cursor.active || 'move';
854
+ }
855
+ }
856
+ });
857
+ }
858
+ /**
859
+ * @internal
860
+ */
861
+ onOptionChanged(opts) {
862
+ const droppable = opts.droppable;
863
+ if (!func_js.isFunction(droppable)) {
864
+ if (func_js.isUndefined(droppable)) {
865
+ opts.droppable = () => { };
866
+ }
867
+ else if (func_js.isString(droppable)) {
868
+ opts.droppable = () => document.querySelectorAll(droppable);
869
+ }
870
+ else if (func_js.isArrayLike(droppable)) {
871
+ opts.droppable = () => droppable;
872
+ }
873
+ else if (func_js.isElement(droppable)) {
874
+ opts.droppable = () => [droppable];
875
+ }
876
+ }
877
+ if (opts.snap) {
878
+ opts.snapTargets = func_js.map(document.querySelectorAll(opts.snap), (el) => {
879
+ let offX = 0, offY = 0;
880
+ func_js.closest(el, (el) => {
881
+ offX += el.offsetLeft;
882
+ offY += el.offsetTop;
883
+ return false;
884
+ }, "offsetParent");
885
+ return {
886
+ x1: offX,
887
+ y1: offY,
888
+ x2: offX + el.offsetWidth,
889
+ y2: offY + el.offsetHeight,
890
+ el: el,
891
+ };
892
+ });
893
+ }
894
+ }
895
+ }
896
+ _Draggable_handleMap = new WeakMap();
897
+ function bindEvent(registerEvent, el, opts, handleMap) {
898
+ registerEvent(el, "mousedown", (e) => {
899
+ // get options
900
+ let dragDom = e.currentTarget;
901
+ let t = e.target;
902
+ if (!t)
903
+ return;
904
+ let handle = handleMap.get(dragDom);
905
+ if (handle && !handle.contains(t)) {
906
+ return;
907
+ }
908
+ const filter = opts.filter;
909
+ //check filter
910
+ if (filter) {
911
+ if (func_js.some(el.querySelectorAll(filter), ele => ele.contains(t)))
912
+ return;
913
+ }
914
+ const computedStyle = window.getComputedStyle(dragDom);
915
+ const container = dragDom.offsetParent || document.body;
916
+ const inContainer = opts.container;
917
+ const threshold = opts.threshold;
918
+ const ghost = opts.ghost;
919
+ const ghostClass = opts.ghostClass;
920
+ const direction = opts.direction;
921
+ const onStart = opts.onStart;
922
+ const onDrag = opts.onDrag;
923
+ const onEnd = opts.onEnd;
924
+ const onClone = opts.onClone;
925
+ const originalZIndex = computedStyle.zIndex;
926
+ let zIndex = opts.zIndex || originalZIndex;
927
+ const classes = opts.classes;
928
+ const group = opts.group;
929
+ if (group) {
930
+ let i = -1;
931
+ func_js.each(DRAGGER_GROUPS[group], el => {
932
+ const z = parseInt(window.getComputedStyle(el).zIndex);
933
+ if (z > i)
934
+ i = z;
935
+ });
936
+ zIndex = i + 1;
937
+ }
938
+ const scroll = opts.scroll;
939
+ const scrollSpeed = opts.scrollSpeed || 10;
940
+ let gridX, gridY;
941
+ const grid = opts.grid;
942
+ if (func_js.isArray(grid)) {
943
+ gridX = grid[0];
944
+ gridY = grid[1];
945
+ }
946
+ else if (func_js.isNumber(grid)) {
947
+ gridX = gridY = grid;
948
+ }
949
+ const snapOn = opts.snap;
950
+ const snappable = opts.snapTargets;
951
+ const snapTolerance = opts.snapOptions.tolerance;
952
+ const onSnap = opts.onSnap;
953
+ let lastSnapDirY = "", lastSnapDirX = "";
954
+ let lastSnapping = "";
955
+ let parentOffsetX = 0, parentOffsetY = 0;
956
+ if (snapOn) {
957
+ func_js.closest(dragDom, (el, times) => {
958
+ if (times > 0) {
959
+ parentOffsetX += el.offsetLeft;
960
+ parentOffsetY += el.offsetTop;
961
+ }
962
+ return false;
963
+ }, "offsetParent");
964
+ }
965
+ const originW = dragDom.offsetWidth + parseFloat(computedStyle.borderLeftWidth) + parseFloat(computedStyle.borderRightWidth);
966
+ const originH = dragDom.offsetHeight + parseFloat(computedStyle.borderTopWidth) + parseFloat(computedStyle.borderBottomWidth);
967
+ // boundary
968
+ let minX;
969
+ let minY;
970
+ let maxX;
971
+ let maxY;
972
+ if (inContainer) {
973
+ minX = 0;
974
+ minY = 0;
975
+ maxX = container.scrollWidth - originW;
976
+ maxY = container.scrollHeight - originH;
977
+ }
978
+ //start point
979
+ const rect = container.getBoundingClientRect();
980
+ const offset = getOffset(t, container);
981
+ const ox = e.offsetX || 0;
982
+ const oy = e.offsetY || 0;
983
+ let hitPosX = offset.x + ox + container.scrollLeft;
984
+ let hitPosY = offset.y + oy + container.scrollTop;
985
+ let cursorX = ox, cursorY = e.offsetY;
986
+ if (e.target !== dragDom) {
987
+ const offset = getOffset(t, dragDom);
988
+ const style = window.getComputedStyle(t);
989
+ cursorX = offset.x + ox + parseFloat(style.borderLeftWidth);
990
+ cursorY = offset.y + oy + parseFloat(style.borderTopWidth);
991
+ }
992
+ const cursorAt = opts.cursorAt;
993
+ if (cursorAt) {
994
+ const l = cursorAt.left;
995
+ const t = cursorAt.top;
996
+ if (func_js.isString(l)) {
997
+ cursorX = parseFloat(l) / 100 * dragDom.offsetWidth;
998
+ }
999
+ else {
1000
+ cursorX = l;
1001
+ }
1002
+ if (func_js.isString(t)) {
1003
+ cursorY = parseFloat(t) / 100 * dragDom.offsetWidth;
1004
+ }
1005
+ else {
1006
+ cursorY = t;
1007
+ }
1008
+ }
1009
+ const style = dragDom.style;
1010
+ let dragging = false;
1011
+ let copyNode;
1012
+ let timer = null;
1013
+ let toLeft = false;
1014
+ let toTop = false;
1015
+ let toRight = false;
1016
+ let toBottom = false;
1017
+ let bodyCursor = document.body.style.cursor;
1018
+ const dragListener = (ev) => {
1019
+ var _a;
1020
+ const newX = ev.clientX - rect.x + container.scrollLeft;
1021
+ const newY = ev.clientY - rect.y + container.scrollTop;
1022
+ let offsetx = newX - hitPosX;
1023
+ let offsety = newY - hitPosY;
1024
+ if (!dragging) {
1025
+ if (Math.abs(offsetx) > threshold || Math.abs(offsety) > threshold) {
1026
+ dragging = true;
1027
+ if (ghost) {
1028
+ if (func_js.isFunction(ghost)) {
1029
+ copyNode = ghost(dragDom);
1030
+ }
1031
+ else {
1032
+ copyNode = dragDom.cloneNode(true);
1033
+ copyNode.style.opacity = "0.3";
1034
+ copyNode.style.pointerEvents = "none";
1035
+ copyNode.style.position = "absolute";
1036
+ }
1037
+ copyNode.style.left = dragDom.style.left;
1038
+ copyNode.style.top = dragDom.style.top;
1039
+ copyNode.style.zIndex = zIndex;
1040
+ if (ghostClass) {
1041
+ copyNode.classList.add(...func_js.compact(func_js.split(ghostClass, ' ')));
1042
+ }
1043
+ copyNode.classList.add(...func_js.compact(func_js.split(classes, ' ')));
1044
+ copyNode.classList.toggle(CLASS_DRAGGABLE_GHOST, true);
1045
+ (_a = dragDom.parentNode) === null || _a === void 0 ? void 0 : _a.appendChild(copyNode);
1046
+ if (onClone) {
1047
+ onClone(copyNode, ev);
1048
+ }
1049
+ }
1050
+ //apply classes
1051
+ dragDom.classList.add(...func_js.compact(func_js.split(classes, ' ')));
1052
+ dragDom.style.zIndex = zIndex;
1053
+ dragDom.classList.toggle(CLASS_DRAGGABLE_ACTIVE, true);
1054
+ func_js.call(onStart, dragDom, ev);
1055
+ lockPage();
1056
+ if (func_js.isDefined(opts.cursor)) {
1057
+ document.body.style.cursor = opts.cursor.active || 'move';
1058
+ }
1059
+ //notify
1060
+ const customEv = new Event("uii-dragactive", { "bubbles": true, "cancelable": false });
1061
+ dragDom.dispatchEvent(customEv);
1062
+ }
1063
+ else {
1064
+ ev.preventDefault();
1065
+ return false;
1066
+ }
1067
+ }
1068
+ //edge detect
1069
+ if (scroll) {
1070
+ const ltX = ev.clientX - rect.x;
1071
+ const ltY = ev.clientY - rect.y;
1072
+ const rbX = rect.x + rect.width - ev.clientX;
1073
+ const rbY = rect.y + rect.height - ev.clientY;
1074
+ toLeft = ltX < EDGE_THRESHOLD;
1075
+ toTop = ltY < EDGE_THRESHOLD;
1076
+ toRight = rbX < EDGE_THRESHOLD;
1077
+ toBottom = rbY < EDGE_THRESHOLD;
1078
+ if (toLeft || toTop
1079
+ ||
1080
+ toRight || toBottom) {
1081
+ if (!timer) {
1082
+ timer = setInterval(() => {
1083
+ if (toLeft) {
1084
+ container.scrollLeft -= scrollSpeed;
1085
+ }
1086
+ else if (toRight) {
1087
+ container.scrollLeft += scrollSpeed;
1088
+ }
1089
+ if (toTop) {
1090
+ container.scrollTop -= scrollSpeed;
1091
+ }
1092
+ else if (toBottom) {
1093
+ container.scrollTop += scrollSpeed;
1094
+ }
1095
+ }, 20);
1096
+ }
1097
+ }
1098
+ else {
1099
+ if (timer) {
1100
+ clearInterval(timer);
1101
+ timer = null;
1102
+ }
1103
+ }
1104
+ }
1105
+ let x = newX - cursorX;
1106
+ let y = newY - cursorY;
1107
+ //grid
1108
+ if (func_js.isNumber(gridX) && func_js.isNumber(gridY)) {
1109
+ x = ((x / gridX) >> 0) * gridX;
1110
+ y = ((y / gridY) >> 0) * gridY;
1111
+ }
1112
+ if (inContainer) {
1113
+ if (x < minX)
1114
+ x = minX;
1115
+ if (y < minY)
1116
+ y = minY;
1117
+ if (x > maxX)
1118
+ x = maxX;
1119
+ if (y > maxY)
1120
+ y = maxY;
1121
+ }
1122
+ let canDrag = true;
1123
+ let emitSnap = false;
1124
+ if (snapOn) {
1125
+ const currPageX1 = parentOffsetX + x;
1126
+ const currPageY1 = parentOffsetY + y;
1127
+ const currPageX2 = currPageX1 + originW;
1128
+ const currPageY2 = currPageY1 + originH;
1129
+ //check snappable
1130
+ let snapX = NaN, snapY = NaN;
1131
+ let targetX, targetY;
1132
+ let snapDirX, snapDirY;
1133
+ if (!direction || direction === "v") {
1134
+ func_js.each(snappable, (data) => {
1135
+ if (Math.abs(data.y1 - currPageY1) <= snapTolerance) {
1136
+ //top parallel
1137
+ snapY = data.y1;
1138
+ snapDirY = "t2t";
1139
+ }
1140
+ else if (Math.abs(data.y2 - currPageY1) <= snapTolerance) {
1141
+ //b2t
1142
+ snapY = data.y2;
1143
+ snapDirY = "t2b";
1144
+ }
1145
+ else if (Math.abs(data.y1 - currPageY2) <= snapTolerance) {
1146
+ //t2b
1147
+ snapY = data.y1 - originH;
1148
+ snapDirY = "b2t";
1149
+ }
1150
+ else if (Math.abs(data.y2 - currPageY2) <= snapTolerance) {
1151
+ //bottom parallel
1152
+ snapY = data.y2 - originH;
1153
+ snapDirY = "b2b";
1154
+ }
1155
+ if (snapY) {
1156
+ lastSnapDirY = snapDirY;
1157
+ targetY = data.el;
1158
+ return false;
1159
+ }
1160
+ });
1161
+ }
1162
+ if (!direction || direction === "h") {
1163
+ func_js.each(snappable, (data) => {
1164
+ if (Math.abs(data.x1 - currPageX1) <= snapTolerance) {
1165
+ //left parallel
1166
+ snapX = data.x1;
1167
+ snapDirX = "l2l";
1168
+ }
1169
+ else if (Math.abs(data.x2 - currPageX1) <= snapTolerance) {
1170
+ //r2l
1171
+ snapX = data.x2;
1172
+ snapDirX = "l2r";
1173
+ }
1174
+ else if (Math.abs(data.x1 - currPageX2) <= snapTolerance) {
1175
+ //l2r
1176
+ snapX = data.x1 - originW;
1177
+ snapDirX = "r2l";
1178
+ }
1179
+ else if (Math.abs(data.x2 - currPageX2) <= snapTolerance) {
1180
+ //right parallel
1181
+ snapX = data.x2 - originW;
1182
+ snapDirX = "r2r";
1183
+ }
1184
+ if (snapX) {
1185
+ lastSnapDirX = snapDirX;
1186
+ targetX = data.el;
1187
+ return false;
1188
+ }
1189
+ });
1190
+ }
1191
+ if (snapX || snapY) {
1192
+ if (snapX) {
1193
+ x = snapX - parentOffsetX;
1194
+ }
1195
+ if (snapY) {
1196
+ y = snapY - parentOffsetY;
1197
+ }
1198
+ if (onSnap && lastSnapping !== lastSnapDirX + "" + lastSnapDirY) {
1199
+ setTimeout(() => {
1200
+ //emit after relocate
1201
+ onSnap(copyNode || dragDom, targetX, targetY, snapDirX, snapDirY);
1202
+ }, 0);
1203
+ lastSnapping = lastSnapDirX + "" + lastSnapDirY;
1204
+ }
1205
+ emitSnap = true;
1206
+ }
1207
+ else {
1208
+ lastSnapDirX = lastSnapDirY = lastSnapping = "";
1209
+ }
1210
+ }
1211
+ if (onDrag && !emitSnap) {
1212
+ if (onDrag(dragDom, ev, offsetx, offsety, x, y) === false) {
1213
+ canDrag = false;
1214
+ }
1215
+ }
1216
+ if (canDrag) {
1217
+ if (copyNode) {
1218
+ if (direction === "v") {
1219
+ copyNode.style.top = `${y}px`;
1220
+ }
1221
+ else if (direction === "v") {
1222
+ copyNode.style.left = `${x}px`;
1223
+ }
1224
+ else {
1225
+ copyNode.style.left = `${x}px`;
1226
+ copyNode.style.top = `${y}px`;
1227
+ }
1228
+ }
1229
+ else {
1230
+ if (direction === "v") {
1231
+ style.top = `${y}px`;
1232
+ }
1233
+ else if (direction === "v") {
1234
+ style.left = `${x}px`;
1235
+ }
1236
+ else {
1237
+ style.left = `${x}px`;
1238
+ style.top = `${y}px`;
1239
+ }
1240
+ }
1241
+ }
1242
+ ev.preventDefault();
1243
+ return false;
1244
+ };
1245
+ const dragEndListener = (ev) => {
1246
+ var _a;
1247
+ document.removeEventListener("mousemove", dragListener);
1248
+ document.removeEventListener("mouseup", dragEndListener);
1249
+ window.removeEventListener("blur", dragEndListener);
1250
+ if (scroll) {
1251
+ if (timer) {
1252
+ clearInterval(timer);
1253
+ timer = null;
1254
+ }
1255
+ }
1256
+ //restore classes
1257
+ dragDom.classList.remove(...func_js.compact(func_js.split(classes, ' ')));
1258
+ dragDom.style.zIndex = originalZIndex;
1259
+ dragDom.classList.remove(CLASS_DRAGGABLE_ACTIVE);
1260
+ let moveToGhost = true;
1261
+ if (dragging) {
1262
+ moveToGhost = func_js.call(onEnd, dragDom, ev);
1263
+ }
1264
+ //notify
1265
+ const customEv = new Event("uii-dragdeactive", { "bubbles": true, "cancelable": false });
1266
+ dragDom.dispatchEvent(customEv);
1267
+ if (dragging) {
1268
+ unlockPage();
1269
+ document.body.style.cursor = bodyCursor;
1270
+ if (ghost) {
1271
+ (_a = dragDom.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(copyNode);
1272
+ if (moveToGhost !== false) {
1273
+ style.left = copyNode.style.left;
1274
+ style.top = copyNode.style.top;
1275
+ }
1276
+ }
1277
+ }
1278
+ };
1279
+ document.addEventListener("mousemove", dragListener);
1280
+ document.addEventListener("mouseup", dragEndListener);
1281
+ window.addEventListener("blur", dragEndListener);
1282
+ e.preventDefault();
1283
+ return false;
1284
+ });
1285
+ }
1286
+ /**
1287
+ * create a draggable pattern for one or more elements with opts
1288
+ * @param els selector string / html element
1289
+ * @param opts
1290
+ * @returns Draggable instance
1291
+ */
1292
+ function newDraggable(els, opts) {
1293
+ return new Draggable(els, opts);
1294
+ }
1295
+
1296
+ var _Droppable_active;
1297
+ const Droppables = [];
1298
+ const CLASS_DROPPABLE = "uii-droppable";
1299
+ /**
1300
+ * 用于表示一个或多个可响应拖动元素的定义
1301
+ * > 可用CSS接口
1302
+ * - .uii-droppable
1303
+ * @public
1304
+ */
1305
+ class Droppable extends Uii {
1306
+ constructor(el, opts) {
1307
+ super(el, func_js.assign({}, opts));
1308
+ _Droppable_active.set(this, void 0);
1309
+ Droppables.push(this);
1310
+ }
1311
+ /**
1312
+ * @internal
1313
+ */
1314
+ bindEvent(el, opts) {
1315
+ //dragenter
1316
+ this.registerEvent(el, "mouseenter", (e) => {
1317
+ if (!__classPrivateFieldGet(this, _Droppable_active, "f"))
1318
+ return;
1319
+ if (opts.hoverClass) {
1320
+ func_js.each(func_js.split(opts.hoverClass, ' '), cls => {
1321
+ el.classList.toggle(cls, true);
1322
+ });
1323
+ }
1324
+ if (__classPrivateFieldGet(this, _Droppable_active, "f").dataset.cursorOver) {
1325
+ document.body.style.cursor = __classPrivateFieldGet(this, _Droppable_active, "f").dataset.cursorOver;
1326
+ }
1327
+ func_js.call(opts.onEnter, el, e);
1328
+ });
1329
+ //dragleave
1330
+ this.registerEvent(el, "mouseleave", (e) => {
1331
+ if (!__classPrivateFieldGet(this, _Droppable_active, "f"))
1332
+ return;
1333
+ if (opts.hoverClass) {
1334
+ func_js.each(func_js.split(opts.hoverClass, ' '), cls => {
1335
+ el.classList.toggle(cls, false);
1336
+ });
1337
+ }
1338
+ if (__classPrivateFieldGet(this, _Droppable_active, "f").dataset.cursorOver) {
1339
+ document.body.style.cursor = __classPrivateFieldGet(this, _Droppable_active, "f").dataset.cursorActive || '';
1340
+ }
1341
+ func_js.call(opts.onLeave, el, e);
1342
+ });
1343
+ //dragover
1344
+ this.registerEvent(el, "mousemove", (e) => {
1345
+ if (!__classPrivateFieldGet(this, _Droppable_active, "f"))
1346
+ return;
1347
+ if (opts.onDragOver) {
1348
+ opts.onDragOver(el, e);
1349
+ }
1350
+ });
1351
+ //drop
1352
+ this.registerEvent(el, "mouseup", (e) => {
1353
+ if (!__classPrivateFieldGet(this, _Droppable_active, "f"))
1354
+ return;
1355
+ if (opts.hoverClass) {
1356
+ func_js.each(func_js.split(opts.hoverClass, ' '), cls => {
1357
+ el.classList.toggle(cls, false);
1358
+ });
1359
+ }
1360
+ func_js.call(opts.onDrop, el, e);
1361
+ });
1362
+ }
1363
+ /**
1364
+ * @internal
1365
+ */
1366
+ active(target) {
1367
+ let valid = true;
1368
+ //check accepts
1369
+ if (func_js.isString(this.opts.accepts)) {
1370
+ valid = !!target.dataset.dropType && func_js.test(this.opts.accepts, target.dataset.dropType);
1371
+ }
1372
+ else if (func_js.isFunction(this.opts.accepts)) {
1373
+ valid = this.opts.accepts(this.ele, target);
1374
+ }
1375
+ if (!valid)
1376
+ return;
1377
+ __classPrivateFieldSet(this, _Droppable_active, target, "f");
1378
+ if (this.opts.activeClass) {
1379
+ func_js.each(this.ele, el => {
1380
+ func_js.each(func_js.split(this.opts.activeClass, ' '), cls => {
1381
+ el.classList.toggle(cls, true);
1382
+ });
1383
+ });
1384
+ }
1385
+ func_js.call(this.opts.onActive, target, this.ele);
1386
+ //bind events
1387
+ func_js.each(this.ele, (el) => {
1388
+ el.classList.toggle(CLASS_DROPPABLE, true);
1389
+ el.style.pointerEvents = 'initial';
1390
+ this.bindEvent(el, this.opts);
1391
+ });
1392
+ }
1393
+ /**
1394
+ * @internal
1395
+ */
1396
+ deactive(target) {
1397
+ if (!__classPrivateFieldGet(this, _Droppable_active, "f"))
1398
+ return;
1399
+ __classPrivateFieldSet(this, _Droppable_active, null, "f");
1400
+ if (this.opts.activeClass) {
1401
+ func_js.each(this.ele, el => {
1402
+ func_js.each(func_js.split(this.opts.activeClass, ' '), cls => {
1403
+ el.classList.toggle(cls, false);
1404
+ });
1405
+ });
1406
+ }
1407
+ func_js.call(this.opts.onDeactive, target, this.ele);
1408
+ //unbind events
1409
+ this.destroy();
1410
+ }
1411
+ }
1412
+ _Droppable_active = new WeakMap();
1413
+ //uii-drag active
1414
+ document.addEventListener("uii-dragactive", (e) => {
1415
+ func_js.each(Droppables, dpb => {
1416
+ dpb.active(e.target);
1417
+ });
1418
+ });
1419
+ document.addEventListener("uii-dragdeactive", (e) => {
1420
+ func_js.each(Droppables, dpb => {
1421
+ dpb.deactive(e.target);
1422
+ });
1423
+ });
1424
+ /**
1425
+ * Enable els to response to draggable objects
1426
+ * @param els selector string / html element
1427
+ * @param opts
1428
+ * @returns
1429
+ */
1430
+ function newDroppable(els, opts) {
1431
+ return new Droppable(els, opts);
1432
+ }
1433
+
1434
+ /* eslint-disable max-len */
1435
+ const ONE_DEG = 180 / Math.PI;
1436
+ const THRESHOLD$1 = 2;
1437
+ const CLASS_ROTATABLE = "uii-rotatable";
1438
+ const CLASS_ROTATABLE_HANDLE = "uii-rotatable-handle";
1439
+ const CLASS_ROTATABLE_ACTIVE = "uii-rotatable-active";
1440
+ /**
1441
+ * 用于表示一个或多个可旋转元素的定义
1442
+ * > 可用CSS接口
1443
+ * - .uii-rotatable
1444
+ * - .uii-rotatable-handle
1445
+ * - .uii-rotatable-active
1446
+ * @public
1447
+ */
1448
+ class Rotatable extends Uii {
1449
+ constructor(els, opts) {
1450
+ super(els, opts);
1451
+ func_js.each(this.ele, (el) => {
1452
+ initHandle(el, this.opts);
1453
+ });
1454
+ }
1455
+ }
1456
+ function initHandle(el, opts) {
1457
+ var _a;
1458
+ const handle = document.createElement('div');
1459
+ handle.className = CLASS_ROTATABLE_HANDLE;
1460
+ handle.style.cssText = `
1461
+ position:absolute;
1462
+ width:12px;
1463
+ height:12px;
1464
+ border-radius:50%;
1465
+ left: calc(50% - 6px);
1466
+ top: -24px;
1467
+ `;
1468
+ handle.style.cursor = ((_a = opts.cursor) === null || _a === void 0 ? void 0 : _a.default) || 'crosshair';
1469
+ bindHandle(handle, el, opts);
1470
+ el.classList.toggle(CLASS_ROTATABLE, true);
1471
+ el.appendChild(handle);
1472
+ }
1473
+ function bindHandle(handle, el, opts) {
1474
+ const onStart = opts.onStart;
1475
+ const onRotate = opts.onRotate;
1476
+ const onEnd = opts.onEnd;
1477
+ handle.onmousedown = function (e) {
1478
+ var _a, _b;
1479
+ // calc center
1480
+ const center = window.getComputedStyle(el).transformOrigin || '';
1481
+ const centerPair = center.split(' ');
1482
+ const shadowDom = el.cloneNode();
1483
+ shadowDom.style.cssText = 'transform:rotate(0);z-index:-999;position:absolute;';
1484
+ (_a = el.parentElement) === null || _a === void 0 ? void 0 : _a.appendChild(shadowDom);
1485
+ const offsetXY = shadowDom.getBoundingClientRect();
1486
+ (_b = el.parentElement) === null || _b === void 0 ? void 0 : _b.removeChild(shadowDom);
1487
+ let centerX = parseFloat(centerPair[0]) + offsetXY.x;
1488
+ let centerY = parseFloat(centerPair[1]) + offsetXY.y;
1489
+ let a = 0, b = 0;
1490
+ const matrix = window.getComputedStyle(el).transform;
1491
+ if (matrix.indexOf('matrix') > -1) {
1492
+ const abcd = matrix.replace(/^matrix\(|\)$/mg, '').split(',');
1493
+ a = parseFloat(abcd[0]);
1494
+ b = parseFloat(abcd[1]);
1495
+ }
1496
+ let deg = Math.atan2(b, a) * ONE_DEG;
1497
+ if (deg < 0)
1498
+ deg = 360 - deg;
1499
+ if (deg > 360)
1500
+ deg = 360 - deg % 360;
1501
+ const style = el.style;
1502
+ let startDeg = Math.atan2(e.clientY - centerY, e.clientX - centerX) * ONE_DEG + 90;
1503
+ if (startDeg < 0)
1504
+ startDeg = 360 + startDeg;
1505
+ const offsetDeg = startDeg - deg;
1506
+ let dragging = false;
1507
+ let bodyCursor = document.body.style.cursor;
1508
+ const dragListener = (ev) => {
1509
+ var _a;
1510
+ const offsetx = ev.clientX - centerX;
1511
+ const offsety = ev.clientY - centerY;
1512
+ if (!dragging) {
1513
+ if (Math.abs(offsetx) > THRESHOLD$1 || Math.abs(offsety) > THRESHOLD$1) {
1514
+ dragging = true;
1515
+ //apply classes
1516
+ el.classList.toggle(CLASS_ROTATABLE_ACTIVE, true);
1517
+ func_js.call(onStart, deg);
1518
+ lockPage();
1519
+ if (func_js.isDefined(opts.cursor)) {
1520
+ document.body.style.cursor = ((_a = opts.cursor) === null || _a === void 0 ? void 0 : _a.active) || 'crosshair';
1521
+ }
1522
+ }
1523
+ else {
1524
+ ev.preventDefault();
1525
+ return false;
1526
+ }
1527
+ }
1528
+ deg = Math.atan2(offsety, offsetx) * ONE_DEG + 90 - offsetDeg;
1529
+ if (deg < 0)
1530
+ deg = 360 + deg;
1531
+ func_js.call(onRotate, deg);
1532
+ style.transform = style.transform.replace(/rotateZ\(.*?\)/, '') + ' rotateZ(' + deg + 'deg)';
1533
+ ev.preventDefault();
1534
+ return false;
1535
+ };
1536
+ const dragEndListener = (ev) => {
1537
+ document.removeEventListener('mousemove', dragListener, false);
1538
+ document.removeEventListener('mouseup', dragEndListener, false);
1539
+ window.removeEventListener('blur', dragEndListener, false);
1540
+ if (dragging) {
1541
+ unlockPage();
1542
+ document.body.style.cursor = bodyCursor;
1543
+ el.classList.toggle(CLASS_ROTATABLE_ACTIVE, false);
1544
+ func_js.call(onEnd, deg);
1545
+ }
1546
+ };
1547
+ document.addEventListener('mousemove', dragListener, false);
1548
+ document.addEventListener('mouseup', dragEndListener, false);
1549
+ window.addEventListener('blur', dragEndListener, false);
1550
+ e.preventDefault();
1551
+ return false;
1552
+ };
1553
+ }
1554
+ /**
1555
+ * Make els rotatable
1556
+ * @param els selector string / html element
1557
+ * @param opts
1558
+ * @returns
1559
+ */
1560
+ function newRotatable(els, opts) {
1561
+ return new Rotatable(els, opts);
1562
+ }
1563
+
1564
+ var _CollisionDetector__targets;
1565
+ class CollisionDetector {
1566
+ constructor(el, targets, opts) {
1567
+ _CollisionDetector__targets.set(this, void 0);
1568
+ __classPrivateFieldSet(this, _CollisionDetector__targets, targets, "f");
1569
+ this.opts = {
1570
+ container: document.body
1571
+ };
1572
+ this.opts = func_js.assign(this.opts, opts);
1573
+ const domEl = func_js.isString(el) ? document.querySelector(el) : el;
1574
+ if (!domEl) {
1575
+ console.error('Invalid selector "' + el + '"');
1576
+ return;
1577
+ }
1578
+ const ele = domEl;
1579
+ this.el = domEl;
1580
+ //el data
1581
+ const offset = getOffset(ele, this.opts.container);
1582
+ const rect = { x: offset.x, y: offset.y, width: ele.offsetWidth, height: ele.offsetHeight };
1583
+ this.elData = {
1584
+ x1: rect.x,
1585
+ y1: rect.y,
1586
+ x2: rect.x + rect.width,
1587
+ y2: rect.y + rect.height,
1588
+ };
1589
+ //targets data
1590
+ this.update();
1591
+ }
1592
+ /**
1593
+ * update targets data if them changed
1594
+ */
1595
+ update() {
1596
+ let targets;
1597
+ if (func_js.isFunction(__classPrivateFieldGet(this, _CollisionDetector__targets, "f"))) {
1598
+ targets = __classPrivateFieldGet(this, _CollisionDetector__targets, "f").call(this);
1599
+ }
1600
+ else if (func_js.isString(__classPrivateFieldGet(this, _CollisionDetector__targets, "f"))) {
1601
+ targets = this.opts.container.querySelectorAll(__classPrivateFieldGet(this, _CollisionDetector__targets, "f"));
1602
+ }
1603
+ else if (func_js.isElement(__classPrivateFieldGet(this, _CollisionDetector__targets, "f"))) {
1604
+ targets = [__classPrivateFieldGet(this, _CollisionDetector__targets, "f")];
1605
+ }
1606
+ else {
1607
+ targets = __classPrivateFieldGet(this, _CollisionDetector__targets, "f");
1608
+ }
1609
+ this.targetsData = func_js.flatMap(targets, t => {
1610
+ if (!t)
1611
+ return [];
1612
+ if (!func_js.isElement(t))
1613
+ return [];
1614
+ const offset = getOffset(t, this.opts.container);
1615
+ const rect = { x: offset.x, y: offset.y, width: t.offsetWidth, height: t.offsetHeight };
1616
+ return {
1617
+ x1: rect.x,
1618
+ y1: rect.y,
1619
+ x2: rect.x + rect.width,
1620
+ y2: rect.y + rect.height,
1621
+ el: t
1622
+ };
1623
+ });
1624
+ }
1625
+ getOverlaps(x1, y1, x2, y2) {
1626
+ let elData = this.elData;
1627
+ if (x1 && x2 && y1 && y2) {
1628
+ elData = {
1629
+ x1,
1630
+ y1,
1631
+ x2,
1632
+ y2,
1633
+ };
1634
+ }
1635
+ let overlaps = func_js.flatMap(this.targetsData, (td, i) => {
1636
+ if (elData.x2 < td.x1 || elData.x1 > td.x2 || elData.y2 < td.y1 || elData.y1 > td.y2)
1637
+ return [];
1638
+ return td.el;
1639
+ });
1640
+ return overlaps;
1641
+ }
1642
+ getInclusions(x1, y1, x2, y2) {
1643
+ let elData = this.elData;
1644
+ if (x1 && x2 && y1 && y2) {
1645
+ elData = {
1646
+ x1,
1647
+ y1,
1648
+ x2,
1649
+ y2,
1650
+ };
1651
+ }
1652
+ let contains = func_js.flatMap(this.targetsData, (td, i) => {
1653
+ if (elData.x2 >= td.x2 && elData.x1 <= td.x1 && elData.y2 >= td.y2 && elData.y1 <= td.y1)
1654
+ return td.el;
1655
+ return [];
1656
+ });
1657
+ return contains;
1658
+ }
1659
+ }
1660
+ _CollisionDetector__targets = new WeakMap();
1661
+ /**
1662
+ * create a detector for the el and return
1663
+ * @param el element to be detected
1664
+ * @param targets
1665
+ * @param opts CollisionDetectorOptions
1666
+ * @param opts.container a root element of targets
1667
+ * @returns
1668
+ */
1669
+ function newCollisionDetector(el, targets, opts) {
1670
+ return new CollisionDetector(el, targets, opts);
1671
+ }
1672
+
1673
+ /* eslint-disable max-len */
1674
+ /**
1675
+ * selector
1676
+ * @author holyhigh2
1677
+ */
1678
+ var _Selectable_instances, _Selectable__detector, _Selectable__lastSelected, _Selectable_bindEvent;
1679
+ const CLASS_SELECTOR = "uii-selector";
1680
+ const CLASS_SELECTING = "uii-selecting";
1681
+ const CLASS_SELECTED = "uii-selected";
1682
+ const THRESHOLD = 2;
1683
+ /**
1684
+ * 用于表示一个元素选择器的定义
1685
+ * > 可用CSS接口
1686
+ * - .uii-selector
1687
+ * - .uii-selecting
1688
+ * - .uii-selected
1689
+ * @public
1690
+ */
1691
+ class Selectable extends Uii {
1692
+ constructor(container, opts) {
1693
+ super(container, func_js.assign({
1694
+ targets: [],
1695
+ scroll: true,
1696
+ }, opts));
1697
+ _Selectable_instances.add(this);
1698
+ _Selectable__detector.set(this, void 0);
1699
+ _Selectable__lastSelected.set(this, void 0);
1700
+ const domEl = this.ele[0];
1701
+ //create selector
1702
+ const selector = document.createElement("div");
1703
+ selector.className = CLASS_SELECTOR;
1704
+ selector.style.cssText = `
1705
+ position:absolute;
1706
+ left:-9999px;
1707
+ `;
1708
+ if (this.opts.class) {
1709
+ selector.className += " " + this.opts.class;
1710
+ }
1711
+ else {
1712
+ selector.style.cssText += "border:1px dashed #000;";
1713
+ }
1714
+ domEl.appendChild(selector);
1715
+ //create detector
1716
+ __classPrivateFieldSet(this, _Selectable__detector, newCollisionDetector(selector, this.opts.targets, {
1717
+ container: domEl,
1718
+ }), "f");
1719
+ __classPrivateFieldGet(this, _Selectable_instances, "m", _Selectable_bindEvent).call(this, selector, domEl);
1720
+ }
1721
+ /**
1722
+ * 更新targets
1723
+ */
1724
+ updateTargets() {
1725
+ __classPrivateFieldGet(this, _Selectable__detector, "f").update();
1726
+ }
1727
+ /**
1728
+ * @internal
1729
+ */
1730
+ onOptionChanged() {
1731
+ this.updateTargets();
1732
+ }
1733
+ }
1734
+ _Selectable__detector = new WeakMap(), _Selectable__lastSelected = new WeakMap(), _Selectable_instances = new WeakSet(), _Selectable_bindEvent = function _Selectable_bindEvent(selector, con) {
1735
+ const that = this;
1736
+ this.registerEvent(con, "mousedown", (e) => {
1737
+ const t = e.target;
1738
+ const onStart = that.opts.onStart;
1739
+ const onSelect = that.opts.onSelect;
1740
+ const onEnd = that.opts.onEnd;
1741
+ const mode = that.opts.mode || "overlap";
1742
+ const scroll = that.opts.scroll;
1743
+ const scrollSpeed = that.opts.scrollSpeed || 10;
1744
+ const filter = that.opts.filter;
1745
+ const selectingClassAry = func_js.compact(func_js.split(that.opts.selectingClass, " "));
1746
+ const selectedClassAry = func_js.compact(func_js.split(that.opts.selectedClass, " "));
1747
+ //check filter
1748
+ if (filter) {
1749
+ if (func_js.isFunction(filter)) {
1750
+ if (filter(t))
1751
+ return;
1752
+ }
1753
+ else if (func_js.some(con.querySelectorAll(filter), (el) => el.contains(t)))
1754
+ return;
1755
+ }
1756
+ let originPos = "";
1757
+ //offset
1758
+ const rect = con.getBoundingClientRect();
1759
+ const conStyle = window.getComputedStyle(con);
1760
+ const blw = parseFloat(conStyle.borderLeftWidth);
1761
+ const btw = parseFloat(conStyle.borderTopWidth);
1762
+ let hitPosX = e.offsetX + con.scrollLeft, hitPosY = e.offsetY + con.scrollTop;
1763
+ if (t !== con) {
1764
+ const offset = getOffset(t, con);
1765
+ const style = window.getComputedStyle(t);
1766
+ hitPosX = offset.x + e.offsetX + parseFloat(style.borderLeftWidth);
1767
+ hitPosY = offset.y + e.offsetY + parseFloat(style.borderTopWidth);
1768
+ }
1769
+ const style = selector.style;
1770
+ let selection = [];
1771
+ let lastSelection = [];
1772
+ let x1 = hitPosX, y1 = hitPosY;
1773
+ let dragging = false;
1774
+ let timer = null;
1775
+ let toLeft = false;
1776
+ let toTop = false;
1777
+ let toRight = false;
1778
+ let toBottom = false;
1779
+ const dragListener = (ev) => {
1780
+ const newX = ev.clientX - rect.x + con.scrollLeft - blw;
1781
+ const newY = ev.clientY - rect.y + con.scrollTop - btw;
1782
+ const offsetx = newX - hitPosX;
1783
+ const offsety = newY - hitPosY;
1784
+ if (!dragging) {
1785
+ if (Math.abs(offsetx) > THRESHOLD || Math.abs(offsety) > THRESHOLD) {
1786
+ dragging = true;
1787
+ //update targets count & positions
1788
+ __classPrivateFieldGet(this, _Selectable__detector, "f").update();
1789
+ //detect container position
1790
+ const pos = window.getComputedStyle(con).position;
1791
+ if (pos === "static") {
1792
+ originPos = con.style.position;
1793
+ con.style.position = "relative";
1794
+ }
1795
+ //clear _lastSelected
1796
+ func_js.each(__classPrivateFieldGet(this, _Selectable__lastSelected, "f"), t => {
1797
+ t.classList.toggle(CLASS_SELECTED, false);
1798
+ });
1799
+ func_js.call(onStart, t);
1800
+ }
1801
+ else {
1802
+ ev.preventDefault();
1803
+ return false;
1804
+ }
1805
+ }
1806
+ //edge detect
1807
+ if (scroll) {
1808
+ const ltX = ev.clientX - rect.x;
1809
+ const ltY = ev.clientY - rect.y;
1810
+ const rbX = rect.x + rect.width - ev.clientX;
1811
+ const rbY = rect.y + rect.height - ev.clientY;
1812
+ toLeft = ltX < EDGE_THRESHOLD;
1813
+ toTop = ltY < EDGE_THRESHOLD;
1814
+ toRight = rbX < EDGE_THRESHOLD;
1815
+ toBottom = rbY < EDGE_THRESHOLD;
1816
+ if (toLeft || toTop || toRight || toBottom) {
1817
+ if (!timer) {
1818
+ timer = setInterval(() => {
1819
+ if (toLeft) {
1820
+ con.scrollLeft -= scrollSpeed;
1821
+ }
1822
+ else if (toRight) {
1823
+ con.scrollLeft += scrollSpeed;
1824
+ }
1825
+ if (toTop) {
1826
+ con.scrollTop -= scrollSpeed;
1827
+ }
1828
+ else if (toBottom) {
1829
+ con.scrollTop += scrollSpeed;
1830
+ }
1831
+ }, 20);
1832
+ }
1833
+ }
1834
+ else {
1835
+ if (timer) {
1836
+ clearInterval(timer);
1837
+ timer = null;
1838
+ }
1839
+ }
1840
+ }
1841
+ let x = hitPosX, y = hitPosY, w = Math.abs(offsetx), h = Math.abs(offsety);
1842
+ if (offsetx > 0 && offsety > 0) {
1843
+ x1 = hitPosX;
1844
+ y1 = hitPosY;
1845
+ }
1846
+ else if (offsetx < 0 && offsety < 0) {
1847
+ x = x1 = newX;
1848
+ y = y1 = newY;
1849
+ }
1850
+ else if (offsetx < 0) {
1851
+ x = x1 = newX;
1852
+ }
1853
+ else if (offsety < 0) {
1854
+ y = y1 = newY;
1855
+ }
1856
+ style.left = x + "px";
1857
+ style.top = y + "px";
1858
+ style.width = w + "px";
1859
+ style.height = h + "px";
1860
+ //detect collision
1861
+ if (mode === "overlap") {
1862
+ selection = __classPrivateFieldGet(that, _Selectable__detector, "f").getOverlaps(x1, y1, x1 + w, y1 + h);
1863
+ }
1864
+ else if (mode === "inclusion") {
1865
+ selection = __classPrivateFieldGet(that, _Selectable__detector, "f").getInclusions(x1, y1, x1 + w, y1 + h);
1866
+ }
1867
+ func_js.each(lastSelection, (t) => {
1868
+ if (!func_js.includes(selection, t)) {
1869
+ t.classList.toggle(CLASS_SELECTING, false);
1870
+ func_js.each(selectingClassAry, (cls) => {
1871
+ t.classList.toggle(cls, false);
1872
+ });
1873
+ }
1874
+ });
1875
+ func_js.each(selection, (t) => {
1876
+ t.classList.toggle(CLASS_SELECTING, true);
1877
+ func_js.each(selectingClassAry, (cls) => {
1878
+ t.classList.toggle(cls, true);
1879
+ });
1880
+ });
1881
+ const changed = lastSelection.length != selection.length;
1882
+ lastSelection = selection;
1883
+ if (changed)
1884
+ func_js.call(onSelect, selection);
1885
+ ev.preventDefault();
1886
+ return false;
1887
+ };
1888
+ const dragEndListener = (ev) => {
1889
+ style.left = "-9999px";
1890
+ style.width = style.height = "0px";
1891
+ document.removeEventListener("mousemove", dragListener, false);
1892
+ document.removeEventListener("mouseup", dragEndListener, false);
1893
+ window.removeEventListener("blur", dragEndListener, false);
1894
+ if (scroll) {
1895
+ if (timer) {
1896
+ clearInterval(timer);
1897
+ timer = null;
1898
+ }
1899
+ }
1900
+ //restore container position
1901
+ if (originPos) {
1902
+ con.style.position = originPos;
1903
+ }
1904
+ func_js.each(selection, (t) => {
1905
+ func_js.each(selectingClassAry, (cls) => {
1906
+ t.classList.toggle(cls, false);
1907
+ });
1908
+ func_js.each(selectedClassAry, (cls) => {
1909
+ t.classList.toggle(cls, true);
1910
+ });
1911
+ t.classList.toggle(CLASS_SELECTING, false);
1912
+ t.classList.toggle(CLASS_SELECTED, true);
1913
+ });
1914
+ __classPrivateFieldSet(this, _Selectable__lastSelected, selection, "f");
1915
+ if (dragging)
1916
+ func_js.call(onEnd, selection);
1917
+ };
1918
+ document.addEventListener("mousemove", dragListener, false);
1919
+ document.addEventListener("mouseup", dragEndListener, false);
1920
+ window.addEventListener("blur", dragEndListener, false);
1921
+ e.preventDefault();
1922
+ return false;
1923
+ });
1924
+ };
1925
+ /**
1926
+ * Add a selector into the container
1927
+ * @param container css selector or html element
1928
+ * @param opts
1929
+ * @returns
1930
+ */
1931
+ function newSelectable(container, opts) {
1932
+ return new Selectable(container, opts);
1933
+ }
1934
+
1935
+ var version = "1.0.0";
1936
+ var repository = {
1937
+ type: "git",
1938
+ url: "https://github.com/holyhigh2/uii"
1939
+ };
1940
+
1941
+ // welcome info
1942
+ const welcome = globalThis.top
1943
+ ? globalThis.top.welcome
1944
+ : globalThis.welcome;
1945
+ if (!welcome) {
1946
+ const ssAry = [];
1947
+ ['102,227,255', '59,208,251', '67,180,255'].forEach((v, i) => {
1948
+ const cu = 'background:rgb(' + v + ');';
1949
+ if (i < 2) {
1950
+ ssAry[i] = ssAry[5 - 1 - i] = cu;
1951
+ }
1952
+ else {
1953
+ ssAry[i] = 'color:#fff;' + cu;
1954
+ }
1955
+ });
1956
+ console.info(`%c %c %c Uii - UI Interactions | v${version} %c %c `, ...ssAry, `💎 ${repository.url}`);
1957
+ if (globalThis.top) {
1958
+ globalThis.top.welcome = true;
1959
+ }
1960
+ else {
1961
+ globalThis.welcome = true;
1962
+ }
1963
+ }
1964
+ const VERSION = version;
1965
+ var index = {
1966
+ VERSION: version,
1967
+ newSplittable,
1968
+ newResizable,
1969
+ newDraggable,
1970
+ newDroppable,
1971
+ newRotatable,
1972
+ newSelectable
1973
+ };
1974
+
1975
+ exports.CollisionDetector = CollisionDetector;
1976
+ exports.Draggable = Draggable;
1977
+ exports.Droppable = Droppable;
1978
+ exports.Resizable = Resizable;
1979
+ exports.Rotatable = Rotatable;
1980
+ exports.Selectable = Selectable;
1981
+ exports.Splittable = Splittable;
1982
+ exports.Uii = Uii;
1983
+ exports.VERSION = VERSION;
1984
+ exports["default"] = index;
1985
+ exports.newCollisionDetector = newCollisionDetector;
1986
+ exports.newDraggable = newDraggable;
1987
+ exports.newDroppable = newDroppable;
1988
+ exports.newResizable = newResizable;
1989
+ exports.newRotatable = newRotatable;
1990
+ exports.newSelectable = newSelectable;
1991
+ exports.newSplittable = newSplittable;
1992
+
1993
+ Object.defineProperty(exports, '__esModule', { value: true });
1994
+
1995
+ }));