@sepveneto/free-dom 0.0.6

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 ADDED
@@ -0,0 +1,614 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+ var __publicField = (obj, key, value) => {
21
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
22
+ return value;
23
+ };
24
+
25
+ // src/index.ts
26
+ var src_exports = {};
27
+ __export(src_exports, {
28
+ freeDom: () => freeDom,
29
+ freeScene: () => freeScene
30
+ });
31
+ module.exports = __toCommonJS(src_exports);
32
+
33
+ // src/components/freeDom.ts
34
+ var import_vue_demi2 = require("vue-demi");
35
+
36
+ // src/hooks/use-normalize-style.ts
37
+ var import_vue_demi = require("vue-demi");
38
+ function useNormalizeStyle(style) {
39
+ const _style = (0, import_vue_demi.ref)({
40
+ transition: "inherit"
41
+ });
42
+ (0, import_vue_demi.watch)(() => style, (data) => {
43
+ const res = Object.entries((0, import_vue_demi.unref)(data)).reduce(
44
+ (obj, _style2) => {
45
+ const [key, value] = _style2;
46
+ if (typeof value === "number") {
47
+ obj[key] = `${value}px`;
48
+ } else {
49
+ obj[key] = value;
50
+ }
51
+ return obj;
52
+ },
53
+ {}
54
+ );
55
+ _style.value = {
56
+ ..._style.value,
57
+ ...res
58
+ };
59
+ }, { deep: true });
60
+ return _style;
61
+ }
62
+
63
+ // src/components/freeDom.ts
64
+ var import_core = require("@vueuse/core");
65
+
66
+ // src/util/EventBus.ts
67
+ var _EventBus = class {
68
+ static on(name, callback) {
69
+ if (!Array.isArray(_EventBus._callbacks[name])) {
70
+ _EventBus._callbacks[name] = [];
71
+ }
72
+ _EventBus._callbacks[name].push(callback);
73
+ }
74
+ static emit(name, ...args) {
75
+ _EventBus._callbacks[name]?.forEach((item) => item.apply(this, args));
76
+ }
77
+ static off(name) {
78
+ _EventBus._callbacks[name].length = 0;
79
+ }
80
+ };
81
+ var EventBus = _EventBus;
82
+ __publicField(EventBus, "_callbacks", {});
83
+
84
+ // src/util/tokens.ts
85
+ var SceneToken = Symbol("Scene");
86
+
87
+ // src/components/freeDom.ts
88
+ var import_uuid = require("uuid");
89
+ var Dots = ["t", "r", "l", "b", "lt", "lb", "rt", "rb"];
90
+ var FreeDom = (0, import_vue_demi2.defineComponent)({
91
+ name: "FreeDom",
92
+ props: {
93
+ customStyle: {
94
+ type: Object,
95
+ required: true
96
+ },
97
+ scale: {
98
+ type: [Boolean, Array],
99
+ default: void 0
100
+ },
101
+ move: Boolean,
102
+ preview: Boolean,
103
+ limitWidth: {
104
+ type: Number,
105
+ default: void 0
106
+ },
107
+ limitHeight: {
108
+ type: Number,
109
+ default: void 0
110
+ }
111
+ },
112
+ emits: ["update:customStyle", "select"],
113
+ setup(props, { emit }) {
114
+ const active = (0, import_vue_demi2.ref)(false);
115
+ const SceneContext = (0, import_vue_demi2.inject)(SceneToken);
116
+ const _preview = (0, import_vue_demi2.computed)(() => SceneContext?.preview || props.preview);
117
+ const canScale = (0, import_vue_demi2.computed)(() => !_preview.value && (SceneContext?.scale || props.scale));
118
+ const canMove = (0, import_vue_demi2.computed)(() => !_preview.value && (SceneContext?.move || props.move));
119
+ const widgetRef = (0, import_vue_demi2.shallowRef)();
120
+ const _style = (0, import_vue_demi2.ref)({});
121
+ const wrapStyle = useNormalizeStyle(_style);
122
+ const uuid = (0, import_uuid.v4)();
123
+ const isScale = (0, import_vue_demi2.ref)(false);
124
+ const isMove = (0, import_vue_demi2.ref)(false);
125
+ const _rect = (0, import_vue_demi2.reactive)({
126
+ x: 0,
127
+ y: 0,
128
+ width: 0,
129
+ height: 0
130
+ });
131
+ const context = {
132
+ _rect,
133
+ trigger
134
+ };
135
+ (0, import_vue_demi2.onMounted)(() => {
136
+ SceneContext?.register(uuid, context);
137
+ });
138
+ (0, import_core.onClickOutside)(widgetRef, () => {
139
+ active.value = false;
140
+ });
141
+ function normalize(style) {
142
+ const { transform, width, height } = style;
143
+ const { x, y } = getPos(transform);
144
+ _rect.width = parseNum(width ?? 0);
145
+ _rect.height = parseNum(height ?? 0);
146
+ _rect.x = x;
147
+ _rect.y = y;
148
+ }
149
+ function parseNum(val) {
150
+ return typeof val === "number" ? val : parseFloat(val);
151
+ }
152
+ (0, import_vue_demi2.watch)(() => props.customStyle, (_style2) => {
153
+ normalize(_style2);
154
+ trigger();
155
+ });
156
+ (0, import_vue_demi2.onMounted)(async () => {
157
+ _style.value = props.customStyle;
158
+ await (0, import_vue_demi2.nextTick)();
159
+ const rect = widgetRef.value.getBoundingClientRect();
160
+ normalize(props.customStyle);
161
+ _rect.width = rect.width;
162
+ _rect.height = rect.height;
163
+ trigger();
164
+ });
165
+ function trigger() {
166
+ const { x, y, width, height } = _rect;
167
+ _style.value = {
168
+ ...props.customStyle,
169
+ transform: `translate(${x}px, ${y}px)`,
170
+ width,
171
+ height
172
+ };
173
+ }
174
+ const _dots = (0, import_vue_demi2.computed)(() => {
175
+ return SceneContext && Array.isArray(SceneContext.scale) ? SceneContext.scale : props.scale;
176
+ });
177
+ const dots = (0, import_vue_demi2.computed)(() => {
178
+ if (!isActive.value)
179
+ return [];
180
+ return Array.isArray(_dots.value) ? _dots.value : Dots;
181
+ });
182
+ const direct = {
183
+ l: "w",
184
+ r: "e",
185
+ t: "n",
186
+ b: "s"
187
+ };
188
+ const isActive = (0, import_vue_demi2.shallowRef)(true);
189
+ function onMousedownDot(evt, dot) {
190
+ evt.stopPropagation();
191
+ evt.preventDefault();
192
+ if (isMove.value)
193
+ return;
194
+ isScale.value = true;
195
+ const { x, y, width, height } = getStyle(_style.value);
196
+ const cWidth = width;
197
+ const cHeight = height;
198
+ const startX = evt.clientX;
199
+ const startY = evt.clientY;
200
+ const isT = /t/.test(dot);
201
+ const isL = /l/.test(dot);
202
+ const isB = /b/.test(dot);
203
+ const isR = /r/.test(dot);
204
+ const isDiagonal = dot.length === 2;
205
+ const move = (mouseEvt) => {
206
+ const currX = mouseEvt.clientX;
207
+ const currY = mouseEvt.clientY;
208
+ const deltaX = currX - startX;
209
+ const deltaY = currY - startY;
210
+ const rate = cWidth / cHeight;
211
+ const newWidth = cWidth + (isL ? -deltaX : isR ? deltaX : 0);
212
+ const newHeight = cHeight + (isT ? -deltaY : isB ? deltaY : 0);
213
+ if (isDiagonal) {
214
+ if (Math.abs(deltaX) >= Math.abs(deltaY)) {
215
+ _rect.x = x + (isL ? deltaX : 0);
216
+ _rect.width = newWidth < 0 ? 0 : newWidth;
217
+ _rect.height = newWidth / rate;
218
+ } else {
219
+ _rect.y = y + (isT ? deltaY : 0);
220
+ _rect.height = newHeight < 0 ? 0 : newHeight;
221
+ _rect.width = newHeight * rate;
222
+ }
223
+ } else {
224
+ _rect.x = x + (isL ? deltaX : 0);
225
+ _rect.y = y + (isT ? deltaY : 0);
226
+ _rect.width = newWidth < 0 ? 0 : newWidth;
227
+ _rect.height = newHeight < 0 ? 0 : newHeight;
228
+ }
229
+ if (!checkValid(_rect))
230
+ return;
231
+ EventBus.emit("move", uuid);
232
+ trigger();
233
+ };
234
+ const up = () => {
235
+ isScale.value = false;
236
+ EventBus.emit("moveup", uuid);
237
+ document.removeEventListener("mousemove", move);
238
+ document.removeEventListener("mouseup", up);
239
+ emit("update:customStyle", _style.value);
240
+ };
241
+ document.addEventListener("mousemove", move);
242
+ document.addEventListener("mouseup", up);
243
+ }
244
+ function getDotPos(dot) {
245
+ if (!_style.value)
246
+ return {};
247
+ const { width, height } = _style.value;
248
+ const isL = /l/.test(dot);
249
+ const isR = /r/.test(dot);
250
+ const isT = /t/.test(dot);
251
+ let left, top;
252
+ if (dot.length === 2) {
253
+ left = isL ? 0 : width;
254
+ top = isT ? 0 : height;
255
+ } else {
256
+ if (isL || isR) {
257
+ left = isL ? 0 : width;
258
+ top = Number(height) / 2;
259
+ } else {
260
+ left = Number(width) / 2;
261
+ top = isT ? 0 : height;
262
+ }
263
+ }
264
+ return {
265
+ top: top + "px",
266
+ left: left + "px",
267
+ cursor: dot.split("").reverse().map((item) => direct[item]).join("") + "-resize"
268
+ };
269
+ }
270
+ function onMousedown(evt) {
271
+ evt.stopPropagation();
272
+ if (isScale.value || !canMove.value)
273
+ return;
274
+ isMove.value = true;
275
+ active.value = true;
276
+ const pos = getStyle(_style.value);
277
+ const move = (mouseEvt) => {
278
+ const { clientX, clientY } = mouseEvt;
279
+ const x = clientX - evt.clientX + pos.x;
280
+ const y = clientY - evt.clientY + pos.y;
281
+ _rect.x = x;
282
+ _rect.y = y;
283
+ _rect.width = pos.width;
284
+ _rect.height = pos.height;
285
+ if (!checkValid(_rect))
286
+ return;
287
+ EventBus.emit("move", uuid);
288
+ trigger();
289
+ };
290
+ const up = () => {
291
+ isMove.value = false;
292
+ EventBus.emit("moveup", uuid);
293
+ document.removeEventListener("mousemove", move);
294
+ document.removeEventListener("mouseup", up);
295
+ emit("update:customStyle", _style.value);
296
+ emit("select", _rect);
297
+ };
298
+ document.addEventListener("mousemove", move);
299
+ document.addEventListener("mouseup", up);
300
+ }
301
+ function checkValid(rect) {
302
+ if (SceneContext) {
303
+ return SceneContext.checkValid(rect);
304
+ } else if (props.limitWidth && props.limitHeight) {
305
+ const { x, y, width, height } = rect;
306
+ return x >= 0 && x + width <= props.limitWidth && y >= 0 && y + height <= props.limitHeight;
307
+ } else {
308
+ return true;
309
+ }
310
+ }
311
+ function getStyle(style) {
312
+ const { transform, width, height } = style;
313
+ const { x, y } = getPos(transform);
314
+ return {
315
+ x: x ? Number(x) : 0,
316
+ y: y ? Number(y) : 0,
317
+ width: parseFloat(width),
318
+ height: parseFloat(height)
319
+ };
320
+ }
321
+ function getPos(transform) {
322
+ if (!transform) {
323
+ return {
324
+ x: 0,
325
+ y: 0
326
+ };
327
+ }
328
+ const posRegexp = /translate\(([.0-9]+)px[, ]+([.0-9]+)px\)/;
329
+ const [, x, y] = posRegexp.exec(transform) ?? [];
330
+ return { x: parseNum(x), y: parseNum(y) };
331
+ }
332
+ return {
333
+ widgetRef,
334
+ canMove,
335
+ wrapStyle,
336
+ canScale,
337
+ dots,
338
+ active,
339
+ getDotPos,
340
+ onMousedown,
341
+ onMousedownDot
342
+ };
343
+ },
344
+ render() {
345
+ const dots = this.canScale ? this.dots.map((dot) => {
346
+ if (import_vue_demi2.isVue2) {
347
+ return (0, import_vue_demi2.h)("div", {
348
+ class: "free-dom__widget-dot",
349
+ style: this.getDotPos(dot),
350
+ on: {
351
+ mousedown: (evt) => this.onMousedownDot(evt, dot)
352
+ }
353
+ });
354
+ }
355
+ return (0, import_vue_demi2.h)("div", {
356
+ class: "free-dom__widget-dot",
357
+ style: this.getDotPos(dot),
358
+ onMousedown: (evt) => this.onMousedownDot(evt, dot)
359
+ });
360
+ }) : null;
361
+ const defaultSlot = typeof this.$slots.default === "function" ? this.$slots.default() : this.$slots.default;
362
+ if (import_vue_demi2.isVue2) {
363
+ return (0, import_vue_demi2.h)(
364
+ "section",
365
+ {
366
+ class: [
367
+ "free-dom__widget-wrapper",
368
+ { "can-move": this.canMove },
369
+ { "is-active": this.active }
370
+ ],
371
+ style: this.wrapStyle,
372
+ ref: "widgetRef",
373
+ on: {
374
+ mousedown: this.onMousedown
375
+ }
376
+ },
377
+ [dots, defaultSlot]
378
+ );
379
+ }
380
+ return (0, import_vue_demi2.h)(
381
+ "section",
382
+ {
383
+ ref: "widgetRef",
384
+ class: [
385
+ "free-dom__widget-wrapper",
386
+ { "can-move": this.canMove },
387
+ { "is-active": this.active }
388
+ ],
389
+ style: this.wrapStyle,
390
+ onMousedown: this.onMousedown
391
+ },
392
+ [dots, defaultSlot]
393
+ );
394
+ }
395
+ });
396
+
397
+ // src/components/freeDomWrap.ts
398
+ var import_vue_demi4 = require("vue-demi");
399
+ var import_core2 = require("@vueuse/core");
400
+
401
+ // src/components/markLine.ts
402
+ var import_vue_demi3 = require("vue-demi");
403
+ var lineType = ["xt", "xc", "xb", "yl", "yc", "yr"];
404
+ var markLine_default = (0, import_vue_demi3.defineComponent)({
405
+ setup() {
406
+ const SceneContext = (0, import_vue_demi3.inject)(SceneToken);
407
+ const lines = (0, import_vue_demi3.shallowRef)(lineType);
408
+ const diff = (0, import_vue_demi3.ref)(SceneContext.diff);
409
+ const nodes = SceneContext.nodes;
410
+ const lineStatus = (0, import_vue_demi3.reactive)({
411
+ xt: {
412
+ show: false,
413
+ pos: 0
414
+ },
415
+ xc: {
416
+ show: false,
417
+ pos: 0
418
+ },
419
+ xb: {
420
+ show: false,
421
+ pos: 0
422
+ },
423
+ yl: {
424
+ show: false,
425
+ pos: 0
426
+ },
427
+ yc: {
428
+ show: false,
429
+ pos: 0
430
+ },
431
+ yr: {
432
+ show: false,
433
+ pos: 0
434
+ }
435
+ });
436
+ EventBus.on("move", async (uuid) => {
437
+ const current = nodes.find((node) => node.uuid === uuid)?.node ?? {};
438
+ clearStatus();
439
+ nodes.forEach((node) => {
440
+ if (node.uuid === uuid)
441
+ return;
442
+ const _current = normalize(current._rect);
443
+ const _target = normalize(node.node._rect);
444
+ if (isNearly(_current.top, _target.top)) {
445
+ lineStatus.xt = {
446
+ show: true,
447
+ pos: _target.top
448
+ };
449
+ current._rect.y = _target.top;
450
+ }
451
+ if (isNearly(_current.bottom, _target.top)) {
452
+ lineStatus.xt = {
453
+ show: true,
454
+ pos: _target.top
455
+ };
456
+ current._rect.y = _target.top - _current.height;
457
+ }
458
+ if (isNearly(_current.centerY, _target.centerY)) {
459
+ lineStatus.xc = {
460
+ show: true,
461
+ pos: _target.centerY
462
+ };
463
+ current._rect.y = _target.centerY - _current.height / 2;
464
+ }
465
+ if (isNearly(_current.top, _target.bottom)) {
466
+ lineStatus.xb = {
467
+ show: true,
468
+ pos: _target.bottom
469
+ };
470
+ current._rect.y = _target.bottom;
471
+ }
472
+ if (isNearly(_current.bottom, _target.bottom)) {
473
+ lineStatus.xb = {
474
+ show: true,
475
+ pos: _target.bottom
476
+ };
477
+ current._rect.y = _target.bottom - _current.height;
478
+ }
479
+ if (isNearly(_current.left, _target.left)) {
480
+ lineStatus.yl = {
481
+ show: true,
482
+ pos: _target.left
483
+ };
484
+ current._rect.x = _target.left;
485
+ }
486
+ if (isNearly(_current.right, _target.left)) {
487
+ lineStatus.yl = {
488
+ show: true,
489
+ pos: _target.left
490
+ };
491
+ current._rect.x = _target.left - _current.width;
492
+ }
493
+ if (isNearly(_current.centerX, _target.centerX)) {
494
+ lineStatus.yc = {
495
+ show: true,
496
+ pos: _target.centerX
497
+ };
498
+ current._rect.x = _target.centerX - _current.width / 2;
499
+ }
500
+ if (isNearly(_current.left, _target.right)) {
501
+ lineStatus.yr = {
502
+ show: true,
503
+ pos: _target.right
504
+ };
505
+ current._rect.x = _target.right;
506
+ }
507
+ if (isNearly(_current.right, _target.right)) {
508
+ lineStatus.yr = {
509
+ show: true,
510
+ pos: _target.right
511
+ };
512
+ current._rect.x = _target.right - _current.width;
513
+ }
514
+ });
515
+ });
516
+ EventBus.on("moveup", clearStatus);
517
+ (0, import_vue_demi3.onBeforeUnmount)(() => {
518
+ EventBus.off("move");
519
+ EventBus.off("moveup");
520
+ });
521
+ function clearStatus() {
522
+ lineStatus.xt.show = false;
523
+ lineStatus.xc.show = false;
524
+ lineStatus.xb.show = false;
525
+ lineStatus.yl.show = false;
526
+ lineStatus.yc.show = false;
527
+ lineStatus.yr.show = false;
528
+ }
529
+ function normalize(rect) {
530
+ return {
531
+ top: rect.y,
532
+ bottom: rect.y + rect.height,
533
+ left: rect.x,
534
+ right: rect.x + rect.width,
535
+ width: rect.width,
536
+ height: rect.height,
537
+ centerX: rect.x + rect.width / 2,
538
+ centerY: rect.y + rect.height / 2
539
+ };
540
+ }
541
+ function isNearly(curr, target) {
542
+ return Math.abs(curr - target) <= diff.value;
543
+ }
544
+ return {
545
+ lines,
546
+ diff,
547
+ lineStatus
548
+ };
549
+ },
550
+ render() {
551
+ const _line = (line, info) => (0, import_vue_demi3.h)("div", {
552
+ style: { [line.includes("x") ? "top" : "left"]: info.pos + "px" },
553
+ class: [line.includes("x") ? "free-dom__xline" : "free-dom__yline", "free-dom__line"]
554
+ });
555
+ const _lines = this.lines.filter((line) => this.lineStatus[line].show).map((line) => _line(line, this.lineStatus[line]));
556
+ return (0, import_vue_demi3.h)("div", {
557
+ class: "free-dom__mark-line"
558
+ }, _lines);
559
+ }
560
+ });
561
+
562
+ // src/components/freeDomWrap.ts
563
+ var freeDomWrapProps = {
564
+ preview: Boolean,
565
+ move: Boolean,
566
+ scale: [Boolean, Array],
567
+ diff: {
568
+ type: Number,
569
+ default: 3
570
+ }
571
+ };
572
+ var FreeDomWrap = (0, import_vue_demi4.defineComponent)({
573
+ name: "FreeDomWrap",
574
+ props: freeDomWrapProps,
575
+ setup(props) {
576
+ const rectRef = (0, import_vue_demi4.shallowRef)(null);
577
+ const rect = (0, import_core2.useElementBounding)(rectRef);
578
+ const nodes = (0, import_vue_demi4.ref)([]);
579
+ function register(uuid, node) {
580
+ nodes.value.push({ uuid, node });
581
+ }
582
+ function checkValid(pos) {
583
+ const { x, y, width, height } = pos;
584
+ return x >= 0 && x + width <= rect.width.value && y >= 0 && y + height <= rect.height.value;
585
+ }
586
+ (0, import_vue_demi4.provide)(
587
+ SceneToken,
588
+ (0, import_vue_demi4.reactive)({
589
+ ...(0, import_vue_demi4.toRefs)(props),
590
+ nodes,
591
+ register,
592
+ checkValid
593
+ })
594
+ );
595
+ return {
596
+ rectRef
597
+ };
598
+ },
599
+ render() {
600
+ const defaultSlot = typeof this.$slots.default === "function" ? this.$slots.default() : this.$slots.default;
601
+ return (0, import_vue_demi4.h)("section", {
602
+ ref: "rectRef"
603
+ }, [defaultSlot, (0, import_vue_demi4.h)(markLine_default)]);
604
+ }
605
+ });
606
+
607
+ // src/index.ts
608
+ var freeDom = FreeDom;
609
+ var freeScene = FreeDomWrap;
610
+ // Annotate the CommonJS export names for ESM import in node:
611
+ 0 && (module.exports = {
612
+ freeDom,
613
+ freeScene
614
+ });