@sepveneto/free-dom 0.10.1 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -29,7 +29,7 @@ __export(src_exports, {
29
29
  module.exports = __toCommonJS(src_exports);
30
30
 
31
31
  // src/components/freeDomWrap.ts
32
- var import_vue_demi14 = require("vue-demi");
32
+ var import_vue_demi18 = require("vue-demi");
33
33
 
34
34
  // src/util/tokens.ts
35
35
  var SceneToken = Symbol("Scene");
@@ -75,6 +75,29 @@ function log(...args) {
75
75
  return;
76
76
  console.log("[grid-layout]", ...args);
77
77
  }
78
+ function addUserSelectStyle(doc) {
79
+ if (!doc)
80
+ return;
81
+ if (!doc.getElementById("free-dom-style-el")) {
82
+ const styleEl = doc.createElement("style");
83
+ styleEl.id = "free-dom-style-el";
84
+ styleEl.innerHTML = ".free-dom-transparent-selection *::selection {all: inherit;}";
85
+ doc.getElementsByTagName("head")[0].appendChild(styleEl);
86
+ }
87
+ if (doc.body)
88
+ doc.body.classList.add("free-dom-transparent-selection");
89
+ }
90
+ function removeUserSelectStyle(doc) {
91
+ if (!doc)
92
+ return;
93
+ if (doc.body) {
94
+ doc.body.classList.remove("free-dom-transparent-selection");
95
+ }
96
+ const selection = doc.getSelection();
97
+ if (selection) {
98
+ selection.removeAllRanges();
99
+ }
100
+ }
78
101
 
79
102
  // src/components/markLine.ts
80
103
  var import_vue_demi2 = require("vue-demi");
@@ -88,6 +111,7 @@ var markLine_default = (0, import_vue_demi2.defineComponent)({
88
111
  const lines = (0, import_vue_demi2.shallowRef)(lineType);
89
112
  const diff = (0, import_vue_demi2.computed)(() => SceneContext.diff / SceneContext.transformScale);
90
113
  const nodes = SceneContext.nodes;
114
+ const staticNodes = (0, import_vue_demi2.computed)(() => nodes.filter((node) => !node.node.selected));
91
115
  const lineStatus = (0, import_vue_demi2.reactive)({
92
116
  xt: {
93
117
  show: false,
@@ -114,78 +138,80 @@ var markLine_default = (0, import_vue_demi2.defineComponent)({
114
138
  pos: 0
115
139
  }
116
140
  });
117
- const runConstraints = (uuid) => {
118
- const current = nodes.find((node) => node.uuid === uuid)?.node ?? {};
141
+ const runConstraints = (uuid, withoutConstraint) => {
142
+ const current = nodes.find((node) => node.uuid === uuid)?.node;
143
+ if (!current)
144
+ return;
119
145
  clearStatus();
120
- nodes.forEach((node) => {
146
+ staticNodes.value.forEach((node) => {
121
147
  if (node.uuid === uuid)
122
148
  return;
123
149
  const _current = normalize(current._rect);
124
150
  const _target = normalize(node.node._rect);
125
- if (isNearly(_current.top, _target.top)) {
151
+ if (isNearly(_current.top, _target.top, withoutConstraint)) {
126
152
  lineStatus.xt = {
127
153
  show: true,
128
154
  pos: _target.top
129
155
  };
130
156
  current._rect.y = _target.top;
131
157
  }
132
- if (isNearly(_current.bottom, _target.top)) {
158
+ if (isNearly(_current.bottom, _target.top, withoutConstraint)) {
133
159
  lineStatus.xt = {
134
160
  show: true,
135
161
  pos: _target.top
136
162
  };
137
163
  current._rect.y = _target.top - _current.height;
138
164
  }
139
- if (isNearly(_current.centerY, _target.centerY)) {
165
+ if (isNearly(_current.centerY, _target.centerY, withoutConstraint)) {
140
166
  lineStatus.xc = {
141
167
  show: true,
142
168
  pos: _target.centerY
143
169
  };
144
170
  current._rect.y = _target.centerY - _current.height / 2;
145
171
  }
146
- if (isNearly(_current.top, _target.bottom)) {
172
+ if (isNearly(_current.top, _target.bottom, withoutConstraint)) {
147
173
  lineStatus.xb = {
148
174
  show: true,
149
175
  pos: _target.bottom
150
176
  };
151
177
  current._rect.y = _target.bottom;
152
178
  }
153
- if (isNearly(_current.bottom, _target.bottom)) {
179
+ if (isNearly(_current.bottom, _target.bottom, withoutConstraint)) {
154
180
  lineStatus.xb = {
155
181
  show: true,
156
182
  pos: _target.bottom
157
183
  };
158
184
  current._rect.y = _target.bottom - _current.height;
159
185
  }
160
- if (isNearly(_current.left, _target.left)) {
186
+ if (isNearly(_current.left, _target.left, withoutConstraint)) {
161
187
  lineStatus.yl = {
162
188
  show: true,
163
189
  pos: _target.left
164
190
  };
165
191
  current._rect.x = _target.left;
166
192
  }
167
- if (isNearly(_current.right, _target.left)) {
193
+ if (isNearly(_current.right, _target.left, withoutConstraint)) {
168
194
  lineStatus.yl = {
169
195
  show: true,
170
196
  pos: _target.left
171
197
  };
172
198
  current._rect.x = _target.left - _current.width;
173
199
  }
174
- if (isNearly(_current.centerX, _target.centerX)) {
200
+ if (isNearly(_current.centerX, _target.centerX, withoutConstraint)) {
175
201
  lineStatus.yc = {
176
202
  show: true,
177
203
  pos: _target.centerX
178
204
  };
179
205
  current._rect.x = _target.centerX - _current.width / 2;
180
206
  }
181
- if (isNearly(_current.left, _target.right)) {
207
+ if (isNearly(_current.left, _target.right, withoutConstraint)) {
182
208
  lineStatus.yr = {
183
209
  show: true,
184
210
  pos: _target.right
185
211
  };
186
212
  current._rect.x = _target.right;
187
213
  }
188
- if (isNearly(_current.right, _target.right)) {
214
+ if (isNearly(_current.right, _target.right, withoutConstraint)) {
189
215
  lineStatus.yr = {
190
216
  show: true,
191
217
  pos: _target.right
@@ -222,8 +248,9 @@ var markLine_default = (0, import_vue_demi2.defineComponent)({
222
248
  centerY: rect.y + rect.height / 2
223
249
  };
224
250
  }
225
- function isNearly(curr, target) {
226
- return Math.abs(curr - target) <= diff.value;
251
+ function isNearly(curr, target, withoutConstraint) {
252
+ const _diff = withoutConstraint ? 0 : diff.value;
253
+ return Math.abs(curr - target) <= _diff;
227
254
  }
228
255
  return {
229
256
  lines,
@@ -250,10 +277,8 @@ var import_vue_demi3 = require("vue-demi");
250
277
  var import_vue_demi4 = require("vue-demi");
251
278
  function useDefaultSlot() {
252
279
  const slots = (0, import_vue_demi4.useSlots)();
253
- const slotList = (0, import_vue_demi4.computed)(() => {
254
- return typeof slots.default === "function" ? slots.default() : slots.default;
255
- });
256
- const only = (0, import_vue_demi4.computed)(() => slotList.value?.[0]);
280
+ const slotList = typeof slots.default === "function" ? slots.default() : slots.default;
281
+ const only = slotList?.[0];
257
282
  return {
258
283
  slots: slotList,
259
284
  only
@@ -368,6 +393,7 @@ function useSceneContext(context, props) {
368
393
  const fixNonMonospaced = (0, import_vue_demi7.computed)(() => {
369
394
  return SceneContext?.fixNonMonospaced || props.fixNonMonospaced;
370
395
  });
396
+ const keyboard = (0, import_vue_demi7.computed)(() => SceneContext?.keyboard || props.keyboard);
371
397
  (0, import_vue_demi7.onMounted)(() => {
372
398
  SceneContext?.register(uuid, context);
373
399
  });
@@ -385,11 +411,15 @@ function useSceneContext(context, props) {
385
411
  return SceneContext.correct(pos);
386
412
  }
387
413
  return {
388
- emit: (name) => SceneContext?.emit(name, uuid),
414
+ emit: (name, withoutConstraint) => {
415
+ SceneContext?.emit(name, uuid, withoutConstraint);
416
+ },
389
417
  check,
390
418
  correct,
419
+ clearSelectState: SceneContext?.clearSelectState,
391
420
  width: SceneContext?.width,
392
421
  height: SceneContext?.height,
422
+ history: SceneContext?.history,
393
423
  scale,
394
424
  handle,
395
425
  lockAspectRatio,
@@ -398,14 +428,15 @@ function useSceneContext(context, props) {
398
428
  disabledDrag,
399
429
  disabledResize,
400
430
  fixNonMonospaced,
401
- transformScale
431
+ transformScale,
432
+ keyboard
402
433
  };
403
434
  }
404
435
 
405
436
  // src/hooks/use-event-bus.ts
406
437
  var import_vue_demi8 = require("vue-demi");
438
+ var callbacks = (0, import_vue_demi8.ref)({});
407
439
  function useEventBus() {
408
- const callbacks = (0, import_vue_demi8.ref)({});
409
440
  const on = (name, cb) => {
410
441
  if (!callbacks.value[name]) {
411
442
  callbacks.value[name] = [cb];
@@ -416,9 +447,9 @@ function useEventBus() {
416
447
  const off = (name) => {
417
448
  callbacks.value[name].length = 0;
418
449
  };
419
- const emit = (name, args) => {
450
+ const emit = (name, ...args) => {
420
451
  const fns = callbacks.value[name] || [];
421
- fns.forEach((fn) => fn(args));
452
+ fns.forEach((fn) => fn(...args));
422
453
  };
423
454
  return {
424
455
  on,
@@ -452,9 +483,9 @@ function useResizableData(props, domRef) {
452
483
  if (fixNonMonospaced) {
453
484
  await document.fonts.ready;
454
485
  }
455
- const { width: w, height: h5 } = window.getComputedStyle(domRef.value.$el);
486
+ const { width: w, height: h7 } = window.getComputedStyle(domRef.value.$el);
456
487
  width.value = Math.max(Math.ceil(parseFloat(w)), minWidth);
457
- height.value = Math.max(Math.ceil(parseFloat(h5)), minHeight);
488
+ height.value = Math.max(Math.ceil(parseFloat(h7)), minHeight);
458
489
  }
459
490
  return {
460
491
  width,
@@ -576,10 +607,10 @@ function useLayout(props) {
576
607
  layout.value = _normalize(_layout);
577
608
  return layout.value;
578
609
  }
579
- function resizeTo(item, w, h5) {
610
+ function resizeTo(item, w, h7) {
580
611
  let hasCollisions = false;
581
612
  if (!props.collision) {
582
- const collisions = layout.value.filter((l) => _collides(l, { ...item, w, h: h5 }));
613
+ const collisions = layout.value.filter((l) => _collides(l, { ...item, w, h: h7 }));
583
614
  hasCollisions = collisions.length > 0;
584
615
  if (hasCollisions) {
585
616
  let leastX = Infinity;
@@ -598,7 +629,7 @@ function useLayout(props) {
598
629
  }
599
630
  if (!hasCollisions) {
600
631
  item.w = w;
601
- item.h = h5;
632
+ item.h = h7;
602
633
  }
603
634
  layout.value = _normalize([...layout.value]);
604
635
  }
@@ -794,15 +825,15 @@ function useLayoutItem(props, layout) {
794
825
  };
795
826
  const onResize = (evt, coreData) => {
796
827
  const { width: width2, height: height2 } = coreData;
797
- const { w, h: h5 } = _calcWH(width2, height2);
828
+ const { w, h: h7 } = _calcWH(width2, height2);
798
829
  resizing.value = { width: width2, height: height2 };
799
- props.resizeFn(evt, { w, h: h5 });
830
+ props.resizeFn(evt, { w, h: h7 });
800
831
  };
801
832
  const onResizeStop = (evt, coreData) => {
802
833
  resizing.value = void 0;
803
834
  const { width: width2, height: height2 } = coreData;
804
- const { w, h: h5 } = _calcWH(width2, height2);
805
- props.resizeStopFn(evt, { w, h: h5 });
835
+ const { w, h: h7 } = _calcWH(width2, height2);
836
+ props.resizeStopFn(evt, { w, h: h7 });
806
837
  };
807
838
  function _calcXY(left, top) {
808
839
  let x2 = Math.round((left - margin.value[0]) / (cellWidth.value + margin.value[0]));
@@ -813,10 +844,10 @@ function useLayoutItem(props, layout) {
813
844
  }
814
845
  function _calcWH(width2, height2) {
815
846
  let w = Math.round((width2 + margin.value[0]) / (cellWidth.value + margin.value[0]));
816
- let h5 = Math.round((height2 + margin.value[1]) / (rowHeight.value + margin.value[1]));
847
+ let h7 = Math.round((height2 + margin.value[1]) / (rowHeight.value + margin.value[1]));
817
848
  w = clamp(w, 0, cols.value - props.x);
818
- h5 = clamp(h5, 0, maxRows.value - props.y);
819
- return { w, h: h5 };
849
+ h7 = clamp(h7, 0, maxRows.value - props.y);
850
+ return { w, h: h7 };
820
851
  }
821
852
  return {
822
853
  x,
@@ -837,12 +868,474 @@ function useLayoutItem(props, layout) {
837
868
  };
838
869
  }
839
870
 
840
- // src/components/freeDom.ts
871
+ // src/hooks/use-mask.ts
841
872
  var import_vue_demi13 = require("vue-demi");
842
873
 
843
- // src/components/freeDomCore.ts
874
+ // ../../node_modules/.pnpm/@vueuse+shared@10.7.1_vue@3.4.6/node_modules/@vueuse/shared/index.mjs
844
875
  var import_vue_demi11 = require("vue-demi");
845
- function noop() {
876
+ function tryOnScopeDispose(fn) {
877
+ if ((0, import_vue_demi11.getCurrentScope)()) {
878
+ (0, import_vue_demi11.onScopeDispose)(fn);
879
+ return true;
880
+ }
881
+ return false;
882
+ }
883
+ function toValue(r) {
884
+ return typeof r === "function" ? r() : (0, import_vue_demi11.unref)(r);
885
+ }
886
+ var isClient = typeof window !== "undefined" && typeof document !== "undefined";
887
+ var isWorker = typeof WorkerGlobalScope !== "undefined" && globalThis instanceof WorkerGlobalScope;
888
+ var toString = Object.prototype.toString;
889
+ var isObject = (val) => toString.call(val) === "[object Object]";
890
+ var noop = () => {
891
+ };
892
+ var isIOS = /* @__PURE__ */ getIsIOS();
893
+ function getIsIOS() {
894
+ var _a, _b;
895
+ return isClient && ((_a = window == null ? void 0 : window.navigator) == null ? void 0 : _a.userAgent) && (/iP(ad|hone|od)/.test(window.navigator.userAgent) || ((_b = window == null ? void 0 : window.navigator) == null ? void 0 : _b.maxTouchPoints) > 2 && /iPad|Macintosh/.test(window == null ? void 0 : window.navigator.userAgent));
896
+ }
897
+ function cacheStringFunction(fn) {
898
+ const cache = /* @__PURE__ */ Object.create(null);
899
+ return (str) => {
900
+ const hit = cache[str];
901
+ return hit || (cache[str] = fn(str));
902
+ };
903
+ }
904
+ var hyphenateRE = /\B([A-Z])/g;
905
+ var hyphenate = cacheStringFunction((str) => str.replace(hyphenateRE, "-$1").toLowerCase());
906
+ var camelizeRE = /-(\w)/g;
907
+ var camelize = cacheStringFunction((str) => {
908
+ return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : "");
909
+ });
910
+ function getLifeCycleTarget(target) {
911
+ return target || (0, import_vue_demi11.getCurrentInstance)();
912
+ }
913
+ function tryOnMounted(fn, sync = true, target) {
914
+ const instance = getLifeCycleTarget();
915
+ if (instance)
916
+ (0, import_vue_demi11.onMounted)(fn, target);
917
+ else if (sync)
918
+ fn();
919
+ else
920
+ (0, import_vue_demi11.nextTick)(fn);
921
+ }
922
+
923
+ // ../../node_modules/.pnpm/@vueuse+core@10.7.1_vue@3.4.6/node_modules/@vueuse/core/index.mjs
924
+ var import_vue_demi12 = require("vue-demi");
925
+ function unrefElement(elRef) {
926
+ var _a;
927
+ const plain = toValue(elRef);
928
+ return (_a = plain == null ? void 0 : plain.$el) != null ? _a : plain;
929
+ }
930
+ var defaultWindow = isClient ? window : void 0;
931
+ var defaultDocument = isClient ? window.document : void 0;
932
+ var defaultNavigator = isClient ? window.navigator : void 0;
933
+ var defaultLocation = isClient ? window.location : void 0;
934
+ function useEventListener(...args) {
935
+ let target;
936
+ let events;
937
+ let listeners;
938
+ let options;
939
+ if (typeof args[0] === "string" || Array.isArray(args[0])) {
940
+ [events, listeners, options] = args;
941
+ target = defaultWindow;
942
+ } else {
943
+ [target, events, listeners, options] = args;
944
+ }
945
+ if (!target)
946
+ return noop;
947
+ if (!Array.isArray(events))
948
+ events = [events];
949
+ if (!Array.isArray(listeners))
950
+ listeners = [listeners];
951
+ const cleanups = [];
952
+ const cleanup = () => {
953
+ cleanups.forEach((fn) => fn());
954
+ cleanups.length = 0;
955
+ };
956
+ const register = (el, event, listener, options2) => {
957
+ el.addEventListener(event, listener, options2);
958
+ return () => el.removeEventListener(event, listener, options2);
959
+ };
960
+ const stopWatch = (0, import_vue_demi12.watch)(
961
+ () => [unrefElement(target), toValue(options)],
962
+ ([el, options2]) => {
963
+ cleanup();
964
+ if (!el)
965
+ return;
966
+ const optionsClone = isObject(options2) ? { ...options2 } : options2;
967
+ cleanups.push(
968
+ ...events.flatMap((event) => {
969
+ return listeners.map((listener) => register(el, event, listener, optionsClone));
970
+ })
971
+ );
972
+ },
973
+ { immediate: true, flush: "post" }
974
+ );
975
+ const stop = () => {
976
+ stopWatch();
977
+ cleanup();
978
+ };
979
+ tryOnScopeDispose(stop);
980
+ return stop;
981
+ }
982
+ var _iOSWorkaround = false;
983
+ function onClickOutside(target, handler, options = {}) {
984
+ const { window: window2 = defaultWindow, ignore = [], capture = true, detectIframe = false } = options;
985
+ if (!window2)
986
+ return noop;
987
+ if (isIOS && !_iOSWorkaround) {
988
+ _iOSWorkaround = true;
989
+ Array.from(window2.document.body.children).forEach((el) => el.addEventListener("click", noop));
990
+ window2.document.documentElement.addEventListener("click", noop);
991
+ }
992
+ let shouldListen = true;
993
+ const shouldIgnore = (event) => {
994
+ return ignore.some((target2) => {
995
+ if (typeof target2 === "string") {
996
+ return Array.from(window2.document.querySelectorAll(target2)).some((el) => el === event.target || event.composedPath().includes(el));
997
+ } else {
998
+ const el = unrefElement(target2);
999
+ return el && (event.target === el || event.composedPath().includes(el));
1000
+ }
1001
+ });
1002
+ };
1003
+ const listener = (event) => {
1004
+ const el = unrefElement(target);
1005
+ if (!el || el === event.target || event.composedPath().includes(el))
1006
+ return;
1007
+ if (event.detail === 0)
1008
+ shouldListen = !shouldIgnore(event);
1009
+ if (!shouldListen) {
1010
+ shouldListen = true;
1011
+ return;
1012
+ }
1013
+ handler(event);
1014
+ };
1015
+ const cleanup = [
1016
+ useEventListener(window2, "click", listener, { passive: true, capture }),
1017
+ useEventListener(window2, "pointerdown", (e) => {
1018
+ const el = unrefElement(target);
1019
+ shouldListen = !shouldIgnore(e) && !!(el && !e.composedPath().includes(el));
1020
+ }, { passive: true }),
1021
+ detectIframe && useEventListener(window2, "blur", (event) => {
1022
+ setTimeout(() => {
1023
+ var _a;
1024
+ const el = unrefElement(target);
1025
+ if (((_a = window2.document.activeElement) == null ? void 0 : _a.tagName) === "IFRAME" && !(el == null ? void 0 : el.contains(window2.document.activeElement)))
1026
+ handler(event);
1027
+ }, 0);
1028
+ })
1029
+ ].filter(Boolean);
1030
+ const stop = () => cleanup.forEach((fn) => fn());
1031
+ return stop;
1032
+ }
1033
+ function useMounted() {
1034
+ const isMounted = (0, import_vue_demi12.ref)(false);
1035
+ if ((0, import_vue_demi12.getCurrentInstance)()) {
1036
+ (0, import_vue_demi12.onMounted)(() => {
1037
+ isMounted.value = true;
1038
+ });
1039
+ }
1040
+ return isMounted;
1041
+ }
1042
+ function useSupported(callback) {
1043
+ const isMounted = useMounted();
1044
+ return (0, import_vue_demi12.computed)(() => {
1045
+ isMounted.value;
1046
+ return Boolean(callback());
1047
+ });
1048
+ }
1049
+ function useMutationObserver(target, callback, options = {}) {
1050
+ const { window: window2 = defaultWindow, ...mutationOptions } = options;
1051
+ let observer;
1052
+ const isSupported = useSupported(() => window2 && "MutationObserver" in window2);
1053
+ const cleanup = () => {
1054
+ if (observer) {
1055
+ observer.disconnect();
1056
+ observer = void 0;
1057
+ }
1058
+ };
1059
+ const stopWatch = (0, import_vue_demi12.watch)(
1060
+ () => unrefElement(target),
1061
+ (el) => {
1062
+ cleanup();
1063
+ if (isSupported.value && window2 && el) {
1064
+ observer = new MutationObserver(callback);
1065
+ observer.observe(el, mutationOptions);
1066
+ }
1067
+ },
1068
+ { immediate: true }
1069
+ );
1070
+ const takeRecords = () => {
1071
+ return observer == null ? void 0 : observer.takeRecords();
1072
+ };
1073
+ const stop = () => {
1074
+ cleanup();
1075
+ stopWatch();
1076
+ };
1077
+ tryOnScopeDispose(stop);
1078
+ return {
1079
+ isSupported,
1080
+ stop,
1081
+ takeRecords
1082
+ };
1083
+ }
1084
+ function useResizeObserver(target, callback, options = {}) {
1085
+ const { window: window2 = defaultWindow, ...observerOptions } = options;
1086
+ let observer;
1087
+ const isSupported = useSupported(() => window2 && "ResizeObserver" in window2);
1088
+ const cleanup = () => {
1089
+ if (observer) {
1090
+ observer.disconnect();
1091
+ observer = void 0;
1092
+ }
1093
+ };
1094
+ const targets = (0, import_vue_demi12.computed)(() => Array.isArray(target) ? target.map((el) => unrefElement(el)) : [unrefElement(target)]);
1095
+ const stopWatch = (0, import_vue_demi12.watch)(
1096
+ targets,
1097
+ (els) => {
1098
+ cleanup();
1099
+ if (isSupported.value && window2) {
1100
+ observer = new ResizeObserver(callback);
1101
+ for (const _el of els)
1102
+ _el && observer.observe(_el, observerOptions);
1103
+ }
1104
+ },
1105
+ { immediate: true, flush: "post", deep: true }
1106
+ );
1107
+ const stop = () => {
1108
+ cleanup();
1109
+ stopWatch();
1110
+ };
1111
+ tryOnScopeDispose(stop);
1112
+ return {
1113
+ isSupported,
1114
+ stop
1115
+ };
1116
+ }
1117
+ function useElementBounding(target, options = {}) {
1118
+ const {
1119
+ reset = true,
1120
+ windowResize = true,
1121
+ windowScroll = true,
1122
+ immediate = true
1123
+ } = options;
1124
+ const height = (0, import_vue_demi12.ref)(0);
1125
+ const bottom = (0, import_vue_demi12.ref)(0);
1126
+ const left = (0, import_vue_demi12.ref)(0);
1127
+ const right = (0, import_vue_demi12.ref)(0);
1128
+ const top = (0, import_vue_demi12.ref)(0);
1129
+ const width = (0, import_vue_demi12.ref)(0);
1130
+ const x = (0, import_vue_demi12.ref)(0);
1131
+ const y = (0, import_vue_demi12.ref)(0);
1132
+ function update() {
1133
+ const el = unrefElement(target);
1134
+ if (!el) {
1135
+ if (reset) {
1136
+ height.value = 0;
1137
+ bottom.value = 0;
1138
+ left.value = 0;
1139
+ right.value = 0;
1140
+ top.value = 0;
1141
+ width.value = 0;
1142
+ x.value = 0;
1143
+ y.value = 0;
1144
+ }
1145
+ return;
1146
+ }
1147
+ const rect = el.getBoundingClientRect();
1148
+ height.value = rect.height;
1149
+ bottom.value = rect.bottom;
1150
+ left.value = rect.left;
1151
+ right.value = rect.right;
1152
+ top.value = rect.top;
1153
+ width.value = rect.width;
1154
+ x.value = rect.x;
1155
+ y.value = rect.y;
1156
+ }
1157
+ useResizeObserver(target, update);
1158
+ (0, import_vue_demi12.watch)(() => unrefElement(target), (ele) => !ele && update());
1159
+ useMutationObserver(target, update, {
1160
+ attributeFilter: ["style", "class"]
1161
+ });
1162
+ if (windowScroll)
1163
+ useEventListener("scroll", update, { capture: true, passive: true });
1164
+ if (windowResize)
1165
+ useEventListener("resize", update, { passive: true });
1166
+ tryOnMounted(() => {
1167
+ if (immediate)
1168
+ update();
1169
+ });
1170
+ return {
1171
+ height,
1172
+ bottom,
1173
+ left,
1174
+ right,
1175
+ top,
1176
+ width,
1177
+ x,
1178
+ y,
1179
+ update
1180
+ };
1181
+ }
1182
+ var DEFAULT_UNITS = [
1183
+ { max: 6e4, value: 1e3, name: "second" },
1184
+ { max: 276e4, value: 6e4, name: "minute" },
1185
+ { max: 72e6, value: 36e5, name: "hour" },
1186
+ { max: 5184e5, value: 864e5, name: "day" },
1187
+ { max: 24192e5, value: 6048e5, name: "week" },
1188
+ { max: 28512e6, value: 2592e6, name: "month" },
1189
+ { max: Number.POSITIVE_INFINITY, value: 31536e6, name: "year" }
1190
+ ];
1191
+
1192
+ // src/hooks/use-mask.ts
1193
+ function useMask(target, nodes) {
1194
+ const eventBus = useEventBus();
1195
+ const startX = (0, import_vue_demi13.ref)(0);
1196
+ const startY = (0, import_vue_demi13.ref)(0);
1197
+ const lastX = (0, import_vue_demi13.ref)(0);
1198
+ const lastY = (0, import_vue_demi13.ref)(0);
1199
+ const history = useOperateHistory(nodes);
1200
+ const hasEmit = (0, import_vue_demi13.ref)(false);
1201
+ const style = (0, import_vue_demi13.computed)(() => {
1202
+ const width = lastX.value - startX.value;
1203
+ const height = lastY.value - startY.value;
1204
+ return {
1205
+ visibility: selecting.value ? "visible" : "hidden",
1206
+ border: "2px solid rgb(0,120,215)",
1207
+ background: "rgb(0,120,215,0.3)",
1208
+ position: "absolute",
1209
+ top: startY.value + (height < 0 ? height : 0) + "px",
1210
+ left: startX.value + (width < 0 ? width : 0) + "px",
1211
+ width: Math.abs(width) + "px",
1212
+ height: Math.abs(height) + "px"
1213
+ };
1214
+ });
1215
+ const selecting = (0, import_vue_demi13.ref)(false);
1216
+ const rect = useElementBounding(target);
1217
+ const ownerDoc = (0, import_vue_demi13.computed)(() => unrefElement(target)?.ownerDocument);
1218
+ function checkNode() {
1219
+ nodes.value.forEach((node) => {
1220
+ const rect2 = node.node._rect;
1221
+ if (rect2.x == void 0 || // eslint-disable-next-line eqeqeq
1222
+ rect2.y == void 0 || // eslint-disable-next-line eqeqeq
1223
+ rect2.width == void 0 || // eslint-disable-next-line eqeqeq
1224
+ rect2.height == void 0)
1225
+ return false;
1226
+ const x1 = rect2.x;
1227
+ const y1 = rect2.y;
1228
+ const x2 = x1 + rect2.width;
1229
+ const y2 = y1 + rect2.height;
1230
+ node.node.selected = inArea(x1, y1, x2, y2);
1231
+ });
1232
+ }
1233
+ function inArea(x1, y1, x2, y2) {
1234
+ const areaStartX = Math.min(startX.value, lastX.value);
1235
+ const areaStartY = Math.min(startY.value, lastY.value);
1236
+ const areaEndX = Math.max(startX.value, lastX.value);
1237
+ const areaEndY = Math.max(startY.value, lastY.value);
1238
+ const crossX = isCrossing(areaStartX, areaEndX, x1, x2, Math.abs(x1 - x2) / 5);
1239
+ const crossY = isCrossing(areaStartY, areaEndY, y1, y2, Math.abs(y1 - y2) / 5);
1240
+ return crossX && crossY;
1241
+ }
1242
+ function isCrossing(a, b, c, d, standard) {
1243
+ return Math.max(a, c) - Math.min(b, d) <= -standard;
1244
+ }
1245
+ function offsetFormat(evt) {
1246
+ const offsetX = evt.clientX - rect.x.value;
1247
+ const offsetY = evt.clientY - rect.y.value;
1248
+ return {
1249
+ x: offsetX,
1250
+ y: offsetY
1251
+ };
1252
+ }
1253
+ function handleMousedown(evt) {
1254
+ addUserSelectStyle(ownerDoc.value);
1255
+ const { x: offsetX, y: offsetY } = offsetFormat(evt);
1256
+ selecting.value = true;
1257
+ startX.value = offsetX;
1258
+ startY.value = offsetY;
1259
+ lastX.value = offsetX;
1260
+ lastY.value = offsetY;
1261
+ document.addEventListener("mouseup", handleMouseup);
1262
+ }
1263
+ function handleMousemove(evt) {
1264
+ if (!selecting.value)
1265
+ return;
1266
+ if (!hasEmit.value) {
1267
+ eventBus.emit("batch-select", "start");
1268
+ hasEmit.value = true;
1269
+ }
1270
+ const { x: offsetX, y: offsetY } = offsetFormat(evt);
1271
+ if (lastX.value === offsetX && lastY.value === offsetY)
1272
+ return;
1273
+ lastX.value = offsetX;
1274
+ lastY.value = offsetY;
1275
+ handleBatchSelect();
1276
+ }
1277
+ function handleMouseup() {
1278
+ removeUserSelectStyle(ownerDoc.value);
1279
+ selecting.value = false;
1280
+ hasEmit.value = false;
1281
+ if (lastX.value === startX.value && lastY.value === startY.value) {
1282
+ } else {
1283
+ history.push({ type: "batch-select" });
1284
+ document.removeEventListener("mouseup", handleMouseup);
1285
+ }
1286
+ lastX.value = 0;
1287
+ lastY.value = 0;
1288
+ startX.value = 0;
1289
+ startY.value = 0;
1290
+ setTimeout(() => {
1291
+ eventBus.emit("batch-select", "end");
1292
+ });
1293
+ }
1294
+ function renderMask() {
1295
+ return (0, import_vue_demi13.h)("div", {
1296
+ id: "mask",
1297
+ style: style.value
1298
+ });
1299
+ }
1300
+ async function handleBatchSelect() {
1301
+ checkNode();
1302
+ }
1303
+ return {
1304
+ selecting,
1305
+ renderMask,
1306
+ handleMousedown,
1307
+ handleMousemove
1308
+ };
1309
+ }
1310
+
1311
+ // src/hooks/use-operate-history.ts
1312
+ var import_vue_demi14 = require("vue-demi");
1313
+ var records = (0, import_vue_demi14.ref)([]);
1314
+ var state = (0, import_vue_demi14.ref)({
1315
+ canClear: false
1316
+ });
1317
+ function useOperateHistory(nodes) {
1318
+ const lastOperate = (0, import_vue_demi14.computed)(() => records.value.slice(-1)[0]?.type);
1319
+ function push(operate) {
1320
+ records.value.push({
1321
+ ...operate,
1322
+ data: nodes
1323
+ });
1324
+ }
1325
+ return {
1326
+ state,
1327
+ records,
1328
+ lastOperate,
1329
+ push
1330
+ };
1331
+ }
1332
+
1333
+ // src/components/freeDom.ts
1334
+ var import_vue_demi17 = require("vue-demi");
1335
+
1336
+ // src/components/freeDomCore.ts
1337
+ var import_vue_demi15 = require("vue-demi");
1338
+ function noop2() {
846
1339
  }
847
1340
  var freeDomCoreProps = {
848
1341
  userSelectHack: {
@@ -851,15 +1344,15 @@ var freeDomCoreProps = {
851
1344
  },
852
1345
  startFn: {
853
1346
  type: Function,
854
- default: noop
1347
+ default: noop2
855
1348
  },
856
1349
  stopFn: {
857
1350
  type: Function,
858
- default: noop
1351
+ default: noop2
859
1352
  },
860
1353
  dragFn: {
861
1354
  type: Function,
862
- default: noop
1355
+ default: noop2
863
1356
  },
864
1357
  disabled: Boolean,
865
1358
  scale: {
@@ -867,23 +1360,24 @@ var freeDomCoreProps = {
867
1360
  default: 1
868
1361
  }
869
1362
  };
870
- var freeDomCore = (0, import_vue_demi11.defineComponent)({
1363
+ var freeDomCore = (0, import_vue_demi15.defineComponent)({
871
1364
  name: "FreeDomCore",
872
1365
  props: freeDomCoreProps,
873
1366
  setup(props) {
874
- const { only } = useDefaultSlot();
875
- const dragging = (0, import_vue_demi11.ref)(false);
876
- const coreRef = (0, import_vue_demi11.ref)();
877
- const node = (0, import_vue_demi11.computed)(() => coreRef.value?.$el || coreRef.value);
878
- const ownerDoc = (0, import_vue_demi11.computed)(() => node.value?.ownerDocument);
1367
+ const dragging = (0, import_vue_demi15.ref)(false);
1368
+ const coreRef = (0, import_vue_demi15.ref)();
1369
+ const node = (0, import_vue_demi15.computed)(() => coreRef.value?.$el || coreRef.value);
1370
+ const ownerDoc = (0, import_vue_demi15.computed)(() => node.value?.ownerDocument);
879
1371
  const { lastX, lastY, create } = useCoreData(node);
1372
+ const startX = (0, import_vue_demi15.ref)(NaN);
1373
+ const startY = (0, import_vue_demi15.ref)(NaN);
880
1374
  let parentNode;
881
1375
  let parentRect;
882
- (0, import_vue_demi11.onUnmounted)(() => {
1376
+ (0, import_vue_demi15.onUnmounted)(() => {
883
1377
  if (!ownerDoc.value)
884
1378
  return;
885
1379
  if (props.userSelectHack)
886
- _removeUserSelectStyle(ownerDoc.value);
1380
+ removeUserSelectStyle(ownerDoc.value);
887
1381
  ownerDoc.value.removeEventListener("mousemove", _handleDrag);
888
1382
  ownerDoc.value.removeEventListener("mouseup", _handleDragStop);
889
1383
  });
@@ -893,51 +1387,33 @@ var freeDomCore = (0, import_vue_demi11.defineComponent)({
893
1387
  function mouseupFn(evt) {
894
1388
  _handleDragStop(evt);
895
1389
  }
896
- function _addUserSelectStyle(doc) {
897
- if (!doc)
898
- return;
899
- if (!doc.getElementById("free-dom-style-el")) {
900
- const styleEl = doc.createElement("style");
901
- styleEl.id = "free-dom-style-el";
902
- styleEl.innerHTML = ".free-dom-transparent-selection *::selection {all: inherit;}";
903
- doc.getElementsByTagName("head")[0].appendChild(styleEl);
904
- }
905
- if (doc.body)
906
- doc.body.classList.add("free-dom-transparent-selection");
907
- }
908
- function _removeUserSelectStyle(doc) {
909
- if (!doc)
910
- return;
911
- if (doc.body) {
912
- doc.body.classList.remove("free-dom-transparent-selection");
913
- }
914
- const selection = doc.getSelection();
915
- if (selection) {
916
- selection.removeAllRanges();
917
- }
918
- }
919
1390
  function _handleDragstart(evt) {
920
1391
  if (props.disabled || !evt.target || !(evt.target instanceof node.value.ownerDocument.defaultView.Node))
921
1392
  return;
922
1393
  const { x, y } = _offsetFormat(evt);
923
1394
  const coreEvent = create(x, y);
924
1395
  props.startFn(evt, coreEvent);
1396
+ startX.value = x;
1397
+ startY.value = y;
925
1398
  lastX.value = x;
926
1399
  lastY.value = y;
927
1400
  dragging.value = true;
928
1401
  if (props.userSelectHack)
929
- _addUserSelectStyle(ownerDoc.value);
1402
+ addUserSelectStyle(ownerDoc.value);
930
1403
  ownerDoc.value?.addEventListener("mousemove", _handleDrag);
931
1404
  ownerDoc.value?.addEventListener("mouseup", _handleDragStop);
932
1405
  }
933
1406
  function _handleDragStop(evt) {
934
1407
  if (!dragging.value)
935
1408
  return;
936
- const { x, y } = _offsetFormat(evt);
937
- const coreEvent = create(x, y);
938
- props.stopFn(evt, coreEvent);
1409
+ if (startX.value === lastX.value && startY.value === lastY.value) {
1410
+ } else {
1411
+ const { x, y } = _offsetFormat(evt);
1412
+ const coreEvent = create(x, y);
1413
+ props.stopFn(evt, coreEvent);
1414
+ }
939
1415
  if (props.userSelectHack)
940
- _removeUserSelectStyle(ownerDoc.value);
1416
+ removeUserSelectStyle(ownerDoc.value);
941
1417
  dragging.value = false;
942
1418
  lastX.value = NaN;
943
1419
  lastY.value = NaN;
@@ -963,13 +1439,13 @@ var freeDomCore = (0, import_vue_demi11.defineComponent)({
963
1439
  return { x, y };
964
1440
  }
965
1441
  return {
966
- only,
967
1442
  coreRef,
968
1443
  mousedownFn,
969
1444
  mouseupFn
970
1445
  };
971
1446
  },
972
1447
  render() {
1448
+ const { only } = useDefaultSlot();
973
1449
  const vue2Props = {
974
1450
  on: {
975
1451
  mousedown: (evt) => {
@@ -988,12 +1464,12 @@ var freeDomCore = (0, import_vue_demi11.defineComponent)({
988
1464
  };
989
1465
  const res = createRender(
990
1466
  // @ts-expect-error: maybe vue2
991
- this.only,
1467
+ only,
992
1468
  { ref: (el) => {
993
1469
  this.coreRef = el;
994
1470
  } },
995
- import_vue_demi11.isVue2 ? {} : vue3Props,
996
- import_vue_demi11.isVue2 ? vue2Props.on : {}
1471
+ import_vue_demi15.isVue2 ? {} : vue3Props,
1472
+ import_vue_demi15.isVue2 ? vue2Props.on : {}
997
1473
  );
998
1474
  if (typeof res === "function") {
999
1475
  return res();
@@ -1005,9 +1481,9 @@ var freeDomCore = (0, import_vue_demi11.defineComponent)({
1005
1481
  var freeDomCore_default = freeDomCore;
1006
1482
 
1007
1483
  // src/components/resizeDomCore.ts
1008
- var import_vue_demi12 = require("vue-demi");
1484
+ var import_vue_demi16 = require("vue-demi");
1009
1485
  var Dots = ["t", "r", "l", "b", "lt", "lb", "rt", "rb"];
1010
- function noop2() {
1486
+ function noop3() {
1011
1487
  }
1012
1488
  var resizeDomCoreProps = {
1013
1489
  dragOpts: {
@@ -1028,15 +1504,15 @@ var resizeDomCoreProps = {
1028
1504
  },
1029
1505
  startFn: {
1030
1506
  type: Function,
1031
- default: noop2
1507
+ default: noop3
1032
1508
  },
1033
1509
  stopFn: {
1034
1510
  type: Function,
1035
- default: noop2
1511
+ default: noop3
1036
1512
  },
1037
1513
  resizeFn: {
1038
1514
  type: Function,
1039
- default: noop2
1515
+ default: noop3
1040
1516
  },
1041
1517
  minWidth: {
1042
1518
  type: Number,
@@ -1048,16 +1524,15 @@ var resizeDomCoreProps = {
1048
1524
  },
1049
1525
  lockAspectRatio: Boolean
1050
1526
  };
1051
- var resizeDomCore = (0, import_vue_demi12.defineComponent)({
1527
+ var resizeDomCore = (0, import_vue_demi16.defineComponent)({
1052
1528
  name: "ResizeDomCore",
1053
1529
  props: resizeDomCoreProps,
1054
1530
  setup(props, { slots }) {
1055
- const { slots: _slots } = useDefaultSlot();
1056
- const dots = (0, import_vue_demi12.computed)(() => {
1531
+ const dots = (0, import_vue_demi16.computed)(() => {
1057
1532
  const _dots = props.scale;
1058
1533
  return Array.isArray(_dots) ? _dots : Dots;
1059
1534
  });
1060
- const lastRect = (0, import_vue_demi12.shallowRef)();
1535
+ const lastRect = (0, import_vue_demi16.shallowRef)();
1061
1536
  function runConstraints(width, height) {
1062
1537
  const { lockAspectRatio } = props;
1063
1538
  if (!props.minHeight && !props.minWidth && !lockAspectRatio)
@@ -1106,7 +1581,8 @@ var resizeDomCore = (0, import_vue_demi12.defineComponent)({
1106
1581
  }
1107
1582
  function renderResizehandler(axis) {
1108
1583
  if (!slots.handler) {
1109
- return () => (0, import_vue_demi12.h)("i", {
1584
+ return () => (0, import_vue_demi16.h)("i", {
1585
+ dataType: "handler",
1110
1586
  class: [
1111
1587
  "vv-resize-dom--handler",
1112
1588
  `vv-resize-dom--handler__${axis}`
@@ -1117,14 +1593,14 @@ var resizeDomCore = (0, import_vue_demi12.defineComponent)({
1117
1593
  }
1118
1594
  return {
1119
1595
  dots,
1120
- children: _slots,
1121
1596
  handleResize,
1122
1597
  renderResizehandler
1123
1598
  };
1124
1599
  },
1125
1600
  render() {
1601
+ const { slots: children } = useDefaultSlot();
1126
1602
  const slots = [
1127
- ...this.children || [],
1603
+ ...children || [],
1128
1604
  this.dots.map((dot) => {
1129
1605
  return createRender(
1130
1606
  freeDomCore_default,
@@ -1147,13 +1623,14 @@ var resizeDomCore = (0, import_vue_demi12.defineComponent)({
1147
1623
  var resizeDomCore_default = resizeDomCore;
1148
1624
 
1149
1625
  // src/components/freeDom.ts
1150
- function noop3() {
1626
+ function noop4() {
1151
1627
  }
1152
1628
  var freeDomProps = {
1153
1629
  modelValue: {
1154
1630
  type: Object,
1155
1631
  default: () => ({})
1156
1632
  },
1633
+ keyboard: Boolean,
1157
1634
  x: {
1158
1635
  type: Number,
1159
1636
  default: 0
@@ -1177,27 +1654,27 @@ var freeDomProps = {
1177
1654
  lockAspectRatio: Boolean,
1178
1655
  dragStartFn: {
1179
1656
  type: Function,
1180
- default: noop3
1657
+ default: noop4
1181
1658
  },
1182
1659
  dragStopFn: {
1183
1660
  type: Function,
1184
- default: noop3
1661
+ default: noop4
1185
1662
  },
1186
1663
  dragFn: {
1187
1664
  type: Function,
1188
- default: noop3
1665
+ default: noop4
1189
1666
  },
1190
1667
  resizeStartFn: {
1191
1668
  type: Function,
1192
- default: noop3
1669
+ default: noop4
1193
1670
  },
1194
1671
  resizeFn: {
1195
1672
  type: Function,
1196
- default: noop3
1673
+ default: noop4
1197
1674
  },
1198
1675
  resizeStopFn: {
1199
1676
  type: Function,
1200
- default: noop3
1677
+ default: noop4
1201
1678
  },
1202
1679
  autoSize: {
1203
1680
  type: Boolean,
@@ -1214,7 +1691,7 @@ var freeDomProps = {
1214
1691
  },
1215
1692
  fixNonMonospaced: Boolean
1216
1693
  };
1217
- var freeDom = (0, import_vue_demi13.defineComponent)({
1694
+ var freeDom = (0, import_vue_demi17.defineComponent)({
1218
1695
  name: "FreeDom",
1219
1696
  props: freeDomProps,
1220
1697
  emits: [
@@ -1225,7 +1702,12 @@ var freeDom = (0, import_vue_demi13.defineComponent)({
1225
1702
  "update:modelValue"
1226
1703
  ],
1227
1704
  setup(props, { emit, expose, slots }) {
1228
- const domRef = (0, import_vue_demi13.ref)();
1705
+ const domRef = (0, import_vue_demi17.ref)();
1706
+ const isBatchSelecting = (0, import_vue_demi17.ref)(false);
1707
+ const eventBus = useEventBus();
1708
+ eventBus.on("batch-select", (state2) => {
1709
+ isBatchSelecting.value = state2 === "start";
1710
+ });
1229
1711
  const {
1230
1712
  x,
1231
1713
  y,
@@ -1237,8 +1719,10 @@ var freeDom = (0, import_vue_demi13.defineComponent)({
1237
1719
  handleDragStop
1238
1720
  } = useDraggableData(props);
1239
1721
  const { width, height, syncSize: _syncSize } = useResizableData(props, domRef);
1240
- const context = {
1241
- _rect: (0, import_vue_demi13.reactive)({
1722
+ const selected = (0, import_vue_demi17.ref)(false);
1723
+ const context = (0, import_vue_demi17.reactive)({
1724
+ selected,
1725
+ _rect: (0, import_vue_demi17.reactive)({
1242
1726
  x,
1243
1727
  y,
1244
1728
  width,
@@ -1249,8 +1733,13 @@ var freeDom = (0, import_vue_demi13.defineComponent)({
1249
1733
  trigger: (pos) => {
1250
1734
  emit("update:modelValue", pos);
1251
1735
  }
1252
- };
1736
+ });
1253
1737
  const sceneContext = useSceneContext(context, props);
1738
+ onClickOutside(domRef, () => {
1739
+ if (!selected.value || isBatchSelecting.value)
1740
+ return;
1741
+ selected.value = false;
1742
+ }, { ignore: [sceneContext.clearSelectState && ".vv-free-dom--draggable"] });
1254
1743
  const syncSize = () => {
1255
1744
  _syncSize(
1256
1745
  sceneContext.fixNonMonospaced.value,
@@ -1258,13 +1747,13 @@ var freeDom = (0, import_vue_demi13.defineComponent)({
1258
1747
  sceneContext.minHeight.value
1259
1748
  );
1260
1749
  };
1261
- const canDrag = (0, import_vue_demi13.ref)(false);
1262
- (0, import_vue_demi13.onMounted)(() => {
1750
+ const canDrag = (0, import_vue_demi17.ref)(false);
1751
+ (0, import_vue_demi17.onMounted)(() => {
1263
1752
  props.autoSize && syncSize();
1264
1753
  const pos = sceneContext.correct(context._rect);
1265
1754
  context.trigger({ x: pos.x, y: pos.y, w: pos.width, h: pos.height });
1266
1755
  });
1267
- const style = (0, import_vue_demi13.computed)(() => ({
1756
+ const style = (0, import_vue_demi17.computed)(() => ({
1268
1757
  width: `${width.value}px`,
1269
1758
  height: `${height.value}px`,
1270
1759
  transform: `translate(${x.value}px, ${y.value}px)`
@@ -1283,7 +1772,7 @@ var freeDom = (0, import_vue_demi13.defineComponent)({
1283
1772
  if (!isValid)
1284
1773
  return;
1285
1774
  handleDrag(evt, data);
1286
- sceneContext.emit("move");
1775
+ sceneContext.emit("move", evt.shiftKey);
1287
1776
  };
1288
1777
  const onDragStop = (evt, coreData) => {
1289
1778
  if (!canDrag.value)
@@ -1304,6 +1793,7 @@ var freeDom = (0, import_vue_demi13.defineComponent)({
1304
1793
  emit("update:x", x.value);
1305
1794
  emit("update:y", y.value);
1306
1795
  emit("update:modelValue", { x: x.value, y: y.value, w: width.value, h: height.value });
1796
+ sceneContext.history?.push({ type: "move-end" });
1307
1797
  };
1308
1798
  const onDragStart = (evt, coreData) => {
1309
1799
  const handle = sceneContext.handle.value;
@@ -1321,9 +1811,9 @@ var freeDom = (0, import_vue_demi13.defineComponent)({
1321
1811
  }
1322
1812
  canDrag.value && handleDragStart(evt, coreData);
1323
1813
  };
1324
- const onResize = (evt, { node, width: w, height: h5, handle: axis }) => {
1814
+ const onResize = (evt, { node, width: w, height: h7, handle: axis }) => {
1325
1815
  const offsetW = -(w - width.value);
1326
- const offsetH = -(h5 - height.value);
1816
+ const offsetH = -(h7 - height.value);
1327
1817
  const axisH = axis[0];
1328
1818
  const axisV = axis[axis.length - 1];
1329
1819
  let _x = x.value;
@@ -1334,14 +1824,14 @@ var freeDom = (0, import_vue_demi13.defineComponent)({
1334
1824
  if (axisV === "t") {
1335
1825
  _y += offsetH;
1336
1826
  }
1337
- const isValid = sceneContext.check?.({ x: _x, y: _y, width: w, height: h5 });
1827
+ const isValid = sceneContext.check?.({ x: _x, y: _y, width: w, height: h7 });
1338
1828
  if (!isValid)
1339
1829
  return;
1340
1830
  width.value = w;
1341
- height.value = h5;
1831
+ height.value = h7;
1342
1832
  x.value = _x;
1343
1833
  y.value = _y;
1344
- props.resizeFn(evt, { node, width: w, height: h5, handle: axis });
1834
+ props.resizeFn(evt, { node, width: w, height: h7, handle: axis });
1345
1835
  sceneContext?.emit("move");
1346
1836
  };
1347
1837
  const onResizeStop = (evt, data) => {
@@ -1355,6 +1845,7 @@ var freeDom = (0, import_vue_demi13.defineComponent)({
1355
1845
  emit("update:height", height.value);
1356
1846
  emit("update:modelValue", { x: x.value, y: y.value, w: width.value, h: height.value });
1357
1847
  sceneContext.emit("moveup");
1848
+ sceneContext.history?.push({ type: "resize-end" });
1358
1849
  };
1359
1850
  const onResizeStart = (evt, data) => {
1360
1851
  props.resizeStartFn(evt, data);
@@ -1377,16 +1868,63 @@ var freeDom = (0, import_vue_demi13.defineComponent)({
1377
1868
  };
1378
1869
  return createRender(resizeDomCore_default, {}, props2)(slots);
1379
1870
  };
1871
+ function handleSelect(evt) {
1872
+ if (evt.ctrlKey) {
1873
+ selected.value = !selected.value;
1874
+ sceneContext.history?.push({ type: "select" });
1875
+ } else if (!selected.value) {
1876
+ sceneContext.clearSelectState?.();
1877
+ selected.value = true;
1878
+ sceneContext.history?.push({ type: "select" });
1879
+ }
1880
+ }
1881
+ function handleKeyboard(evt) {
1882
+ if (!canDrag.value || !sceneContext.keyboard.value)
1883
+ return;
1884
+ evt.preventDefault();
1885
+ switch (evt.key) {
1886
+ case "ArrowUp":
1887
+ y.value -= 1;
1888
+ break;
1889
+ case "ArrowDown":
1890
+ y.value += 1;
1891
+ break;
1892
+ case "ArrowLeft":
1893
+ x.value -= 1;
1894
+ break;
1895
+ case "ArrowRight":
1896
+ x.value += 1;
1897
+ break;
1898
+ }
1899
+ const newPos = {
1900
+ x: x.value,
1901
+ y: y.value,
1902
+ width: width.value,
1903
+ height: height.value
1904
+ };
1905
+ const isValid = sceneContext.check?.(newPos);
1906
+ if (!isValid) {
1907
+ x.value = clamp(x.value, 0, sceneContext.width);
1908
+ y.value = clamp(y.value, 0, sceneContext.height);
1909
+ }
1910
+ emit("update:x", x.value);
1911
+ emit("update:y", y.value);
1912
+ emit("update:modelValue", { x: x.value, y: y.value, w: width.value, h: height.value });
1913
+ sceneContext.emit("move", true);
1914
+ }
1380
1915
  expose?.({
1381
1916
  syncSize
1382
1917
  });
1383
1918
  return {
1919
+ selected,
1384
1920
  domRef,
1385
1921
  style,
1386
1922
  onDragStop,
1387
1923
  onDrag,
1388
1924
  onDragStart,
1389
1925
  resizeNode,
1926
+ handleKeyboard,
1927
+ handleSelect,
1390
1928
  disabled: sceneContext.disabledDrag,
1391
1929
  scale: sceneContext.transformScale
1392
1930
  };
@@ -1397,17 +1935,35 @@ var freeDom = (0, import_vue_demi13.defineComponent)({
1397
1935
  stopFn: this.onDragStop,
1398
1936
  dragFn: this.onDrag,
1399
1937
  disabled: this.disabled,
1400
- scale: this.scale
1938
+ scale: this.scale,
1939
+ keyboard: this.keyboard
1940
+ };
1941
+ const vue2Listener = {
1942
+ on: {
1943
+ click: this.handleSelect,
1944
+ keydown: this.handleKeyboard
1945
+ }
1946
+ };
1947
+ const vue3Props = {
1948
+ ...props,
1949
+ onClick: this.handleSelect,
1950
+ onKeydown: this.handleKeyboard
1401
1951
  };
1402
1952
  const slots = () => this.resizeNode();
1403
1953
  return createRender(
1404
1954
  freeDomCore_default,
1405
1955
  {
1406
1956
  ref: "domRef",
1407
- class: ["vv-free-dom--draggable", this.disabled && "vv-free-dom--draggable__disabled"],
1957
+ tabindex: -1,
1958
+ class: [
1959
+ "vv-free-dom--draggable",
1960
+ this.disabled && "vv-free-dom--draggable__disabled",
1961
+ this.selected && "vv-free-dom--draggable__selected"
1962
+ ],
1408
1963
  style: this.style
1409
1964
  },
1410
- props
1965
+ import_vue_demi17.isVue2 ? props : vue3Props,
1966
+ import_vue_demi17.isVue2 ? vue2Listener.on : {}
1411
1967
  )?.(slots);
1412
1968
  }
1413
1969
  });
@@ -1435,6 +1991,7 @@ var freeDomWrapProps = {
1435
1991
  type: Number,
1436
1992
  default: 1
1437
1993
  },
1994
+ keyboard: Boolean,
1438
1995
  handle: freeDomProps.handle,
1439
1996
  minWidth: freeDomProps.minWidth,
1440
1997
  minHeight: freeDomProps.minHeight,
@@ -1444,32 +2001,47 @@ var freeDomWrapProps = {
1444
2001
  scale: freeDomProps.scale,
1445
2002
  fixNonMonospaced: freeDomProps.fixNonMonospaced
1446
2003
  };
1447
- var FreeDomWrap = (0, import_vue_demi14.defineComponent)({
2004
+ var FreeDomWrap = (0, import_vue_demi18.defineComponent)({
1448
2005
  name: "FreeDomWrap",
1449
2006
  props: freeDomWrapProps,
1450
2007
  setup(props) {
1451
- const { slots } = useDefaultSlot();
1452
2008
  const eventBus = useEventBus();
1453
- const rectRef = (0, import_vue_demi14.shallowRef)();
1454
- const nodes = (0, import_vue_demi14.ref)([]);
1455
- const width = (0, import_vue_demi14.ref)(props.width);
1456
- const height = (0, import_vue_demi14.ref)(props.height);
1457
- (0, import_vue_demi14.watchEffect)(() => {
2009
+ const rectRef = (0, import_vue_demi18.shallowRef)();
2010
+ const nodes = (0, import_vue_demi18.ref)([]);
2011
+ const history = useOperateHistory(nodes);
2012
+ const width = (0, import_vue_demi18.ref)(props.width);
2013
+ const height = (0, import_vue_demi18.ref)(props.height);
2014
+ const selectedNodes = (0, import_vue_demi18.computed)(() => nodes.value.filter((node) => node.node.selected));
2015
+ eventBus.on("move", (nodeId) => {
2016
+ const mainNode = selectedNodes.value.find((node) => node.uuid === nodeId);
2017
+ if (!mainNode)
2018
+ return;
2019
+ const { deltaX, deltaY } = mainNode.node._rect;
2020
+ selectedNodes.value.forEach((node) => {
2021
+ if (node.uuid === nodeId)
2022
+ return;
2023
+ node.node._rect.x += deltaX || 0;
2024
+ node.node._rect.y += deltaY || 0;
2025
+ });
2026
+ });
2027
+ const selecting = (0, import_vue_demi18.ref)(false);
2028
+ const mask = useMask(rectRef, nodes);
2029
+ (0, import_vue_demi18.watchEffect)(() => {
1458
2030
  width.value = props.width;
1459
2031
  });
1460
- (0, import_vue_demi14.watchEffect)(() => {
2032
+ (0, import_vue_demi18.watchEffect)(() => {
1461
2033
  height.value = props.height;
1462
2034
  });
1463
- (0, import_vue_demi14.onMounted)(() => {
2035
+ (0, import_vue_demi18.onMounted)(() => {
1464
2036
  if (!props.width || !props.height) {
1465
2037
  if (!rectRef.value)
1466
2038
  console.warn("[free-dom] cannot find element, width or height may be set to 0");
1467
- const h5 = rectRef.value?.clientHeight;
2039
+ const h7 = rectRef.value?.clientHeight;
1468
2040
  const w = rectRef.value?.clientWidth;
1469
2041
  if (!props.width)
1470
2042
  width.value = w || 0;
1471
2043
  if (!props.height)
1472
- height.value = h5 || 0;
2044
+ height.value = h7 || 0;
1473
2045
  }
1474
2046
  nodes.value.forEach((pos) => {
1475
2047
  const { x, y, width: width2, height: height2 } = correct(pos.node._rect);
@@ -1481,23 +2053,26 @@ var FreeDomWrap = (0, import_vue_demi14.defineComponent)({
1481
2053
  });
1482
2054
  });
1483
2055
  function register(uuid, node) {
1484
- nodes.value.push({ uuid, node });
2056
+ nodes.value.push({
2057
+ uuid,
2058
+ node
2059
+ });
1485
2060
  }
1486
2061
  function remove(uuid) {
1487
2062
  const index = nodes.value.findIndex((item) => item.uuid === uuid);
1488
2063
  nodes.value.splice(index, 1);
1489
2064
  }
1490
2065
  function checkValid(pos) {
1491
- const { x, y, width: w, height: h5 } = pos;
2066
+ const { x, y, width: w, height: h7 } = pos;
1492
2067
  return x >= 0 && // @ts-expect-error: trigger after mounted
1493
2068
  x + w <= width.value && y >= 0 && // @ts-expect-error: trigger after mounted
1494
- y + h5 <= height.value;
2069
+ y + h7 <= height.value;
1495
2070
  }
1496
2071
  function correct(pos) {
1497
2072
  let x = Math.max(pos.x, 0);
1498
2073
  let y = Math.max(pos.y, 0);
1499
2074
  let w = pos.width;
1500
- let h5 = pos.height;
2075
+ let h7 = pos.height;
1501
2076
  if (pos.x + pos.width > width.value) {
1502
2077
  x = width.value - pos.width;
1503
2078
  if (x < 0) {
@@ -1508,7 +2083,7 @@ var FreeDomWrap = (0, import_vue_demi14.defineComponent)({
1508
2083
  if (pos.y + pos.height > height.value) {
1509
2084
  y = height.value - pos.height;
1510
2085
  if (y < 0) {
1511
- h5 = height.value;
2086
+ h7 = height.value;
1512
2087
  y = 0;
1513
2088
  }
1514
2089
  }
@@ -1516,16 +2091,23 @@ var FreeDomWrap = (0, import_vue_demi14.defineComponent)({
1516
2091
  x,
1517
2092
  y,
1518
2093
  width: w,
1519
- height: h5
2094
+ height: h7
1520
2095
  };
1521
2096
  }
1522
- (0, import_vue_demi14.provide)(
2097
+ function clearSelectState() {
2098
+ selectedNodes.value.forEach((node) => {
2099
+ node.node.selected = false;
2100
+ });
2101
+ }
2102
+ (0, import_vue_demi18.provide)(
1523
2103
  SceneToken,
1524
- (0, import_vue_demi14.reactive)({
1525
- ...(0, import_vue_demi14.toRefs)(props),
2104
+ (0, import_vue_demi18.reactive)({
2105
+ ...(0, import_vue_demi18.toRefs)(props),
1526
2106
  nodes,
1527
2107
  width,
1528
2108
  height,
2109
+ history,
2110
+ clearSelectState,
1529
2111
  register,
1530
2112
  remove,
1531
2113
  checkValid,
@@ -1535,41 +2117,52 @@ var FreeDomWrap = (0, import_vue_demi14.defineComponent)({
1535
2117
  emit: eventBus.emit
1536
2118
  })
1537
2119
  );
1538
- const style = (0, import_vue_demi14.computed)(() => ({
2120
+ const style = (0, import_vue_demi18.computed)(() => ({
1539
2121
  width: `${props.width}px`,
1540
2122
  height: `${props.height}px`
1541
2123
  }));
1542
2124
  return {
1543
2125
  rectRef,
1544
2126
  style,
1545
- slots
2127
+ selecting,
2128
+ mask,
2129
+ history
1546
2130
  };
1547
2131
  },
1548
2132
  render() {
2133
+ const { slots } = useDefaultSlot();
1549
2134
  const marklineComp = createRender(markLine_default, {}, { showLine: this.showLine })();
1550
- const slots = [this.slots, marklineComp];
2135
+ const slotList = [
2136
+ this.mask.selecting && this.mask.renderMask(),
2137
+ slots,
2138
+ marklineComp
2139
+ ];
1551
2140
  return createRender(
1552
2141
  "section",
1553
2142
  {
1554
2143
  ref: "rectRef",
1555
2144
  class: "vv-free-dom--scene",
1556
2145
  style: this.style
2146
+ },
2147
+ {
2148
+ onMousedown: this.mask.handleMousedown,
2149
+ onMousemove: this.mask.handleMousemove
1557
2150
  }
1558
- )(slots);
2151
+ )(slotList);
1559
2152
  }
1560
2153
  });
1561
2154
 
1562
2155
  // src/components/gridLayout.ts
1563
- var import_vue_demi16 = require("vue-demi");
2156
+ var import_vue_demi20 = require("vue-demi");
1564
2157
 
1565
2158
  // src/components/gridItem.ts
1566
- var import_vue_demi15 = require("vue-demi");
2159
+ var import_vue_demi19 = require("vue-demi");
1567
2160
 
1568
2161
  // src/components/tokens.ts
1569
2162
  var gridLayoutContextKey = Symbol("gridLayoutContext");
1570
2163
 
1571
2164
  // src/components/gridItem.ts
1572
- var noop4 = () => {
2165
+ var noop5 = () => {
1573
2166
  };
1574
2167
  var gridItemProps = {
1575
2168
  x: {
@@ -1590,27 +2183,27 @@ var gridItemProps = {
1590
2183
  },
1591
2184
  dragStartFn: {
1592
2185
  type: Function,
1593
- default: noop4
2186
+ default: noop5
1594
2187
  },
1595
2188
  dragFn: {
1596
2189
  type: Function,
1597
- default: noop4
2190
+ default: noop5
1598
2191
  },
1599
2192
  dragEndFn: {
1600
2193
  type: Function,
1601
- default: noop4
2194
+ default: noop5
1602
2195
  },
1603
2196
  resizeStartFn: {
1604
2197
  type: Function,
1605
- default: noop4
2198
+ default: noop5
1606
2199
  },
1607
2200
  resizeFn: {
1608
2201
  type: Function,
1609
- default: noop4
2202
+ default: noop5
1610
2203
  },
1611
2204
  resizeStopFn: {
1612
2205
  type: Function,
1613
- default: noop4
2206
+ default: noop5
1614
2207
  },
1615
2208
  isDraggable: Boolean,
1616
2209
  isResizable: Boolean,
@@ -1620,12 +2213,12 @@ var gridItemProps = {
1620
2213
  }
1621
2214
  };
1622
2215
  var gridItemEmits = ["dragMove"];
1623
- var GridItem = (0, import_vue_demi15.defineComponent)({
2216
+ var GridItem = (0, import_vue_demi19.defineComponent)({
1624
2217
  name: "GridItem",
1625
2218
  props: gridItemProps,
1626
2219
  emits: gridItemEmits,
1627
2220
  setup(props) {
1628
- const layout = (0, import_vue_demi15.inject)(gridLayoutContextKey);
2221
+ const layout = (0, import_vue_demi19.inject)(gridLayoutContextKey);
1629
2222
  if (!layout) {
1630
2223
  throw new Error("TODO");
1631
2224
  }
@@ -1645,7 +2238,6 @@ var GridItem = (0, import_vue_demi15.defineComponent)({
1645
2238
  onResize,
1646
2239
  onResizeStop
1647
2240
  } = useLayoutItem(props, layout);
1648
- const { only, slots } = useDefaultSlot();
1649
2241
  const resizeNode = (child) => {
1650
2242
  const _props = {
1651
2243
  width: width.value,
@@ -1684,8 +2276,6 @@ var GridItem = (0, import_vue_demi15.defineComponent)({
1684
2276
  y,
1685
2277
  width,
1686
2278
  height,
1687
- child: only,
1688
- slots,
1689
2279
  style,
1690
2280
  dragging,
1691
2281
  onDragStart,
@@ -1698,7 +2288,8 @@ var GridItem = (0, import_vue_demi15.defineComponent)({
1698
2288
  };
1699
2289
  },
1700
2290
  render() {
1701
- const node = this.slots;
2291
+ const { slots } = useDefaultSlot();
2292
+ const node = slots;
1702
2293
  return this.dragNode(node);
1703
2294
  }
1704
2295
  });
@@ -1750,15 +2341,15 @@ var gridLayoutProps = {
1750
2341
  disabledResize: Boolean,
1751
2342
  collision: Boolean
1752
2343
  };
1753
- var GridLayout = (0, import_vue_demi16.defineComponent)({
2344
+ var GridLayout = (0, import_vue_demi20.defineComponent)({
1754
2345
  name: "GridLayout",
1755
2346
  inheritAttrs: false,
1756
2347
  props: gridLayoutProps,
1757
2348
  emits: ["update:modelValue"],
1758
2349
  setup(props, { emit }) {
1759
2350
  const layout = useLayout(props);
1760
- (0, import_vue_demi16.provide)(gridLayoutContextKey, layout);
1761
- const activeDrag = (0, import_vue_demi16.ref)(null);
2351
+ (0, import_vue_demi20.provide)(gridLayoutContextKey, layout);
2352
+ const activeDrag = (0, import_vue_demi20.ref)(null);
1762
2353
  function processItem(node) {
1763
2354
  const key = node.key;
1764
2355
  if (!key)
@@ -1805,12 +2396,12 @@ var GridLayout = (0, import_vue_demi16.defineComponent)({
1805
2396
  height: config.h
1806
2397
  };
1807
2398
  activeDrag.value = placeholder2;
1808
- const { w, h: h5 } = data;
1809
- layout.resizeTo(config, w, h5);
2399
+ const { w, h: h7 } = data;
2400
+ layout.resizeTo(config, w, h7);
1810
2401
  },
1811
2402
  resizeStopFn: (evt, data) => {
1812
- const { w, h: h5 } = data;
1813
- layout.resizeTo(config, w, h5);
2403
+ const { w, h: h7 } = data;
2404
+ layout.resizeTo(config, w, h7);
1814
2405
  activeDrag.value = null;
1815
2406
  }
1816
2407
  };
@@ -1843,7 +2434,7 @@ var GridLayout = (0, import_vue_demi16.defineComponent)({
1843
2434
  height: this.layout.calContainerHeight()
1844
2435
  };
1845
2436
  const defaultSlot = typeof this.$slots.default === "function" ? this.$slots.default() : this.$slots.default || [];
1846
- return (0, import_vue_demi16.h)("div", {
2437
+ return (0, import_vue_demi20.h)("div", {
1847
2438
  class: "vv-grid-layout",
1848
2439
  style: mergedStyle
1849
2440
  }, [