mce 0.13.5 → 0.13.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Node as Node$1, Element2D, Timeline, Engine, Camera2D, DrawboardEffect, IN_BROWSER, clamp, assets, TimelineNode, Transform2D, DEG_TO_RAD, render, Animation } from "modern-canvas";
2
- import { ref, computed, watch, markRaw, reactive, warn, shallowRef, onBeforeUnmount, onMounted, inject, provide, defineComponent, createVNode, mergeProps, createElementVNode, toValue, getCurrentInstance, onScopeDispose, createElementBlock, openBlock, Fragment, renderList, unref, normalizeStyle, normalizeClass, readonly, toRef, useId, onDeactivated, onActivated, useAttrs, createBlock, resolveDynamicComponent, useTemplateRef, renderSlot, Teleport, createCommentVNode, mergeModels, useModel, resolveComponent, withCtx, createTextVNode, toDisplayString, createSlots, normalizeProps, guardReactiveProps, onBeforeMount, withDirectives, vShow, vModelText, nextTick, withModifiers, h, isRef } from "vue";
3
- import { useFileDialog, useEventListener, isClient, useResizeObserver as useResizeObserver$1, useLocalStorage, onClickOutside, useMouse, useDebounceFn } from "@vueuse/core";
4
- import { getObjectValueByPath, setObjectValueByPath, Observable, Reactivable, idGenerator, property, normalizeElement, normalizeTextContent } from "modern-idoc";
2
+ import { ref, computed, watch, markRaw, reactive, warn, shallowRef, onBeforeUnmount, onMounted, inject, provide, defineComponent, createVNode, mergeProps, createElementVNode, toValue, getCurrentInstance, onScopeDispose, createElementBlock, openBlock, Fragment, renderList, unref, normalizeStyle, normalizeClass, readonly, toRef, useId, onDeactivated, onActivated, useAttrs, createBlock, resolveDynamicComponent, useTemplateRef, renderSlot, Teleport, createCommentVNode, mergeModels, useModel, resolveComponent, withCtx, createTextVNode, toDisplayString, createSlots, normalizeProps, guardReactiveProps, onBeforeMount, nextTick, h, withDirectives, vShow, vModelText, withModifiers, isRef } from "vue";
3
+ import { useFileDialog, useEventListener, isClient, useResizeObserver as useResizeObserver$1, useLocalStorage, onClickOutside, useMouse, useImage, useDebounceFn } from "@vueuse/core";
4
+ import { getObjectValueByPath, setObjectValueByPath, Observable, Reactivable, idGenerator, property, normalizeElement, normalizeTextContent, normalizeCRLF, isEqualObject } from "modern-idoc";
5
5
  import { saveAs } from "file-saver";
6
6
  import { Fonts } from "modern-font";
7
7
  import * as Y from "yjs";
@@ -2258,12 +2258,14 @@ const _3_view = defineMixin((editor) => {
2258
2258
  });
2259
2259
  const _4_0_text = defineMixin((editor) => {
2260
2260
  const {
2261
- config
2261
+ config,
2262
+ elementSelection,
2263
+ textSelection
2262
2264
  } = editor;
2263
- function textFontSizeToFit(element, scale) {
2264
- function _handle(element2) {
2265
+ function textFontSizeToFit(element2, scale) {
2266
+ function _handle(element3) {
2265
2267
  if (!scale) {
2266
- const chars = element2.text.base.characters;
2268
+ const chars = element3.text.base.characters;
2267
2269
  let pos = 0;
2268
2270
  let char;
2269
2271
  chars.forEach((_char) => {
@@ -2284,7 +2286,7 @@ const _4_0_text = defineMixin((editor) => {
2284
2286
  }).join("");
2285
2287
  const { boundingBox } = measureText({
2286
2288
  style: {
2287
- ...element2.style.toJSON(),
2289
+ ...element3.style.toJSON(),
2288
2290
  width: "auto"
2289
2291
  },
2290
2292
  content: [
@@ -2295,8 +2297,8 @@ const _4_0_text = defineMixin((editor) => {
2295
2297
  }
2296
2298
  ]
2297
2299
  });
2298
- const fontSize = (element2.style.fontSize || 12) / 2;
2299
- scale = (element2.style.width ?? 0) / (boundingBox.width + fontSize);
2300
+ const fontSize = (element3.style.fontSize || 12) / 2;
2301
+ scale = (element3.style.width ?? 0) / (boundingBox.width + fontSize);
2300
2302
  }
2301
2303
  function _scaleStyle(style) {
2302
2304
  if (style.fontSize)
@@ -2304,38 +2306,38 @@ const _4_0_text = defineMixin((editor) => {
2304
2306
  if (style.letterSpacing)
2305
2307
  style.letterSpacing = style.letterSpacing * scale;
2306
2308
  }
2307
- _scaleStyle(element2.style);
2308
- if (element2.text?.isValid?.() && Array.isArray(element2.text?.content)) {
2309
- element2.text.content.forEach((p) => {
2309
+ _scaleStyle(element3.style);
2310
+ if (element3.text?.isValid?.() && Array.isArray(element3.text?.content)) {
2311
+ element3.text.content.forEach((p) => {
2310
2312
  _scaleStyle(p);
2311
2313
  p.fragments.forEach((f) => {
2312
2314
  _scaleStyle(f);
2313
2315
  });
2314
2316
  });
2315
2317
  }
2316
- element2.requestRedraw();
2318
+ element3.requestRedraw();
2317
2319
  }
2318
- _handle(element);
2319
- element.findOne((descendant) => {
2320
+ _handle(element2);
2321
+ element2.findOne((descendant) => {
2320
2322
  if (descendant instanceof Element2D) {
2321
2323
  _handle(descendant);
2322
2324
  }
2323
2325
  return false;
2324
2326
  });
2325
2327
  }
2326
- function textToFit(element, typography) {
2328
+ function textToFit(element2, typography) {
2327
2329
  const strategy = typography ?? config.value.typographyStrategy;
2328
2330
  if (strategy === "fixedWidthHeight") {
2329
2331
  return;
2330
2332
  } else if (strategy === "autoFontSize") {
2331
- textFontSizeToFit(element);
2333
+ textFontSizeToFit(element2);
2332
2334
  return;
2333
2335
  }
2334
- function _handle(element2) {
2335
- if (!element2.text?.isValid?.() || typeof element2.text?.content !== "object") {
2336
+ function _handle(element3) {
2337
+ if (!element3.text?.isValid?.() || typeof element3.text?.content !== "object") {
2336
2338
  return;
2337
2339
  }
2338
- const style = element2.style.toJSON();
2340
+ const style = element3.style.toJSON();
2339
2341
  switch (strategy) {
2340
2342
  case "autoWidth":
2341
2343
  style.width = "auto";
@@ -2346,25 +2348,205 @@ const _4_0_text = defineMixin((editor) => {
2346
2348
  }
2347
2349
  const { boundingBox } = measureText({
2348
2350
  style,
2349
- content: element2.text.content
2351
+ content: element3.text.content
2350
2352
  });
2351
- if (element2.style.width !== boundingBox.width || element2.style.height !== boundingBox.height) {
2352
- element2.style.width = boundingBox.width;
2353
- element2.style.height = boundingBox.height;
2354
- element2.requestRedraw();
2353
+ if (element3.style.width !== boundingBox.width || element3.style.height !== boundingBox.height) {
2354
+ element3.style.width = boundingBox.width;
2355
+ element3.style.height = boundingBox.height;
2356
+ element3.requestRedraw();
2355
2357
  }
2356
2358
  }
2357
- _handle(element);
2358
- element.findOne((descendant) => {
2359
+ _handle(element2);
2360
+ element2.findOne((descendant) => {
2359
2361
  if (descendant instanceof Element2D) {
2360
2362
  _handle(descendant);
2361
2363
  }
2362
2364
  return false;
2363
2365
  });
2364
2366
  }
2367
+ const element = computed(() => elementSelection.value[0]);
2368
+ const hasSelectionRange = computed(() => {
2369
+ return (textSelection.value?.length ?? 0) > 1 && textSelection.value[0] !== textSelection.value[1];
2370
+ });
2371
+ function handleSelection([start, end], cb) {
2372
+ let flag = true;
2373
+ element.value?.text?.content.forEach((p, pIndex, pItems) => {
2374
+ if (!flag)
2375
+ return;
2376
+ p.fragments.forEach((f, fIndex, fItems) => {
2377
+ if (!flag)
2378
+ return;
2379
+ const { content, ...fStyle } = f;
2380
+ Array.from(normalizeCRLF(content)).forEach((c, cIndex, cItems) => {
2381
+ flag = cb({
2382
+ selected: (pIndex > start.paragraphIndex || pIndex === start.paragraphIndex && fIndex > start.fragmentIndex || pIndex === start.paragraphIndex && fIndex === start.fragmentIndex && cIndex >= start.charIndex) && (pIndex < end.paragraphIndex || pIndex === end.paragraphIndex && fIndex < end.fragmentIndex || pIndex === end.paragraphIndex && fIndex === end.fragmentIndex && (end.isLastSelected ? cIndex <= end.charIndex : cIndex < end.charIndex)),
2383
+ p,
2384
+ pIndex,
2385
+ pLength: pItems.length,
2386
+ f,
2387
+ fIndex,
2388
+ fStyle,
2389
+ fLength: fItems.length,
2390
+ c,
2391
+ cLength: cItems.length,
2392
+ cIndex
2393
+ });
2394
+ });
2395
+ });
2396
+ });
2397
+ }
2398
+ function getTextStyle(key) {
2399
+ if (!element.value) {
2400
+ return void 0;
2401
+ }
2402
+ let value = element.value.style[key];
2403
+ const content = element.value.text.content;
2404
+ if (hasSelectionRange.value) {
2405
+ const selection = textSelection.value;
2406
+ if (selection && selection[0] && selection[1]) {
2407
+ handleSelection(selection, ({ selected, fStyle }) => {
2408
+ if (selected && fStyle[key]) {
2409
+ value = fStyle[key];
2410
+ return false;
2411
+ }
2412
+ return true;
2413
+ });
2414
+ }
2415
+ } else {
2416
+ switch (key) {
2417
+ case "fontSize":
2418
+ return content?.reduce((prev, p) => {
2419
+ return p.fragments.reduce((prev2, f) => {
2420
+ return ~~Math.max(prev2, f[key] ?? 0);
2421
+ }, prev);
2422
+ }, value) ?? value;
2423
+ default:
2424
+ if (content.length === 1 && content[0].fragments.length === 1 && content[0].fragments[0][key]) {
2425
+ return content[0].fragments[0][key];
2426
+ }
2427
+ }
2428
+ }
2429
+ return value;
2430
+ }
2431
+ function setTextStyle(key, value) {
2432
+ if (!element.value) {
2433
+ return;
2434
+ }
2435
+ let isAllSelected = false;
2436
+ if (hasSelectionRange.value) {
2437
+ const selection = textSelection.value;
2438
+ if (selection && selection[0] && selection[1]) {
2439
+ if (selection[0].isFirst && selection[1].isLast && selection[1].isLastSelected) {
2440
+ isAllSelected = true;
2441
+ } else {
2442
+ const newContent = [];
2443
+ let newParagraph = { fragments: [] };
2444
+ let newFragment;
2445
+ handleSelection(selection, ({ selected, fIndex, fStyle, fLength, c, cIndex, cLength }) => {
2446
+ if (fIndex === 0 && cIndex === 0) {
2447
+ newParagraph = { fragments: [] };
2448
+ newFragment = void 0;
2449
+ }
2450
+ const style = { ...fStyle };
2451
+ if (selected) {
2452
+ style[key] = value;
2453
+ }
2454
+ if (newFragment) {
2455
+ const { content: _, ..._style } = newFragment;
2456
+ if (isEqualObject(style, _style)) {
2457
+ newFragment.content += c;
2458
+ } else {
2459
+ newParagraph.fragments.push(newFragment);
2460
+ newFragment = { ...style, content: c };
2461
+ }
2462
+ } else {
2463
+ newFragment = { ...style, content: c };
2464
+ }
2465
+ if (fIndex === fLength - 1 && cIndex === cLength - 1) {
2466
+ if (newFragment) {
2467
+ newParagraph.fragments.push(newFragment);
2468
+ }
2469
+ if (newParagraph.fragments.length) {
2470
+ newContent.push(newParagraph);
2471
+ newParagraph = { fragments: [] };
2472
+ }
2473
+ }
2474
+ return true;
2475
+ });
2476
+ if (newContent.length) {
2477
+ element.value.text.content = newContent;
2478
+ }
2479
+ }
2480
+ }
2481
+ } else {
2482
+ isAllSelected = true;
2483
+ }
2484
+ if (isAllSelected) {
2485
+ const el = element.value;
2486
+ switch (key) {
2487
+ case "fill":
2488
+ case "outline":
2489
+ el.text[key] = value;
2490
+ break;
2491
+ default:
2492
+ el.style[key] = value;
2493
+ break;
2494
+ }
2495
+ const content = element.value.text.content;
2496
+ content.forEach((p) => {
2497
+ delete p[key];
2498
+ p.fragments.forEach((f) => {
2499
+ delete f[key];
2500
+ });
2501
+ });
2502
+ el.text.content = content;
2503
+ }
2504
+ element.value.requestRedraw();
2505
+ textToFit(element.value);
2506
+ }
2507
+ function getTextFill() {
2508
+ if (!element.value) {
2509
+ return void 0;
2510
+ }
2511
+ let fill;
2512
+ if (hasSelectionRange.value) {
2513
+ fill = getTextStyle("fill");
2514
+ if (!fill) {
2515
+ const color = getTextStyle("color");
2516
+ fill = { color };
2517
+ }
2518
+ }
2519
+ fill = fill ?? element.value.text.fill ?? { color: element.value.style.color };
2520
+ return fill;
2521
+ }
2522
+ function setTextFill(value) {
2523
+ if (!element.value) {
2524
+ return;
2525
+ }
2526
+ if (hasSelectionRange.value && value?.color) {
2527
+ setTextStyle("fill", value);
2528
+ } else {
2529
+ element.value.text.fill = value;
2530
+ if (value?.color) {
2531
+ element.value.style.color = value.color;
2532
+ }
2533
+ element.value.text.content.forEach((p) => {
2534
+ delete p.fill;
2535
+ delete p.color;
2536
+ p.fragments.forEach((f) => {
2537
+ delete f.fill;
2538
+ delete f.color;
2539
+ });
2540
+ });
2541
+ }
2542
+ }
2365
2543
  Object.assign(editor, {
2366
2544
  textFontSizeToFit,
2367
- textToFit
2545
+ textToFit,
2546
+ setTextStyle,
2547
+ getTextStyle,
2548
+ getTextFill,
2549
+ setTextFill
2368
2550
  });
2369
2551
  return () => {
2370
2552
  TextEditor.register();
@@ -5896,6 +6078,7 @@ const plugins = [
5896
6078
  class Editor extends Observable {
5897
6079
  static injectionKey = Symbol.for("EditorKey");
5898
6080
  debug = ref(false);
6081
+ showMadeWith = ref(false);
5899
6082
  onEmit;
5900
6083
  plugins = /* @__PURE__ */ new Map();
5901
6084
  _setups = [];
@@ -5922,10 +6105,12 @@ class Editor extends Observable {
5922
6105
  _setupOptions(options) {
5923
6106
  const {
5924
6107
  debug = false,
6108
+ showMadeWith = false,
5925
6109
  plugins: plugins$1 = [],
5926
6110
  configCacheInLocal
5927
6111
  } = options;
5928
6112
  this.debug.value = debug;
6113
+ this.showMadeWith.value = showMadeWith;
5929
6114
  this.config = configCacheInLocal ? useLocalStorage("config", () => ({})) : ref({});
5930
6115
  this._setups = [];
5931
6116
  this._useMixins(
@@ -6268,13 +6453,13 @@ const defaultHoverStrategy = (context) => {
6268
6453
  }
6269
6454
  return element.findAncestor(cb);
6270
6455
  };
6271
- const _hoisted_1$l = { class: "mce-auxiliary" };
6272
- const _sfc_main$A = /* @__PURE__ */ defineComponent({
6456
+ const _hoisted_1$n = { class: "mce-auxiliary" };
6457
+ const _sfc_main$D = /* @__PURE__ */ defineComponent({
6273
6458
  __name: "Auxiliary",
6274
6459
  setup(__props) {
6275
6460
  const { auxiliaryLines } = useEditor();
6276
6461
  return (_ctx, _cache) => {
6277
- return openBlock(), createElementBlock("div", _hoisted_1$l, [
6462
+ return openBlock(), createElementBlock("div", _hoisted_1$n, [
6278
6463
  (openBlock(true), createElementBlock(Fragment, null, renderList(unref(auxiliaryLines), (item, key) => {
6279
6464
  return openBlock(), createElementBlock("div", {
6280
6465
  key,
@@ -6628,7 +6813,7 @@ function createLayout(props) {
6628
6813
  };
6629
6814
  }
6630
6815
  const MceMenuSymbol = Symbol.for("MceMenuSymbol");
6631
- const _sfc_main$z = /* @__PURE__ */ defineComponent({
6816
+ const _sfc_main$C = /* @__PURE__ */ defineComponent({
6632
6817
  __name: "Icon",
6633
6818
  props: {
6634
6819
  disabled: Boolean,
@@ -6653,7 +6838,7 @@ const _sfc_main$z = /* @__PURE__ */ defineComponent({
6653
6838
  };
6654
6839
  }
6655
6840
  });
6656
- const _sfc_main$y = /* @__PURE__ */ defineComponent({
6841
+ const _sfc_main$B = /* @__PURE__ */ defineComponent({
6657
6842
  ...{
6658
6843
  inheritAttrs: false
6659
6844
  },
@@ -6766,7 +6951,7 @@ const _sfc_main$y = /* @__PURE__ */ defineComponent({
6766
6951
  };
6767
6952
  }
6768
6953
  });
6769
- const _hoisted_1$k = ["onMouseenter"];
6954
+ const _hoisted_1$m = ["onMouseenter"];
6770
6955
  const _hoisted_2$a = ["onClick"];
6771
6956
  const _hoisted_3$7 = {
6772
6957
  key: 0,
@@ -6777,7 +6962,7 @@ const _hoisted_5$3 = {
6777
6962
  key: 1,
6778
6963
  class: "mce-list-item__append"
6779
6964
  };
6780
- const _sfc_main$x = /* @__PURE__ */ defineComponent({
6965
+ const _sfc_main$A = /* @__PURE__ */ defineComponent({
6781
6966
  ...{
6782
6967
  name: "MceMenu"
6783
6968
  },
@@ -6856,7 +7041,7 @@ const _sfc_main$x = /* @__PURE__ */ defineComponent({
6856
7041
  });
6857
7042
  return (_ctx, _cache) => {
6858
7043
  const _component_MceMenu = resolveComponent("MceMenu");
6859
- return openBlock(), createBlock(_sfc_main$y, {
7044
+ return openBlock(), createBlock(_sfc_main$B, {
6860
7045
  ref: "overlayTpl",
6861
7046
  modelValue: isActive.value,
6862
7047
  "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => isActive.value = $event),
@@ -6900,7 +7085,7 @@ const _sfc_main$x = /* @__PURE__ */ defineComponent({
6900
7085
  onClick: (e) => onClickItem(item, index, e)
6901
7086
  }, [
6902
7087
  hasPrepend.value ? (openBlock(), createElementBlock("div", _hoisted_3$7, [
6903
- item.checked ? (openBlock(), createBlock(_sfc_main$z, {
7088
+ item.checked ? (openBlock(), createBlock(_sfc_main$C, {
6904
7089
  key: 0,
6905
7090
  icon: "$check"
6906
7091
  })) : createCommentVNode("", true)
@@ -6911,10 +7096,10 @@ const _sfc_main$x = /* @__PURE__ */ defineComponent({
6911
7096
  ])
6912
7097
  ]),
6913
7098
  item.children?.length ? (openBlock(), createElementBlock("div", _hoisted_5$3, [
6914
- createVNode(_sfc_main$z, { icon: "$arrowRight" })
7099
+ createVNode(_sfc_main$C, { icon: "$arrowRight" })
6915
7100
  ])) : createCommentVNode("", true)
6916
7101
  ], 10, _hoisted_2$a)
6917
- ], 40, _hoisted_1$k))
7102
+ ], 40, _hoisted_1$m))
6918
7103
  ], 64);
6919
7104
  }), 128)),
6920
7105
  opened.value > -1 && __props.items?.[opened.value]?.children?.length ? (openBlock(), createBlock(_component_MceMenu, {
@@ -6944,12 +7129,12 @@ const _sfc_main$x = /* @__PURE__ */ defineComponent({
6944
7129
  };
6945
7130
  }
6946
7131
  });
6947
- const _hoisted_1$j = { class: "mce-context-menu__title" };
7132
+ const _hoisted_1$l = { class: "mce-context-menu__title" };
6948
7133
  const _hoisted_2$9 = {
6949
7134
  key: 0,
6950
7135
  class: "mce-context-menu__kbd"
6951
7136
  };
6952
- const _sfc_main$w = /* @__PURE__ */ defineComponent({
7137
+ const _sfc_main$z = /* @__PURE__ */ defineComponent({
6953
7138
  __name: "ContextMenu",
6954
7139
  props: {
6955
7140
  "modelValue": { type: Boolean },
@@ -7007,7 +7192,7 @@ const _sfc_main$w = /* @__PURE__ */ defineComponent({
7007
7192
  updateLocation
7008
7193
  });
7009
7194
  return (_ctx, _cache) => {
7010
- return openBlock(), createBlock(_sfc_main$x, {
7195
+ return openBlock(), createBlock(_sfc_main$A, {
7011
7196
  ref: "menuTplRef",
7012
7197
  modelValue: model.value,
7013
7198
  "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => model.value = $event),
@@ -7022,7 +7207,7 @@ const _sfc_main$w = /* @__PURE__ */ defineComponent({
7022
7207
  "onClick:item": onClickItem
7023
7208
  }, {
7024
7209
  title: withCtx(({ item }) => [
7025
- createElementVNode("span", _hoisted_1$j, toDisplayString(unref(t)(item.key)), 1),
7210
+ createElementVNode("span", _hoisted_1$l, toDisplayString(unref(t)(item.key)), 1),
7026
7211
  unref(hotkeys).has(item.key) ? (openBlock(), createElementBlock("span", _hoisted_2$9, toDisplayString(unref(getKbd)(item.key)), 1)) : createCommentVNode("", true)
7027
7212
  ]),
7028
7213
  _: 1
@@ -7030,11 +7215,11 @@ const _sfc_main$w = /* @__PURE__ */ defineComponent({
7030
7215
  };
7031
7216
  }
7032
7217
  });
7033
- const _hoisted_1$i = {
7218
+ const _hoisted_1$k = {
7034
7219
  key: 0,
7035
7220
  class: "mce-drawing__content"
7036
7221
  };
7037
- const _sfc_main$v = /* @__PURE__ */ defineComponent({
7222
+ const _sfc_main$y = /* @__PURE__ */ defineComponent({
7038
7223
  __name: "Drawing",
7039
7224
  setup(__props) {
7040
7225
  const {
@@ -7064,16 +7249,15 @@ const _sfc_main$v = /* @__PURE__ */ defineComponent({
7064
7249
  }),
7065
7250
  onMousedown
7066
7251
  }, [
7067
- unref(stateContext)?.content ? (openBlock(), createElementBlock("div", _hoisted_1$i, toDisplayString(unref(t)(unref(stateContext).content)), 1)) : createCommentVNode("", true)
7252
+ unref(stateContext)?.content ? (openBlock(), createElementBlock("div", _hoisted_1$k, toDisplayString(unref(t)(unref(stateContext).content)), 1)) : createCommentVNode("", true)
7068
7253
  ], 36)) : createCommentVNode("", true);
7069
7254
  };
7070
7255
  }
7071
7256
  });
7072
- const _sfc_main$u = /* @__PURE__ */ defineComponent({
7257
+ const _sfc_main$x = /* @__PURE__ */ defineComponent({
7073
7258
  __name: "Floatbar",
7074
7259
  props: {
7075
7260
  ...makeMceOverlayProps({
7076
- location: "top-start",
7077
7261
  middlewares: ["offset", "shift"],
7078
7262
  offset: 8
7079
7263
  })
@@ -7096,7 +7280,7 @@ const _sfc_main$u = /* @__PURE__ */ defineComponent({
7096
7280
  updateLocation
7097
7281
  });
7098
7282
  return (_ctx, _cache) => {
7099
- return openBlock(), createBlock(_sfc_main$y, {
7283
+ return openBlock(), createBlock(_sfc_main$B, {
7100
7284
  ref: "overlayTpl",
7101
7285
  class: "mce-floatbar",
7102
7286
  location: props.location,
@@ -7114,1600 +7298,1815 @@ const _sfc_main$u = /* @__PURE__ */ defineComponent({
7114
7298
  };
7115
7299
  }
7116
7300
  });
7117
- const _sfc_main$t = /* @__PURE__ */ defineComponent({
7118
- __name: "Frame",
7301
+ const _hoisted_1$j = { class: "mce-transformable__svg" };
7302
+ const _hoisted_2$8 = ["rx", "ry"];
7303
+ const _hoisted_3$6 = ["x", "y", "width", "height", "aria-label"];
7304
+ const _hoisted_4$3 = ["cx", "cy", "r", "aria-label"];
7305
+ const _hoisted_5$2 = { "pointer-events": "all" };
7306
+ const _hoisted_6$2 = ["x", "y", "width", "height", "aria-label", "cursor", "onPointerdown"];
7307
+ const _hoisted_7$2 = {
7308
+ "pointer-events": "all",
7309
+ class: "mce-transformable__svg-slot"
7310
+ };
7311
+ const _hoisted_8$1 = {
7312
+ key: 0,
7313
+ class: "mce-transformable__tip"
7314
+ };
7315
+ const _sfc_main$w = /* @__PURE__ */ defineComponent({
7316
+ __name: "Transformable",
7119
7317
  props: {
7120
- "modelValue": { required: true },
7121
- "modelModifiers": {}
7318
+ tag: { default: "div" },
7319
+ modelValue: {},
7320
+ movable: { type: Boolean, default: true },
7321
+ rotatable: { type: Boolean, default: true },
7322
+ resizable: { type: Boolean, default: true },
7323
+ adjustableBorderRadius: { type: Boolean, default: false },
7324
+ threshold: { default: 0 },
7325
+ resizeStrategy: {},
7326
+ handleStrategy: {},
7327
+ handleShape: { default: "rect" },
7328
+ hideUi: { type: Boolean },
7329
+ handles: { default: () => [
7330
+ "move",
7331
+ // resize
7332
+ "resize-left",
7333
+ "resize-top",
7334
+ "resize-right",
7335
+ "resize-bottom",
7336
+ "resize-top-left",
7337
+ "resize-top-right",
7338
+ "resize-bottom-right",
7339
+ "resize-bottom-left",
7340
+ // border-radius
7341
+ "border-radius-top-left",
7342
+ "border-radius-top-right",
7343
+ "border-radius-bottom-left",
7344
+ "border-radius-bottom-right",
7345
+ // rotate
7346
+ "rotate-top-left",
7347
+ "rotate-top-right",
7348
+ "rotate-bottom-left",
7349
+ "rotate-bottom-right"
7350
+ ] },
7351
+ initialSize: { type: Boolean },
7352
+ borderStyle: {},
7353
+ tipFormat: {}
7122
7354
  },
7123
- emits: ["update:modelValue"],
7124
- setup(__props) {
7125
- const frame = useModel(__props, "modelValue");
7126
- const input = useTemplateRef("inputTpl");
7127
- const {
7128
- getObbInDrawboard,
7129
- hoverElement,
7130
- selection,
7131
- state,
7132
- config,
7133
- exec
7134
- } = useEditor();
7135
- const editing = ref(false);
7136
- async function onDblclick() {
7137
- editing.value = true;
7138
- await nextTick();
7139
- if (input.value) {
7140
- input.value.focus();
7141
- input.value.select();
7142
- }
7143
- }
7144
- async function onPointerdown(ev) {
7145
- if (!editing.value) {
7146
- selection.value = [frame.value];
7147
- await nextTick();
7148
- exec("startTransform", ev);
7149
- }
7150
- }
7151
- return (_ctx, _cache) => {
7152
- return withDirectives((openBlock(), createElementBlock("div", {
7153
- style: normalizeStyle(unref(boundingBoxToStyle)(unref(getObbInDrawboard)(frame.value))),
7154
- class: normalizeClass(["mce-frame", [
7155
- unref(config).frameOutline && "mce-frame--outline"
7156
- ]])
7157
- }, [
7158
- withDirectives(createElementVNode("div", {
7159
- class: "mce-frame__name",
7160
- onDblclick,
7161
- onPointerdown,
7162
- onPointerenter: _cache[2] || (_cache[2] = ($event) => !unref(state) && (hoverElement.value = frame.value)),
7163
- onPointerleave: _cache[3] || (_cache[3] = ($event) => !unref(state) && (hoverElement.value = void 0))
7164
- }, [
7165
- createElementVNode("div", null, toDisplayString(frame.value.name), 1),
7166
- withDirectives(createElementVNode("input", {
7167
- ref: "inputTpl",
7168
- "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => frame.value.name = $event),
7169
- onBlur: _cache[1] || (_cache[1] = ($event) => editing.value = false)
7170
- }, null, 544), [
7171
- [vShow, editing.value],
7172
- [vModelText, frame.value.name]
7173
- ])
7174
- ], 544), [
7175
- [vShow, unref(config).viewMode === "edgeless"]
7176
- ])
7177
- ], 6)), [
7178
- [vShow, frame.value.visible]
7179
- ]);
7180
- };
7181
- }
7182
- });
7183
- const _sfc_main$s = /* @__PURE__ */ defineComponent({
7184
- __name: "Frames",
7185
- setup(__props) {
7186
- const {
7187
- frames
7188
- } = useEditor();
7189
- return (_ctx, _cache) => {
7190
- return openBlock(true), createElementBlock(Fragment, null, renderList(unref(frames), (frame, key) => {
7191
- return openBlock(), createBlock(_sfc_main$t, {
7192
- key,
7193
- "model-value": frame
7194
- }, null, 8, ["model-value"]);
7195
- }), 128);
7355
+ emits: ["update:modelValue", "start", "move", "end"],
7356
+ setup(__props, { expose: __expose, emit: __emit }) {
7357
+ const props = __props;
7358
+ const emit = __emit;
7359
+ const cursors = {
7360
+ "rotate-top-left": (angle) => createCursor("rotate", 360 + angle),
7361
+ "rotate-top-right": (angle) => createCursor("rotate", 90 + angle),
7362
+ "rotate-bottom-left": (angle) => createCursor("rotate", 270 + angle),
7363
+ "rotate-bottom-right": (angle) => createCursor("rotate", 180 + angle),
7364
+ "resize-left": (angle) => createCursor("resizeXy", 180 + angle),
7365
+ "resize-top": (angle) => createCursor("resizeXy", 90 + angle),
7366
+ "resize-right": (angle) => createCursor("resizeXy", 180 + angle),
7367
+ "resize-bottom": (angle) => createCursor("resizeXy", 90 + angle),
7368
+ "resize-top-left": (angle) => createCursor("resizeBevel", 90 + angle),
7369
+ "resize-top-right": (angle) => createCursor("resizeBevel", 180 + angle),
7370
+ "resize-bottom-right": (angle) => createCursor("resizeBevel", 90 + angle),
7371
+ "resize-bottom-left": (angle) => createCursor("resizeBevel", 180 + angle)
7196
7372
  };
7197
- }
7198
- });
7199
- const _sfc_main$r = /* @__PURE__ */ defineComponent({
7200
- __name: "GoBackSelectedArea",
7201
- setup(__props) {
7202
- const {
7203
- selectionAabb,
7204
- drawboardAabb,
7205
- aabbToDrawboardAabb,
7206
- t,
7207
- exec
7208
- } = useEditor();
7209
- const isActive = computed(() => {
7210
- return selectionAabb.value.width && selectionAabb.value.height && !isOverlappingAabb(
7211
- drawboardAabb.value,
7212
- aabbToDrawboardAabb(selectionAabb.value)
7213
- );
7373
+ const modelValue = useModel(props, "modelValue");
7374
+ const model = computed({
7375
+ get: () => {
7376
+ let { left = 0, top = 0, width = 0, height = 0, rotate = 0, borderRadius = 0 } = modelValue.value ?? {};
7377
+ if (Number.isNaN(Number(width)))
7378
+ width = 0;
7379
+ if (Number.isNaN(Number(height)))
7380
+ height = 0;
7381
+ return { left, top, width, height, rotate, borderRadius };
7382
+ },
7383
+ set: (val) => modelValue.value = val
7214
7384
  });
7215
- return (_ctx, _cache) => {
7216
- return isActive.value ? (openBlock(), createElementBlock("div", {
7217
- key: 0,
7218
- class: "mce-back-selected-aera",
7219
- onClick: _cache[0] || (_cache[0] = withModifiers(($event) => unref(exec)("scrollToSelection", { behavior: "smooth" }), ["prevent"]))
7220
- }, [
7221
- createVNode(_sfc_main$z, { icon: "$gps" }),
7222
- createElementVNode("span", null, toDisplayString(unref(t)("goBackSelectedArea")), 1)
7223
- ])) : createCommentVNode("", true);
7224
- };
7385
+ const transforming = ref(false);
7386
+ const activeHandle = ref();
7387
+ const computedHandles = computed(() => {
7388
+ const size = 8;
7389
+ const { width = 0, height = 0, borderRadius } = model.value;
7390
+ const center = { x: width / 2, y: height / 2 };
7391
+ const shape = props.handleShape;
7392
+ const lines = [
7393
+ { type: "top", points: [[0, 0], [1, 0]] },
7394
+ { type: "right", points: [[1, 0], [1, 1]] },
7395
+ { type: "bottom", points: [[0, 1], [1, 1]] },
7396
+ { type: "left", points: [[0, 0], [0, 1]] }
7397
+ ];
7398
+ const points = [
7399
+ { type: "top", point: [0.5, 0] },
7400
+ { type: "right", point: [1, 0.5] },
7401
+ { type: "bottom", point: [0.5, 1] },
7402
+ { type: "left", point: [0, 0.5] },
7403
+ { type: "top-left", point: [0, 0] },
7404
+ { type: "top-right", point: [1, 0] },
7405
+ { type: "bottom-left", point: [0, 1] },
7406
+ { type: "bottom-right", point: [1, 1] }
7407
+ ];
7408
+ const lineHandles = lines.map((item) => {
7409
+ const [p1, p2] = item.points;
7410
+ const minX = Math.min(p1[0], p2[0]) * width;
7411
+ const maxX = Math.max(p1[0], p2[0]) * width;
7412
+ const minY = Math.min(p1[1], p2[1]) * height;
7413
+ const maxY = Math.max(p1[1], p2[1]) * height;
7414
+ return {
7415
+ type: item.type,
7416
+ x: minX - size / 2,
7417
+ y: minY - size / 2,
7418
+ width: maxX - minX + size,
7419
+ height: maxY - minY + size
7420
+ };
7421
+ });
7422
+ const pointHandles = points.map((item) => {
7423
+ return {
7424
+ type: item.type,
7425
+ shape,
7426
+ x: item.point[0] * width - size / 2,
7427
+ y: item.point[1] * height - size / 2,
7428
+ width: size,
7429
+ height: size
7430
+ };
7431
+ });
7432
+ const diagonalPointHandles = pointHandles.filter((item) => item.type.split("-").length === 2);
7433
+ const rotateHandles = diagonalPointHandles.map((item) => {
7434
+ const sign = {
7435
+ x: center.x - item.x > 0 ? 1 : -1,
7436
+ y: center.y - item.y > 0 ? 1 : -1
7437
+ };
7438
+ return {
7439
+ ...item,
7440
+ shape: void 0,
7441
+ type: `rotate-${item.type}`,
7442
+ x: item.x - sign.x * size,
7443
+ y: item.y - sign.y * size
7444
+ };
7445
+ });
7446
+ const minSize = Math.min(width, height);
7447
+ const borderRadiusHandles = props.adjustableBorderRadius ? diagonalPointHandles.map((item) => {
7448
+ const sign = {
7449
+ x: center.x - item.x > 0 ? 1 : -1,
7450
+ y: center.y - item.y > 0 ? 1 : -1
7451
+ };
7452
+ const offset2 = minSize * 0.1;
7453
+ return {
7454
+ ...item,
7455
+ shape: "circle",
7456
+ type: `border-radius-${item.type}`,
7457
+ x: item.x + sign.x * Math.min(width / 2, offset2 + borderRadius),
7458
+ y: item.y + sign.y * Math.min(height / 2, offset2 + borderRadius)
7459
+ };
7460
+ }) : [];
7461
+ let handles;
7462
+ if (props.handleStrategy === "point") {
7463
+ handles = [
7464
+ // move
7465
+ ...lineHandles.map((item) => ({ ...item, type: "move" })),
7466
+ // resize
7467
+ ...pointHandles.map((item) => ({ ...item, type: `resize-${item.type}` })),
7468
+ // border-radius
7469
+ ...borderRadiusHandles,
7470
+ // rotate
7471
+ ...rotateHandles
7472
+ ];
7473
+ } else {
7474
+ handles = [
7475
+ // resize
7476
+ ...lineHandles.map((item) => ({ ...item, type: `resize-${item.type}` })),
7477
+ ...diagonalPointHandles.map((item) => ({ ...item, type: `resize-${item.type}` })),
7478
+ // border-radius
7479
+ ...borderRadiusHandles,
7480
+ // rotate
7481
+ ...rotateHandles
7482
+ ];
7483
+ }
7484
+ return handles.filter((handle) => {
7485
+ if (props.handles.includes(handle.type)) {
7486
+ return !(!props.resizable && handle.type.startsWith("resize") || !props.rotatable && handle.type.startsWith("rotate") || !props.movable && handle.type === "move");
7487
+ }
7488
+ return false;
7489
+ }).map((anchor) => {
7490
+ anchor.width = Math.max(anchor.width, 0);
7491
+ anchor.height = Math.max(anchor.height, 0);
7492
+ return anchor;
7493
+ });
7494
+ });
7495
+ const handlesRef = ref();
7496
+ const sizeStyle = computed(() => {
7497
+ const { width = 0, height = 0 } = model.value;
7498
+ return {
7499
+ width: props.initialSize && !width ? void 0 : `${width}px`,
7500
+ height: props.initialSize && !height ? void 0 : `${height}px`
7501
+ };
7502
+ });
7503
+ const style = computed(() => {
7504
+ const { left = 0, top = 0, rotate = 0 } = model.value;
7505
+ const radian = rotate * Math.PI / 180;
7506
+ const cos = Math.cos(radian);
7507
+ const sin = Math.sin(radian);
7508
+ return {
7509
+ ...sizeStyle.value,
7510
+ transform: `matrix(${cos}, ${sin}, ${-sin}, ${cos}, ${left}, ${top})`
7511
+ };
7512
+ });
7513
+ const tip = computed(() => props.tipFormat?.("size"));
7514
+ function start(event, index) {
7515
+ if (event && event.button !== void 0 && event.button !== 0) {
7516
+ return false;
7517
+ }
7518
+ event?.preventDefault();
7519
+ event?.stopPropagation();
7520
+ const { left, top, width, height, rotate, borderRadius } = model.value;
7521
+ let aspectRatio = 0;
7522
+ if (width && height) {
7523
+ aspectRatio = width / height;
7524
+ }
7525
+ const handle = index === void 0 ? { type: "move", x: 0, y: 0, width: 0, height: 0 } : computedHandles.value[index];
7526
+ activeHandle.value = handle.type;
7527
+ const isMove = handle.type === "move";
7528
+ const isRotate = handle.type.startsWith("rotate");
7529
+ const isBorderRadius = handle.type.startsWith("border-radius");
7530
+ const isHorizontal = handle.type === "resize-left" || handle.type === "resize-right";
7531
+ const isHorizontalVertical = handle.type.split("-").length === 2;
7532
+ const centerPoint = {
7533
+ x: left + width / 2,
7534
+ y: top + height / 2
7535
+ };
7536
+ const startPoint = {
7537
+ x: left,
7538
+ y: top
7539
+ };
7540
+ if (!isMove) {
7541
+ startPoint.x += handle.x + handle.width / 2;
7542
+ startPoint.y += handle.y + handle.height / 2;
7543
+ }
7544
+ const sign = {
7545
+ x: startPoint.x - centerPoint.x > 0 ? 1 : -1,
7546
+ y: startPoint.y - centerPoint.y > 0 ? 1 : -1
7547
+ };
7548
+ const rotatedStartPoint = rotatePoint(startPoint, centerPoint, rotate);
7549
+ const rotatedSymmetricPoint = {
7550
+ x: centerPoint.x * 2 - rotatedStartPoint.x,
7551
+ y: centerPoint.y * 2 - rotatedStartPoint.y
7552
+ };
7553
+ const startAngle = Math.atan2(
7554
+ rotatedStartPoint.y - centerPoint.y,
7555
+ rotatedStartPoint.x - centerPoint.x
7556
+ ) / (Math.PI / 180);
7557
+ let startClientPoint = event ? { x: event.clientX, y: event.clientY } : void 0;
7558
+ function startTransform() {
7559
+ transforming.value = true;
7560
+ emit("start", model.value);
7561
+ }
7562
+ if (!props.threshold && !transforming.value) {
7563
+ startTransform();
7564
+ }
7565
+ function onMove(event2) {
7566
+ const updated = {};
7567
+ if (!startClientPoint) {
7568
+ startClientPoint = { x: event2.clientX, y: event2.clientY };
7569
+ }
7570
+ const rotatedOffset = {
7571
+ x: event2.clientX - startClientPoint.x,
7572
+ y: event2.clientY - startClientPoint.y
7573
+ };
7574
+ if (!transforming.value) {
7575
+ if (Math.abs(rotatedOffset.x) < props.threshold && Math.abs(rotatedOffset.y) < props.threshold) {
7576
+ return;
7577
+ }
7578
+ startTransform();
7579
+ }
7580
+ const rotatedCurrentPoint = {
7581
+ x: rotatedStartPoint.x + rotatedOffset.x,
7582
+ y: rotatedStartPoint.y + rotatedOffset.y
7583
+ };
7584
+ if (isMove) {
7585
+ if (props.movable) {
7586
+ updated.left = startPoint.x + rotatedOffset.x;
7587
+ updated.top = startPoint.y + rotatedOffset.y;
7588
+ }
7589
+ } else if (isRotate) {
7590
+ if (props.rotatable) {
7591
+ const endAngle = Math.atan2(
7592
+ rotatedCurrentPoint.y - centerPoint.y,
7593
+ rotatedCurrentPoint.x - centerPoint.x
7594
+ ) / (Math.PI / 180);
7595
+ updated.rotate = (rotate + endAngle - startAngle + 360) % 360;
7596
+ }
7597
+ } else if (isBorderRadius) {
7598
+ const offset2 = rotatePoint(rotatedOffset, { x: 0, y: 0 }, -rotate);
7599
+ const _offset = Math.abs(offset2.x) < Math.abs(offset2.y) ? -sign.x * offset2.x : -sign.y * offset2.y * aspectRatio;
7600
+ updated.borderRadius = Math.min(
7601
+ Math.max(0, borderRadius + _offset),
7602
+ Math.min(width / 2, height / 2)
7603
+ );
7604
+ } else if (isHorizontalVertical) {
7605
+ const currentPoint = rotatePoint(rotatedCurrentPoint, centerPoint, -rotate);
7606
+ const newCurrentPoint = isHorizontal ? { x: currentPoint.x, y: startPoint.y } : { x: startPoint.x, y: currentPoint.y };
7607
+ const newRotatedCurrentPoint = rotatePoint(newCurrentPoint, centerPoint, rotate);
7608
+ const distance = Math.abs(getDistance(newRotatedCurrentPoint, rotatedSymmetricPoint));
7609
+ if (isHorizontal) {
7610
+ updated.width = distance;
7611
+ if (props.resizeStrategy === "lockAspectRatio" && aspectRatio) {
7612
+ updated.height = distance / aspectRatio;
7613
+ } else {
7614
+ updated.height = height;
7615
+ }
7616
+ } else {
7617
+ updated.height = distance;
7618
+ if (props.resizeStrategy === "lockAspectRatio" && aspectRatio) {
7619
+ updated.width = distance * aspectRatio;
7620
+ } else {
7621
+ updated.width = width;
7622
+ }
7623
+ }
7624
+ const newCenterPoint = getMidpoint(newRotatedCurrentPoint, rotatedSymmetricPoint);
7625
+ updated.left = newCenterPoint.x - updated.width / 2;
7626
+ updated.top = newCenterPoint.y - updated.height / 2;
7627
+ } else {
7628
+ let newRotatedCurrentPoint;
7629
+ if ((props.resizeStrategy === "lockAspectRatio" || props.resizeStrategy === "lockAspectRatioDiagonal") && aspectRatio) {
7630
+ const offset2 = rotatePoint(rotatedOffset, { x: 0, y: 0 }, -rotate);
7631
+ const _offset = Math.abs(offset2.x) < Math.abs(offset2.y) ? sign.x * offset2.x : sign.y * offset2.y * aspectRatio;
7632
+ newRotatedCurrentPoint = rotatePoint(
7633
+ {
7634
+ x: startPoint.x + sign.x * _offset,
7635
+ y: startPoint.y + sign.y * _offset / aspectRatio
7636
+ },
7637
+ centerPoint,
7638
+ rotate
7639
+ );
7640
+ } else {
7641
+ newRotatedCurrentPoint = rotatedCurrentPoint;
7642
+ }
7643
+ const newCenterPoint = getMidpoint(newRotatedCurrentPoint, rotatedSymmetricPoint);
7644
+ const points = [
7645
+ rotatePoint(newRotatedCurrentPoint, newCenterPoint, -rotate),
7646
+ rotatePoint(rotatedSymmetricPoint, newCenterPoint, -rotate)
7647
+ ];
7648
+ const [minX, maxX] = points[0].x > points[1].x ? [points[1].x, points[0].x] : [points[0].x, points[1].x];
7649
+ const [minY, maxY] = points[0].y > points[1].y ? [points[1].y, points[0].y] : [points[0].y, points[1].y];
7650
+ updated.width = maxX - minX;
7651
+ updated.height = maxY - minY;
7652
+ updated.left = minX;
7653
+ updated.top = minY;
7654
+ }
7655
+ if ("width" in updated && updated.width <= 0 || "height" in updated && updated.height <= 0) {
7656
+ return;
7657
+ }
7658
+ const oldValue = { ...model.value };
7659
+ const newValue = { ...model.value, ...updated };
7660
+ model.value = newValue;
7661
+ emit("move", newValue, oldValue);
7662
+ }
7663
+ function onEnd() {
7664
+ window.removeEventListener("pointermove", onMove);
7665
+ window.removeEventListener("pointerup", onEnd, true);
7666
+ transforming.value = false;
7667
+ activeHandle.value = void 0;
7668
+ emit("end", model.value);
7669
+ }
7670
+ window.addEventListener("pointermove", onMove);
7671
+ window.addEventListener("pointerup", onEnd, true);
7672
+ return true;
7673
+ }
7674
+ const cursorMap = {
7675
+ rotate: '<path d="M22.4789 9.45728L25.9935 12.9942L22.4789 16.5283V14.1032C18.126 14.1502 14.6071 17.6737 14.5675 22.0283H17.05L13.513 25.543L9.97889 22.0283H12.5674C12.6071 16.5691 17.0214 12.1503 22.4789 12.1031L22.4789 9.45728Z" fill="black"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21.4789 7.03223L27.4035 12.9945L21.4789 18.9521V15.1868C18.4798 15.6549 16.1113 18.0273 15.649 21.0284H19.475L13.5128 26.953L7.55519 21.0284H11.6189C12.1243 15.8155 16.2679 11.6677 21.4789 11.1559L21.4789 7.03223ZM22.4789 12.1031C17.0214 12.1503 12.6071 16.5691 12.5674 22.0284H9.97889L13.513 25.543L17.05 22.0284H14.5675C14.5705 21.6896 14.5947 21.3558 14.6386 21.0284C15.1157 17.4741 17.9266 14.6592 21.4789 14.1761C21.8063 14.1316 22.1401 14.1069 22.4789 14.1032V16.5284L25.9935 12.9942L22.4789 9.45729L22.4789 12.1031Z" fill="white"/>',
7676
+ resizeXy: '<path d="m9 17.9907v.005l5.997 5.996.001-3.999h1.999 2.02v4l5.98-6.001-5.98-5.999.001 4.019-2.021.002h-2l.001-4.022zm1.411.003 3.587-3.588-.001 2.587h3.5 2.521v-2.585l3.565 3.586-3.564 3.585-.001-2.585h-2.521l-3.499-.001-.001 2.586z" fill="white"/><path d="m17.4971 18.9932h2.521v2.586l3.565-3.586-3.565-3.585v2.605h-2.521-3.5v-2.607l-3.586 3.587 3.586 3.586v-2.587z" fill="black"/>',
7677
+ resizeBevel: '<path d="m19.7432 17.0869-4.072 4.068 2.829 2.828-8.473-.013-.013-8.47 2.841 2.842 4.075-4.068 1.414-1.415-2.844-2.842h8.486v8.484l-2.83-2.827z" fill="white"/><path d="m18.6826 16.7334-4.427 4.424 1.828 1.828-5.056-.016-.014-5.054 1.842 1.841 4.428-4.422 2.474-2.475-1.844-1.843h5.073v5.071l-1.83-1.828z" fill="black"/>'
7678
+ };
7679
+ function createCursor(type, angle) {
7680
+ const path = cursorMap[type];
7681
+ return `<svg height="32" width="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"><defs><filter id="shadow" color-interpolation-filters="sRGB"><feDropShadow dx="1" dy="1" stdDeviation="1.2" flood-opacity=".5"/></filter></defs><g fill="none" transform="rotate(${angle} 16 16)" filter="url(%23shadow)">${path}</g></svg>`.replace(/"/g, "'");
7682
+ }
7683
+ function getCursor(type) {
7684
+ if (type === "move")
7685
+ return "move";
7686
+ const create = cursors[type];
7687
+ if (!create) {
7688
+ return "default";
7689
+ }
7690
+ return `url("data:image/svg+xml,${create(model.value.rotate ?? 0)}") 16 16, pointer`;
7691
+ }
7692
+ function rotatePoint(point, origin, angle) {
7693
+ const radian = angle * Math.PI / 180;
7694
+ const cos = Math.cos(radian);
7695
+ const sin = Math.sin(radian);
7696
+ return {
7697
+ x: (point.x - origin.x) * cos - (point.y - origin.y) * sin + origin.x,
7698
+ y: (point.x - origin.x) * sin + (point.y - origin.y) * cos + origin.y
7699
+ };
7700
+ }
7701
+ function getMidpoint(point1, point2) {
7702
+ return {
7703
+ x: (point2.x + point1.x) / 2,
7704
+ y: (point2.y + point1.y) / 2
7705
+ };
7706
+ }
7707
+ function getDistance(point1, point2) {
7708
+ const dx = point2.x - point1.x;
7709
+ const dy = point2.y - point1.y;
7710
+ return (dx + dy >= 0 ? 1 : -1) * Math.sqrt(dx * dx + dy * dy);
7711
+ }
7712
+ onMounted(async () => {
7713
+ const vm = getCurrentInstance();
7714
+ const root = vm?.proxy?.$el;
7715
+ if (root && props.initialSize) {
7716
+ await nextTick();
7717
+ let width;
7718
+ let height;
7719
+ const style2 = getComputedStyle(root);
7720
+ if (style2.width.endsWith("px") && style2.height.endsWith("px")) {
7721
+ width = Number(style2.width.replace("px", ""));
7722
+ height = Number(style2.height.replace("px", ""));
7723
+ } else {
7724
+ ({ width, height } = root.getBoundingClientRect());
7725
+ }
7726
+ if (width && height) {
7727
+ model.value = { ...model.value, width, height };
7728
+ } else if ("ResizeObserver" in globalThis) {
7729
+ const observer = new ResizeObserver(([entry]) => {
7730
+ if (entry.contentRect.width && entry.contentRect.height) {
7731
+ model.value = {
7732
+ ...model.value,
7733
+ width: entry.contentRect.width,
7734
+ height: entry.contentRect.height
7735
+ };
7736
+ observer.unobserve(root);
7737
+ }
7738
+ });
7739
+ observer.observe(root);
7740
+ }
7741
+ }
7742
+ });
7743
+ __expose({
7744
+ start,
7745
+ activeHandle,
7746
+ transforming
7747
+ });
7748
+ function Diagonal() {
7749
+ const handle = activeHandle.value;
7750
+ if (!handle || !handle.startsWith("resize")) {
7751
+ return void 0;
7752
+ }
7753
+ switch (props.resizeStrategy) {
7754
+ case "lockAspectRatio":
7755
+ break;
7756
+ case "lockAspectRatioDiagonal":
7757
+ if (handle.split("-").length === 2) {
7758
+ return void 0;
7759
+ }
7760
+ break;
7761
+ default:
7762
+ return void 0;
7763
+ }
7764
+ if (handle === "resize-top" || handle === "resize-right" || handle === "resize-top-right" || handle === "resize-bottom-left") {
7765
+ return h("line", {
7766
+ class: "mce-transformable__diagonal",
7767
+ x1: "100%",
7768
+ y1: "0",
7769
+ x2: "0",
7770
+ y2: "100%"
7771
+ });
7772
+ } else if (handle === "resize-left" || handle === "resize-bottom" || handle === "resize-top-left" || handle === "resize-bottom-right") {
7773
+ return h("line", {
7774
+ class: "mce-transformable__diagonal",
7775
+ x1: "0",
7776
+ y1: "0",
7777
+ x2: "100%",
7778
+ y2: "100%"
7779
+ });
7780
+ }
7781
+ return void 0;
7782
+ }
7783
+ return (_ctx, _cache) => {
7784
+ return openBlock(), createBlock(resolveDynamicComponent(__props.tag), {
7785
+ class: normalizeClass(["mce-transformable", [
7786
+ transforming.value && "mce-transformable--transforming",
7787
+ props.hideUi && "mce-transformable--hide-ui",
7788
+ __props.resizeStrategy && `mce-transformable--${__props.resizeStrategy}`,
7789
+ activeHandle.value && `mce-transformable--${activeHandle.value}`,
7790
+ activeHandle.value === "move" && "mce-transformable--moving",
7791
+ activeHandle.value?.startsWith("resize") && "mce-transformable--resizing",
7792
+ activeHandle.value?.startsWith("rotate") && "mce-transformable--rotateing",
7793
+ props.borderStyle && `mce-transformable--${props.borderStyle}`
7794
+ ]]),
7795
+ style: normalizeStyle(style.value)
7796
+ }, {
7797
+ default: withCtx(() => [
7798
+ renderSlot(_ctx.$slots, "default", {
7799
+ value: unref(modelValue),
7800
+ props: {
7801
+ onPointerdown: start
7802
+ },
7803
+ start
7804
+ }),
7805
+ (openBlock(), createElementBlock("svg", _hoisted_1$j, [
7806
+ _cache[0] || (_cache[0] = createElementVNode("rect", {
7807
+ width: "100%",
7808
+ height: "100%",
7809
+ fill: "none",
7810
+ class: "mce-transformable__rect"
7811
+ }, null, -1)),
7812
+ createElementVNode("rect", {
7813
+ class: "mce-transformable__rect",
7814
+ width: "100%",
7815
+ height: "100%",
7816
+ fill: "none",
7817
+ rx: model.value.borderRadius,
7818
+ ry: model.value.borderRadius
7819
+ }, null, 8, _hoisted_2$8),
7820
+ createVNode(Diagonal),
7821
+ createElementVNode("g", null, [
7822
+ (openBlock(true), createElementBlock(Fragment, null, renderList(computedHandles.value, (handle, index) => {
7823
+ return openBlock(), createElementBlock(Fragment, { key: index }, [
7824
+ handle.shape ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
7825
+ handle.shape === "rect" ? (openBlock(), createElementBlock("rect", {
7826
+ key: 0,
7827
+ x: handle.x,
7828
+ y: handle.y,
7829
+ width: handle.width,
7830
+ height: handle.height,
7831
+ "aria-label": handle.type,
7832
+ class: "mce-transformable__handle"
7833
+ }, null, 8, _hoisted_3$6)) : (openBlock(), createElementBlock("circle", {
7834
+ key: 1,
7835
+ cx: handle.x + handle.width / 2,
7836
+ cy: handle.y + handle.width / 2,
7837
+ r: handle.width / 2,
7838
+ "aria-label": handle.type,
7839
+ class: "mce-transformable__handle"
7840
+ }, null, 8, _hoisted_4$3))
7841
+ ], 64)) : createCommentVNode("", true)
7842
+ ], 64);
7843
+ }), 128))
7844
+ ]),
7845
+ createElementVNode("g", _hoisted_5$2, [
7846
+ (openBlock(true), createElementBlock(Fragment, null, renderList(computedHandles.value, (handle, index) => {
7847
+ return openBlock(), createElementBlock("rect", {
7848
+ key: index,
7849
+ ref_for: true,
7850
+ ref_key: "handlesRef",
7851
+ ref: handlesRef,
7852
+ x: handle.x,
7853
+ y: handle.y,
7854
+ width: handle.width,
7855
+ height: handle.height,
7856
+ "aria-label": handle.type,
7857
+ class: "mce-transformable__handle-rect",
7858
+ cursor: transforming.value ? "auto" : getCursor(handle.type),
7859
+ onPointerdown: (event) => start(event, index)
7860
+ }, null, 40, _hoisted_6$2);
7861
+ }), 128))
7862
+ ]),
7863
+ createElementVNode("g", _hoisted_7$2, [
7864
+ renderSlot(_ctx.$slots, "svg", { box: model.value })
7865
+ ])
7866
+ ])),
7867
+ tip.value ? (openBlock(), createElementBlock("div", _hoisted_8$1, toDisplayString(tip.value), 1)) : createCommentVNode("", true)
7868
+ ]),
7869
+ _: 3
7870
+ }, 8, ["class", "style"]);
7871
+ };
7225
7872
  }
7226
7873
  });
7227
- const _hoisted_1$h = ["data-name"];
7228
- const _sfc_main$q = /* @__PURE__ */ defineComponent({
7229
- __name: "Hover",
7230
- setup(__props) {
7231
- const {
7232
- selection,
7233
- hoverElement,
7234
- getObbInDrawboard
7235
- } = useEditor();
7236
- const hoverElementObb = computed(() => getObbInDrawboard(hoverElement.value));
7874
+ const _hoisted_1$i = { class: "mce-cropper" };
7875
+ const _sfc_main$v = /* @__PURE__ */ defineComponent({
7876
+ __name: "Cropper",
7877
+ props: /* @__PURE__ */ mergeModels({
7878
+ image: {},
7879
+ minScale: { default: 0.1 },
7880
+ maxScale: { default: 3 }
7881
+ }, {
7882
+ "modelValue": { default: () => ({}) },
7883
+ "modelModifiers": {},
7884
+ "style": { default: () => ({}) },
7885
+ "styleModifiers": {}
7886
+ }),
7887
+ emits: /* @__PURE__ */ mergeModels(["start", "end", "update:transform"], ["update:modelValue", "update:style"]),
7888
+ setup(__props, { emit: __emit }) {
7889
+ const props = __props;
7890
+ const emit = __emit;
7891
+ const cropRect = useModel(__props, "modelValue");
7892
+ const styleModel = useModel(__props, "style");
7893
+ const rootBox = ref({ width: 0, height: 0 });
7894
+ const { state: imageRef } = useImage(
7895
+ computed(() => ({
7896
+ src: props.image
7897
+ }))
7898
+ );
7899
+ const backup = cloneDeep(cropRect.value);
7900
+ const canvasRef = useTemplateRef("canvasRef");
7901
+ const computedCropRect = computed({
7902
+ get: () => {
7903
+ const { left = 0, top = 0, right = 0, bottom = 0 } = cropRect.value;
7904
+ return { left, top, right, bottom };
7905
+ },
7906
+ set: (val) => cropRect.value = val
7907
+ });
7908
+ const inverseMat = computed(() => {
7909
+ const { left, top, right, bottom } = computedCropRect.value;
7910
+ const sx = 1 / (1 - left - right);
7911
+ const sy = 1 / (1 - top - bottom);
7912
+ const tx = -left;
7913
+ const ty = -top;
7914
+ return { sx, sy, tx, ty };
7915
+ });
7916
+ const sourceTransform = computed({
7917
+ get: () => {
7918
+ const { sx, sy, tx, ty } = inverseMat.value;
7919
+ const { scaleX = 1, scaleY = 1 } = styleModel.value;
7920
+ const { width, height } = rootBox.value;
7921
+ return {
7922
+ width: sx * width,
7923
+ height: sy * height,
7924
+ left: tx * scaleX * (sx * width),
7925
+ top: ty * scaleY * (sy * height)
7926
+ };
7927
+ },
7928
+ set: (newValue) => {
7929
+ const { width, height } = rootBox.value;
7930
+ const { scaleX = 1, scaleY = 1 } = styleModel.value;
7931
+ const transform = {
7932
+ sx: newValue.width / width,
7933
+ sy: newValue.height / height,
7934
+ tx: newValue.left / newValue.width / scaleX,
7935
+ ty: newValue.top / newValue.height / scaleY
7936
+ };
7937
+ const left = -transform.tx;
7938
+ const top = -transform.ty;
7939
+ const w = 1 - 1 / transform.sx;
7940
+ const h2 = 1 - 1 / transform.sy;
7941
+ const right = w - left;
7942
+ const bottom = h2 - top;
7943
+ computedCropRect.value = { left, top, right, bottom };
7944
+ }
7945
+ });
7946
+ const scale = computed({
7947
+ get: () => inverseMat.value.sx,
7948
+ set: (value) => {
7949
+ const transform = inverseMat.value;
7950
+ const rate = transform.sx / value;
7951
+ const left = -transform.tx;
7952
+ const top = -transform.ty;
7953
+ const w = 1 - 1 / value;
7954
+ const h2 = 1 - 1 / transform.sy * rate;
7955
+ const right = w - left;
7956
+ const bottom = h2 - top;
7957
+ computedCropRect.value = { left, top, right, bottom };
7958
+ }
7959
+ });
7960
+ onBeforeMount(() => emit("start"));
7961
+ onBeforeUnmount(() => emit("end"));
7962
+ const sourceStyle = computed(() => {
7963
+ const { sx, sy, tx, ty } = inverseMat.value;
7964
+ const { scaleX = 1, scaleY = 1 } = styleModel.value;
7965
+ return {
7966
+ transform: [
7967
+ `scale(${sx}, ${sy})`,
7968
+ `translate(${tx * scaleX * 100}%, ${ty * scaleY * 100}%)`
7969
+ ].join(" ")
7970
+ };
7971
+ });
7972
+ watch([canvasRef, imageRef], render2);
7973
+ watch(computedCropRect, render2, { deep: true });
7974
+ watch([() => styleModel.value.scaleX, () => styleModel.value.scaleY], render2);
7975
+ function render2() {
7976
+ const ctx = canvasRef.value?.getContext("2d");
7977
+ if (!ctx || !imageRef.value)
7978
+ return;
7979
+ const { scaleX = 1, scaleY = 1 } = styleModel.value;
7980
+ const { naturalWidth, naturalHeight } = imageRef.value;
7981
+ ctx.canvas.width = naturalWidth;
7982
+ ctx.canvas.height = naturalHeight;
7983
+ ctx.clearRect(0, 0, naturalWidth, naturalHeight);
7984
+ ctx.globalAlpha = 0.4;
7985
+ ctx.scale(scaleX, scaleY);
7986
+ ctx.drawImage(imageRef.value, 0, 0, naturalWidth, naturalHeight);
7987
+ }
7988
+ function ok() {
7989
+ emit("end");
7990
+ }
7991
+ function cancel() {
7992
+ cropRect.value = backup;
7993
+ ok();
7994
+ }
7995
+ function onResizeObserver(entries) {
7996
+ const { width, height } = entries[0].contentRect;
7997
+ rootBox.value = { width, height };
7998
+ }
7999
+ function applySourceTransformToStyle() {
8000
+ const { left = 0, top = 0, width = 0, height = 0 } = styleModel.value;
8001
+ const { sx, sy, tx, ty } = inverseMat.value;
8002
+ cropRect.value = {};
8003
+ styleModel.value = {
8004
+ ...styleModel.value,
8005
+ width: sx * width,
8006
+ height: sy * height,
8007
+ left: left + tx * (sx * width),
8008
+ top: top + ty * (sy * height)
8009
+ };
8010
+ ok();
8011
+ }
7237
8012
  return (_ctx, _cache) => {
7238
- return unref(hoverElement) && !unref(hoverElement).equal(unref(selection)[0]) ? (openBlock(), createElementBlock("div", {
7239
- key: 0,
7240
- class: "mce-hover",
7241
- "data-name": unref(hoverElement).name,
7242
- style: normalizeStyle({
7243
- borderColor: "currentcolor",
7244
- ...unref(boundingBoxToStyle)(hoverElementObb.value)
8013
+ return withDirectives((openBlock(), createElementBlock("div", _hoisted_1$i, [
8014
+ createElementVNode("div", {
8015
+ class: "mce-cropper__source",
8016
+ style: normalizeStyle(sourceStyle.value)
8017
+ }, [
8018
+ createElementVNode("canvas", {
8019
+ ref_key: "canvasRef",
8020
+ ref: canvasRef
8021
+ }, null, 512)
8022
+ ], 4),
8023
+ createVNode(_sfc_main$w, {
8024
+ modelValue: sourceTransform.value,
8025
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => sourceTransform.value = $event),
8026
+ class: "mce-cropper__transformable",
8027
+ rotatable: false
8028
+ }, {
8029
+ default: withCtx(({ props: slotProps }) => [
8030
+ createElementVNode("div", mergeProps({ class: "mce-cropper__transformable_rect" }, slotProps), null, 16)
8031
+ ]),
8032
+ _: 1
8033
+ }, 8, ["modelValue"]),
8034
+ renderSlot(_ctx.$slots, "default", {
8035
+ scale: scale.value,
8036
+ ok,
8037
+ cancel,
8038
+ applySourceTransformToStyle
7245
8039
  })
7246
- }, null, 12, _hoisted_1$h)) : createCommentVNode("", true);
8040
+ ])), [
8041
+ [unref(vResizeObserver), onResizeObserver]
8042
+ ]);
7247
8043
  };
7248
8044
  }
7249
8045
  });
7250
- const _hoisted_1$g = { class: "mce-btn" };
7251
- const _sfc_main$p = /* @__PURE__ */ defineComponent({
7252
- __name: "Btn",
8046
+ const _sfc_main$u = /* @__PURE__ */ defineComponent({
8047
+ __name: "ForegroundCropper",
7253
8048
  setup(__props) {
8049
+ const {
8050
+ state,
8051
+ setState,
8052
+ elementSelection
8053
+ } = useEditor();
8054
+ const element = computed(() => elementSelection.value[0]);
7254
8055
  return (_ctx, _cache) => {
7255
- return openBlock(), createElementBlock("div", _hoisted_1$g, [
7256
- renderSlot(_ctx.$slots, "default")
7257
- ]);
8056
+ return unref(state) === "cropping" && element.value?.foreground.isValid() ? (openBlock(), createBlock(_sfc_main$v, {
8057
+ key: 0,
8058
+ modelValue: element.value.foreground.cropRect,
8059
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => element.value.foreground.cropRect = $event),
8060
+ style: normalizeStyle(element.value.style.toJSON()),
8061
+ image: element.value.foreground.image,
8062
+ class: "pointer-events-auto",
8063
+ "onUpdate:style": _cache[1] || (_cache[1] = (val) => element.value.style.setProperties(val)),
8064
+ onEnd: _cache[2] || (_cache[2] = () => unref(setState)(void 0))
8065
+ }, null, 8, ["modelValue", "style", "image"])) : createCommentVNode("", true);
7258
8066
  };
7259
8067
  }
7260
8068
  });
7261
- const _hoisted_1$f = { class: "mce-layer__name" };
7262
- const _hoisted_2$8 = { class: "mce-layer__action" };
7263
- const _sfc_main$o = /* @__PURE__ */ defineComponent({
7264
- ...{
7265
- name: "MceLayer",
7266
- inheritAttrs: false
8069
+ const _sfc_main$t = /* @__PURE__ */ defineComponent({
8070
+ __name: "Frame",
8071
+ props: {
8072
+ "modelValue": { required: true },
8073
+ "modelModifiers": {}
7267
8074
  },
7268
- __name: "Layer",
7269
- props: /* @__PURE__ */ mergeModels({
7270
- root: Boolean,
7271
- node: {
7272
- type: Object,
7273
- required: true
7274
- },
7275
- active: Boolean,
7276
- indent: {
7277
- type: Number,
7278
- default: 0
7279
- }
7280
- }, {
7281
- "opened": { default: false },
7282
- "openedModifiers": {}
7283
- }),
7284
- emits: ["update:opened"],
8075
+ emits: ["update:modelValue"],
7285
8076
  setup(__props) {
7286
- const props = __props;
8077
+ const frame = useModel(__props, "modelValue");
8078
+ const input = useTemplateRef("inputTpl");
7287
8079
  const {
7288
- isElement,
7289
- isFrame,
7290
- isVisible,
7291
- setVisible,
7292
- isLock,
7293
- setLock,
7294
- selection,
7295
- nodes,
7296
- nodeIndexMap,
7297
- zoomTo,
8080
+ getObbInDrawboard,
7298
8081
  hoverElement,
7299
- exec
7300
- } = useEditor();
7301
- const opened = useModel(__props, "opened");
7302
- const dom = ref();
7303
- const {
7304
- selecting,
7305
- sortedSelection
7306
- } = useLayerItem({
7307
- id: props.node.id,
7308
- opened,
7309
- node: computed(() => props.node),
7310
- dom: computed(() => dom.value)
7311
- });
7312
- const isFrist = computed(() => sortedSelection.value[0]?.equal(props.node));
7313
- const isLast = computed(() => {
7314
- const last = sortedSelection.value[sortedSelection.value.length - 1];
7315
- if (last) {
7316
- if (last.equal(props.node)) {
7317
- if (!opened.value || !props.node?.children.length)
7318
- return true;
7319
- } else if (last.equal(props.node?.parent)) ;
7320
- }
7321
- return false;
7322
- });
7323
- const isActive = computed(() => selection.value.some((v) => v.equal(props.node)));
7324
- const inputDom = ref();
7325
- const isHoverElement = computed(() => props.node?.equal(hoverElement.value));
7326
- const hovering = ref(false);
7327
- const editing = ref(false);
7328
- const editValue = ref();
7329
- const thumbnailIcon = computed(() => {
7330
- const node = props.node;
7331
- if (isFrame(node)) {
7332
- return "$frame";
7333
- } else if (node.children.length) {
7334
- return "$group";
7335
- } else if (isElement(node)) {
7336
- if (node.foreground.isValid() && node.foreground.image) {
7337
- return "$image";
7338
- }
7339
- if (node.text.isValid()) {
7340
- return "$text";
7341
- }
7342
- }
7343
- return "$shape";
7344
- });
7345
- function onMousedown() {
7346
- }
7347
- function onClickExpand() {
7348
- opened.value = !opened.value;
7349
- }
7350
- function onClickContent(e) {
7351
- selecting.value = true;
7352
- if (isElement(props.node)) {
7353
- if (e.shiftKey) {
7354
- const _nodes = [
7355
- ...selection.value.filter((v) => !v.equal(props.node)),
7356
- props.node
7357
- ];
7358
- let min;
7359
- let max;
7360
- _nodes.forEach((el) => {
7361
- const index = nodeIndexMap.get(el.id);
7362
- if (index !== void 0) {
7363
- min = min === void 0 ? index : Math.min(min, index);
7364
- max = max === void 0 ? index : Math.max(max, index);
7365
- }
7366
- });
7367
- if (min !== void 0 && max !== void 0) {
7368
- let _selection = nodes.value.slice(min, max + 1);
7369
- const result = new Set(_selection.map((node) => node.id));
7370
- const parents = /* @__PURE__ */ new Set();
7371
- _selection.forEach((node) => node.parent && parents.add(node.parent));
7372
- parents.forEach((parent) => {
7373
- if (parent.children.every((ch) => result.has(ch.id))) {
7374
- const ids = new Set(parent.children.map((ch) => ch.id));
7375
- _selection = [
7376
- ..._selection.filter((v) => !ids.has(v.id)),
7377
- parent
7378
- ];
7379
- }
7380
- });
7381
- selection.value = _selection;
7382
- }
7383
- } else if (e.ctrlKey || e.metaKey) {
7384
- const filtered = selection.value.filter((v) => !v.equal(props.node));
7385
- if (filtered.length !== selection.value.length) {
7386
- selection.value = filtered;
7387
- } else {
7388
- selection.value = [...filtered, props.node];
7389
- }
7390
- } else {
7391
- selection.value = [props.node];
7392
- }
7393
- }
7394
- nextTick().then(() => {
7395
- selecting.value = false;
7396
- });
7397
- }
7398
- function onDblclickThumbnail(e) {
7399
- e.stopPropagation();
7400
- if (isElement(props.node)) {
7401
- zoomTo("selection", {
7402
- behavior: "smooth"
7403
- });
7404
- }
7405
- }
7406
- function onDblclickContent() {
7407
- editing.value = true;
7408
- editValue.value = props.node.name;
7409
- nextTick().then(() => {
7410
- inputDom.value?.focus();
7411
- });
7412
- }
7413
- function onMouseenter() {
7414
- if (isElement(props.node)) {
7415
- hoverElement.value = props.node;
7416
- hovering.value = true;
7417
- }
7418
- }
7419
- function onMouseleave() {
7420
- hoverElement.value = void 0;
7421
- hovering.value = false;
7422
- }
7423
- function onContextmenu(e) {
7424
- if (isElement(props.node)) {
7425
- if (!selection.value.some((v) => v.equal(props.node))) {
7426
- selection.value = [props.node];
7427
- }
7428
- exec("openContextMenu", e);
8082
+ selection,
8083
+ state,
8084
+ config,
8085
+ exec
8086
+ } = useEditor();
8087
+ const editing = ref(false);
8088
+ async function onDblclick() {
8089
+ editing.value = true;
8090
+ await nextTick();
8091
+ if (input.value) {
8092
+ input.value.focus();
8093
+ input.value.select();
7429
8094
  }
7430
8095
  }
7431
- function onInputBlur() {
7432
- console.log("onInputBlur");
7433
- editing.value = false;
7434
- if (editValue.value) {
7435
- props.node.name = editValue.value;
7436
- editValue.value = void 0;
8096
+ async function onPointerdown(ev) {
8097
+ if (!editing.value) {
8098
+ selection.value = [frame.value];
8099
+ await nextTick();
8100
+ exec("startTransform", ev);
7437
8101
  }
7438
8102
  }
7439
8103
  return (_ctx, _cache) => {
7440
- const _component_MceLayer = resolveComponent("MceLayer");
7441
- return openBlock(), createElementBlock(Fragment, null, [
7442
- createElementVNode("div", {
7443
- ref_key: "dom",
7444
- ref: dom,
7445
- class: normalizeClass(["mce-layer", [
7446
- props.root && "mce-layer--root",
7447
- (__props.active || isActive.value) && "mce-layer--active",
7448
- isFrist.value && "mce-layer--first",
7449
- isLast.value && "mce-layer--last",
7450
- opened.value && "mce-layer--open",
7451
- isHoverElement.value && "mce-layer--hover"
7452
- ]]),
7453
- style: normalizeStyle({
7454
- "--indent-padding": `${props.indent * 16}px`
7455
- }),
7456
- onMousedown,
7457
- onMouseenter,
7458
- onMouseleave,
7459
- onContextmenu
8104
+ return withDirectives((openBlock(), createElementBlock("div", {
8105
+ style: normalizeStyle(unref(boundingBoxToStyle)(unref(getObbInDrawboard)(frame.value))),
8106
+ class: normalizeClass(["mce-frame", [
8107
+ unref(config).frameOutline && "mce-frame--outline"
8108
+ ]])
8109
+ }, [
8110
+ withDirectives(createElementVNode("div", {
8111
+ class: "mce-frame__name",
8112
+ onDblclick,
8113
+ onPointerdown,
8114
+ onPointerenter: _cache[2] || (_cache[2] = ($event) => !unref(state) && (hoverElement.value = frame.value)),
8115
+ onPointerleave: _cache[3] || (_cache[3] = ($event) => !unref(state) && (hoverElement.value = void 0))
7460
8116
  }, [
7461
- createElementVNode("div", {
7462
- class: "mce-layer__expand",
7463
- onClick: onClickExpand
7464
- }, [
7465
- props.node.children.length ? (openBlock(), createBlock(_sfc_main$z, {
7466
- key: 0,
7467
- icon: "$arrowRight"
7468
- })) : createCommentVNode("", true)
7469
- ]),
7470
- createElementVNode("div", {
7471
- class: "mce-layer__content",
7472
- onClick: onClickContent,
7473
- onDblclick: onDblclickContent
7474
- }, [
7475
- createElementVNode("div", {
7476
- class: "mce-layer__thumbnail",
7477
- onDblclick: onDblclickThumbnail
7478
- }, [
7479
- createVNode(_sfc_main$z, { icon: thumbnailIcon.value }, null, 8, ["icon"])
7480
- ], 32),
7481
- createElementVNode("div", _hoisted_1$f, [
7482
- withDirectives(createElementVNode("input", {
7483
- ref_key: "inputDom",
7484
- ref: inputDom,
7485
- "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => editValue.value = $event),
7486
- type: "text",
7487
- class: "mce-layer__input",
7488
- autofocus: "",
7489
- onBlur: onInputBlur
7490
- }, null, 544), [
7491
- [vShow, editing.value],
7492
- [vModelText, editValue.value]
7493
- ]),
7494
- createElementVNode("div", {
7495
- style: normalizeStyle({ visibility: editing.value ? "hidden" : void 0 })
7496
- }, toDisplayString(editValue.value || props.node.name || props.node.id), 5)
7497
- ]),
7498
- createElementVNode("div", _hoisted_2$8, [
7499
- props.root ? (openBlock(), createElementBlock("div", {
7500
- key: 0,
7501
- class: normalizeClass(["mce-btn", {
7502
- "mce-btn--hide": !hovering.value && !unref(isLock)(props.node)
7503
- }]),
7504
- onClick: _cache[1] || (_cache[1] = ($event) => unref(setLock)(props.node, !unref(isLock)(props.node)))
7505
- }, [
7506
- createVNode(_sfc_main$z, {
7507
- icon: unref(isLock)(props.node) ? "$lock" : "$unlock"
7508
- }, null, 8, ["icon"])
7509
- ], 2)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
7510
- createVNode(_sfc_main$p, {
7511
- class: normalizeClass({
7512
- "mce-btn--hide": !hovering.value && !unref(isLock)(props.node)
7513
- }),
7514
- onClick: _cache[2] || (_cache[2] = withModifiers(($event) => unref(setLock)(props.node, !unref(isLock)(props.node)), ["prevent", "stop"]))
7515
- }, {
7516
- default: withCtx(() => [
7517
- createVNode(_sfc_main$z, {
7518
- icon: unref(isLock)(props.node) ? "$lock" : "$unlock"
7519
- }, null, 8, ["icon"])
7520
- ]),
7521
- _: 1
7522
- }, 8, ["class"]),
7523
- createVNode(_sfc_main$p, {
7524
- class: normalizeClass({
7525
- "mce-btn--hide": !hovering.value && unref(isVisible)(props.node)
7526
- }),
7527
- onClick: _cache[3] || (_cache[3] = withModifiers(($event) => unref(setVisible)(props.node, !unref(isVisible)(props.node)), ["prevent", "stop"]))
7528
- }, {
7529
- default: withCtx(() => [
7530
- createVNode(_sfc_main$z, {
7531
- icon: unref(isVisible)(props.node) ? "$visible" : "$unvisible"
7532
- }, null, 8, ["icon"])
7533
- ]),
7534
- _: 1
7535
- }, 8, ["class"])
7536
- ], 64))
7537
- ])
7538
- ], 32)
7539
- ], 38),
7540
- opened.value ? (openBlock(true), createElementBlock(Fragment, { key: 0 }, renderList(props.node.children, (child, key) => {
7541
- return openBlock(), createBlock(_component_MceLayer, {
7542
- key,
7543
- node: child,
7544
- indent: __props.root ? props.indent : props.indent + 1,
7545
- active: __props.active || isActive.value
7546
- }, null, 8, ["node", "indent", "active"]);
7547
- }), 128)) : createCommentVNode("", true)
7548
- ], 64);
8117
+ createElementVNode("div", null, toDisplayString(frame.value.name), 1),
8118
+ withDirectives(createElementVNode("input", {
8119
+ ref: "inputTpl",
8120
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => frame.value.name = $event),
8121
+ onBlur: _cache[1] || (_cache[1] = ($event) => editing.value = false)
8122
+ }, null, 544), [
8123
+ [vShow, editing.value],
8124
+ [vModelText, frame.value.name]
8125
+ ])
8126
+ ], 544), [
8127
+ [vShow, unref(config).viewMode === "edgeless"]
8128
+ ])
8129
+ ], 6)), [
8130
+ [vShow, frame.value.visible]
8131
+ ]);
7549
8132
  };
7550
8133
  }
7551
8134
  });
7552
- const _hoisted_1$e = { class: "mce-layers" };
7553
- const _hoisted_2$7 = { class: "mce-layers__wrapper" };
7554
- const _sfc_main$n = /* @__PURE__ */ defineComponent({
7555
- __name: "Layers",
8135
+ const _sfc_main$s = /* @__PURE__ */ defineComponent({
8136
+ __name: "Frames",
7556
8137
  setup(__props) {
7557
8138
  const {
7558
- root,
7559
- selection,
7560
- state,
7561
- nodeIndexMap
8139
+ frames
7562
8140
  } = useEditor();
7563
- const sortedSelection = computed(() => {
7564
- return selection.value.map((node) => {
7565
- return {
7566
- node,
7567
- index: nodeIndexMap.get(node.id) ?? 0
7568
- };
7569
- }).sort((a, b) => a.index - b.index).map((v) => v.node);
7570
- });
8141
+ return (_ctx, _cache) => {
8142
+ return openBlock(true), createElementBlock(Fragment, null, renderList(unref(frames), (frame, key) => {
8143
+ return openBlock(), createBlock(_sfc_main$t, {
8144
+ key,
8145
+ "model-value": frame
8146
+ }, null, 8, ["model-value"]);
8147
+ }), 128);
8148
+ };
8149
+ }
8150
+ });
8151
+ const _sfc_main$r = /* @__PURE__ */ defineComponent({
8152
+ __name: "GoBackSelectedArea",
8153
+ setup(__props) {
7571
8154
  const {
7572
- selecting,
7573
- openedItems,
7574
- domItems
7575
- } = createLayer({
7576
- sortedSelection
7577
- });
7578
- watch(selection, (selection2) => {
7579
- if (state.value === "selecting" || selecting.value) {
7580
- return;
7581
- }
7582
- let last;
7583
- selection2.forEach((node) => {
7584
- node.findAncestor((ancestor) => {
7585
- const opened = openedItems.get(ancestor.id);
7586
- if (opened) {
7587
- opened.value = true;
7588
- }
7589
- return false;
7590
- });
7591
- last = node;
7592
- });
7593
- if (last) {
7594
- nextTick().then(() => {
7595
- domItems.get(last.id)?.value?.scrollIntoView({
7596
- block: "center"
7597
- });
7598
- });
7599
- }
8155
+ selectionAabb,
8156
+ drawboardAabb,
8157
+ aabbToDrawboardAabb,
8158
+ t,
8159
+ exec
8160
+ } = useEditor();
8161
+ const isActive = computed(() => {
8162
+ return selectionAabb.value.width && selectionAabb.value.height && !isOverlappingAabb(
8163
+ drawboardAabb.value,
8164
+ aabbToDrawboardAabb(selectionAabb.value)
8165
+ );
7600
8166
  });
7601
8167
  return (_ctx, _cache) => {
7602
- return openBlock(), createElementBlock("div", _hoisted_1$e, [
7603
- createElementVNode("div", _hoisted_2$7, [
7604
- createVNode(_sfc_main$o, {
7605
- root: true,
7606
- node: unref(root),
7607
- opened: true
7608
- }, null, 8, ["node"])
7609
- ])
7610
- ]);
8168
+ return isActive.value ? (openBlock(), createElementBlock("div", {
8169
+ key: 0,
8170
+ class: "mce-back-selected-aera",
8171
+ onClick: _cache[0] || (_cache[0] = withModifiers(($event) => unref(exec)("scrollToSelection", { behavior: "smooth" }), ["prevent"]))
8172
+ }, [
8173
+ createVNode(_sfc_main$C, { icon: "$gps" }),
8174
+ createElementVNode("span", null, toDisplayString(unref(t)("goBackSelectedArea")), 1)
8175
+ ])) : createCommentVNode("", true);
8176
+ };
8177
+ }
8178
+ });
8179
+ const _hoisted_1$h = ["data-name"];
8180
+ const _sfc_main$q = /* @__PURE__ */ defineComponent({
8181
+ __name: "Hover",
8182
+ setup(__props) {
8183
+ const {
8184
+ selection,
8185
+ hoverElement,
8186
+ getObbInDrawboard
8187
+ } = useEditor();
8188
+ const hoverElementObb = computed(() => getObbInDrawboard(hoverElement.value));
8189
+ return (_ctx, _cache) => {
8190
+ return unref(hoverElement) && !unref(hoverElement).equal(unref(selection)[0]) ? (openBlock(), createElementBlock("div", {
8191
+ key: 0,
8192
+ class: "mce-hover",
8193
+ "data-name": unref(hoverElement).name,
8194
+ style: normalizeStyle({
8195
+ borderColor: "currentcolor",
8196
+ ...unref(boundingBoxToStyle)(hoverElementObb.value)
8197
+ })
8198
+ }, null, 12, _hoisted_1$h)) : createCommentVNode("", true);
7611
8199
  };
7612
8200
  }
7613
8201
  });
7614
- const _sfc_main$m = /* @__PURE__ */ defineComponent({
7615
- __name: "Tooltip",
7616
- props: /* @__PURE__ */ mergeModels({
7617
- ...makeMceOverlayProps({
7618
- location: "right",
7619
- offset: 8
7620
- })
7621
- }, {
7622
- "modelValue": { type: Boolean },
7623
- "modelModifiers": {}
7624
- }),
7625
- emits: ["update:modelValue"],
7626
- setup(__props, { expose: __expose }) {
7627
- const props = __props;
7628
- const isActive = useModel(__props, "modelValue");
7629
- const overlay = useTemplateRef("overlayTpl");
7630
- function updateLocation() {
7631
- overlay.value?.updateLocation();
7632
- }
7633
- __expose({
7634
- updateLocation
7635
- });
8202
+ const _hoisted_1$g = { class: "mce-btn" };
8203
+ const _sfc_main$p = /* @__PURE__ */ defineComponent({
8204
+ __name: "Btn",
8205
+ setup(__props) {
7636
8206
  return (_ctx, _cache) => {
7637
- return openBlock(), createBlock(_sfc_main$y, {
7638
- ref: "overlayTpl",
7639
- modelValue: isActive.value,
7640
- "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => isActive.value = $event),
7641
- class: "mce-tooltip",
7642
- location: props.location,
7643
- offset: props.offset,
7644
- target: props.target,
7645
- attach: props.attach
7646
- }, createSlots({
7647
- default: withCtx(() => [
7648
- isActive.value ? renderSlot(_ctx.$slots, "default", { key: 0 }) : createCommentVNode("", true)
7649
- ]),
7650
- _: 2
7651
- }, [
7652
- _ctx.$slots.activator ? {
7653
- name: "activator",
7654
- fn: withCtx((activatorProps) => [
7655
- renderSlot(_ctx.$slots, "activator", normalizeProps(guardReactiveProps(activatorProps)))
7656
- ]),
7657
- key: "0"
7658
- } : void 0
7659
- ]), 1032, ["modelValue", "location", "offset", "target", "attach"]);
8207
+ return openBlock(), createElementBlock("div", _hoisted_1$g, [
8208
+ renderSlot(_ctx.$slots, "default")
8209
+ ]);
7660
8210
  };
7661
8211
  }
7662
8212
  });
7663
- const _hoisted_1$d = ["width", "height"];
7664
- const _hoisted_2$6 = ["onDblclick", "onMousedown", "onMousemove"];
7665
- const _hoisted_3$6 = { style: { "font-size": "12px", "text-wrap": "nowrap" } };
7666
- const _sfc_main$l = /* @__PURE__ */ defineComponent({
8213
+ const _hoisted_1$f = { class: "mce-layer__name" };
8214
+ const _hoisted_2$7 = { class: "mce-layer__action" };
8215
+ const _sfc_main$o = /* @__PURE__ */ defineComponent({
7667
8216
  ...{
8217
+ name: "MceLayer",
7668
8218
  inheritAttrs: false
7669
8219
  },
7670
- __name: "Ruler",
7671
- props: {
7672
- size: { default: 16 },
7673
- vertical: { type: Boolean },
7674
- zoom: { default: 1 },
7675
- position: { default: 0 },
7676
- unit: { default: 50 },
7677
- unitFractions: { default: () => [1, 2, 5, 10] },
7678
- selected: {},
7679
- pixelRatio: { default: window.devicePixelRatio || 1 },
7680
- refline: { type: Boolean },
7681
- axis: { type: Boolean },
7682
- labelFormat: { type: Function, default: (tick) => String(tick) }
7683
- },
7684
- setup(__props, { expose: __expose }) {
8220
+ __name: "Layer",
8221
+ props: /* @__PURE__ */ mergeModels({
8222
+ root: Boolean,
8223
+ node: {
8224
+ type: Object,
8225
+ required: true
8226
+ },
8227
+ active: Boolean,
8228
+ indent: {
8229
+ type: Number,
8230
+ default: 0
8231
+ }
8232
+ }, {
8233
+ "opened": { default: false },
8234
+ "openedModifiers": {}
8235
+ }),
8236
+ emits: ["update:opened"],
8237
+ setup(__props) {
7685
8238
  const props = __props;
7686
- const attrs = useAttrs();
7687
- const pixelRatio = computed(() => props.pixelRatio);
7688
- const tipText = ref();
7689
- const tipPos = ref({ x: 0, y: 0 });
7690
- const canvas = useTemplateRef("canvasTpl");
7691
- const offscreenCanvas = "OffscreenCanvas" in window ? new OffscreenCanvas(props.size, props.size) : document.createElement("canvas");
7692
- const ctx = offscreenCanvas.getContext("2d");
7693
- const box = ref();
7694
- const colors = reactive({
7695
- text: "#000",
7696
- border: "#000"
8239
+ const {
8240
+ isElement,
8241
+ isFrame,
8242
+ isVisible,
8243
+ setVisible,
8244
+ isLock,
8245
+ setLock,
8246
+ selection,
8247
+ nodes,
8248
+ nodeIndexMap,
8249
+ zoomTo,
8250
+ hoverElement,
8251
+ exec
8252
+ } = useEditor();
8253
+ const opened = useModel(__props, "opened");
8254
+ const dom = ref();
8255
+ const {
8256
+ selecting,
8257
+ sortedSelection
8258
+ } = useLayerItem({
8259
+ id: props.node.id,
8260
+ opened,
8261
+ node: computed(() => props.node),
8262
+ dom: computed(() => dom.value)
7697
8263
  });
7698
- function drawSelected() {
7699
- if (!props.selected?.width || !props.selected?.height)
7700
- return;
7701
- ctx.fillStyle = "#6165FD20";
7702
- const offset2 = props.vertical ? props.selected.top : props.selected.left;
7703
- const length = props.vertical ? props.selected.height : props.selected.width;
7704
- ctx.fillRect(offset2, 0, length, props.size);
7705
- }
7706
- function drawAxis(start2, end2, size, color) {
7707
- ctx.lineWidth = size;
7708
- ctx.strokeStyle = color;
7709
- ctx.beginPath();
7710
- ctx.moveTo(start2[0], start2[1]);
7711
- ctx.lineTo(end2[0], end2[1]);
7712
- ctx.stroke();
7713
- }
7714
- function drawTick(tick, len, direction = 1) {
7715
- const x1 = tick;
7716
- const y1 = props.size;
7717
- const x2 = tick;
7718
- const y2 = props.size - len * direction;
7719
- ctx.moveTo(x1, y1);
7720
- ctx.lineTo(x2, y2);
7721
- }
7722
- function drawText(content, tick, top, size) {
7723
- ctx.font = `${size}px sans-serif`;
7724
- ctx.textAlign = "left";
7725
- ctx.textBaseline = "bottom";
7726
- const x2 = tick;
7727
- const y2 = props.size - top;
7728
- ctx.save();
7729
- if (props.vertical) {
7730
- ctx.translate(0, props.size);
7731
- ctx.scale(1, -1);
7732
- }
7733
- ctx.fillText(content, x2, y2);
7734
- ctx.restore();
7735
- }
7736
- const unit = computed(() => {
7737
- const idealUnit = Math.max(props.unit / props.zoom, 1);
7738
- const unitFractions = props.unitFractions;
7739
- const exponent = Math.floor(Math.log10(idealUnit));
7740
- const fraction = idealUnit / 10 ** exponent;
7741
- let niceFraction = unitFractions[unitFractions.length - 1];
7742
- for (const cur of unitFractions) {
7743
- if (fraction <= cur) {
7744
- niceFraction = cur;
7745
- break;
7746
- }
8264
+ const isFrist = computed(() => sortedSelection.value[0]?.equal(props.node));
8265
+ const isLast = computed(() => {
8266
+ const last = sortedSelection.value[sortedSelection.value.length - 1];
8267
+ if (last) {
8268
+ if (last.equal(props.node)) {
8269
+ if (!opened.value || !props.node?.children.length)
8270
+ return true;
8271
+ } else if (last.equal(props.node?.parent)) ;
7747
8272
  }
7748
- return niceFraction * 10 ** exponent;
7749
- });
7750
- const start = computed(() => {
7751
- const value = props.position / props.zoom;
7752
- return Math.floor(value / unit.value) * unit.value;
7753
- });
7754
- const end = computed(() => {
7755
- const len = (props.vertical ? box.value?.height : box.value?.width) ?? 0;
7756
- const value = len / props.zoom;
7757
- return start.value + Math.ceil(value / unit.value) * unit.value;
8273
+ return false;
7758
8274
  });
7759
- function numToPx(num) {
7760
- return Math.round(num * props.zoom - props.position);
7761
- }
7762
- function pxToNum(px) {
7763
- return Math.round((px + props.position) / props.zoom);
7764
- }
7765
- function render2() {
7766
- const cvs = canvas.value;
7767
- if (!cvs || !offscreenCanvas.width || !offscreenCanvas.height)
7768
- return;
7769
- ctx.clearRect(0, 0, offscreenCanvas.width, offscreenCanvas.height);
7770
- ctx.save();
7771
- ctx.scale(pixelRatio.value, pixelRatio.value);
7772
- if (props.vertical) {
7773
- ctx.scale(1, -1);
7774
- ctx.translate(0, 0);
7775
- ctx.rotate(-Math.PI / 2);
7776
- }
7777
- drawSelected();
7778
- if (props.axis) {
7779
- drawAxis(
7780
- [0, props.size],
7781
- [props.vertical ? cvs.height : cvs.width, props.size],
7782
- 2,
7783
- colors.border
7784
- );
7785
- }
7786
- const drawPrimary = (tick, label) => {
7787
- drawTick(tick, 10);
7788
- drawText(label, tick + 2, 4, 8);
7789
- };
7790
- const drawSecondary = (tick) => drawTick(tick, 4);
7791
- let inc = unit.value / 10;
7792
- inc = (inc > 0 ? 1 : -1) * Math.max(1, Math.abs(inc));
7793
- ctx.beginPath();
7794
- ctx.lineWidth = 1;
7795
- ctx.strokeStyle = colors.text;
7796
- ctx.fillStyle = colors.text;
7797
- for (let tick = start.value; tick <= end.value; tick += inc) {
7798
- if (tick % unit.value === 0) {
7799
- drawPrimary(numToPx(tick), props.labelFormat(tick));
7800
- }
7801
- }
7802
- ctx.stroke();
7803
- ctx.beginPath();
7804
- ctx.lineWidth = 1;
7805
- ctx.strokeStyle = colors.border;
7806
- for (let tick = start.value; tick <= end.value; tick += inc) {
7807
- if (tick % unit.value === 0) ;
7808
- else if (tick % inc === 0) {
7809
- drawSecondary(numToPx(tick));
8275
+ const isActive = computed(() => selection.value.some((v) => v.equal(props.node)));
8276
+ const inputDom = ref();
8277
+ const isHoverElement = computed(() => props.node?.equal(hoverElement.value));
8278
+ const hovering = ref(false);
8279
+ const editing = ref(false);
8280
+ const editValue = ref();
8281
+ const thumbnailIcon = computed(() => {
8282
+ const node = props.node;
8283
+ if (isFrame(node)) {
8284
+ return "$frame";
8285
+ } else if (node.children.length) {
8286
+ return "$group";
8287
+ } else if (isElement(node)) {
8288
+ if (node.foreground.isValid() && node.foreground.image) {
8289
+ return "$image";
7810
8290
  }
7811
- }
7812
- ctx.stroke();
7813
- ctx.restore();
7814
- if ("transferToImageBitmap" in offscreenCanvas) {
7815
- cvs.getContext("bitmaprenderer").transferFromImageBitmap(offscreenCanvas.transferToImageBitmap());
7816
- } else {
7817
- const mainCtx = cvs.getContext("2d");
7818
- if (mainCtx) {
7819
- mainCtx.clearRect(0, 0, cvs.width, cvs.height);
7820
- mainCtx.drawImage(offscreenCanvas, 0, 0);
8291
+ if (node.text.isValid()) {
8292
+ return "$text";
7821
8293
  }
7822
8294
  }
8295
+ return "$shape";
8296
+ });
8297
+ function onMousedown() {
7823
8298
  }
7824
- watch(
7825
- [canvas, () => props.zoom, () => props.position, () => props.selected],
7826
- () => {
7827
- render2();
7828
- },
7829
- { immediate: true, deep: true }
7830
- );
7831
- const resize = useDebounceFn(() => {
7832
- if (!canvas.value)
7833
- return;
7834
- const _box = canvas.value.parentElement.getBoundingClientRect();
7835
- offscreenCanvas.width = canvas.value.width = _box.width * pixelRatio.value;
7836
- offscreenCanvas.height = canvas.value.height = _box.height * pixelRatio.value;
7837
- canvas.value.style.width = `${_box.width}px`;
7838
- canvas.value.style.height = `${_box.height}px`;
7839
- box.value = _box;
7840
- render2();
7841
- }, 50);
7842
- onMounted(() => {
7843
- resize();
7844
- const dom = canvas.value;
7845
- if (dom) {
7846
- const style = window.getComputedStyle(dom);
7847
- colors.text = style.getPropertyValue("--text-color").trim();
7848
- colors.border = style.getPropertyValue("--border-color").trim();
8299
+ function onClickExpand() {
8300
+ opened.value = !opened.value;
8301
+ }
8302
+ function onClickContent(e) {
8303
+ selecting.value = true;
8304
+ if (isElement(props.node)) {
8305
+ if (e.shiftKey) {
8306
+ const _nodes = [
8307
+ ...selection.value.filter((v) => !v.equal(props.node)),
8308
+ props.node
8309
+ ];
8310
+ let min;
8311
+ let max;
8312
+ _nodes.forEach((el) => {
8313
+ const index = nodeIndexMap.get(el.id);
8314
+ if (index !== void 0) {
8315
+ min = min === void 0 ? index : Math.min(min, index);
8316
+ max = max === void 0 ? index : Math.max(max, index);
8317
+ }
8318
+ });
8319
+ if (min !== void 0 && max !== void 0) {
8320
+ let _selection = nodes.value.slice(min, max + 1);
8321
+ const result = new Set(_selection.map((node) => node.id));
8322
+ const parents = /* @__PURE__ */ new Set();
8323
+ _selection.forEach((node) => node.parent && parents.add(node.parent));
8324
+ parents.forEach((parent) => {
8325
+ if (parent.children.every((ch) => result.has(ch.id))) {
8326
+ const ids = new Set(parent.children.map((ch) => ch.id));
8327
+ _selection = [
8328
+ ..._selection.filter((v) => !ids.has(v.id)),
8329
+ parent
8330
+ ];
8331
+ }
8332
+ });
8333
+ selection.value = _selection;
8334
+ }
8335
+ } else if (e.ctrlKey || e.metaKey) {
8336
+ const filtered = selection.value.filter((v) => !v.equal(props.node));
8337
+ if (filtered.length !== selection.value.length) {
8338
+ selection.value = filtered;
8339
+ } else {
8340
+ selection.value = [...filtered, props.node];
8341
+ }
8342
+ } else {
8343
+ selection.value = [props.node];
8344
+ }
7849
8345
  }
7850
- });
7851
- onBeforeUnmount(() => {
7852
- offscreenCanvas.width = 0;
7853
- offscreenCanvas.height = 0;
7854
- });
7855
- const savedLines = ref([]);
7856
- const tempLine = ref();
7857
- const lines = computed(() => {
7858
- const res = [...savedLines.value];
7859
- if (typeof tempLine.value === "number")
7860
- res.unshift(tempLine.value);
7861
- return res;
7862
- });
7863
- function getTick(e) {
7864
- return pxToNum(
7865
- props.vertical ? e.clientY - box.value.top : e.clientX - box.value.left
7866
- );
8346
+ nextTick().then(() => {
8347
+ selecting.value = false;
8348
+ });
7867
8349
  }
7868
- function onMousedown(e) {
7869
- const tick = getTick(e);
7870
- if (props.refline) {
7871
- savedLines.value.push(tick);
8350
+ function onDblclickThumbnail(e) {
8351
+ e.stopPropagation();
8352
+ if (isElement(props.node)) {
8353
+ zoomTo("selection", {
8354
+ behavior: "smooth"
8355
+ });
7872
8356
  }
7873
8357
  }
7874
- function onMousemove(e, temp = false) {
7875
- const tick = getTick(e);
7876
- if (props.refline && temp) {
7877
- tempLine.value = tick;
8358
+ function onDblclickContent() {
8359
+ editing.value = true;
8360
+ editValue.value = props.node.name;
8361
+ nextTick().then(() => {
8362
+ inputDom.value?.focus();
8363
+ });
8364
+ }
8365
+ function onMouseenter() {
8366
+ if (isElement(props.node)) {
8367
+ hoverElement.value = props.node;
8368
+ hovering.value = true;
7878
8369
  }
7879
- tipText.value = props.labelFormat(tick);
7880
- tipPos.value = { x: e.clientX, y: e.clientY };
7881
8370
  }
7882
- function onLeave() {
7883
- tempLine.value = void 0;
7884
- tipText.value = void 0;
8371
+ function onMouseleave() {
8372
+ hoverElement.value = void 0;
8373
+ hovering.value = false;
7885
8374
  }
7886
- function onReflineDblclick(index) {
7887
- savedLines.value.splice(index, 1);
8375
+ function onContextmenu(e) {
8376
+ if (isElement(props.node)) {
8377
+ if (!selection.value.some((v) => v.equal(props.node))) {
8378
+ selection.value = [props.node];
8379
+ }
8380
+ exec("openContextMenu", e);
8381
+ }
7888
8382
  }
7889
- function onReflineMousedown(e, index) {
7890
- e.stopPropagation();
7891
- e.preventDefault();
7892
- const move = (e2) => {
7893
- savedLines.value[index] = getTick(e2);
7894
- };
7895
- const up = () => {
7896
- window.removeEventListener("mousemove", move);
7897
- window.removeEventListener("mouseup", up);
7898
- };
7899
- window.addEventListener("mousemove", move);
7900
- window.addEventListener("mouseup", up);
8383
+ function onInputBlur() {
8384
+ console.log("onInputBlur");
8385
+ editing.value = false;
8386
+ if (editValue.value) {
8387
+ props.node.name = editValue.value;
8388
+ editValue.value = void 0;
8389
+ }
7901
8390
  }
7902
- __expose({
7903
- box
7904
- });
7905
8391
  return (_ctx, _cache) => {
8392
+ const _component_MceLayer = resolveComponent("MceLayer");
7906
8393
  return openBlock(), createElementBlock(Fragment, null, [
7907
- withDirectives((openBlock(), createElementBlock("div", mergeProps({
7908
- class: ["mce-ruler", [
7909
- `mce-ruler--${props.vertical ? "vertical" : "horizontal"}`
7910
- ]],
7911
- style: { "--size": `${props.size}px` }
7912
- }, unref(attrs), {
8394
+ createElementVNode("div", {
8395
+ ref_key: "dom",
8396
+ ref: dom,
8397
+ class: normalizeClass(["mce-layer", [
8398
+ props.root && "mce-layer--root",
8399
+ (__props.active || isActive.value) && "mce-layer--active",
8400
+ isFrist.value && "mce-layer--first",
8401
+ isLast.value && "mce-layer--last",
8402
+ opened.value && "mce-layer--open",
8403
+ isHoverElement.value && "mce-layer--hover"
8404
+ ]]),
8405
+ style: normalizeStyle({
8406
+ "--indent-padding": `${props.indent * 16}px`
8407
+ }),
7913
8408
  onMousedown,
7914
- onMousemove: _cache[0] || (_cache[0] = ($event) => onMousemove($event, true)),
7915
- onMouseleave: onLeave
7916
- }), [
7917
- createElementVNode("canvas", {
7918
- ref: "canvasTpl",
7919
- class: "mce-ruler__canvas",
7920
- width: props.size,
7921
- height: props.size
7922
- }, null, 8, _hoisted_1$d)
7923
- ], 16)), [
7924
- [unref(vResizeObserver), unref(resize)]
7925
- ]),
7926
- (openBlock(true), createElementBlock(Fragment, null, renderList(lines.value, (item, index) => {
7927
- return openBlock(), createElementBlock("div", {
7928
- key: index,
7929
- class: normalizeClass(["mce-ruler-refline", {
7930
- "mce-ruler-refline--vertical": props.vertical,
7931
- "mce-ruler-refline--horizontal": !props.vertical,
7932
- "mce-ruler-refline--temp": item === tempLine.value
7933
- }]),
7934
- style: normalizeStyle({
7935
- [props.vertical ? "height" : "width"]: "0",
7936
- [props.vertical ? "width" : "height"]: "100%",
7937
- [props.vertical ? "top" : "left"]: `${numToPx(item)}px`,
7938
- [props.vertical ? "left" : "top"]: 0
7939
- }),
7940
- onDblclick: ($event) => onReflineDblclick(index),
7941
- onMousedown: ($event) => onReflineMousedown($event, index),
7942
- onMousemove: () => tipText.value = `${item}`,
7943
- onMouseleave: onLeave
7944
- }, null, 46, _hoisted_2$6);
7945
- }), 128)),
7946
- createVNode(_sfc_main$m, {
7947
- "model-value": !!tipText.value,
7948
- target: tipPos.value,
7949
- offset: 24
7950
- }, {
7951
- default: withCtx(() => [
7952
- createElementVNode("div", _hoisted_3$6, toDisplayString(tipText.value), 1)
8409
+ onMouseenter,
8410
+ onMouseleave,
8411
+ onContextmenu
8412
+ }, [
8413
+ createElementVNode("div", {
8414
+ class: "mce-layer__expand",
8415
+ onClick: onClickExpand
8416
+ }, [
8417
+ props.node.children.length ? (openBlock(), createBlock(_sfc_main$C, {
8418
+ key: 0,
8419
+ icon: "$arrowRight"
8420
+ })) : createCommentVNode("", true)
7953
8421
  ]),
7954
- _: 1
7955
- }, 8, ["model-value", "target"])
8422
+ createElementVNode("div", {
8423
+ class: "mce-layer__content",
8424
+ onClick: onClickContent,
8425
+ onDblclick: onDblclickContent
8426
+ }, [
8427
+ createElementVNode("div", {
8428
+ class: "mce-layer__thumbnail",
8429
+ onDblclick: onDblclickThumbnail
8430
+ }, [
8431
+ createVNode(_sfc_main$C, { icon: thumbnailIcon.value }, null, 8, ["icon"])
8432
+ ], 32),
8433
+ createElementVNode("div", _hoisted_1$f, [
8434
+ withDirectives(createElementVNode("input", {
8435
+ ref_key: "inputDom",
8436
+ ref: inputDom,
8437
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => editValue.value = $event),
8438
+ type: "text",
8439
+ class: "mce-layer__input",
8440
+ autofocus: "",
8441
+ onBlur: onInputBlur
8442
+ }, null, 544), [
8443
+ [vShow, editing.value],
8444
+ [vModelText, editValue.value]
8445
+ ]),
8446
+ createElementVNode("div", {
8447
+ style: normalizeStyle({ visibility: editing.value ? "hidden" : void 0 })
8448
+ }, toDisplayString(editValue.value || props.node.name || props.node.id), 5)
8449
+ ]),
8450
+ createElementVNode("div", _hoisted_2$7, [
8451
+ props.root ? (openBlock(), createElementBlock("div", {
8452
+ key: 0,
8453
+ class: normalizeClass(["mce-btn", {
8454
+ "mce-btn--hide": !hovering.value && !unref(isLock)(props.node)
8455
+ }]),
8456
+ onClick: _cache[1] || (_cache[1] = ($event) => unref(setLock)(props.node, !unref(isLock)(props.node)))
8457
+ }, [
8458
+ createVNode(_sfc_main$C, {
8459
+ icon: unref(isLock)(props.node) ? "$lock" : "$unlock"
8460
+ }, null, 8, ["icon"])
8461
+ ], 2)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
8462
+ createVNode(_sfc_main$p, {
8463
+ class: normalizeClass({
8464
+ "mce-btn--hide": !hovering.value && !unref(isLock)(props.node)
8465
+ }),
8466
+ onClick: _cache[2] || (_cache[2] = withModifiers(($event) => unref(setLock)(props.node, !unref(isLock)(props.node)), ["prevent", "stop"]))
8467
+ }, {
8468
+ default: withCtx(() => [
8469
+ createVNode(_sfc_main$C, {
8470
+ icon: unref(isLock)(props.node) ? "$lock" : "$unlock"
8471
+ }, null, 8, ["icon"])
8472
+ ]),
8473
+ _: 1
8474
+ }, 8, ["class"]),
8475
+ createVNode(_sfc_main$p, {
8476
+ class: normalizeClass({
8477
+ "mce-btn--hide": !hovering.value && unref(isVisible)(props.node)
8478
+ }),
8479
+ onClick: _cache[3] || (_cache[3] = withModifiers(($event) => unref(setVisible)(props.node, !unref(isVisible)(props.node)), ["prevent", "stop"]))
8480
+ }, {
8481
+ default: withCtx(() => [
8482
+ createVNode(_sfc_main$C, {
8483
+ icon: unref(isVisible)(props.node) ? "$visible" : "$unvisible"
8484
+ }, null, 8, ["icon"])
8485
+ ]),
8486
+ _: 1
8487
+ }, 8, ["class"])
8488
+ ], 64))
8489
+ ])
8490
+ ], 32)
8491
+ ], 38),
8492
+ opened.value ? (openBlock(true), createElementBlock(Fragment, { key: 0 }, renderList(props.node.children, (child, key) => {
8493
+ return openBlock(), createBlock(_component_MceLayer, {
8494
+ key,
8495
+ node: child,
8496
+ indent: __props.root ? props.indent : props.indent + 1,
8497
+ active: __props.active || isActive.value
8498
+ }, null, 8, ["node", "indent", "active"]);
8499
+ }), 128)) : createCommentVNode("", true)
7956
8500
  ], 64);
7957
8501
  };
7958
8502
  }
7959
8503
  });
7960
- const _hoisted_1$c = { class: "mce-rulers" };
7961
- const _sfc_main$k = /* @__PURE__ */ defineComponent({
7962
- ...{
7963
- inheritAttrs: false
7964
- },
7965
- __name: "Rulers",
8504
+ const _hoisted_1$e = { class: "mce-layers" };
8505
+ const _hoisted_2$6 = { class: "mce-layers__wrapper" };
8506
+ const _sfc_main$n = /* @__PURE__ */ defineComponent({
8507
+ __name: "Layers",
7966
8508
  setup(__props) {
7967
8509
  const {
7968
- camera,
7969
- getAabbInDrawboard,
7970
- selection
8510
+ root,
8511
+ selection,
8512
+ state,
8513
+ nodeIndexMap
7971
8514
  } = useEditor();
7972
- const activeAabb = computed(() => getAabbInDrawboard(selection.value));
8515
+ const sortedSelection = computed(() => {
8516
+ return selection.value.map((node) => {
8517
+ return {
8518
+ node,
8519
+ index: nodeIndexMap.get(node.id) ?? 0
8520
+ };
8521
+ }).sort((a, b) => a.index - b.index).map((v) => v.node);
8522
+ });
8523
+ const {
8524
+ selecting,
8525
+ openedItems,
8526
+ domItems
8527
+ } = createLayer({
8528
+ sortedSelection
8529
+ });
8530
+ watch(selection, (selection2) => {
8531
+ if (state.value === "selecting" || selecting.value) {
8532
+ return;
8533
+ }
8534
+ let last;
8535
+ selection2.forEach((node) => {
8536
+ node.findAncestor((ancestor) => {
8537
+ const opened = openedItems.get(ancestor.id);
8538
+ if (opened) {
8539
+ opened.value = true;
8540
+ }
8541
+ return false;
8542
+ });
8543
+ last = node;
8544
+ });
8545
+ if (last) {
8546
+ nextTick().then(() => {
8547
+ domItems.get(last.id)?.value?.scrollIntoView({
8548
+ block: "center"
8549
+ });
8550
+ });
8551
+ }
8552
+ });
7973
8553
  return (_ctx, _cache) => {
7974
- return openBlock(), createElementBlock("div", _hoisted_1$c, [
7975
- createVNode(_sfc_main$l, {
7976
- refline: "",
7977
- zoom: unref(camera).zoom.x,
7978
- position: unref(camera).position.x,
7979
- selected: activeAabb.value,
7980
- axis: "",
7981
- size: 16
7982
- }, null, 8, ["zoom", "position", "selected"]),
7983
- createVNode(_sfc_main$l, {
7984
- refline: "",
7985
- zoom: unref(camera).zoom.y,
7986
- position: unref(camera).position.y,
7987
- selected: activeAabb.value,
7988
- axis: "",
7989
- vertical: "",
7990
- size: 16
7991
- }, null, 8, ["zoom", "position", "selected"]),
7992
- _cache[0] || (_cache[0] = createElementVNode("div", { class: "mce-rulers__left-top" }, null, -1))
8554
+ return openBlock(), createElementBlock("div", _hoisted_1$e, [
8555
+ createElementVNode("div", _hoisted_2$6, [
8556
+ createVNode(_sfc_main$o, {
8557
+ root: true,
8558
+ node: unref(root),
8559
+ opened: true
8560
+ }, null, 8, ["node"])
8561
+ ])
7993
8562
  ]);
7994
8563
  };
7995
8564
  }
7996
8565
  });
7997
- const _hoisted_1$b = {
7998
- ref: "trackTplRef",
7999
- class: "mce-scrollbar__track"
8566
+ const _export_sfc = (sfc, props) => {
8567
+ const target = sfc.__vccOpts || sfc;
8568
+ for (const [key, val] of props) {
8569
+ target[key] = val;
8570
+ }
8571
+ return target;
8000
8572
  };
8001
- const _sfc_main$j = /* @__PURE__ */ defineComponent({
8002
- __name: "Scrollbar",
8573
+ const _sfc_main$m = {};
8574
+ const _hoisted_1$d = {
8575
+ class: "mce-made-with",
8576
+ href: "https://github.com/qq15725/mce",
8577
+ target: "_blank"
8578
+ };
8579
+ function _sfc_render$1(_ctx, _cache) {
8580
+ return openBlock(), createElementBlock("a", _hoisted_1$d, [..._cache[0] || (_cache[0] = [
8581
+ createElementVNode("div", null, "MADE WITH", -1),
8582
+ createElementVNode("div", null, "MCE", -1)
8583
+ ])]);
8584
+ }
8585
+ const MadeWith = /* @__PURE__ */ _export_sfc(_sfc_main$m, [["render", _sfc_render$1]]);
8586
+ const _sfc_main$l = /* @__PURE__ */ defineComponent({
8587
+ __name: "Tooltip",
8003
8588
  props: /* @__PURE__ */ mergeModels({
8004
- length: {},
8005
- vertical: { type: Boolean },
8006
- size: {},
8007
- offset: {}
8589
+ ...makeMceOverlayProps({
8590
+ location: "right",
8591
+ offset: 8
8592
+ })
8008
8593
  }, {
8009
- "modelValue": { required: true },
8594
+ "modelValue": { type: Boolean },
8010
8595
  "modelModifiers": {}
8011
8596
  }),
8012
- emits: /* @__PURE__ */ mergeModels(["scroll"], ["update:modelValue"]),
8013
- setup(__props, { emit: __emit }) {
8597
+ emits: ["update:modelValue"],
8598
+ setup(__props, { expose: __expose }) {
8014
8599
  const props = __props;
8015
- const emit = __emit;
8016
- const position = useModel(__props, "modelValue");
8017
- const track = useTemplateRef("trackTplRef");
8018
- const thumb = useTemplateRef("thumbTplRef");
8019
- const trackLength = ref(0);
8020
- const contentLength = computed(() => {
8021
- return props.length + trackLength.value + Math.abs(position.value) * 2;
8022
- });
8023
- const thumbLength = computed(() => {
8024
- return Math.max(0.05, Math.min(1, trackLength.value / contentLength.value));
8025
- });
8026
- const thumbPosition = computed(() => {
8027
- return (Math.abs(position.value) + position.value) / (contentLength.value - trackLength.value) * (1 - thumbLength.value);
8028
- });
8029
- const resize = useDebounceFn(() => {
8030
- const box = track.value?.getBoundingClientRect() ?? { width: 0, height: 0 };
8031
- trackLength.value = props.vertical ? box.height : box.width;
8032
- }, 50);
8033
- const lerp = (a, b, t) => a * (1 - t) + b * t;
8034
- const thumbToTrack = (thumbLength2, thumbPosition2) => lerp(thumbLength2 / 2, 1 - thumbLength2 / 2, thumbPosition2);
8035
- const start = computed(() => thumbToTrack(thumbLength.value, thumbPosition.value));
8036
- const end = computed(() => 1 - start.value - thumbLength.value);
8037
- const thumbTop = computed(() => props.vertical ? `${start.value * 100}%` : "0%");
8038
- const thumbBottom = computed(() => props.vertical ? `${end.value * 100}%` : "50%");
8039
- const thumbLeft = computed(() => props.vertical ? "0%" : `${start.value * 100}%`);
8040
- const thumbRight = computed(() => props.vertical ? "50%" : `${end.value * 100}%`);
8041
- function update(val) {
8042
- emit("scroll", val - position.value);
8043
- position.value = val;
8044
- }
8045
- function amount(val) {
8046
- update(position.value + val);
8600
+ const isActive = useModel(__props, "modelValue");
8601
+ const overlay = useTemplateRef("overlayTpl");
8602
+ function updateLocation() {
8603
+ overlay.value?.updateLocation();
8047
8604
  }
8048
- const isActive = ref(false);
8049
- watch(track, (track2, oldTrack) => {
8050
- function onMousedown(event) {
8051
- if (!thumb.value?.contains(event.target)) {
8052
- return;
8053
- }
8054
- isActive.value = true;
8055
- let last = event;
8056
- event.stopPropagation();
8057
- function onMousemove(event2) {
8058
- const offset2 = {
8059
- x: last.clientX - event2.clientX,
8060
- y: last.clientY - event2.clientY
8061
- };
8062
- last = event2;
8063
- amount((props.vertical ? offset2.y : offset2.x) / (trackLength.value * (1 - thumbLength.value)) * contentLength.value * -1);
8064
- }
8065
- function onMouseup() {
8066
- isActive.value = false;
8067
- window.removeEventListener("mousemove", onMousemove);
8068
- window.removeEventListener("mouseup", onMouseup);
8069
- }
8070
- window.addEventListener("mousemove", onMousemove);
8071
- window.addEventListener("mouseup", onMouseup);
8072
- }
8073
- oldTrack?.removeEventListener("mousedown", onMousedown);
8074
- track2?.addEventListener("mousedown", onMousedown);
8605
+ __expose({
8606
+ updateLocation
8075
8607
  });
8076
8608
  return (_ctx, _cache) => {
8077
- return withDirectives((openBlock(), createElementBlock("div", {
8078
- class: normalizeClass(["mce-scrollbar", {
8079
- "mce-scrollbar--vertical": props.vertical,
8080
- "mce-scrollbar--horizontal": !props.vertical
8081
- }]),
8082
- style: normalizeStyle({
8083
- [props.vertical ? "height" : "width"]: `calc(100% - ${props.size + props.offset}px)`,
8084
- [props.vertical ? "width" : "height"]: `${props.size}px`,
8085
- [props.vertical ? "top" : "left"]: `${props.offset}px`
8086
- })
8087
- }, [
8088
- createElementVNode("div", _hoisted_1$b, [
8089
- createElementVNode("div", {
8090
- ref: "thumbTplRef",
8091
- class: normalizeClass(["mce-scrollbar__thumb", {
8092
- "mce-scrollbar__thumb--active": isActive.value
8093
- }]),
8094
- style: normalizeStyle({
8095
- top: thumbTop.value,
8096
- bottom: thumbBottom.value,
8097
- left: thumbLeft.value,
8098
- right: thumbRight.value
8099
- })
8100
- }, null, 6)
8101
- ], 512)
8102
- ], 6)), [
8103
- [unref(vResizeObserver), unref(resize)]
8104
- ]);
8609
+ return openBlock(), createBlock(_sfc_main$B, {
8610
+ ref: "overlayTpl",
8611
+ modelValue: isActive.value,
8612
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => isActive.value = $event),
8613
+ class: "mce-tooltip",
8614
+ location: props.location,
8615
+ offset: props.offset,
8616
+ target: props.target,
8617
+ attach: props.attach
8618
+ }, createSlots({
8619
+ default: withCtx(() => [
8620
+ isActive.value ? renderSlot(_ctx.$slots, "default", { key: 0 }) : createCommentVNode("", true)
8621
+ ]),
8622
+ _: 2
8623
+ }, [
8624
+ _ctx.$slots.activator ? {
8625
+ name: "activator",
8626
+ fn: withCtx((activatorProps) => [
8627
+ renderSlot(_ctx.$slots, "activator", normalizeProps(guardReactiveProps(activatorProps)))
8628
+ ]),
8629
+ key: "0"
8630
+ } : void 0
8631
+ ]), 1032, ["modelValue", "location", "offset", "target", "attach"]);
8105
8632
  };
8106
8633
  }
8107
8634
  });
8108
- const _sfc_main$i = /* @__PURE__ */ defineComponent({
8635
+ const _hoisted_1$c = ["width", "height"];
8636
+ const _hoisted_2$5 = ["onDblclick", "onMousedown", "onMousemove"];
8637
+ const _hoisted_3$5 = { style: { "font-size": "12px", "text-wrap": "nowrap" } };
8638
+ const _sfc_main$k = /* @__PURE__ */ defineComponent({
8109
8639
  ...{
8110
8640
  inheritAttrs: false
8111
8641
  },
8112
- __name: "Scrollbars",
8113
- props: {
8114
- infinite: { type: Boolean, default: true },
8115
- offset: { default: 0 },
8116
- size: { default: 8 }
8117
- },
8118
- setup(__props) {
8119
- const props = __props;
8120
- const {
8121
- camera,
8122
- viewAabb
8123
- } = useEditor();
8124
- return (_ctx, _cache) => {
8125
- return openBlock(), createElementBlock(Fragment, null, [
8126
- createVNode(_sfc_main$j, mergeProps(props, {
8127
- modelValue: unref(camera).position.y,
8128
- "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => unref(camera).position.y = $event),
8129
- vertical: "",
8130
- length: unref(viewAabb).height * unref(camera).zoom.y
8131
- }), null, 16, ["modelValue", "length"]),
8132
- createVNode(_sfc_main$j, mergeProps(props, {
8133
- modelValue: unref(camera).position.x,
8134
- "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => unref(camera).position.x = $event),
8135
- length: unref(viewAabb).width * unref(camera).zoom.x
8136
- }), null, 16, ["modelValue", "length"])
8137
- ], 64);
8138
- };
8139
- }
8140
- });
8141
- const _hoisted_1$a = { class: "mce-transformable__svg" };
8142
- const _hoisted_2$5 = ["rx", "ry"];
8143
- const _hoisted_3$5 = ["x", "y", "width", "height", "aria-label"];
8144
- const _hoisted_4$3 = ["cx", "cy", "r", "aria-label"];
8145
- const _hoisted_5$2 = { "pointer-events": "all" };
8146
- const _hoisted_6$2 = ["x", "y", "width", "height", "aria-label", "cursor", "onPointerdown"];
8147
- const _hoisted_7$2 = {
8148
- "pointer-events": "all",
8149
- class: "mce-transformable__svg-slot"
8150
- };
8151
- const _hoisted_8$1 = {
8152
- key: 0,
8153
- class: "mce-transformable__tip"
8154
- };
8155
- const _sfc_main$h = /* @__PURE__ */ defineComponent({
8156
- __name: "Transformable",
8642
+ __name: "Ruler",
8157
8643
  props: {
8158
- tag: { default: "div" },
8159
- modelValue: {},
8160
- movable: { type: Boolean, default: true },
8161
- rotatable: { type: Boolean, default: true },
8162
- resizable: { type: Boolean, default: true },
8163
- adjustableBorderRadius: { type: Boolean, default: false },
8164
- threshold: { default: 0 },
8165
- resizeStrategy: {},
8166
- handleStrategy: {},
8167
- handleShape: { default: "rect" },
8168
- hideUi: { type: Boolean },
8169
- handles: { default: () => [
8170
- "move",
8171
- // resize
8172
- "resize-left",
8173
- "resize-top",
8174
- "resize-right",
8175
- "resize-bottom",
8176
- "resize-top-left",
8177
- "resize-top-right",
8178
- "resize-bottom-right",
8179
- "resize-bottom-left",
8180
- // border-radius
8181
- "border-radius-top-left",
8182
- "border-radius-top-right",
8183
- "border-radius-bottom-left",
8184
- "border-radius-bottom-right",
8185
- // rotate
8186
- "rotate-top-left",
8187
- "rotate-top-right",
8188
- "rotate-bottom-left",
8189
- "rotate-bottom-right"
8190
- ] },
8191
- initialSize: { type: Boolean },
8192
- borderStyle: {},
8193
- tipFormat: {}
8644
+ size: { default: 16 },
8645
+ vertical: { type: Boolean },
8646
+ zoom: { default: 1 },
8647
+ position: { default: 0 },
8648
+ unit: { default: 50 },
8649
+ unitFractions: { default: () => [1, 2, 5, 10] },
8650
+ selected: {},
8651
+ pixelRatio: { default: window.devicePixelRatio || 1 },
8652
+ refline: { type: Boolean },
8653
+ axis: { type: Boolean },
8654
+ labelFormat: { type: Function, default: (tick) => String(tick) }
8194
8655
  },
8195
- emits: ["update:modelValue", "start", "move", "end"],
8196
- setup(__props, { expose: __expose, emit: __emit }) {
8656
+ setup(__props, { expose: __expose }) {
8197
8657
  const props = __props;
8198
- const emit = __emit;
8199
- const cursors = {
8200
- "rotate-top-left": (angle) => createCursor("rotate", 360 + angle),
8201
- "rotate-top-right": (angle) => createCursor("rotate", 90 + angle),
8202
- "rotate-bottom-left": (angle) => createCursor("rotate", 270 + angle),
8203
- "rotate-bottom-right": (angle) => createCursor("rotate", 180 + angle),
8204
- "resize-left": (angle) => createCursor("resizeXy", 180 + angle),
8205
- "resize-top": (angle) => createCursor("resizeXy", 90 + angle),
8206
- "resize-right": (angle) => createCursor("resizeXy", 180 + angle),
8207
- "resize-bottom": (angle) => createCursor("resizeXy", 90 + angle),
8208
- "resize-top-left": (angle) => createCursor("resizeBevel", 90 + angle),
8209
- "resize-top-right": (angle) => createCursor("resizeBevel", 180 + angle),
8210
- "resize-bottom-right": (angle) => createCursor("resizeBevel", 90 + angle),
8211
- "resize-bottom-left": (angle) => createCursor("resizeBevel", 180 + angle)
8212
- };
8213
- const modelValue = useModel(props, "modelValue");
8214
- const model = computed({
8215
- get: () => {
8216
- let { left = 0, top = 0, width = 0, height = 0, rotate = 0, borderRadius = 0 } = modelValue.value ?? {};
8217
- if (Number.isNaN(Number(width)))
8218
- width = 0;
8219
- if (Number.isNaN(Number(height)))
8220
- height = 0;
8221
- return { left, top, width, height, rotate, borderRadius };
8222
- },
8223
- set: (val) => modelValue.value = val
8658
+ const attrs = useAttrs();
8659
+ const pixelRatio = computed(() => props.pixelRatio);
8660
+ const tipText = ref();
8661
+ const tipPos = ref({ x: 0, y: 0 });
8662
+ const canvas = useTemplateRef("canvasTpl");
8663
+ const offscreenCanvas = "OffscreenCanvas" in window ? new OffscreenCanvas(props.size, props.size) : document.createElement("canvas");
8664
+ const ctx = offscreenCanvas.getContext("2d");
8665
+ const box = ref();
8666
+ const colors = reactive({
8667
+ text: "#000",
8668
+ border: "#000"
8224
8669
  });
8225
- const transforming = ref(false);
8226
- const activeHandle = ref();
8227
- const computedHandles = computed(() => {
8228
- const size = 8;
8229
- const { width = 0, height = 0, borderRadius } = model.value;
8230
- const center = { x: width / 2, y: height / 2 };
8231
- const shape = props.handleShape;
8232
- const lines = [
8233
- { type: "top", points: [[0, 0], [1, 0]] },
8234
- { type: "right", points: [[1, 0], [1, 1]] },
8235
- { type: "bottom", points: [[0, 1], [1, 1]] },
8236
- { type: "left", points: [[0, 0], [0, 1]] }
8237
- ];
8238
- const points = [
8239
- { type: "top", point: [0.5, 0] },
8240
- { type: "right", point: [1, 0.5] },
8241
- { type: "bottom", point: [0.5, 1] },
8242
- { type: "left", point: [0, 0.5] },
8243
- { type: "top-left", point: [0, 0] },
8244
- { type: "top-right", point: [1, 0] },
8245
- { type: "bottom-left", point: [0, 1] },
8246
- { type: "bottom-right", point: [1, 1] }
8247
- ];
8248
- const lineHandles = lines.map((item) => {
8249
- const [p1, p2] = item.points;
8250
- const minX = Math.min(p1[0], p2[0]) * width;
8251
- const maxX = Math.max(p1[0], p2[0]) * width;
8252
- const minY = Math.min(p1[1], p2[1]) * height;
8253
- const maxY = Math.max(p1[1], p2[1]) * height;
8254
- return {
8255
- type: item.type,
8256
- x: minX - size / 2,
8257
- y: minY - size / 2,
8258
- width: maxX - minX + size,
8259
- height: maxY - minY + size
8260
- };
8261
- });
8262
- const pointHandles = points.map((item) => {
8263
- return {
8264
- type: item.type,
8265
- shape,
8266
- x: item.point[0] * width - size / 2,
8267
- y: item.point[1] * height - size / 2,
8268
- width: size,
8269
- height: size
8270
- };
8271
- });
8272
- const diagonalPointHandles = pointHandles.filter((item) => item.type.split("-").length === 2);
8273
- const rotateHandles = diagonalPointHandles.map((item) => {
8274
- const sign = {
8275
- x: center.x - item.x > 0 ? 1 : -1,
8276
- y: center.y - item.y > 0 ? 1 : -1
8277
- };
8278
- return {
8279
- ...item,
8280
- shape: void 0,
8281
- type: `rotate-${item.type}`,
8282
- x: item.x - sign.x * size,
8283
- y: item.y - sign.y * size
8284
- };
8285
- });
8286
- const minSize = Math.min(width, height);
8287
- const borderRadiusHandles = props.adjustableBorderRadius ? diagonalPointHandles.map((item) => {
8288
- const sign = {
8289
- x: center.x - item.x > 0 ? 1 : -1,
8290
- y: center.y - item.y > 0 ? 1 : -1
8291
- };
8292
- const offset2 = minSize * 0.1;
8293
- return {
8294
- ...item,
8295
- shape: "circle",
8296
- type: `border-radius-${item.type}`,
8297
- x: item.x + sign.x * Math.min(width / 2, offset2 + borderRadius),
8298
- y: item.y + sign.y * Math.min(height / 2, offset2 + borderRadius)
8299
- };
8300
- }) : [];
8301
- let handles;
8302
- if (props.handleStrategy === "point") {
8303
- handles = [
8304
- // move
8305
- ...lineHandles.map((item) => ({ ...item, type: "move" })),
8306
- // resize
8307
- ...pointHandles.map((item) => ({ ...item, type: `resize-${item.type}` })),
8308
- // border-radius
8309
- ...borderRadiusHandles,
8310
- // rotate
8311
- ...rotateHandles
8312
- ];
8313
- } else {
8314
- handles = [
8315
- // resize
8316
- ...lineHandles.map((item) => ({ ...item, type: `resize-${item.type}` })),
8317
- ...diagonalPointHandles.map((item) => ({ ...item, type: `resize-${item.type}` })),
8318
- // border-radius
8319
- ...borderRadiusHandles,
8320
- // rotate
8321
- ...rotateHandles
8322
- ];
8670
+ function drawSelected() {
8671
+ if (!props.selected?.width || !props.selected?.height)
8672
+ return;
8673
+ ctx.fillStyle = "#6165FD20";
8674
+ const offset2 = props.vertical ? props.selected.top : props.selected.left;
8675
+ const length = props.vertical ? props.selected.height : props.selected.width;
8676
+ ctx.fillRect(offset2, 0, length, props.size);
8677
+ }
8678
+ function drawAxis(start2, end2, size, color) {
8679
+ ctx.lineWidth = size;
8680
+ ctx.strokeStyle = color;
8681
+ ctx.beginPath();
8682
+ ctx.moveTo(start2[0], start2[1]);
8683
+ ctx.lineTo(end2[0], end2[1]);
8684
+ ctx.stroke();
8685
+ }
8686
+ function drawTick(tick, len, direction = 1) {
8687
+ const x1 = tick;
8688
+ const y1 = props.size;
8689
+ const x2 = tick;
8690
+ const y2 = props.size - len * direction;
8691
+ ctx.moveTo(x1, y1);
8692
+ ctx.lineTo(x2, y2);
8693
+ }
8694
+ function drawText(content, tick, top, size) {
8695
+ ctx.font = `${size}px sans-serif`;
8696
+ ctx.textAlign = "left";
8697
+ ctx.textBaseline = "bottom";
8698
+ const x2 = tick;
8699
+ const y2 = props.size - top;
8700
+ ctx.save();
8701
+ if (props.vertical) {
8702
+ ctx.translate(0, props.size);
8703
+ ctx.scale(1, -1);
8323
8704
  }
8324
- return handles.filter((handle) => {
8325
- if (props.handles.includes(handle.type)) {
8326
- return !(!props.resizable && handle.type.startsWith("resize") || !props.rotatable && handle.type.startsWith("rotate") || !props.movable && handle.type === "move");
8705
+ ctx.fillText(content, x2, y2);
8706
+ ctx.restore();
8707
+ }
8708
+ const unit = computed(() => {
8709
+ const idealUnit = Math.max(props.unit / props.zoom, 1);
8710
+ const unitFractions = props.unitFractions;
8711
+ const exponent = Math.floor(Math.log10(idealUnit));
8712
+ const fraction = idealUnit / 10 ** exponent;
8713
+ let niceFraction = unitFractions[unitFractions.length - 1];
8714
+ for (const cur of unitFractions) {
8715
+ if (fraction <= cur) {
8716
+ niceFraction = cur;
8717
+ break;
8327
8718
  }
8328
- return false;
8329
- }).map((anchor) => {
8330
- anchor.width = Math.max(anchor.width, 0);
8331
- anchor.height = Math.max(anchor.height, 0);
8332
- return anchor;
8333
- });
8719
+ }
8720
+ return niceFraction * 10 ** exponent;
8334
8721
  });
8335
- const handlesRef = ref();
8336
- const sizeStyle = computed(() => {
8337
- const { width = 0, height = 0 } = model.value;
8338
- return {
8339
- width: props.initialSize && !width ? void 0 : `${width}px`,
8340
- height: props.initialSize && !height ? void 0 : `${height}px`
8341
- };
8722
+ const start = computed(() => {
8723
+ const value = props.position / props.zoom;
8724
+ return Math.floor(value / unit.value) * unit.value;
8342
8725
  });
8343
- const style = computed(() => {
8344
- const { left = 0, top = 0, rotate = 0 } = model.value;
8345
- const radian = rotate * Math.PI / 180;
8346
- const cos = Math.cos(radian);
8347
- const sin = Math.sin(radian);
8348
- return {
8349
- ...sizeStyle.value,
8350
- transform: `matrix(${cos}, ${sin}, ${-sin}, ${cos}, ${left}, ${top})`
8351
- };
8726
+ const end = computed(() => {
8727
+ const len = (props.vertical ? box.value?.height : box.value?.width) ?? 0;
8728
+ const value = len / props.zoom;
8729
+ return start.value + Math.ceil(value / unit.value) * unit.value;
8352
8730
  });
8353
- const tip = computed(() => props.tipFormat?.("size"));
8354
- function start(event, index) {
8355
- if (event && event.button !== void 0 && event.button !== 0) {
8356
- return false;
8357
- }
8358
- event?.preventDefault();
8359
- event?.stopPropagation();
8360
- const { left, top, width, height, rotate, borderRadius } = model.value;
8361
- let aspectRatio = 0;
8362
- if (width && height) {
8363
- aspectRatio = width / height;
8731
+ function numToPx(num) {
8732
+ return Math.round(num * props.zoom - props.position);
8733
+ }
8734
+ function pxToNum(px) {
8735
+ return Math.round((px + props.position) / props.zoom);
8736
+ }
8737
+ function render2() {
8738
+ const cvs = canvas.value;
8739
+ if (!cvs || !offscreenCanvas.width || !offscreenCanvas.height)
8740
+ return;
8741
+ ctx.clearRect(0, 0, offscreenCanvas.width, offscreenCanvas.height);
8742
+ ctx.save();
8743
+ ctx.scale(pixelRatio.value, pixelRatio.value);
8744
+ if (props.vertical) {
8745
+ ctx.scale(1, -1);
8746
+ ctx.translate(0, 0);
8747
+ ctx.rotate(-Math.PI / 2);
8364
8748
  }
8365
- const handle = index === void 0 ? { type: "move", x: 0, y: 0, width: 0, height: 0 } : computedHandles.value[index];
8366
- activeHandle.value = handle.type;
8367
- const isMove = handle.type === "move";
8368
- const isRotate = handle.type.startsWith("rotate");
8369
- const isBorderRadius = handle.type.startsWith("border-radius");
8370
- const isHorizontal = handle.type === "resize-left" || handle.type === "resize-right";
8371
- const isHorizontalVertical = handle.type.split("-").length === 2;
8372
- const centerPoint = {
8373
- x: left + width / 2,
8374
- y: top + height / 2
8375
- };
8376
- const startPoint = {
8377
- x: left,
8378
- y: top
8379
- };
8380
- if (!isMove) {
8381
- startPoint.x += handle.x + handle.width / 2;
8382
- startPoint.y += handle.y + handle.height / 2;
8749
+ drawSelected();
8750
+ if (props.axis) {
8751
+ drawAxis(
8752
+ [0, props.size],
8753
+ [props.vertical ? cvs.height : cvs.width, props.size],
8754
+ 2,
8755
+ colors.border
8756
+ );
8383
8757
  }
8384
- const sign = {
8385
- x: startPoint.x - centerPoint.x > 0 ? 1 : -1,
8386
- y: startPoint.y - centerPoint.y > 0 ? 1 : -1
8387
- };
8388
- const rotatedStartPoint = rotatePoint(startPoint, centerPoint, rotate);
8389
- const rotatedSymmetricPoint = {
8390
- x: centerPoint.x * 2 - rotatedStartPoint.x,
8391
- y: centerPoint.y * 2 - rotatedStartPoint.y
8758
+ const drawPrimary = (tick, label) => {
8759
+ drawTick(tick, 10);
8760
+ drawText(label, tick + 2, 4, 8);
8392
8761
  };
8393
- const startAngle = Math.atan2(
8394
- rotatedStartPoint.y - centerPoint.y,
8395
- rotatedStartPoint.x - centerPoint.x
8396
- ) / (Math.PI / 180);
8397
- let startClientPoint = event ? { x: event.clientX, y: event.clientY } : void 0;
8398
- function startTransform() {
8399
- transforming.value = true;
8400
- emit("start", model.value);
8401
- }
8402
- if (!props.threshold && !transforming.value) {
8403
- startTransform();
8404
- }
8405
- function onMove(event2) {
8406
- const updated = {};
8407
- if (!startClientPoint) {
8408
- startClientPoint = { x: event2.clientX, y: event2.clientY };
8409
- }
8410
- const rotatedOffset = {
8411
- x: event2.clientX - startClientPoint.x,
8412
- y: event2.clientY - startClientPoint.y
8413
- };
8414
- if (!transforming.value) {
8415
- if (Math.abs(rotatedOffset.x) < props.threshold && Math.abs(rotatedOffset.y) < props.threshold) {
8416
- return;
8417
- }
8418
- startTransform();
8762
+ const drawSecondary = (tick) => drawTick(tick, 4);
8763
+ let inc = unit.value / 10;
8764
+ inc = (inc > 0 ? 1 : -1) * Math.max(1, Math.abs(inc));
8765
+ ctx.beginPath();
8766
+ ctx.lineWidth = 1;
8767
+ ctx.strokeStyle = colors.text;
8768
+ ctx.fillStyle = colors.text;
8769
+ for (let tick = start.value; tick <= end.value; tick += inc) {
8770
+ if (tick % unit.value === 0) {
8771
+ drawPrimary(numToPx(tick), props.labelFormat(tick));
8419
8772
  }
8420
- const rotatedCurrentPoint = {
8421
- x: rotatedStartPoint.x + rotatedOffset.x,
8422
- y: rotatedStartPoint.y + rotatedOffset.y
8423
- };
8424
- if (isMove) {
8425
- if (props.movable) {
8426
- updated.left = startPoint.x + rotatedOffset.x;
8427
- updated.top = startPoint.y + rotatedOffset.y;
8428
- }
8429
- } else if (isRotate) {
8430
- if (props.rotatable) {
8431
- const endAngle = Math.atan2(
8432
- rotatedCurrentPoint.y - centerPoint.y,
8433
- rotatedCurrentPoint.x - centerPoint.x
8434
- ) / (Math.PI / 180);
8435
- updated.rotate = (rotate + endAngle - startAngle + 360) % 360;
8436
- }
8437
- } else if (isBorderRadius) {
8438
- const offset2 = rotatePoint(rotatedOffset, { x: 0, y: 0 }, -rotate);
8439
- const _offset = Math.abs(offset2.x) < Math.abs(offset2.y) ? -sign.x * offset2.x : -sign.y * offset2.y * aspectRatio;
8440
- updated.borderRadius = Math.min(
8441
- Math.max(0, borderRadius + _offset),
8442
- Math.min(width / 2, height / 2)
8443
- );
8444
- } else if (isHorizontalVertical) {
8445
- const currentPoint = rotatePoint(rotatedCurrentPoint, centerPoint, -rotate);
8446
- const newCurrentPoint = isHorizontal ? { x: currentPoint.x, y: startPoint.y } : { x: startPoint.x, y: currentPoint.y };
8447
- const newRotatedCurrentPoint = rotatePoint(newCurrentPoint, centerPoint, rotate);
8448
- const distance = Math.abs(getDistance(newRotatedCurrentPoint, rotatedSymmetricPoint));
8449
- if (isHorizontal) {
8450
- updated.width = distance;
8451
- if (props.resizeStrategy === "lockAspectRatio" && aspectRatio) {
8452
- updated.height = distance / aspectRatio;
8453
- } else {
8454
- updated.height = height;
8455
- }
8456
- } else {
8457
- updated.height = distance;
8458
- if (props.resizeStrategy === "lockAspectRatio" && aspectRatio) {
8459
- updated.width = distance * aspectRatio;
8460
- } else {
8461
- updated.width = width;
8462
- }
8463
- }
8464
- const newCenterPoint = getMidpoint(newRotatedCurrentPoint, rotatedSymmetricPoint);
8465
- updated.left = newCenterPoint.x - updated.width / 2;
8466
- updated.top = newCenterPoint.y - updated.height / 2;
8467
- } else {
8468
- let newRotatedCurrentPoint;
8469
- if ((props.resizeStrategy === "lockAspectRatio" || props.resizeStrategy === "lockAspectRatioDiagonal") && aspectRatio) {
8470
- const offset2 = rotatePoint(rotatedOffset, { x: 0, y: 0 }, -rotate);
8471
- const _offset = Math.abs(offset2.x) < Math.abs(offset2.y) ? sign.x * offset2.x : sign.y * offset2.y * aspectRatio;
8472
- newRotatedCurrentPoint = rotatePoint(
8473
- {
8474
- x: startPoint.x + sign.x * _offset,
8475
- y: startPoint.y + sign.y * _offset / aspectRatio
8476
- },
8477
- centerPoint,
8478
- rotate
8479
- );
8480
- } else {
8481
- newRotatedCurrentPoint = rotatedCurrentPoint;
8482
- }
8483
- const newCenterPoint = getMidpoint(newRotatedCurrentPoint, rotatedSymmetricPoint);
8484
- const points = [
8485
- rotatePoint(newRotatedCurrentPoint, newCenterPoint, -rotate),
8486
- rotatePoint(rotatedSymmetricPoint, newCenterPoint, -rotate)
8487
- ];
8488
- const [minX, maxX] = points[0].x > points[1].x ? [points[1].x, points[0].x] : [points[0].x, points[1].x];
8489
- const [minY, maxY] = points[0].y > points[1].y ? [points[1].y, points[0].y] : [points[0].y, points[1].y];
8490
- updated.width = maxX - minX;
8491
- updated.height = maxY - minY;
8492
- updated.left = minX;
8493
- updated.top = minY;
8773
+ }
8774
+ ctx.stroke();
8775
+ ctx.beginPath();
8776
+ ctx.lineWidth = 1;
8777
+ ctx.strokeStyle = colors.border;
8778
+ for (let tick = start.value; tick <= end.value; tick += inc) {
8779
+ if (tick % unit.value === 0) ;
8780
+ else if (tick % inc === 0) {
8781
+ drawSecondary(numToPx(tick));
8494
8782
  }
8495
- if ("width" in updated && updated.width <= 0 || "height" in updated && updated.height <= 0) {
8496
- return;
8783
+ }
8784
+ ctx.stroke();
8785
+ ctx.restore();
8786
+ if ("transferToImageBitmap" in offscreenCanvas) {
8787
+ cvs.getContext("bitmaprenderer").transferFromImageBitmap(offscreenCanvas.transferToImageBitmap());
8788
+ } else {
8789
+ const mainCtx = cvs.getContext("2d");
8790
+ if (mainCtx) {
8791
+ mainCtx.clearRect(0, 0, cvs.width, cvs.height);
8792
+ mainCtx.drawImage(offscreenCanvas, 0, 0);
8497
8793
  }
8498
- const oldValue = { ...model.value };
8499
- const newValue = { ...model.value, ...updated };
8500
- model.value = newValue;
8501
- emit("move", newValue, oldValue);
8502
8794
  }
8503
- function onEnd() {
8504
- window.removeEventListener("pointermove", onMove);
8505
- window.removeEventListener("pointerup", onEnd, true);
8506
- transforming.value = false;
8507
- activeHandle.value = void 0;
8508
- emit("end", model.value);
8795
+ }
8796
+ watch(
8797
+ [canvas, () => props.zoom, () => props.position, () => props.selected],
8798
+ () => {
8799
+ render2();
8800
+ },
8801
+ { immediate: true, deep: true }
8802
+ );
8803
+ const resize = useDebounceFn(() => {
8804
+ if (!canvas.value)
8805
+ return;
8806
+ const _box = canvas.value.parentElement.getBoundingClientRect();
8807
+ offscreenCanvas.width = canvas.value.width = _box.width * pixelRatio.value;
8808
+ offscreenCanvas.height = canvas.value.height = _box.height * pixelRatio.value;
8809
+ canvas.value.style.width = `${_box.width}px`;
8810
+ canvas.value.style.height = `${_box.height}px`;
8811
+ box.value = _box;
8812
+ render2();
8813
+ }, 50);
8814
+ onMounted(() => {
8815
+ resize();
8816
+ const dom = canvas.value;
8817
+ if (dom) {
8818
+ const style = window.getComputedStyle(dom);
8819
+ colors.text = style.getPropertyValue("--text-color").trim();
8820
+ colors.border = style.getPropertyValue("--border-color").trim();
8509
8821
  }
8510
- window.addEventListener("pointermove", onMove);
8511
- window.addEventListener("pointerup", onEnd, true);
8512
- return true;
8822
+ });
8823
+ onBeforeUnmount(() => {
8824
+ offscreenCanvas.width = 0;
8825
+ offscreenCanvas.height = 0;
8826
+ });
8827
+ const savedLines = ref([]);
8828
+ const tempLine = ref();
8829
+ const lines = computed(() => {
8830
+ const res = [...savedLines.value];
8831
+ if (typeof tempLine.value === "number")
8832
+ res.unshift(tempLine.value);
8833
+ return res;
8834
+ });
8835
+ function getTick(e) {
8836
+ return pxToNum(
8837
+ props.vertical ? e.clientY - box.value.top : e.clientX - box.value.left
8838
+ );
8513
8839
  }
8514
- const cursorMap = {
8515
- rotate: '<path d="M22.4789 9.45728L25.9935 12.9942L22.4789 16.5283V14.1032C18.126 14.1502 14.6071 17.6737 14.5675 22.0283H17.05L13.513 25.543L9.97889 22.0283H12.5674C12.6071 16.5691 17.0214 12.1503 22.4789 12.1031L22.4789 9.45728Z" fill="black"/><path fill-rule="evenodd" clip-rule="evenodd" d="M21.4789 7.03223L27.4035 12.9945L21.4789 18.9521V15.1868C18.4798 15.6549 16.1113 18.0273 15.649 21.0284H19.475L13.5128 26.953L7.55519 21.0284H11.6189C12.1243 15.8155 16.2679 11.6677 21.4789 11.1559L21.4789 7.03223ZM22.4789 12.1031C17.0214 12.1503 12.6071 16.5691 12.5674 22.0284H9.97889L13.513 25.543L17.05 22.0284H14.5675C14.5705 21.6896 14.5947 21.3558 14.6386 21.0284C15.1157 17.4741 17.9266 14.6592 21.4789 14.1761C21.8063 14.1316 22.1401 14.1069 22.4789 14.1032V16.5284L25.9935 12.9942L22.4789 9.45729L22.4789 12.1031Z" fill="white"/>',
8516
- resizeXy: '<path d="m9 17.9907v.005l5.997 5.996.001-3.999h1.999 2.02v4l5.98-6.001-5.98-5.999.001 4.019-2.021.002h-2l.001-4.022zm1.411.003 3.587-3.588-.001 2.587h3.5 2.521v-2.585l3.565 3.586-3.564 3.585-.001-2.585h-2.521l-3.499-.001-.001 2.586z" fill="white"/><path d="m17.4971 18.9932h2.521v2.586l3.565-3.586-3.565-3.585v2.605h-2.521-3.5v-2.607l-3.586 3.587 3.586 3.586v-2.587z" fill="black"/>',
8517
- resizeBevel: '<path d="m19.7432 17.0869-4.072 4.068 2.829 2.828-8.473-.013-.013-8.47 2.841 2.842 4.075-4.068 1.414-1.415-2.844-2.842h8.486v8.484l-2.83-2.827z" fill="white"/><path d="m18.6826 16.7334-4.427 4.424 1.828 1.828-5.056-.016-.014-5.054 1.842 1.841 4.428-4.422 2.474-2.475-1.844-1.843h5.073v5.071l-1.83-1.828z" fill="black"/>'
8518
- };
8519
- function createCursor(type, angle) {
8520
- const path = cursorMap[type];
8521
- return `<svg height="32" width="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"><defs><filter id="shadow" color-interpolation-filters="sRGB"><feDropShadow dx="1" dy="1" stdDeviation="1.2" flood-opacity=".5"/></filter></defs><g fill="none" transform="rotate(${angle} 16 16)" filter="url(%23shadow)">${path}</g></svg>`.replace(/"/g, "'");
8840
+ function onMousedown(e) {
8841
+ const tick = getTick(e);
8842
+ if (props.refline) {
8843
+ savedLines.value.push(tick);
8844
+ }
8522
8845
  }
8523
- function getCursor(type) {
8524
- if (type === "move")
8525
- return "move";
8526
- const create = cursors[type];
8527
- if (!create) {
8528
- return "default";
8846
+ function onMousemove(e, temp = false) {
8847
+ const tick = getTick(e);
8848
+ if (props.refline && temp) {
8849
+ tempLine.value = tick;
8529
8850
  }
8530
- return `url("data:image/svg+xml,${create(model.value.rotate ?? 0)}") 16 16, pointer`;
8851
+ tipText.value = props.labelFormat(tick);
8852
+ tipPos.value = { x: e.clientX, y: e.clientY };
8531
8853
  }
8532
- function rotatePoint(point, origin, angle) {
8533
- const radian = angle * Math.PI / 180;
8534
- const cos = Math.cos(radian);
8535
- const sin = Math.sin(radian);
8536
- return {
8537
- x: (point.x - origin.x) * cos - (point.y - origin.y) * sin + origin.x,
8538
- y: (point.x - origin.x) * sin + (point.y - origin.y) * cos + origin.y
8539
- };
8854
+ function onLeave() {
8855
+ tempLine.value = void 0;
8856
+ tipText.value = void 0;
8540
8857
  }
8541
- function getMidpoint(point1, point2) {
8542
- return {
8543
- x: (point2.x + point1.x) / 2,
8544
- y: (point2.y + point1.y) / 2
8858
+ function onReflineDblclick(index) {
8859
+ savedLines.value.splice(index, 1);
8860
+ }
8861
+ function onReflineMousedown(e, index) {
8862
+ e.stopPropagation();
8863
+ e.preventDefault();
8864
+ const move = (e2) => {
8865
+ savedLines.value[index] = getTick(e2);
8545
8866
  };
8867
+ const up = () => {
8868
+ window.removeEventListener("mousemove", move);
8869
+ window.removeEventListener("mouseup", up);
8870
+ };
8871
+ window.addEventListener("mousemove", move);
8872
+ window.addEventListener("mouseup", up);
8873
+ }
8874
+ __expose({
8875
+ box
8876
+ });
8877
+ return (_ctx, _cache) => {
8878
+ return openBlock(), createElementBlock(Fragment, null, [
8879
+ withDirectives((openBlock(), createElementBlock("div", mergeProps({
8880
+ class: ["mce-ruler", [
8881
+ `mce-ruler--${props.vertical ? "vertical" : "horizontal"}`
8882
+ ]],
8883
+ style: { "--size": `${props.size}px` }
8884
+ }, unref(attrs), {
8885
+ onMousedown,
8886
+ onMousemove: _cache[0] || (_cache[0] = ($event) => onMousemove($event, true)),
8887
+ onMouseleave: onLeave
8888
+ }), [
8889
+ createElementVNode("canvas", {
8890
+ ref: "canvasTpl",
8891
+ class: "mce-ruler__canvas",
8892
+ width: props.size,
8893
+ height: props.size
8894
+ }, null, 8, _hoisted_1$c)
8895
+ ], 16)), [
8896
+ [unref(vResizeObserver), unref(resize)]
8897
+ ]),
8898
+ (openBlock(true), createElementBlock(Fragment, null, renderList(lines.value, (item, index) => {
8899
+ return openBlock(), createElementBlock("div", {
8900
+ key: index,
8901
+ class: normalizeClass(["mce-ruler-refline", {
8902
+ "mce-ruler-refline--vertical": props.vertical,
8903
+ "mce-ruler-refline--horizontal": !props.vertical,
8904
+ "mce-ruler-refline--temp": item === tempLine.value
8905
+ }]),
8906
+ style: normalizeStyle({
8907
+ [props.vertical ? "height" : "width"]: "0",
8908
+ [props.vertical ? "width" : "height"]: "100%",
8909
+ [props.vertical ? "top" : "left"]: `${numToPx(item)}px`,
8910
+ [props.vertical ? "left" : "top"]: 0
8911
+ }),
8912
+ onDblclick: ($event) => onReflineDblclick(index),
8913
+ onMousedown: ($event) => onReflineMousedown($event, index),
8914
+ onMousemove: () => tipText.value = `${item}`,
8915
+ onMouseleave: onLeave
8916
+ }, null, 46, _hoisted_2$5);
8917
+ }), 128)),
8918
+ createVNode(_sfc_main$l, {
8919
+ "model-value": !!tipText.value,
8920
+ target: tipPos.value,
8921
+ offset: 24
8922
+ }, {
8923
+ default: withCtx(() => [
8924
+ createElementVNode("div", _hoisted_3$5, toDisplayString(tipText.value), 1)
8925
+ ]),
8926
+ _: 1
8927
+ }, 8, ["model-value", "target"])
8928
+ ], 64);
8929
+ };
8930
+ }
8931
+ });
8932
+ const _hoisted_1$b = { class: "mce-rulers" };
8933
+ const _sfc_main$j = /* @__PURE__ */ defineComponent({
8934
+ ...{
8935
+ inheritAttrs: false
8936
+ },
8937
+ __name: "Rulers",
8938
+ setup(__props) {
8939
+ const {
8940
+ camera,
8941
+ getAabbInDrawboard,
8942
+ selection
8943
+ } = useEditor();
8944
+ const activeAabb = computed(() => getAabbInDrawboard(selection.value));
8945
+ return (_ctx, _cache) => {
8946
+ return openBlock(), createElementBlock("div", _hoisted_1$b, [
8947
+ createVNode(_sfc_main$k, {
8948
+ refline: "",
8949
+ zoom: unref(camera).zoom.x,
8950
+ position: unref(camera).position.x,
8951
+ selected: activeAabb.value,
8952
+ axis: "",
8953
+ size: 16
8954
+ }, null, 8, ["zoom", "position", "selected"]),
8955
+ createVNode(_sfc_main$k, {
8956
+ refline: "",
8957
+ zoom: unref(camera).zoom.y,
8958
+ position: unref(camera).position.y,
8959
+ selected: activeAabb.value,
8960
+ axis: "",
8961
+ vertical: "",
8962
+ size: 16
8963
+ }, null, 8, ["zoom", "position", "selected"]),
8964
+ _cache[0] || (_cache[0] = createElementVNode("div", { class: "mce-rulers__left-top" }, null, -1))
8965
+ ]);
8966
+ };
8967
+ }
8968
+ });
8969
+ const _hoisted_1$a = {
8970
+ ref: "trackTplRef",
8971
+ class: "mce-scrollbar__track"
8972
+ };
8973
+ const _sfc_main$i = /* @__PURE__ */ defineComponent({
8974
+ __name: "Scrollbar",
8975
+ props: /* @__PURE__ */ mergeModels({
8976
+ length: {},
8977
+ vertical: { type: Boolean },
8978
+ size: {},
8979
+ offset: {}
8980
+ }, {
8981
+ "modelValue": { required: true },
8982
+ "modelModifiers": {}
8983
+ }),
8984
+ emits: /* @__PURE__ */ mergeModels(["scroll"], ["update:modelValue"]),
8985
+ setup(__props, { emit: __emit }) {
8986
+ const props = __props;
8987
+ const emit = __emit;
8988
+ const position = useModel(__props, "modelValue");
8989
+ const track = useTemplateRef("trackTplRef");
8990
+ const thumb = useTemplateRef("thumbTplRef");
8991
+ const trackLength = ref(0);
8992
+ const contentLength = computed(() => {
8993
+ return props.length + trackLength.value + Math.abs(position.value) * 2;
8994
+ });
8995
+ const thumbLength = computed(() => {
8996
+ return Math.max(0.05, Math.min(1, trackLength.value / contentLength.value));
8997
+ });
8998
+ const thumbPosition = computed(() => {
8999
+ return (Math.abs(position.value) + position.value) / (contentLength.value - trackLength.value) * (1 - thumbLength.value);
9000
+ });
9001
+ const resize = useDebounceFn(() => {
9002
+ const box = track.value?.getBoundingClientRect() ?? { width: 0, height: 0 };
9003
+ trackLength.value = props.vertical ? box.height : box.width;
9004
+ }, 50);
9005
+ const lerp = (a, b, t) => a * (1 - t) + b * t;
9006
+ const thumbToTrack = (thumbLength2, thumbPosition2) => lerp(thumbLength2 / 2, 1 - thumbLength2 / 2, thumbPosition2);
9007
+ const start = computed(() => thumbToTrack(thumbLength.value, thumbPosition.value));
9008
+ const end = computed(() => 1 - start.value - thumbLength.value);
9009
+ const thumbTop = computed(() => props.vertical ? `${start.value * 100}%` : "0%");
9010
+ const thumbBottom = computed(() => props.vertical ? `${end.value * 100}%` : "50%");
9011
+ const thumbLeft = computed(() => props.vertical ? "0%" : `${start.value * 100}%`);
9012
+ const thumbRight = computed(() => props.vertical ? "50%" : `${end.value * 100}%`);
9013
+ function update(val) {
9014
+ emit("scroll", val - position.value);
9015
+ position.value = val;
8546
9016
  }
8547
- function getDistance(point1, point2) {
8548
- const dx = point2.x - point1.x;
8549
- const dy = point2.y - point1.y;
8550
- return (dx + dy >= 0 ? 1 : -1) * Math.sqrt(dx * dx + dy * dy);
9017
+ function amount(val) {
9018
+ update(position.value + val);
8551
9019
  }
8552
- onMounted(async () => {
8553
- const vm = getCurrentInstance();
8554
- const root = vm?.proxy?.$el;
8555
- if (root && props.initialSize) {
8556
- await nextTick();
8557
- let width;
8558
- let height;
8559
- const style2 = getComputedStyle(root);
8560
- if (style2.width.endsWith("px") && style2.height.endsWith("px")) {
8561
- width = Number(style2.width.replace("px", ""));
8562
- height = Number(style2.height.replace("px", ""));
8563
- } else {
8564
- ({ width, height } = root.getBoundingClientRect());
9020
+ const isActive = ref(false);
9021
+ watch(track, (track2, oldTrack) => {
9022
+ function onMousedown(event) {
9023
+ if (!thumb.value?.contains(event.target)) {
9024
+ return;
8565
9025
  }
8566
- if (width && height) {
8567
- model.value = { ...model.value, width, height };
8568
- } else if ("ResizeObserver" in globalThis) {
8569
- const observer = new ResizeObserver(([entry]) => {
8570
- if (entry.contentRect.width && entry.contentRect.height) {
8571
- model.value = {
8572
- ...model.value,
8573
- width: entry.contentRect.width,
8574
- height: entry.contentRect.height
8575
- };
8576
- observer.unobserve(root);
8577
- }
8578
- });
8579
- observer.observe(root);
9026
+ isActive.value = true;
9027
+ let last = event;
9028
+ event.stopPropagation();
9029
+ function onMousemove(event2) {
9030
+ const offset2 = {
9031
+ x: last.clientX - event2.clientX,
9032
+ y: last.clientY - event2.clientY
9033
+ };
9034
+ last = event2;
9035
+ amount((props.vertical ? offset2.y : offset2.x) / (trackLength.value * (1 - thumbLength.value)) * contentLength.value * -1);
9036
+ }
9037
+ function onMouseup() {
9038
+ isActive.value = false;
9039
+ window.removeEventListener("mousemove", onMousemove);
9040
+ window.removeEventListener("mouseup", onMouseup);
8580
9041
  }
9042
+ window.addEventListener("mousemove", onMousemove);
9043
+ window.addEventListener("mouseup", onMouseup);
8581
9044
  }
9045
+ oldTrack?.removeEventListener("mousedown", onMousedown);
9046
+ track2?.addEventListener("mousedown", onMousedown);
8582
9047
  });
8583
- __expose({
8584
- start,
8585
- activeHandle,
8586
- transforming
8587
- });
8588
- function Diagonal() {
8589
- const handle = activeHandle.value;
8590
- if (!handle || !handle.startsWith("resize")) {
8591
- return void 0;
8592
- }
8593
- switch (props.resizeStrategy) {
8594
- case "lockAspectRatio":
8595
- break;
8596
- case "lockAspectRatioDiagonal":
8597
- if (handle.split("-").length === 2) {
8598
- return void 0;
8599
- }
8600
- break;
8601
- default:
8602
- return void 0;
8603
- }
8604
- if (handle === "resize-top" || handle === "resize-right" || handle === "resize-top-right" || handle === "resize-bottom-left") {
8605
- return h("line", {
8606
- class: "mce-transformable__diagonal",
8607
- x1: "100%",
8608
- y1: "0",
8609
- x2: "0",
8610
- y2: "100%"
8611
- });
8612
- } else if (handle === "resize-left" || handle === "resize-bottom" || handle === "resize-top-left" || handle === "resize-bottom-right") {
8613
- return h("line", {
8614
- class: "mce-transformable__diagonal",
8615
- x1: "0",
8616
- y1: "0",
8617
- x2: "100%",
8618
- y2: "100%"
8619
- });
8620
- }
8621
- return void 0;
8622
- }
8623
9048
  return (_ctx, _cache) => {
8624
- return openBlock(), createBlock(resolveDynamicComponent(__props.tag), {
8625
- class: normalizeClass(["mce-transformable", [
8626
- transforming.value && "mce-transformable--transforming",
8627
- props.hideUi && "mce-transformable--hide-ui",
8628
- __props.resizeStrategy && `mce-transformable--${__props.resizeStrategy}`,
8629
- activeHandle.value && `mce-transformable--${activeHandle.value}`,
8630
- activeHandle.value === "move" && "mce-transformable--moving",
8631
- activeHandle.value?.startsWith("resize") && "mce-transformable--resizing",
8632
- activeHandle.value?.startsWith("rotate") && "mce-transformable--rotateing",
8633
- props.borderStyle && `mce-transformable--${props.borderStyle}`
8634
- ]]),
8635
- style: normalizeStyle(style.value)
8636
- }, {
8637
- default: withCtx(() => [
8638
- renderSlot(_ctx.$slots, "default", {
8639
- value: unref(modelValue),
8640
- props: {
8641
- onPointerdown: start
8642
- },
8643
- start
8644
- }),
8645
- (openBlock(), createElementBlock("svg", _hoisted_1$a, [
8646
- _cache[0] || (_cache[0] = createElementVNode("rect", {
8647
- width: "100%",
8648
- height: "100%",
8649
- fill: "none",
8650
- class: "mce-transformable__rect"
8651
- }, null, -1)),
8652
- createElementVNode("rect", {
8653
- class: "mce-transformable__rect",
8654
- width: "100%",
8655
- height: "100%",
8656
- fill: "none",
8657
- rx: model.value.borderRadius,
8658
- ry: model.value.borderRadius
8659
- }, null, 8, _hoisted_2$5),
8660
- createVNode(Diagonal),
8661
- createElementVNode("g", null, [
8662
- (openBlock(true), createElementBlock(Fragment, null, renderList(computedHandles.value, (handle, index) => {
8663
- return openBlock(), createElementBlock(Fragment, { key: index }, [
8664
- handle.shape ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
8665
- handle.shape === "rect" ? (openBlock(), createElementBlock("rect", {
8666
- key: 0,
8667
- x: handle.x,
8668
- y: handle.y,
8669
- width: handle.width,
8670
- height: handle.height,
8671
- "aria-label": handle.type,
8672
- class: "mce-transformable__handle"
8673
- }, null, 8, _hoisted_3$5)) : (openBlock(), createElementBlock("circle", {
8674
- key: 1,
8675
- cx: handle.x + handle.width / 2,
8676
- cy: handle.y + handle.width / 2,
8677
- r: handle.width / 2,
8678
- "aria-label": handle.type,
8679
- class: "mce-transformable__handle"
8680
- }, null, 8, _hoisted_4$3))
8681
- ], 64)) : createCommentVNode("", true)
8682
- ], 64);
8683
- }), 128))
8684
- ]),
8685
- createElementVNode("g", _hoisted_5$2, [
8686
- (openBlock(true), createElementBlock(Fragment, null, renderList(computedHandles.value, (handle, index) => {
8687
- return openBlock(), createElementBlock("rect", {
8688
- key: index,
8689
- ref_for: true,
8690
- ref_key: "handlesRef",
8691
- ref: handlesRef,
8692
- x: handle.x,
8693
- y: handle.y,
8694
- width: handle.width,
8695
- height: handle.height,
8696
- "aria-label": handle.type,
8697
- class: "mce-transformable__handle-rect",
8698
- cursor: transforming.value ? "auto" : getCursor(handle.type),
8699
- onPointerdown: (event) => start(event, index)
8700
- }, null, 40, _hoisted_6$2);
8701
- }), 128))
8702
- ]),
8703
- createElementVNode("g", _hoisted_7$2, [
8704
- renderSlot(_ctx.$slots, "svg", { box: model.value })
8705
- ])
8706
- ])),
8707
- tip.value ? (openBlock(), createElementBlock("div", _hoisted_8$1, toDisplayString(tip.value), 1)) : createCommentVNode("", true)
8708
- ]),
8709
- _: 3
8710
- }, 8, ["class", "style"]);
9049
+ return withDirectives((openBlock(), createElementBlock("div", {
9050
+ class: normalizeClass(["mce-scrollbar", {
9051
+ "mce-scrollbar--vertical": props.vertical,
9052
+ "mce-scrollbar--horizontal": !props.vertical
9053
+ }]),
9054
+ style: normalizeStyle({
9055
+ [props.vertical ? "height" : "width"]: `calc(100% - ${props.size + props.offset}px)`,
9056
+ [props.vertical ? "width" : "height"]: `${props.size}px`,
9057
+ [props.vertical ? "top" : "left"]: `${props.offset}px`
9058
+ })
9059
+ }, [
9060
+ createElementVNode("div", _hoisted_1$a, [
9061
+ createElementVNode("div", {
9062
+ ref: "thumbTplRef",
9063
+ class: normalizeClass(["mce-scrollbar__thumb", {
9064
+ "mce-scrollbar__thumb--active": isActive.value
9065
+ }]),
9066
+ style: normalizeStyle({
9067
+ top: thumbTop.value,
9068
+ bottom: thumbBottom.value,
9069
+ left: thumbLeft.value,
9070
+ right: thumbRight.value
9071
+ })
9072
+ }, null, 6)
9073
+ ], 512)
9074
+ ], 6)), [
9075
+ [unref(vResizeObserver), unref(resize)]
9076
+ ]);
9077
+ };
9078
+ }
9079
+ });
9080
+ const _sfc_main$h = /* @__PURE__ */ defineComponent({
9081
+ ...{
9082
+ inheritAttrs: false
9083
+ },
9084
+ __name: "Scrollbars",
9085
+ props: {
9086
+ infinite: { type: Boolean, default: true },
9087
+ offset: { default: 0 },
9088
+ size: { default: 8 }
9089
+ },
9090
+ setup(__props) {
9091
+ const props = __props;
9092
+ const {
9093
+ camera,
9094
+ viewAabb
9095
+ } = useEditor();
9096
+ return (_ctx, _cache) => {
9097
+ return openBlock(), createElementBlock(Fragment, null, [
9098
+ createVNode(_sfc_main$i, mergeProps(props, {
9099
+ modelValue: unref(camera).position.y,
9100
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => unref(camera).position.y = $event),
9101
+ vertical: "",
9102
+ length: unref(viewAabb).height * unref(camera).zoom.y
9103
+ }), null, 16, ["modelValue", "length"]),
9104
+ createVNode(_sfc_main$i, mergeProps(props, {
9105
+ modelValue: unref(camera).position.x,
9106
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => unref(camera).position.x = $event),
9107
+ length: unref(viewAabb).width * unref(camera).zoom.x
9108
+ }), null, 16, ["modelValue", "length"])
9109
+ ], 64);
8711
9110
  };
8712
9111
  }
8713
9112
  });
@@ -8875,7 +9274,7 @@ const _sfc_main$g = /* @__PURE__ */ defineComponent({
8875
9274
  })
8876
9275
  }, null, 4);
8877
9276
  }), 128)),
8878
- selectionTransform.value.width && selectionTransform.value.height ? (openBlock(), createBlock(_sfc_main$h, {
9277
+ selectionTransform.value.width && selectionTransform.value.height ? (openBlock(), createBlock(_sfc_main$w, {
8879
9278
  key: 1,
8880
9279
  ref: "transformableRef",
8881
9280
  modelValue: selectionTransform.value,
@@ -8944,7 +9343,7 @@ const _sfc_main$e = /* @__PURE__ */ defineComponent({
8944
9343
  ...props.defaultTransform
8945
9344
  });
8946
9345
  return (_ctx, _cache) => {
8947
- return openBlock(), createBlock(_sfc_main$h, {
9346
+ return openBlock(), createBlock(_sfc_main$w, {
8948
9347
  modelValue: transform.value,
8949
9348
  "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => transform.value = $event),
8950
9349
  class: "mce-float-panel",
@@ -8960,7 +9359,7 @@ const _sfc_main$e = /* @__PURE__ */ defineComponent({
8960
9359
  onClick: _cache[0] || (_cache[0] = ($event) => isActive.value = false)
8961
9360
  }, {
8962
9361
  default: withCtx(() => [
8963
- createVNode(_sfc_main$z, { icon: "$close" })
9362
+ createVNode(_sfc_main$C, { icon: "$close" })
8964
9363
  ]),
8965
9364
  _: 1
8966
9365
  })
@@ -9110,13 +9509,6 @@ const _sfc_main$a = /* @__PURE__ */ defineComponent({
9110
9509
  };
9111
9510
  }
9112
9511
  });
9113
- const _export_sfc = (sfc, props) => {
9114
- const target = sfc.__vccOpts || sfc;
9115
- for (const [key, val] of props) {
9116
- target[key] = val;
9117
- }
9118
- return target;
9119
- };
9120
9512
  const ProgressIndicator = /* @__PURE__ */ _export_sfc(_sfc_main$a, [["__scopeId", "data-v-c4234331"]]);
9121
9513
  const _hoisted_1$6 = { class: "mce-statusbar" };
9122
9514
  const _hoisted_2$3 = { class: "mce-statusbar__main" };
@@ -9164,7 +9556,7 @@ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
9164
9556
  ])
9165
9557
  ], 64)) : unref(state) === "transforming" ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [
9166
9558
  createElementVNode("div", _hoisted_8, [
9167
- createVNode(_sfc_main$z, { icon: "$mouseRightClick" })
9559
+ createVNode(_sfc_main$C, { icon: "$mouseRightClick" })
9168
9560
  ]),
9169
9561
  _cache[2] || (_cache[2] = createElementVNode("span", null, " / ", -1)),
9170
9562
  createElementVNode("div", _hoisted_9, [
@@ -9178,7 +9570,7 @@ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
9178
9570
  ])
9179
9571
  ], 64)) : unref(state) ? (openBlock(), createElementBlock("span", _hoisted_13, toDisplayString(unref(t)(unref(state))), 1)) : (openBlock(), createElementBlock(Fragment, { key: 3 }, [
9180
9572
  createElementVNode("div", _hoisted_14, [
9181
- createVNode(_sfc_main$z, { icon: "$mouseLeftClick" }),
9573
+ createVNode(_sfc_main$C, { icon: "$mouseLeftClick" }),
9182
9574
  createElementVNode("span", null, toDisplayString(unref(t)("selectObject")), 1)
9183
9575
  ]),
9184
9576
  _cache[4] || (_cache[4] = createElementVNode("span", null, " + ", -1)),
@@ -9188,7 +9580,7 @@ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
9188
9580
  ]),
9189
9581
  _cache[5] || (_cache[5] = createElementVNode("div", { class: "mce-statusbar__divider" }, null, -1)),
9190
9582
  createElementVNode("div", _hoisted_17, [
9191
- createVNode(_sfc_main$z, { icon: "$mouseLeftClick" }),
9583
+ createVNode(_sfc_main$C, { icon: "$mouseLeftClick" }),
9192
9584
  createElementVNode("span", null, toDisplayString(unref(t)("selectArea")), 1)
9193
9585
  ]),
9194
9586
  _cache[6] || (_cache[6] = createElementVNode("span", null, " + ", -1)),
@@ -9198,7 +9590,7 @@ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
9198
9590
  ]),
9199
9591
  _cache[7] || (_cache[7] = createElementVNode("div", { class: "mce-statusbar__divider" }, null, -1)),
9200
9592
  createElementVNode("div", _hoisted_20, [
9201
- createVNode(_sfc_main$z, { icon: "$mouseLeftClick" }),
9593
+ createVNode(_sfc_main$C, { icon: "$mouseLeftClick" }),
9202
9594
  createElementVNode("span", null, toDisplayString(unref(t)("dragSelected")), 1)
9203
9595
  ])
9204
9596
  ], 64))
@@ -9521,7 +9913,7 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
9521
9913
  class: "mce-timeline__play",
9522
9914
  onClick: toggle
9523
9915
  }, [
9524
- createVNode(_sfc_main$z, {
9916
+ createVNode(_sfc_main$C, {
9525
9917
  icon: paused.value ? "$play" : "$pause"
9526
9918
  }, null, 8, ["icon"])
9527
9919
  ])
@@ -9550,7 +9942,7 @@ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
9550
9942
  }, [
9551
9943
  createElementVNode("div", _hoisted_5, [
9552
9944
  createElementVNode("div", _hoisted_6, [
9553
- createVNode(_sfc_main$l, {
9945
+ createVNode(_sfc_main$k, {
9554
9946
  ref: "rulerTpl",
9555
9947
  zoom: 1 / unref(msPerPx) * fps.value,
9556
9948
  unit: 100,
@@ -9630,6 +10022,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
9630
10022
  }
9631
10023
  provide(IconsSymbol, createIcons());
9632
10024
  const {
10025
+ showMadeWith,
9633
10026
  config,
9634
10027
  drawboardDom,
9635
10028
  renderEngine,
@@ -9906,10 +10299,10 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
9906
10299
  }, [
9907
10300
  createElementVNode("canvas", _hoisted_2, null, 512),
9908
10301
  createVNode(_sfc_main$8, { ref: "textEditorTpl" }, null, 512),
9909
- createVNode(_sfc_main$A),
10302
+ createVNode(_sfc_main$D),
9910
10303
  createVNode(_sfc_main$q),
9911
10304
  createVNode(_sfc_main$s),
9912
- createVNode(_sfc_main$v),
10305
+ createVNode(_sfc_main$y),
9913
10306
  createVNode(_sfc_main$g, {
9914
10307
  ref: "selectorTpl",
9915
10308
  "selected-area": selectedArea.value,
@@ -9919,25 +10312,38 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
9919
10312
  renderSlot(_ctx.$slots, "transformer", { box })
9920
10313
  ]),
9921
10314
  default: withCtx(({ box }) => [
10315
+ createVNode(_sfc_main$u),
9922
10316
  renderSlot(_ctx.$slots, "selector", { box })
9923
10317
  ]),
9924
10318
  _: 3
9925
10319
  }, 8, ["selected-area", "resize-strategy"]),
9926
- unref(config).scrollbar ? (openBlock(), createBlock(_sfc_main$i, { key: 0 })) : createCommentVNode("", true),
9927
- _ctx.$slots.floatbar ? (openBlock(), createBlock(_sfc_main$u, {
10320
+ unref(config).scrollbar ? (openBlock(), createBlock(_sfc_main$h, { key: 0 })) : createCommentVNode("", true),
10321
+ _ctx.$slots.floatbar || _ctx.$slots["floatbar-top"] ? (openBlock(), createBlock(_sfc_main$x, {
9928
10322
  key: 1,
10323
+ location: "top-start",
9929
10324
  target: unref(state) === "typing" ? textEditor.value?.textEditor : selector.value?.transformable?.$el
9930
10325
  }, {
9931
10326
  default: withCtx(() => [
9932
- renderSlot(_ctx.$slots, "floatbar")
10327
+ renderSlot(_ctx.$slots, "floatbar"),
10328
+ renderSlot(_ctx.$slots, "floatbar-top")
10329
+ ]),
10330
+ _: 3
10331
+ }, 8, ["target"])) : createCommentVNode("", true),
10332
+ _ctx.$slots["floatbar-bottom"] ? (openBlock(), createBlock(_sfc_main$x, {
10333
+ key: 2,
10334
+ location: "bottom-start",
10335
+ target: selector.value?.transformable?.$el
10336
+ }, {
10337
+ default: withCtx(() => [
10338
+ renderSlot(_ctx.$slots, "floatbar-bottom")
9933
10339
  ]),
9934
10340
  _: 3
9935
10341
  }, 8, ["target"])) : createCommentVNode("", true),
9936
- createVNode(_sfc_main$w),
10342
+ createVNode(_sfc_main$z),
9937
10343
  createVNode(_sfc_main$r),
9938
- unref(config).ruler ? (openBlock(), createBlock(_sfc_main$k, { key: 2 })) : createCommentVNode("", true),
10344
+ unref(config).ruler ? (openBlock(), createBlock(_sfc_main$j, { key: 3 })) : createCommentVNode("", true),
9939
10345
  unref(config).layers ? (openBlock(), createBlock(_sfc_main$e, {
9940
- key: 3,
10346
+ key: 4,
9941
10347
  modelValue: unref(config).layers,
9942
10348
  "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => unref(config).layers = $event),
9943
10349
  title: unref(t)("layers"),
@@ -9953,6 +10359,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
9953
10359
  ]),
9954
10360
  _: 1
9955
10361
  }, 8, ["modelValue", "title", "default-transform"])) : createCommentVNode("", true),
10362
+ unref(showMadeWith) ? (openBlock(), createBlock(MadeWith, { key: 5 })) : createCommentVNode("", true),
9956
10363
  createVNode(Toolbelt),
9957
10364
  renderSlot(_ctx.$slots, "drawboard")
9958
10365
  ], 40, _hoisted_1)
@@ -10016,7 +10423,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
10016
10423
  updateLocation
10017
10424
  });
10018
10425
  return (_ctx, _cache) => {
10019
- return openBlock(), createBlock(_sfc_main$y, {
10426
+ return openBlock(), createBlock(_sfc_main$B, {
10020
10427
  ref: "overlayTpl",
10021
10428
  modelValue: isActive.value,
10022
10429
  "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => isActive.value = $event),
@@ -10040,6 +10447,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
10040
10447
  }
10041
10448
  });
10042
10449
  export {
10450
+ _sfc_main$v as Cropper,
10043
10451
  _sfc_main as Dialog,
10044
10452
  Doc,
10045
10453
  Editor,
@@ -10056,12 +10464,12 @@ export {
10056
10464
  MceMenuSymbol,
10057
10465
  MceOverlaySymbol,
10058
10466
  MceSvgIcon,
10059
- _sfc_main$x as Menu,
10467
+ _sfc_main$A as Menu,
10060
10468
  Model,
10061
- _sfc_main$l as Ruler,
10469
+ _sfc_main$k as Ruler,
10062
10470
  SUPPORTS_CLIPBOARD,
10063
- _sfc_main$j as Scrollbar,
10064
- _sfc_main$h as Transformable,
10471
+ _sfc_main$i as Scrollbar,
10472
+ _sfc_main$w as Transformable,
10065
10473
  USER_AGENT,
10066
10474
  boundingBoxToStyle,
10067
10475
  consoleError,