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