mce 0.22.1 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.css +48 -0
- package/dist/index.js +262 -66
- package/dist/mixins/snapper.d.ts +10 -0
- package/dist/plugins/transform.d.ts +2 -0
- package/package.json +2 -2
package/dist/index.css
CHANGED
|
@@ -842,6 +842,54 @@
|
|
|
842
842
|
height: 1px;
|
|
843
843
|
width: 1px;
|
|
844
844
|
}
|
|
845
|
+
.m-smart-guides__distance {
|
|
846
|
+
position: absolute;
|
|
847
|
+
display: flex;
|
|
848
|
+
align-items: center;
|
|
849
|
+
justify-content: center;
|
|
850
|
+
background-color: rgb(var(--m-theme-primary));
|
|
851
|
+
}
|
|
852
|
+
.m-smart-guides__distance::before, .m-smart-guides__distance::after {
|
|
853
|
+
content: "";
|
|
854
|
+
position: absolute;
|
|
855
|
+
background-color: rgb(var(--m-theme-primary));
|
|
856
|
+
}
|
|
857
|
+
.m-smart-guides__distance::before {
|
|
858
|
+
inset: 50% auto auto 0;
|
|
859
|
+
width: 1px;
|
|
860
|
+
height: 8px;
|
|
861
|
+
transform: translateY(-50%);
|
|
862
|
+
}
|
|
863
|
+
.m-smart-guides__distance::after {
|
|
864
|
+
inset: 50% 0 auto auto;
|
|
865
|
+
width: 1px;
|
|
866
|
+
height: 8px;
|
|
867
|
+
transform: translateY(-50%);
|
|
868
|
+
}
|
|
869
|
+
.m-smart-guides__distance--vertical::before {
|
|
870
|
+
inset: 0 auto auto 50%;
|
|
871
|
+
width: 8px;
|
|
872
|
+
height: 1px;
|
|
873
|
+
transform: translateX(-50%);
|
|
874
|
+
}
|
|
875
|
+
.m-smart-guides__distance--vertical::after {
|
|
876
|
+
inset: auto auto 0 50%;
|
|
877
|
+
width: 8px;
|
|
878
|
+
height: 1px;
|
|
879
|
+
transform: translateX(-50%);
|
|
880
|
+
}
|
|
881
|
+
.m-smart-guides__label {
|
|
882
|
+
position: absolute;
|
|
883
|
+
padding: 1px 5px;
|
|
884
|
+
border-radius: 8px;
|
|
885
|
+
font-size: 10px;
|
|
886
|
+
font-weight: 600;
|
|
887
|
+
line-height: 1.4;
|
|
888
|
+
white-space: nowrap;
|
|
889
|
+
color: rgb(var(--m-theme-on-primary));
|
|
890
|
+
background-color: rgb(var(--m-theme-primary));
|
|
891
|
+
pointer-events: none;
|
|
892
|
+
}
|
|
845
893
|
.m-smart-guides__area {
|
|
846
894
|
position: absolute;
|
|
847
895
|
display: flex;
|
package/dist/index.js
CHANGED
|
@@ -7228,53 +7228,115 @@ var snapper_default = defineMixin((editor) => {
|
|
|
7228
7228
|
const unregisterSnapper = (key) => {
|
|
7229
7229
|
snappers.delete(key);
|
|
7230
7230
|
};
|
|
7231
|
-
|
|
7231
|
+
function getSnapAxes() {
|
|
7232
7232
|
const axisX = /* @__PURE__ */ new Set();
|
|
7233
7233
|
const axisY = /* @__PURE__ */ new Set();
|
|
7234
|
+
const gutterX = /* @__PURE__ */ new Set();
|
|
7235
|
+
const gutterY = /* @__PURE__ */ new Set();
|
|
7234
7236
|
snappers.forEach((snapper) => {
|
|
7235
|
-
const { xLines, yLines } = snapper.getLines();
|
|
7237
|
+
const { xLines, yLines, xGutters, yGutters } = snapper.getLines();
|
|
7236
7238
|
xLines?.forEach((v) => axisX.add(v));
|
|
7237
7239
|
yLines?.forEach((v) => axisY.add(v));
|
|
7240
|
+
xGutters?.forEach((v) => gutterX.add(v));
|
|
7241
|
+
yGutters?.forEach((v) => gutterY.add(v));
|
|
7238
7242
|
});
|
|
7243
|
+
return {
|
|
7244
|
+
axisX,
|
|
7245
|
+
axisY,
|
|
7246
|
+
gutterX,
|
|
7247
|
+
gutterY
|
|
7248
|
+
};
|
|
7249
|
+
}
|
|
7250
|
+
function closestLine(lines, position) {
|
|
7251
|
+
let closest;
|
|
7252
|
+
let minDist = Infinity;
|
|
7253
|
+
for (const num of lines) {
|
|
7254
|
+
const absDist = Math.abs(num - position);
|
|
7255
|
+
if (absDist < minDist) {
|
|
7256
|
+
minDist = absDist;
|
|
7257
|
+
closest = num;
|
|
7258
|
+
}
|
|
7259
|
+
}
|
|
7260
|
+
return minDist < snapThreshold.value ? closest : void 0;
|
|
7261
|
+
}
|
|
7262
|
+
const snap = (box) => {
|
|
7263
|
+
const { axisX, axisY, gutterX, gutterY } = getSnapAxes();
|
|
7239
7264
|
const posList = [
|
|
7240
|
-
[
|
|
7241
|
-
|
|
7242
|
-
|
|
7243
|
-
|
|
7244
|
-
|
|
7245
|
-
[
|
|
7265
|
+
[
|
|
7266
|
+
0,
|
|
7267
|
+
"x",
|
|
7268
|
+
true
|
|
7269
|
+
],
|
|
7270
|
+
[
|
|
7271
|
+
box.width / 2,
|
|
7272
|
+
"x",
|
|
7273
|
+
false
|
|
7274
|
+
],
|
|
7275
|
+
[
|
|
7276
|
+
box.width,
|
|
7277
|
+
"x",
|
|
7278
|
+
true
|
|
7279
|
+
],
|
|
7280
|
+
[
|
|
7281
|
+
0,
|
|
7282
|
+
"y",
|
|
7283
|
+
true
|
|
7284
|
+
],
|
|
7285
|
+
[
|
|
7286
|
+
box.height / 2,
|
|
7287
|
+
"y",
|
|
7288
|
+
false
|
|
7289
|
+
],
|
|
7290
|
+
[
|
|
7291
|
+
box.height,
|
|
7292
|
+
"y",
|
|
7293
|
+
true
|
|
7294
|
+
]
|
|
7246
7295
|
];
|
|
7247
7296
|
for (let i = 0; i < posList.length; i++) {
|
|
7248
|
-
const [offset, axis] = posList[i];
|
|
7249
|
-
|
|
7250
|
-
let
|
|
7251
|
-
if (axis === "x")
|
|
7252
|
-
|
|
7253
|
-
|
|
7254
|
-
|
|
7255
|
-
|
|
7256
|
-
|
|
7297
|
+
const [offset, axis, isEdge] = posList[i];
|
|
7298
|
+
const position = (axis === "x" ? box.left : box.top) + offset;
|
|
7299
|
+
let closest = closestLine(axis === "x" ? axisX : axisY, position);
|
|
7300
|
+
if (closest === void 0 && isEdge) closest = closestLine(axis === "x" ? gutterX : gutterY, position);
|
|
7301
|
+
if (closest === void 0) continue;
|
|
7302
|
+
if (axis === "x") box.left = closest - offset;
|
|
7303
|
+
else box.top = closest - offset;
|
|
7304
|
+
}
|
|
7305
|
+
};
|
|
7306
|
+
const snapResize = (box, dir) => {
|
|
7307
|
+
if (dir.length !== 1) return;
|
|
7308
|
+
const { axisX, axisY, gutterX, gutterY } = getSnapAxes();
|
|
7309
|
+
const snapEdge = (main, gutter, pos) => {
|
|
7310
|
+
return closestLine(main, pos) ?? closestLine(gutter, pos);
|
|
7311
|
+
};
|
|
7312
|
+
const right = box.left + box.width;
|
|
7313
|
+
const bottom = box.top + box.height;
|
|
7314
|
+
if (dir === "l") {
|
|
7315
|
+
const s = snapEdge(axisX, gutterX, box.left);
|
|
7316
|
+
if (s !== void 0 && right - s >= 1) {
|
|
7317
|
+
box.left = s;
|
|
7318
|
+
box.width = right - s;
|
|
7257
7319
|
}
|
|
7258
|
-
|
|
7259
|
-
|
|
7260
|
-
|
|
7261
|
-
|
|
7262
|
-
|
|
7263
|
-
|
|
7264
|
-
|
|
7265
|
-
|
|
7266
|
-
}
|
|
7320
|
+
} else if (dir === "r") {
|
|
7321
|
+
const s = snapEdge(axisX, gutterX, right);
|
|
7322
|
+
if (s !== void 0 && s - box.left >= 1) box.width = s - box.left;
|
|
7323
|
+
} else if (dir === "t") {
|
|
7324
|
+
const s = snapEdge(axisY, gutterY, box.top);
|
|
7325
|
+
if (s !== void 0 && bottom - s >= 1) {
|
|
7326
|
+
box.top = s;
|
|
7327
|
+
box.height = bottom - s;
|
|
7267
7328
|
}
|
|
7268
|
-
|
|
7269
|
-
|
|
7270
|
-
|
|
7329
|
+
} else if (dir === "b") {
|
|
7330
|
+
const s = snapEdge(axisY, gutterY, bottom);
|
|
7331
|
+
if (s !== void 0 && s - box.top >= 1) box.height = s - box.top;
|
|
7271
7332
|
}
|
|
7272
7333
|
};
|
|
7273
7334
|
Object.assign(editor, {
|
|
7274
7335
|
snappers,
|
|
7275
7336
|
registerSnapper,
|
|
7276
7337
|
unregisterSnapper,
|
|
7277
|
-
snap
|
|
7338
|
+
snap,
|
|
7339
|
+
snapResize
|
|
7278
7340
|
});
|
|
7279
7341
|
});
|
|
7280
7342
|
//#endregion
|
|
@@ -9469,7 +9531,7 @@ var Btn_default = /* @__PURE__ */ defineComponent({
|
|
|
9469
9531
|
//#endregion
|
|
9470
9532
|
//#region src/components/Layer.vue?vue&type=script&setup=true&lang.ts
|
|
9471
9533
|
var _hoisted_1$30 = ["data-id"];
|
|
9472
|
-
var _hoisted_2$
|
|
9534
|
+
var _hoisted_2$17 = { class: "m-layer__content" };
|
|
9473
9535
|
var _hoisted_3$15 = { class: "m-layer__prepend" };
|
|
9474
9536
|
var _hoisted_4$9 = {
|
|
9475
9537
|
key: 0,
|
|
@@ -9622,7 +9684,7 @@ var Layer_default = /* @__PURE__ */ defineComponent({
|
|
|
9622
9684
|
}, [
|
|
9623
9685
|
_cache[5] || (_cache[5] = createElementVNode("span", { class: "m-layer__underlay" }, null, -1)),
|
|
9624
9686
|
_cache[6] || (_cache[6] = createElementVNode("span", { class: "m-layer__overlay" }, null, -1)),
|
|
9625
|
-
createElementVNode("div", _hoisted_2$
|
|
9687
|
+
createElementVNode("div", _hoisted_2$17, [
|
|
9626
9688
|
createElementVNode("div", _hoisted_3$15, [childrenLength.value ? (openBlock(), createBlock(unref(Icon_default), {
|
|
9627
9689
|
key: 0,
|
|
9628
9690
|
class: "m-layer__arrow",
|
|
@@ -9699,7 +9761,7 @@ var Layer_default = /* @__PURE__ */ defineComponent({
|
|
|
9699
9761
|
//#endregion
|
|
9700
9762
|
//#region src/components/Layers.vue?vue&type=script&setup=true&lang.ts
|
|
9701
9763
|
var _hoisted_1$29 = { class: "m-layers" };
|
|
9702
|
-
var _hoisted_2$
|
|
9764
|
+
var _hoisted_2$16 = { class: "m-layers__wrapper" };
|
|
9703
9765
|
//#endregion
|
|
9704
9766
|
//#region src/components/Layers.vue
|
|
9705
9767
|
var Layers_default = /* @__PURE__ */ defineComponent({
|
|
@@ -9733,7 +9795,7 @@ var Layers_default = /* @__PURE__ */ defineComponent({
|
|
|
9733
9795
|
layerScrollIntoView();
|
|
9734
9796
|
});
|
|
9735
9797
|
return (_ctx, _cache) => {
|
|
9736
|
-
return openBlock(), createElementBlock("div", _hoisted_1$29, [createElementVNode("div", _hoisted_2$
|
|
9798
|
+
return openBlock(), createElementBlock("div", _hoisted_1$29, [createElementVNode("div", _hoisted_2$16, [createVNode(Layer_default, {
|
|
9737
9799
|
root: true,
|
|
9738
9800
|
node: unref(root),
|
|
9739
9801
|
opened: true
|
|
@@ -9954,7 +10016,7 @@ var Overlay_default = /* @__PURE__ */ defineComponent({
|
|
|
9954
10016
|
//#endregion
|
|
9955
10017
|
//#region src/components/shared/Menu.vue?vue&type=script&setup=true&lang.ts
|
|
9956
10018
|
var _hoisted_1$26 = ["onMouseenter"];
|
|
9957
|
-
var _hoisted_2$
|
|
10019
|
+
var _hoisted_2$15 = ["onClick"];
|
|
9958
10020
|
var _hoisted_3$14 = {
|
|
9959
10021
|
key: 0,
|
|
9960
10022
|
class: "m-list-item__checked"
|
|
@@ -10091,7 +10153,7 @@ var Menu_default = /* @__PURE__ */ defineComponent({
|
|
|
10091
10153
|
key: 0,
|
|
10092
10154
|
icon: "$arrowRight"
|
|
10093
10155
|
})) : createCommentVNode("", true)])) : createCommentVNode("", true)
|
|
10094
|
-
], 10, _hoisted_2$
|
|
10156
|
+
], 10, _hoisted_2$15)], 40, _hoisted_1$26))], 64);
|
|
10095
10157
|
}), 128)), opened.value > -1 && __props.items?.[opened.value]?.children?.length ? (openBlock(), createBlock(_component_MceMenu, {
|
|
10096
10158
|
key: 0,
|
|
10097
10159
|
"open-on-hover": "",
|
|
@@ -10616,7 +10678,7 @@ var menu_default = definePlugin((editor, options) => {
|
|
|
10616
10678
|
//#endregion
|
|
10617
10679
|
//#region src/components/Creator.vue?vue&type=script&setup=true&lang.ts
|
|
10618
10680
|
var _hoisted_1$25 = { class: "m-creator" };
|
|
10619
|
-
var _hoisted_2$
|
|
10681
|
+
var _hoisted_2$14 = { class: "m-creator__tree" };
|
|
10620
10682
|
var _hoisted_3$13 = { class: "m-creator__actions" };
|
|
10621
10683
|
//#endregion
|
|
10622
10684
|
//#region src/components/Creator.vue
|
|
@@ -10688,7 +10750,7 @@ var Creator_default = /* @__PURE__ */ defineComponent({
|
|
|
10688
10750
|
})];
|
|
10689
10751
|
}
|
|
10690
10752
|
return (_ctx, _cache) => {
|
|
10691
|
-
return openBlock(), createElementBlock("div", _hoisted_1$25, [createElementVNode("div", _hoisted_2$
|
|
10753
|
+
return openBlock(), createElementBlock("div", _hoisted_1$25, [createElementVNode("div", _hoisted_2$14, [(openBlock(true), createElementBlock(Fragment, null, renderList(tree.value, (node, index) => {
|
|
10692
10754
|
return openBlock(), createBlock(CreatorNode, {
|
|
10693
10755
|
key: index,
|
|
10694
10756
|
node
|
|
@@ -10872,7 +10934,7 @@ var _hoisted_1$24 = {
|
|
|
10872
10934
|
key: 0,
|
|
10873
10935
|
class: "m-tooltip__arrow"
|
|
10874
10936
|
};
|
|
10875
|
-
var _hoisted_2$
|
|
10937
|
+
var _hoisted_2$13 = { class: "m-tooltip__content" };
|
|
10876
10938
|
var _hoisted_3$12 = {
|
|
10877
10939
|
key: 0,
|
|
10878
10940
|
class: "m-tooltip__kbd"
|
|
@@ -10916,7 +10978,7 @@ var Tooltip_default = /* @__PURE__ */ defineComponent({
|
|
|
10916
10978
|
target: props.target,
|
|
10917
10979
|
attach: props.attach
|
|
10918
10980
|
}, createSlots({
|
|
10919
|
-
default: withCtx(() => [isActive.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [__props.showArrow ? (openBlock(), createElementBlock("div", _hoisted_1$24)) : createCommentVNode("", true), createElementVNode("div", _hoisted_2$
|
|
10981
|
+
default: withCtx(() => [isActive.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [__props.showArrow ? (openBlock(), createElementBlock("div", _hoisted_1$24)) : createCommentVNode("", true), createElementVNode("div", _hoisted_2$13, [renderSlot(_ctx.$slots, "default"), _ctx.$slots.kbd ? (openBlock(), createElementBlock("div", _hoisted_3$12, [renderSlot(_ctx.$slots, "kbd")])) : createCommentVNode("", true)])], 64)) : createCommentVNode("", true)]),
|
|
10920
10982
|
_: 2
|
|
10921
10983
|
}, [_ctx.$slots.activator ? {
|
|
10922
10984
|
name: "activator",
|
|
@@ -10940,7 +11002,7 @@ var Tooltip_default = /* @__PURE__ */ defineComponent({
|
|
|
10940
11002
|
//#endregion
|
|
10941
11003
|
//#region src/components/shared/Ruler.vue?vue&type=script&setup=true&lang.ts
|
|
10942
11004
|
var _hoisted_1$23 = ["width", "height"];
|
|
10943
|
-
var _hoisted_2$
|
|
11005
|
+
var _hoisted_2$12 = [
|
|
10944
11006
|
"onDblclick",
|
|
10945
11007
|
"onMousedown",
|
|
10946
11008
|
"onMousemove"
|
|
@@ -11237,7 +11299,7 @@ var Ruler_default = /* @__PURE__ */ defineComponent({
|
|
|
11237
11299
|
onMousedown: ($event) => onReflineMousedown($event, index),
|
|
11238
11300
|
onMousemove: (e) => updateTip(e, item),
|
|
11239
11301
|
onMouseleave: onLeave
|
|
11240
|
-
}, null, 46, _hoisted_2$
|
|
11302
|
+
}, null, 46, _hoisted_2$12);
|
|
11241
11303
|
}), 128)),
|
|
11242
11304
|
createVNode(Tooltip_default, {
|
|
11243
11305
|
"model-value": !!tipText.value,
|
|
@@ -11635,7 +11697,7 @@ var ScrollToSelection_default = /* @__PURE__ */ defineComponent({
|
|
|
11635
11697
|
//#endregion
|
|
11636
11698
|
//#region src/components/shared/Transform.vue?vue&type=script&setup=true&lang.ts
|
|
11637
11699
|
var _hoisted_1$19 = ["rx", "ry"];
|
|
11638
|
-
var _hoisted_2$
|
|
11700
|
+
var _hoisted_2$11 = { "pointer-events": "none" };
|
|
11639
11701
|
var _hoisted_3$10 = [
|
|
11640
11702
|
"x",
|
|
11641
11703
|
"y",
|
|
@@ -12273,7 +12335,7 @@ var Transform_default = /* @__PURE__ */ defineComponent({
|
|
|
12273
12335
|
ry: model.value.borderRadius
|
|
12274
12336
|
}, null, 8, _hoisted_1$19),
|
|
12275
12337
|
createVNode(Diagonal),
|
|
12276
|
-
createElementVNode("g", _hoisted_2$
|
|
12338
|
+
createElementVNode("g", _hoisted_2$11, [(openBlock(true), createElementBlock(Fragment, null, renderList(computedHandles.value, (handle, index) => {
|
|
12277
12339
|
return openBlock(), createElementBlock(Fragment, { key: index }, [handle.shape ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [handle.shape === "rect" ? (openBlock(), createElementBlock("rect", {
|
|
12278
12340
|
key: 0,
|
|
12279
12341
|
x: handle.x,
|
|
@@ -12610,7 +12672,7 @@ var _hoisted_1$17 = {
|
|
|
12610
12672
|
class: "m-path-editor",
|
|
12611
12673
|
style: { overflow: "visible" }
|
|
12612
12674
|
};
|
|
12613
|
-
var _hoisted_2$
|
|
12675
|
+
var _hoisted_2$10 = ["d"];
|
|
12614
12676
|
var _hoisted_3$9 = [
|
|
12615
12677
|
"x1",
|
|
12616
12678
|
"y1",
|
|
@@ -13315,7 +13377,7 @@ var PathEditor_default = /* @__PURE__ */ defineComponent({
|
|
|
13315
13377
|
class: "m-path-editor__hit",
|
|
13316
13378
|
d: screenPath.value,
|
|
13317
13379
|
onDblclick: onInsert
|
|
13318
|
-
}, null, 40, _hoisted_2$
|
|
13380
|
+
}, null, 40, _hoisted_2$10),
|
|
13319
13381
|
(openBlock(true), createElementBlock(Fragment, null, renderList(controls.value, (c, i) => {
|
|
13320
13382
|
return openBlock(), createElementBlock("line", {
|
|
13321
13383
|
key: `l${i}`,
|
|
@@ -14084,6 +14146,10 @@ var _hoisted_1$15 = {
|
|
|
14084
14146
|
key: 0,
|
|
14085
14147
|
class: "m-smart-guides"
|
|
14086
14148
|
};
|
|
14149
|
+
var _hoisted_2$9 = {
|
|
14150
|
+
key: 0,
|
|
14151
|
+
class: "m-smart-guides__label"
|
|
14152
|
+
};
|
|
14087
14153
|
//#endregion
|
|
14088
14154
|
//#region src/components/SmartGuides.vue
|
|
14089
14155
|
var SmartGuides_default = /* @__PURE__ */ defineComponent({
|
|
@@ -14102,7 +14168,7 @@ var SmartGuides_default = /* @__PURE__ */ defineComponent({
|
|
|
14102
14168
|
width: `${item.style.width}px`,
|
|
14103
14169
|
height: `${item.style.height}px`
|
|
14104
14170
|
})
|
|
14105
|
-
},
|
|
14171
|
+
}, [item.label ? (openBlock(), createElementBlock("span", _hoisted_2$9, toDisplayString(item.label), 1)) : createCommentVNode("", true)], 6);
|
|
14106
14172
|
}), 128))])) : createCommentVNode("", true);
|
|
14107
14173
|
};
|
|
14108
14174
|
}
|
|
@@ -14960,7 +15026,7 @@ var BSTree = class extends BSTreeKV {};
|
|
|
14960
15026
|
//#endregion
|
|
14961
15027
|
//#region src/plugins/smartGuides.ts
|
|
14962
15028
|
var smartGuides_default = definePlugin((editor) => {
|
|
14963
|
-
const { isNode, isElement, elementSelection, selectionAabb, getAabb, root, camera, viewportAabb, registerSnapper } = editor;
|
|
15029
|
+
const { isNode, isElement, isFrameNode, elementSelection, selectionAabb, getAabb, root, camera, viewportAabb, registerSnapper } = editor;
|
|
14964
15030
|
const snapThreshold = computed(() => Math.max(1, 5 / camera.value.zoom.x));
|
|
14965
15031
|
const parent = computed(() => elementSelection.value[0]?.parent ?? root.value);
|
|
14966
15032
|
const parentBox = computed(() => createBox(parent.value));
|
|
@@ -14988,6 +15054,13 @@ var smartGuides_default = definePlugin((editor) => {
|
|
|
14988
15054
|
box.hr = createLine(left + width, "hr", box);
|
|
14989
15055
|
return box;
|
|
14990
15056
|
}
|
|
15057
|
+
function createCanvasBox() {
|
|
15058
|
+
const p = parent.value;
|
|
15059
|
+
if (!isNode(p) || !isFrameNode(p)) return void 0;
|
|
15060
|
+
const box = createBox(p);
|
|
15061
|
+
if (box) box.id = -1;
|
|
15062
|
+
return box;
|
|
15063
|
+
}
|
|
14991
15064
|
function isCanvasLine(line) {
|
|
14992
15065
|
return line.box?.id === -1;
|
|
14993
15066
|
}
|
|
@@ -15050,15 +15123,82 @@ var smartGuides_default = definePlugin((editor) => {
|
|
|
15050
15123
|
};
|
|
15051
15124
|
return areas;
|
|
15052
15125
|
}
|
|
15126
|
+
function findDistancePairs(box, boxes) {
|
|
15127
|
+
const moving = toBoundingBox(box);
|
|
15128
|
+
let bestV;
|
|
15129
|
+
let bestH;
|
|
15130
|
+
for (const nb of boxes) {
|
|
15131
|
+
if (nb.id === -1) continue;
|
|
15132
|
+
const b = toBoundingBox(nb);
|
|
15133
|
+
if (moving.overlap(b, "x")) {
|
|
15134
|
+
const below = nb.vt.pos - box.vb.pos;
|
|
15135
|
+
const above = box.vt.pos - nb.vb.pos;
|
|
15136
|
+
if (below > 0 && (!bestV || below < bestV.gap)) bestV = {
|
|
15137
|
+
gap: below,
|
|
15138
|
+
below: true,
|
|
15139
|
+
nb
|
|
15140
|
+
};
|
|
15141
|
+
if (above > 0 && (!bestV || above < bestV.gap)) bestV = {
|
|
15142
|
+
gap: above,
|
|
15143
|
+
below: false,
|
|
15144
|
+
nb
|
|
15145
|
+
};
|
|
15146
|
+
}
|
|
15147
|
+
if (moving.overlap(b, "y")) {
|
|
15148
|
+
const after = nb.hl.pos - box.hr.pos;
|
|
15149
|
+
const before = box.hl.pos - nb.hr.pos;
|
|
15150
|
+
if (after > 0 && (!bestH || after < bestH.gap)) bestH = {
|
|
15151
|
+
gap: after,
|
|
15152
|
+
after: true,
|
|
15153
|
+
nb
|
|
15154
|
+
};
|
|
15155
|
+
if (before > 0 && (!bestH || before < bestH.gap)) bestH = {
|
|
15156
|
+
gap: before,
|
|
15157
|
+
after: false,
|
|
15158
|
+
nb
|
|
15159
|
+
};
|
|
15160
|
+
}
|
|
15161
|
+
}
|
|
15162
|
+
const pairs = [];
|
|
15163
|
+
if (bestV) pairs.push({
|
|
15164
|
+
source: bestV.below ? box.vb : box.vt,
|
|
15165
|
+
target: bestV.below ? bestV.nb.vt : bestV.nb.vb,
|
|
15166
|
+
type: "distance",
|
|
15167
|
+
distance: bestV.gap
|
|
15168
|
+
});
|
|
15169
|
+
if (bestH) pairs.push({
|
|
15170
|
+
source: bestH.after ? box.hr : box.hl,
|
|
15171
|
+
target: bestH.after ? bestH.nb.hl : bestH.nb.hr,
|
|
15172
|
+
type: "distance",
|
|
15173
|
+
distance: bestH.gap
|
|
15174
|
+
});
|
|
15175
|
+
return pairs;
|
|
15176
|
+
}
|
|
15053
15177
|
const linePairs = ref([]);
|
|
15054
|
-
|
|
15178
|
+
const gutterPoints = ref({
|
|
15179
|
+
x: [],
|
|
15180
|
+
y: []
|
|
15181
|
+
});
|
|
15182
|
+
const GUTTERS = [
|
|
15183
|
+
4,
|
|
15184
|
+
8,
|
|
15185
|
+
12,
|
|
15186
|
+
16
|
|
15187
|
+
];
|
|
15188
|
+
function updateSmartGuides(handle = "move") {
|
|
15055
15189
|
const _linePairs = [];
|
|
15190
|
+
const _gutterX = [];
|
|
15191
|
+
const _gutterY = [];
|
|
15192
|
+
const resizeDir = handle.startsWith("resize") ? handle.split("-")[1] ?? "" : "";
|
|
15056
15193
|
const box = createBox(selectionAabb.value);
|
|
15057
15194
|
if (box) {
|
|
15058
15195
|
const excluded = new Set(elementSelection.value.map((el) => el.instanceId));
|
|
15059
|
-
const
|
|
15196
|
+
const boxes = parent.value.children.filter((node) => {
|
|
15060
15197
|
return !excluded.has(node.instanceId) && isElement(node) && !node.connection?.isValid() && viewportAabb.value.overlap(node.globalAabb);
|
|
15061
|
-
}).map((node) => createBox(node)).filter(Boolean)
|
|
15198
|
+
}).map((node) => createBox(node)).filter(Boolean);
|
|
15199
|
+
const canvasBox = createCanvasBox();
|
|
15200
|
+
if (canvasBox) boxes.push(canvasBox);
|
|
15201
|
+
const { vLines, hLines } = boxes.reduce((store, box) => {
|
|
15062
15202
|
[
|
|
15063
15203
|
box.vt,
|
|
15064
15204
|
box.vm,
|
|
@@ -15074,6 +15214,14 @@ var smartGuides_default = definePlugin((editor) => {
|
|
|
15074
15214
|
vLines: new BSTree((a, b) => a.pos - b.pos),
|
|
15075
15215
|
hLines: new BSTree((a, b) => a.pos - b.pos)
|
|
15076
15216
|
});
|
|
15217
|
+
hLines.inorderTraversal((line) => {
|
|
15218
|
+
if (line.type === "hm") return;
|
|
15219
|
+
for (const g of GUTTERS) _gutterX.push(line.pos + g, line.pos - g);
|
|
15220
|
+
});
|
|
15221
|
+
vLines.inorderTraversal((line) => {
|
|
15222
|
+
if (line.type === "vm") return;
|
|
15223
|
+
for (const g of GUTTERS) _gutterY.push(line.pos + g, line.pos - g);
|
|
15224
|
+
});
|
|
15077
15225
|
const areaLine = {
|
|
15078
15226
|
vt: [],
|
|
15079
15227
|
vb: [],
|
|
@@ -15081,14 +15229,14 @@ var smartGuides_default = definePlugin((editor) => {
|
|
|
15081
15229
|
hr: []
|
|
15082
15230
|
};
|
|
15083
15231
|
[{
|
|
15084
|
-
sources: [
|
|
15232
|
+
sources: resizeDir ? [resizeDir.includes("t") && box.vt, resizeDir.includes("b") && box.vb].filter(Boolean) : [
|
|
15085
15233
|
box.vt,
|
|
15086
15234
|
box.vm,
|
|
15087
15235
|
box.vb
|
|
15088
15236
|
],
|
|
15089
15237
|
targets: vLines
|
|
15090
15238
|
}, {
|
|
15091
|
-
sources: [
|
|
15239
|
+
sources: resizeDir ? [resizeDir.includes("l") && box.hl, resizeDir.includes("r") && box.hr].filter(Boolean) : [
|
|
15092
15240
|
box.hl,
|
|
15093
15241
|
box.hm,
|
|
15094
15242
|
box.hr
|
|
@@ -15124,13 +15272,13 @@ var smartGuides_default = definePlugin((editor) => {
|
|
|
15124
15272
|
});
|
|
15125
15273
|
areaLine.vt = areaLine.vt.sort((a, b) => b.pos - a.pos);
|
|
15126
15274
|
areaLine.hl = areaLine.hl.sort((a, b) => b.pos - a.pos);
|
|
15127
|
-
[{
|
|
15275
|
+
(resizeDir ? [] : [{
|
|
15128
15276
|
targets: [areaLine.vt, areaLine.vb],
|
|
15129
15277
|
sources: [box.vt, box.vb]
|
|
15130
15278
|
}, {
|
|
15131
15279
|
targets: [areaLine.hl, areaLine.hr],
|
|
15132
15280
|
sources: [box.hl, box.hr]
|
|
15133
|
-
}].forEach(({ sources, targets }) => {
|
|
15281
|
+
}]).forEach(({ sources, targets }) => {
|
|
15134
15282
|
const targetA = targets[0][0];
|
|
15135
15283
|
const sourceA = sources[0];
|
|
15136
15284
|
const targetB = targets[1][0];
|
|
@@ -15167,8 +15315,18 @@ var smartGuides_default = definePlugin((editor) => {
|
|
|
15167
15315
|
}
|
|
15168
15316
|
}
|
|
15169
15317
|
});
|
|
15318
|
+
if (!resizeDir) {
|
|
15319
|
+
const isV = (t) => t === "vt" || t === "vm" || t === "vb";
|
|
15320
|
+
const hasV = _linePairs.some((p) => isV(p.target.type));
|
|
15321
|
+
const hasH = _linePairs.some((p) => !isV(p.target.type));
|
|
15322
|
+
for (const pair of findDistancePairs(box, boxes)) if (isV(pair.target.type) ? !hasV : !hasH) _linePairs.push(pair);
|
|
15323
|
+
}
|
|
15170
15324
|
}
|
|
15171
15325
|
linePairs.value = _linePairs;
|
|
15326
|
+
gutterPoints.value = {
|
|
15327
|
+
x: _gutterX,
|
|
15328
|
+
y: _gutterY
|
|
15329
|
+
};
|
|
15172
15330
|
}
|
|
15173
15331
|
const snapLines = computed(() => {
|
|
15174
15332
|
const { zoom, position } = camera.value;
|
|
@@ -15232,8 +15390,28 @@ var smartGuides_default = definePlugin((editor) => {
|
|
|
15232
15390
|
height: scaleY(bottom - top)
|
|
15233
15391
|
};
|
|
15234
15392
|
}
|
|
15393
|
+
itemProps.label = String(Math.round(linePair.distance));
|
|
15235
15394
|
break;
|
|
15236
15395
|
}
|
|
15396
|
+
case "distance":
|
|
15397
|
+
itemProps.class = ["distance"];
|
|
15398
|
+
if (vertical) {
|
|
15399
|
+
itemProps.class.push("distance--vertical");
|
|
15400
|
+
const top = Math.min(source.pos, target.pos);
|
|
15401
|
+
itemProps.style = {
|
|
15402
|
+
left: scaleX(boxSource.hm.pos) - position.left,
|
|
15403
|
+
top: scaleY(top) - position.top,
|
|
15404
|
+
width: 1,
|
|
15405
|
+
height: scaleY(linePair.distance)
|
|
15406
|
+
};
|
|
15407
|
+
} else itemProps.style = {
|
|
15408
|
+
left: scaleX(Math.min(source.pos, target.pos)) - position.left,
|
|
15409
|
+
top: scaleY(boxSource.vm.pos) - position.top,
|
|
15410
|
+
width: scaleX(linePair.distance),
|
|
15411
|
+
height: 1
|
|
15412
|
+
};
|
|
15413
|
+
itemProps.label = String(Math.round(linePair.distance));
|
|
15414
|
+
break;
|
|
15237
15415
|
}
|
|
15238
15416
|
return itemProps;
|
|
15239
15417
|
});
|
|
@@ -15269,17 +15447,23 @@ var smartGuides_default = definePlugin((editor) => {
|
|
|
15269
15447
|
const lines = getSnapPoints();
|
|
15270
15448
|
return {
|
|
15271
15449
|
xLines: lines.x,
|
|
15272
|
-
yLines: lines.y
|
|
15450
|
+
yLines: lines.y,
|
|
15451
|
+
xGutters: gutterPoints.value.x,
|
|
15452
|
+
yGutters: gutterPoints.value.y
|
|
15273
15453
|
};
|
|
15274
15454
|
} });
|
|
15275
15455
|
return {
|
|
15276
15456
|
name: "mce:smartGuides",
|
|
15277
15457
|
events: {
|
|
15278
15458
|
selectionTransformed: ({ handle }) => {
|
|
15279
|
-
if (handle === "move") updateSmartGuides();
|
|
15459
|
+
if (handle === "move" || /^resize-[tlrb]$/.test(handle)) updateSmartGuides(handle);
|
|
15280
15460
|
},
|
|
15281
15461
|
selectionTransformEnded: () => {
|
|
15282
15462
|
linePairs.value = [];
|
|
15463
|
+
gutterPoints.value = {
|
|
15464
|
+
x: [],
|
|
15465
|
+
y: []
|
|
15466
|
+
};
|
|
15283
15467
|
}
|
|
15284
15468
|
},
|
|
15285
15469
|
components: [{
|
|
@@ -18307,7 +18491,7 @@ var toolbelt_default = definePlugin((editor) => {
|
|
|
18307
18491
|
//#endregion
|
|
18308
18492
|
//#region src/plugins/transform.ts
|
|
18309
18493
|
var transform_default = definePlugin((editor) => {
|
|
18310
|
-
const { selectionObb, selectionAabb, elementSelection, exec, inEditorIs, resizeElement, state, registerConfig, snap } = editor;
|
|
18494
|
+
const { selectionObb, selectionAabb, elementSelection, exec, inEditorIs, resizeElement, state, registerConfig, snap, snapResize } = editor;
|
|
18311
18495
|
registerConfig("interaction.transform", { default: {
|
|
18312
18496
|
handleShape: "rect",
|
|
18313
18497
|
handleStyle: "4-points",
|
|
@@ -18365,7 +18549,7 @@ var transform_default = definePlugin((editor) => {
|
|
|
18365
18549
|
return transform.value;
|
|
18366
18550
|
}
|
|
18367
18551
|
const setTransform = (type, value, options = {}) => {
|
|
18368
|
-
const { event, isCorner } = options;
|
|
18552
|
+
const { event, isCorner, direction = "" } = options;
|
|
18369
18553
|
if (!context) initContext();
|
|
18370
18554
|
const _context = context;
|
|
18371
18555
|
const oldTransform = getTransform();
|
|
@@ -18397,7 +18581,7 @@ var transform_default = definePlugin((editor) => {
|
|
|
18397
18581
|
else transform.left = ctx.startPoint.x;
|
|
18398
18582
|
}
|
|
18399
18583
|
if (!transform.rotate) snap(transform);
|
|
18400
|
-
}
|
|
18584
|
+
} else if (type === "resize" && !transform.rotate && !isMultiple) snapResize(transform, direction);
|
|
18401
18585
|
const offsetStyle = {
|
|
18402
18586
|
left: transform.left - oldTransform.left,
|
|
18403
18587
|
top: transform.top - oldTransform.top,
|
|
@@ -18624,7 +18808,8 @@ var transform_default = definePlugin((editor) => {
|
|
|
18624
18808
|
const [type, direction = ""] = handle.split("-");
|
|
18625
18809
|
setTransform(type, value, {
|
|
18626
18810
|
event,
|
|
18627
|
-
isCorner: direction.length > 1
|
|
18811
|
+
isCorner: direction.length > 1,
|
|
18812
|
+
direction
|
|
18628
18813
|
});
|
|
18629
18814
|
},
|
|
18630
18815
|
selectionTransformEnded: () => {
|
|
@@ -19421,15 +19606,18 @@ var Workflow_default = /* @__PURE__ */ defineComponent({
|
|
|
19421
19606
|
function placeholderImage(svg) {
|
|
19422
19607
|
return `data:image/svg+xml,${encodeURIComponent(svg)}`;
|
|
19423
19608
|
}
|
|
19424
|
-
var
|
|
19425
|
-
var
|
|
19609
|
+
var PLACEHOLDER_ICON_OPACITY = .4;
|
|
19610
|
+
var PLACEHOLDER_BUILDERS = {
|
|
19611
|
+
image: (bg, icon) => `<svg xmlns="http://www.w3.org/2000/svg" width="380" height="280" viewBox="0 0 380 280" fill="none"><rect width="380" height="280" rx="20" fill="${bg}"/><rect x="124" y="92" width="132" height="96" rx="12" stroke="${icon}" stroke-opacity="${PLACEHOLDER_ICON_OPACITY}" stroke-width="6" stroke-linejoin="round"/><circle cx="156" cy="124" r="12" fill="${icon}" fill-opacity="${PLACEHOLDER_ICON_OPACITY}"/><path d="M132 184l40-40 26 26 22-22 36 36" stroke="${icon}" stroke-opacity="${PLACEHOLDER_ICON_OPACITY}" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/></svg>`,
|
|
19612
|
+
video: (bg, icon) => `<svg xmlns="http://www.w3.org/2000/svg" width="380" height="280" viewBox="0 0 380 280" fill="none"><rect width="380" height="280" rx="20" fill="${bg}"/><circle cx="190" cy="140" r="48" stroke="${icon}" stroke-opacity="${PLACEHOLDER_ICON_OPACITY}" stroke-width="6"/><path d="M178 116l40 24-40 24z" fill="${icon}" fill-opacity="${PLACEHOLDER_ICON_OPACITY}"/></svg>`
|
|
19613
|
+
};
|
|
19426
19614
|
var DEFAULT_NODES = {
|
|
19427
19615
|
text: {
|
|
19428
19616
|
title: "✍️ Double-click to add text",
|
|
19429
19617
|
body: ["Or describe it below and let AI write for you."]
|
|
19430
19618
|
},
|
|
19431
|
-
image: {
|
|
19432
|
-
video: {
|
|
19619
|
+
image: {},
|
|
19620
|
+
video: {}
|
|
19433
19621
|
};
|
|
19434
19622
|
//#endregion
|
|
19435
19623
|
//#region src/plugins/index.ts
|
|
@@ -19481,6 +19669,13 @@ var plugins = [
|
|
|
19481
19669
|
...options.workflowNodes?.[type]
|
|
19482
19670
|
};
|
|
19483
19671
|
}
|
|
19672
|
+
function themeRgb(name, fallback) {
|
|
19673
|
+
const el = editor.drawboardDom.value;
|
|
19674
|
+
return `rgb(${el && getComputedStyle(el).getPropertyValue(name).trim() || fallback})`;
|
|
19675
|
+
}
|
|
19676
|
+
function buildPlaceholder(type) {
|
|
19677
|
+
return placeholderImage(PLACEHOLDER_BUILDERS[type](themeRgb("--m-theme-surface", "255, 255, 255"), themeRgb("--m-theme-on-surface", "30, 30, 30")));
|
|
19678
|
+
}
|
|
19484
19679
|
function buildContent(t) {
|
|
19485
19680
|
return [...t.title ? [{ fragments: [{
|
|
19486
19681
|
content: t.title,
|
|
@@ -19493,6 +19688,7 @@ var plugins = [
|
|
|
19493
19688
|
}
|
|
19494
19689
|
function createWorkflowNode(type) {
|
|
19495
19690
|
const t = getTemplate(type);
|
|
19691
|
+
const image = t.image ?? (type in PLACEHOLDER_BUILDERS ? buildPlaceholder(type) : void 0);
|
|
19496
19692
|
const node = {
|
|
19497
19693
|
name: t.label,
|
|
19498
19694
|
style: {
|
|
@@ -19508,7 +19704,7 @@ var plugins = [
|
|
|
19508
19704
|
inEditorIs: `Workflow${type.charAt(0).toUpperCase()}${type.slice(1)}`
|
|
19509
19705
|
}
|
|
19510
19706
|
};
|
|
19511
|
-
if (
|
|
19707
|
+
if (image) node.foreground = { image };
|
|
19512
19708
|
else {
|
|
19513
19709
|
Object.assign(node.style, {
|
|
19514
19710
|
padding: 28,
|
package/dist/mixins/snapper.d.ts
CHANGED
|
@@ -6,6 +6,9 @@ declare global {
|
|
|
6
6
|
xLines?: number[];
|
|
7
7
|
yLines?: number[];
|
|
8
8
|
points?: Vector2Like[];
|
|
9
|
+
/** 间距卡点候选位(如 4/8/12/16 间距)。仅当主吸附线(对齐/区域)未命中时作为次选。 */
|
|
10
|
+
xGutters?: number[];
|
|
11
|
+
yGutters?: number[];
|
|
9
12
|
}
|
|
10
13
|
interface Snapper {
|
|
11
14
|
getLines: () => SnapperData;
|
|
@@ -20,6 +23,13 @@ declare global {
|
|
|
20
23
|
width: number;
|
|
21
24
|
height: number;
|
|
22
25
|
}) => void;
|
|
26
|
+
/** 缩放吸附:按被拖动的边(dir 含 t/l/r/b)将该边对齐到最近的吸附线,调整对应宽高。 */
|
|
27
|
+
snapResize: (box: {
|
|
28
|
+
left: number;
|
|
29
|
+
top: number;
|
|
30
|
+
width: number;
|
|
31
|
+
height: number;
|
|
32
|
+
}, dir: string) => void;
|
|
23
33
|
}
|
|
24
34
|
}
|
|
25
35
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mce",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.23.0",
|
|
5
5
|
"description": "A headless infinite canvas editor framework built on WebGL rendering, supports exporting to image, video, and PPT. Only the ESM.",
|
|
6
6
|
"author": "wxm",
|
|
7
7
|
"license": "MIT",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"@vueuse/core": "^14.3.0",
|
|
61
61
|
"diff": "^9.0.0",
|
|
62
62
|
"lodash-es": "^4.18.1",
|
|
63
|
-
"modern-canvas": "^0.21.
|
|
63
|
+
"modern-canvas": "^0.21.3",
|
|
64
64
|
"modern-font": "^0.6.0",
|
|
65
65
|
"modern-idoc": "^0.11.8",
|
|
66
66
|
"modern-text": "^2.0.3",
|