mce 0.22.2 → 0.24.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 +55 -0
- package/dist/index.js +274 -64
- package/dist/mixins/snapper.d.ts +10 -0
- package/dist/plugins/transform.d.ts +2 -0
- package/dist/typed-global.d.ts +2 -1
- package/package.json +2 -2
package/dist/index.css
CHANGED
|
@@ -842,6 +842,61 @@
|
|
|
842
842
|
height: 1px;
|
|
843
843
|
width: 1px;
|
|
844
844
|
}
|
|
845
|
+
.m-smart-guides__dashed {
|
|
846
|
+
position: absolute;
|
|
847
|
+
background-image: repeating-linear-gradient(to right, rgba(var(--m-theme-secondary), 0.6) 0 4px, transparent 4px 7px);
|
|
848
|
+
}
|
|
849
|
+
.m-smart-guides__dashed--vertical {
|
|
850
|
+
background-image: repeating-linear-gradient(to bottom, rgba(var(--m-theme-secondary), 0.6) 0 4px, transparent 4px 7px);
|
|
851
|
+
}
|
|
852
|
+
.m-smart-guides__distance {
|
|
853
|
+
position: absolute;
|
|
854
|
+
display: flex;
|
|
855
|
+
align-items: center;
|
|
856
|
+
justify-content: center;
|
|
857
|
+
background-color: rgb(var(--m-theme-primary));
|
|
858
|
+
}
|
|
859
|
+
.m-smart-guides__distance::before, .m-smart-guides__distance::after {
|
|
860
|
+
content: "";
|
|
861
|
+
position: absolute;
|
|
862
|
+
background-color: rgb(var(--m-theme-primary));
|
|
863
|
+
}
|
|
864
|
+
.m-smart-guides__distance::before {
|
|
865
|
+
inset: 50% auto auto 0;
|
|
866
|
+
width: 1px;
|
|
867
|
+
height: 8px;
|
|
868
|
+
transform: translateY(-50%);
|
|
869
|
+
}
|
|
870
|
+
.m-smart-guides__distance::after {
|
|
871
|
+
inset: 50% 0 auto auto;
|
|
872
|
+
width: 1px;
|
|
873
|
+
height: 8px;
|
|
874
|
+
transform: translateY(-50%);
|
|
875
|
+
}
|
|
876
|
+
.m-smart-guides__distance--vertical::before {
|
|
877
|
+
inset: 0 auto auto 50%;
|
|
878
|
+
width: 8px;
|
|
879
|
+
height: 1px;
|
|
880
|
+
transform: translateX(-50%);
|
|
881
|
+
}
|
|
882
|
+
.m-smart-guides__distance--vertical::after {
|
|
883
|
+
inset: auto auto 0 50%;
|
|
884
|
+
width: 8px;
|
|
885
|
+
height: 1px;
|
|
886
|
+
transform: translateX(-50%);
|
|
887
|
+
}
|
|
888
|
+
.m-smart-guides__label {
|
|
889
|
+
position: absolute;
|
|
890
|
+
padding: 1px 5px;
|
|
891
|
+
border-radius: 8px;
|
|
892
|
+
font-size: 10px;
|
|
893
|
+
font-weight: 600;
|
|
894
|
+
line-height: 1.4;
|
|
895
|
+
white-space: nowrap;
|
|
896
|
+
color: rgb(var(--m-theme-on-primary));
|
|
897
|
+
background-color: rgb(var(--m-theme-primary));
|
|
898
|
+
pointer-events: none;
|
|
899
|
+
}
|
|
845
900
|
.m-smart-guides__area {
|
|
846
901
|
position: absolute;
|
|
847
902
|
display: flex;
|
package/dist/index.js
CHANGED
|
@@ -5767,7 +5767,7 @@ var _0_context_default = defineMixin((editor, options) => {
|
|
|
5767
5767
|
const textSelection = ref();
|
|
5768
5768
|
const hoverElement = ref();
|
|
5769
5769
|
const state = ref();
|
|
5770
|
-
const mode = ref("canvas");
|
|
5770
|
+
const mode = ref(options.mode ?? "canvas");
|
|
5771
5771
|
function setCursor(mode) {
|
|
5772
5772
|
renderEngine.value.input.setCursor(mode);
|
|
5773
5773
|
}
|
|
@@ -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,14 +15315,24 @@ 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;
|
|
15175
15333
|
const scaleX = (v) => v * zoom.x;
|
|
15176
15334
|
const scaleY = (v) => v * zoom.y;
|
|
15177
|
-
return linePairs.value.
|
|
15335
|
+
return linePairs.value.flatMap((linePair) => {
|
|
15178
15336
|
const { target, source, type } = linePair;
|
|
15179
15337
|
const boxSource = source.box;
|
|
15180
15338
|
const boxTarget = target.box;
|
|
@@ -15184,6 +15342,7 @@ var smartGuides_default = definePlugin((editor) => {
|
|
|
15184
15342
|
"vb"
|
|
15185
15343
|
].includes(target.type);
|
|
15186
15344
|
const itemProps = {};
|
|
15345
|
+
const extra = [];
|
|
15187
15346
|
switch (type) {
|
|
15188
15347
|
case "alignment":
|
|
15189
15348
|
itemProps.class = ["alignment"];
|
|
@@ -15232,10 +15391,54 @@ var smartGuides_default = definePlugin((editor) => {
|
|
|
15232
15391
|
height: scaleY(bottom - top)
|
|
15233
15392
|
};
|
|
15234
15393
|
}
|
|
15394
|
+
itemProps.label = String(Math.round(linePair.distance));
|
|
15235
15395
|
break;
|
|
15236
15396
|
}
|
|
15397
|
+
case "distance":
|
|
15398
|
+
itemProps.class = ["distance"];
|
|
15399
|
+
if (vertical) {
|
|
15400
|
+
itemProps.class.push("distance--vertical");
|
|
15401
|
+
const top = Math.min(source.pos, target.pos);
|
|
15402
|
+
itemProps.style = {
|
|
15403
|
+
left: scaleX(boxSource.hm.pos) - position.left,
|
|
15404
|
+
top: scaleY(top) - position.top,
|
|
15405
|
+
width: 1,
|
|
15406
|
+
height: scaleY(linePair.distance)
|
|
15407
|
+
};
|
|
15408
|
+
const auxLeft = Math.min(boxSource.hl.pos, boxTarget.hl.pos);
|
|
15409
|
+
const auxRight = Math.max(boxSource.hr.pos, boxTarget.hr.pos);
|
|
15410
|
+
extra.push({
|
|
15411
|
+
class: ["dashed"],
|
|
15412
|
+
style: {
|
|
15413
|
+
left: scaleX(auxLeft) - position.left,
|
|
15414
|
+
top: scaleY(target.pos) - position.top,
|
|
15415
|
+
width: scaleX(auxRight - auxLeft),
|
|
15416
|
+
height: 1
|
|
15417
|
+
}
|
|
15418
|
+
});
|
|
15419
|
+
} else {
|
|
15420
|
+
itemProps.style = {
|
|
15421
|
+
left: scaleX(Math.min(source.pos, target.pos)) - position.left,
|
|
15422
|
+
top: scaleY(boxSource.vm.pos) - position.top,
|
|
15423
|
+
width: scaleX(linePair.distance),
|
|
15424
|
+
height: 1
|
|
15425
|
+
};
|
|
15426
|
+
const auxTop = Math.min(boxSource.vt.pos, boxTarget.vt.pos);
|
|
15427
|
+
const auxBottom = Math.max(boxSource.vb.pos, boxTarget.vb.pos);
|
|
15428
|
+
extra.push({
|
|
15429
|
+
class: ["dashed", "dashed--vertical"],
|
|
15430
|
+
style: {
|
|
15431
|
+
left: scaleX(target.pos) - position.left,
|
|
15432
|
+
top: scaleY(auxTop) - position.top,
|
|
15433
|
+
width: 1,
|
|
15434
|
+
height: scaleY(auxBottom - auxTop)
|
|
15435
|
+
}
|
|
15436
|
+
});
|
|
15437
|
+
}
|
|
15438
|
+
itemProps.label = String(Math.round(linePair.distance));
|
|
15439
|
+
break;
|
|
15237
15440
|
}
|
|
15238
|
-
return itemProps;
|
|
15441
|
+
return [itemProps, ...extra];
|
|
15239
15442
|
});
|
|
15240
15443
|
});
|
|
15241
15444
|
function getSnapPoints() {
|
|
@@ -15269,17 +15472,23 @@ var smartGuides_default = definePlugin((editor) => {
|
|
|
15269
15472
|
const lines = getSnapPoints();
|
|
15270
15473
|
return {
|
|
15271
15474
|
xLines: lines.x,
|
|
15272
|
-
yLines: lines.y
|
|
15475
|
+
yLines: lines.y,
|
|
15476
|
+
xGutters: gutterPoints.value.x,
|
|
15477
|
+
yGutters: gutterPoints.value.y
|
|
15273
15478
|
};
|
|
15274
15479
|
} });
|
|
15275
15480
|
return {
|
|
15276
15481
|
name: "mce:smartGuides",
|
|
15277
15482
|
events: {
|
|
15278
15483
|
selectionTransformed: ({ handle }) => {
|
|
15279
|
-
if (handle === "move") updateSmartGuides();
|
|
15484
|
+
if (handle === "move" || /^resize-[tlrb]$/.test(handle)) updateSmartGuides(handle);
|
|
15280
15485
|
},
|
|
15281
15486
|
selectionTransformEnded: () => {
|
|
15282
15487
|
linePairs.value = [];
|
|
15488
|
+
gutterPoints.value = {
|
|
15489
|
+
x: [],
|
|
15490
|
+
y: []
|
|
15491
|
+
};
|
|
15283
15492
|
}
|
|
15284
15493
|
},
|
|
15285
15494
|
components: [{
|
|
@@ -18307,7 +18516,7 @@ var toolbelt_default = definePlugin((editor) => {
|
|
|
18307
18516
|
//#endregion
|
|
18308
18517
|
//#region src/plugins/transform.ts
|
|
18309
18518
|
var transform_default = definePlugin((editor) => {
|
|
18310
|
-
const { selectionObb, selectionAabb, elementSelection, exec, inEditorIs, resizeElement, state, registerConfig, snap } = editor;
|
|
18519
|
+
const { selectionObb, selectionAabb, elementSelection, exec, inEditorIs, resizeElement, state, registerConfig, snap, snapResize } = editor;
|
|
18311
18520
|
registerConfig("interaction.transform", { default: {
|
|
18312
18521
|
handleShape: "rect",
|
|
18313
18522
|
handleStyle: "4-points",
|
|
@@ -18365,7 +18574,7 @@ var transform_default = definePlugin((editor) => {
|
|
|
18365
18574
|
return transform.value;
|
|
18366
18575
|
}
|
|
18367
18576
|
const setTransform = (type, value, options = {}) => {
|
|
18368
|
-
const { event, isCorner } = options;
|
|
18577
|
+
const { event, isCorner, direction = "" } = options;
|
|
18369
18578
|
if (!context) initContext();
|
|
18370
18579
|
const _context = context;
|
|
18371
18580
|
const oldTransform = getTransform();
|
|
@@ -18397,7 +18606,7 @@ var transform_default = definePlugin((editor) => {
|
|
|
18397
18606
|
else transform.left = ctx.startPoint.x;
|
|
18398
18607
|
}
|
|
18399
18608
|
if (!transform.rotate) snap(transform);
|
|
18400
|
-
}
|
|
18609
|
+
} else if (type === "resize" && !transform.rotate && !isMultiple) snapResize(transform, direction);
|
|
18401
18610
|
const offsetStyle = {
|
|
18402
18611
|
left: transform.left - oldTransform.left,
|
|
18403
18612
|
top: transform.top - oldTransform.top,
|
|
@@ -18624,7 +18833,8 @@ var transform_default = definePlugin((editor) => {
|
|
|
18624
18833
|
const [type, direction = ""] = handle.split("-");
|
|
18625
18834
|
setTransform(type, value, {
|
|
18626
18835
|
event,
|
|
18627
|
-
isCorner: direction.length > 1
|
|
18836
|
+
isCorner: direction.length > 1,
|
|
18837
|
+
direction
|
|
18628
18838
|
});
|
|
18629
18839
|
},
|
|
18630
18840
|
selectionTransformEnded: () => {
|
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/dist/typed-global.d.ts
CHANGED
|
@@ -28,7 +28,8 @@ declare global {
|
|
|
28
28
|
interface Exporters {}
|
|
29
29
|
interface Config {}
|
|
30
30
|
interface Options extends DeepMaybe<Config> {
|
|
31
|
-
|
|
31
|
+
/** 编辑器初始模式,默认 'canvas'。见 {@link Mode}。 */
|
|
32
|
+
mode?: Mode
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
// Persistent editor mode, orthogonal to the transient `State`. 'canvas' is
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mce",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.24.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.
|
|
63
|
+
"modern-canvas": "^0.22.0",
|
|
64
64
|
"modern-font": "^0.6.0",
|
|
65
65
|
"modern-idoc": "^0.11.8",
|
|
66
66
|
"modern-text": "^2.0.3",
|