mce 0.12.1 → 0.12.2

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.d.ts CHANGED
@@ -17,4 +17,4 @@ export * from './plugins';
17
17
  export * from './types';
18
18
  export * from './utils';
19
19
  export type { Camera2D, Element2D, Engine } from 'modern-canvas';
20
- export type { Element, NormalizedElement } from 'modern-idoc';
20
+ export type { Document, Element, NormalizedElement } from 'modern-idoc';
package/dist/index.js CHANGED
@@ -124,26 +124,7 @@ const _0_config_base = defineMixin((editor, options) => {
124
124
  registerConfig("typographyStrategy", "autoHeight");
125
125
  registerConfig("handleShape", "rect");
126
126
  registerConfig("localDb", false);
127
- const screenCenterOffset = { left: 0, top: 0, bottom: 0, right: 0 };
128
- registerConfig("screenCenterOffset", { ...screenCenterOffset });
129
- const getScreenCenterOffset = () => {
130
- const offset2 = {
131
- ...screenCenterOffset,
132
- ...config.value.screenCenterOffset
133
- };
134
- if (config.value.scrollbar) {
135
- offset2.right += 8;
136
- offset2.bottom += 8;
137
- }
138
- if (config.value.ruler) {
139
- offset2.left += 16;
140
- offset2.top += 16;
141
- }
142
- return offset2;
143
- };
144
- Object.assign(editor, {
145
- getScreenCenterOffset
146
- });
127
+ registerConfig("screenCenterOffset", { left: 0, top: 0, bottom: 0, right: 0 });
147
128
  return () => {
148
129
  const {
149
130
  camera,
@@ -667,6 +648,10 @@ class Doc extends Model {
667
648
  this.reset();
668
649
  this.addElements(children);
669
650
  this.setProperties(props);
651
+ this._yProps.clear();
652
+ for (const key in props) {
653
+ this._yProps.set(key, props[key]);
654
+ }
670
655
  this._yProps.set("meta", new Y.Map(Object.entries(meta)));
671
656
  return this;
672
657
  }
@@ -998,6 +983,30 @@ const _0_font = defineMixin((editor, options) => {
998
983
  }
999
984
  };
1000
985
  });
986
+ const _0_helper = defineMixin((editor) => {
987
+ const block = ["top", "bottom"];
988
+ const inline = ["start", "end", "left", "right"];
989
+ function toPhysical(str, isRtl) {
990
+ if (str === "start")
991
+ return isRtl ? "right" : "left";
992
+ if (str === "end")
993
+ return isRtl ? "left" : "right";
994
+ return str;
995
+ }
996
+ const parseAnchor = (anchor, isRtl) => {
997
+ let [side, align] = anchor.split(" ");
998
+ if (!align) {
999
+ align = block.includes(side) ? "start" : inline.includes(side) ? "top" : "center";
1000
+ }
1001
+ return {
1002
+ side: toPhysical(side, isRtl),
1003
+ align: toPhysical(align, isRtl)
1004
+ };
1005
+ };
1006
+ Object.assign(editor, {
1007
+ parseAnchor
1008
+ });
1009
+ });
1001
1010
  const en = {
1002
1011
  "cancel": "Cancel",
1003
1012
  "constrainToAxis": "Constrain to axis",
@@ -1561,6 +1570,41 @@ const _1_hotkey = defineMixin((editor) => {
1561
1570
  );
1562
1571
  };
1563
1572
  });
1573
+ const _1_screen = defineMixin((editor) => {
1574
+ const {
1575
+ config,
1576
+ drawboardAabb
1577
+ } = editor;
1578
+ const getScreenCenterOffset = () => {
1579
+ const offset2 = {
1580
+ left: 0,
1581
+ top: 0,
1582
+ bottom: 0,
1583
+ right: 0,
1584
+ ...config.value.screenCenterOffset
1585
+ };
1586
+ if (config.value.scrollbar) {
1587
+ offset2.right += 8;
1588
+ offset2.bottom += 8;
1589
+ }
1590
+ if (config.value.ruler) {
1591
+ offset2.left += 16;
1592
+ offset2.top += 16;
1593
+ }
1594
+ return offset2;
1595
+ };
1596
+ const getScreenCenter = () => {
1597
+ const offset2 = getScreenCenterOffset();
1598
+ return {
1599
+ x: offset2.left + (drawboardAabb.value.width - offset2.left - offset2.right) / 2,
1600
+ y: offset2.top + (drawboardAabb.value.height - offset2.top - offset2.bottom) / 2
1601
+ };
1602
+ };
1603
+ Object.assign(editor, {
1604
+ getScreenCenterOffset,
1605
+ getScreenCenter
1606
+ });
1607
+ });
1564
1608
  const _1_timeline = defineMixin((editor) => {
1565
1609
  const {
1566
1610
  root,
@@ -2187,64 +2231,48 @@ const _4_2_element = defineMixin((editor) => {
2187
2231
  getAncestorFrame,
2188
2232
  getAabb,
2189
2233
  getGlobalPointer,
2234
+ getScreenCenter,
2190
2235
  selection,
2191
- getScreenCenterOffset,
2192
2236
  camera,
2193
- drawboardAabb
2237
+ parseAnchor
2194
2238
  } = editor;
2195
2239
  function addElement(value, options = {}) {
2196
2240
  log("addElement", value, options);
2241
+ const {
2242
+ frameGap
2243
+ } = config.value;
2197
2244
  let {
2198
- frame,
2245
+ parent,
2199
2246
  sizeToFit,
2200
2247
  position,
2201
2248
  active,
2202
2249
  regenId
2203
2250
  } = options;
2204
- if (!frame) {
2251
+ if (!parent) {
2205
2252
  if (config.value.viewMode === "frame") {
2206
- frame = currentFrame.value;
2253
+ parent = currentFrame.value;
2207
2254
  } else {
2208
2255
  const element = selection.value[0];
2209
2256
  if (element) {
2210
2257
  if (isFrame(element)) {
2211
- frame = element;
2258
+ parent = element;
2212
2259
  } else {
2213
- frame = getAncestorFrame(element);
2260
+ parent = getAncestorFrame(element);
2214
2261
  }
2215
2262
  }
2216
2263
  }
2217
2264
  }
2218
- let initPos;
2219
- switch (position) {
2220
- case "screenCenter": {
2221
- const screenCenterOffset = getScreenCenterOffset();
2222
- const { zoom, position: position2 } = camera.value;
2223
- const centerOffset = {
2224
- x: position2.x + screenCenterOffset.left + (drawboardAabb.value.width - screenCenterOffset.left - screenCenterOffset.right) / 2,
2225
- y: position2.y + screenCenterOffset.top + (drawboardAabb.value.height - screenCenterOffset.top - screenCenterOffset.bottom) / 2
2226
- };
2227
- initPos = {
2228
- x: centerOffset.x * zoom.x,
2229
- y: centerOffset.y * zoom.y
2230
- };
2231
- break;
2232
- }
2233
- case "fit":
2234
- initPos = {
2235
- x: rootAabb.value.left + rootAabb.value.width + config.value.frameGap,
2236
- y: rootAabb.value.top
2237
- };
2238
- break;
2239
- }
2240
2265
  const isArray = Array.isArray(value);
2241
2266
  let offsetX = 0;
2242
2267
  const elements = doc.value.transact(() => {
2243
2268
  const values = isArray ? value : [value];
2244
2269
  const elements2 = values.map((element) => {
2245
- const el = doc.value.addElement(element, { parentId: frame?.id, regenId });
2246
- if (frame) {
2247
- const { width, height } = frame.style;
2270
+ const el = doc.value.addElement(element, {
2271
+ parentId: parent?.id,
2272
+ regenId
2273
+ });
2274
+ if (parent) {
2275
+ const { width, height } = parent.style;
2248
2276
  const halfWidth = width / 2;
2249
2277
  const halfHeight = height / 2;
2250
2278
  if (!el.style.width)
@@ -2265,22 +2293,79 @@ const _4_2_element = defineMixin((editor) => {
2265
2293
  }
2266
2294
  );
2267
2295
  }
2268
- if (position === "fit") {
2269
- el.style.left = Math.round(width - el.style.width) / 2;
2270
- el.style.top = Math.round(height - el.style.height) / 2;
2271
- }
2272
- } else {
2273
- if (initPos) {
2274
- el.style.top = Math.round(initPos.x);
2275
- el.style.left = Math.round(initPos.y);
2276
- initPos.x += el.style.height + config.value.frameGap;
2277
- }
2278
2296
  }
2279
2297
  el.style.left += offsetX;
2280
2298
  offsetX += el.style.width;
2281
2299
  return el;
2282
2300
  });
2283
2301
  const aabb = getAabb(elements2);
2302
+ const parentAabb = parent ? getAabb(parent) : void 0;
2303
+ let globalPosition;
2304
+ if (typeof position === "string") {
2305
+ switch (position) {
2306
+ case "pointer":
2307
+ break;
2308
+ case "screenCenter":
2309
+ globalPosition = camera.value.toGlobal(getScreenCenter());
2310
+ break;
2311
+ default: {
2312
+ const _parentAabb = parentAabb ?? rootAabb.value;
2313
+ const anchor = parseAnchor(position);
2314
+ globalPosition = { x: 0, y: 0 };
2315
+ const map = {
2316
+ centerX: () => globalPosition.x = _parentAabb.left + _parentAabb.width / 2,
2317
+ centerY: () => globalPosition.y = _parentAabb.top + _parentAabb.height / 2
2318
+ };
2319
+ if (anchor.side === "center") {
2320
+ map.centerX();
2321
+ map.centerY();
2322
+ } else {
2323
+ if (anchor.side === "left" || anchor.side === "right") {
2324
+ switch (anchor.side) {
2325
+ case "left":
2326
+ globalPosition.x = _parentAabb.left - (aabb.width + frameGap);
2327
+ break;
2328
+ case "right":
2329
+ globalPosition.x = _parentAabb.left + _parentAabb.width + frameGap;
2330
+ break;
2331
+ }
2332
+ switch (anchor.align) {
2333
+ case "top":
2334
+ globalPosition.y = _parentAabb.top;
2335
+ break;
2336
+ case "bottom":
2337
+ globalPosition.y = _parentAabb.top + _parentAabb.height;
2338
+ break;
2339
+ case "center":
2340
+ map.centerY();
2341
+ break;
2342
+ }
2343
+ } else if (anchor.side === "top" || anchor.side === "bottom") {
2344
+ switch (anchor.side) {
2345
+ case "top":
2346
+ globalPosition.y = _parentAabb.top - (aabb.height + frameGap);
2347
+ break;
2348
+ case "bottom":
2349
+ globalPosition.y = _parentAabb.top + _parentAabb.height + frameGap;
2350
+ break;
2351
+ }
2352
+ switch (anchor.align) {
2353
+ case "left":
2354
+ globalPosition.x = _parentAabb.left;
2355
+ break;
2356
+ case "right":
2357
+ globalPosition.x = _parentAabb.left + _parentAabb.width;
2358
+ break;
2359
+ case "center":
2360
+ map.centerX();
2361
+ break;
2362
+ }
2363
+ }
2364
+ }
2365
+ break;
2366
+ }
2367
+ }
2368
+ }
2284
2369
  if (position === "pointer") {
2285
2370
  const pointer = getGlobalPointer();
2286
2371
  const diff = {
@@ -2291,6 +2376,16 @@ const _4_2_element = defineMixin((editor) => {
2291
2376
  el.style.left += diff.x;
2292
2377
  el.style.top += diff.y;
2293
2378
  });
2379
+ } else if (globalPosition) {
2380
+ elements2.forEach((el) => {
2381
+ el.style.left = Math.round(
2382
+ parentAabb ? parentAabb.left - globalPosition.x : globalPosition.x
2383
+ );
2384
+ el.style.top = Math.round(
2385
+ parentAabb ? parentAabb.top - globalPosition.y : globalPosition.y
2386
+ );
2387
+ globalPosition.x += el.style.width + frameGap;
2388
+ });
2294
2389
  }
2295
2390
  return elements2;
2296
2391
  });
@@ -2503,17 +2598,18 @@ const _4_4_doc = defineMixin((editor, options) => {
2503
2598
  }
2504
2599
  const setDoc = async (source) => {
2505
2600
  let id;
2601
+ let _source = source;
2506
2602
  if (typeof source === "string") {
2507
2603
  id = source;
2508
2604
  } else if (source) {
2509
2605
  if (Array.isArray(source) && source.length === 1) {
2510
- source = source[0];
2606
+ _source = source[0];
2511
2607
  }
2512
2608
  if (!Array.isArray(source)) {
2513
2609
  if (source.meta?.inEditorIs === "Doc") {
2514
2610
  id = source.id;
2515
2611
  } else {
2516
- source = [source];
2612
+ _source = [source];
2517
2613
  }
2518
2614
  }
2519
2615
  }
@@ -2522,7 +2618,7 @@ const _4_4_doc = defineMixin((editor, options) => {
2522
2618
  try {
2523
2619
  await waitUntilFontLoad();
2524
2620
  clearDoc();
2525
- await initDoc(_doc, source);
2621
+ await initDoc(_doc, _source);
2526
2622
  doc.value = _doc;
2527
2623
  emit("setDoc", _doc);
2528
2624
  } finally {
@@ -2558,8 +2654,7 @@ const _scroll$1 = defineMixin((editor) => {
2558
2654
  getAabb,
2559
2655
  selectionAabb,
2560
2656
  viewAabb,
2561
- drawboardAabb,
2562
- getScreenCenterOffset
2657
+ getScreenCenter
2563
2658
  } = editor;
2564
2659
  const scrollTo = async (target, options = {}) => {
2565
2660
  const {
@@ -2567,7 +2662,7 @@ const _scroll$1 = defineMixin((editor) => {
2567
2662
  duration = 500
2568
2663
  } = options;
2569
2664
  const _camera = camera.value;
2570
- const screenCenterOffset = getScreenCenterOffset();
2665
+ const screenCenter = getScreenCenter();
2571
2666
  const offset2 = { x: 0, y: 0 };
2572
2667
  let position = { x: 0, y: 0 };
2573
2668
  if (typeof target === "object" && "x" in target && "y" in target) {
@@ -2589,10 +2684,8 @@ const _scroll$1 = defineMixin((editor) => {
2589
2684
  }
2590
2685
  }
2591
2686
  position = { x: aabb.left + aabb.width / 2, y: aabb.top + aabb.height / 2 };
2592
- offset2.x -= screenCenterOffset.left;
2593
- offset2.x -= (drawboardAabb.value.width - screenCenterOffset.left - screenCenterOffset.right) / 2;
2594
- offset2.y -= screenCenterOffset.top;
2595
- offset2.y -= (drawboardAabb.value.height - screenCenterOffset.top - screenCenterOffset.bottom) / 2;
2687
+ offset2.x += -screenCenter.x;
2688
+ offset2.y = -screenCenter.y;
2596
2689
  }
2597
2690
  position.x *= _camera.zoom.x;
2598
2691
  position.x += offset2.x;
@@ -2700,8 +2793,8 @@ const _snapshot = defineMixin((editor) => {
2700
2793
  const sh = aabb.height * zoom.y;
2701
2794
  ctx.drawImage(
2702
2795
  view,
2703
- (aabb.left * zoom.x + position.x) * pixelRatio,
2704
- (aabb.top * zoom.x + position.y) * pixelRatio,
2796
+ (aabb.left * zoom.x - position.x) * pixelRatio,
2797
+ (aabb.top * zoom.x - position.y) * pixelRatio,
2705
2798
  sw * pixelRatio,
2706
2799
  sh * pixelRatio,
2707
2800
  0,
@@ -2860,9 +2953,11 @@ const mixins = [
2860
2953
  _0_context,
2861
2954
  _0_element,
2862
2955
  _0_font,
2956
+ _0_helper,
2863
2957
  _0_locale,
2864
2958
  _1_frame,
2865
2959
  _1_hotkey,
2960
+ _1_screen,
2866
2961
  _1_timeline,
2867
2962
  _1_upload,
2868
2963
  _2_box,
@@ -4696,7 +4791,7 @@ const _image = definePlugin((editor) => {
4696
4791
  const insertImage = async (url, options) => {
4697
4792
  return addElement(await createImageElement(url), {
4698
4793
  sizeToFit: true,
4699
- position: "fit",
4794
+ position: "right",
4700
4795
  ...options
4701
4796
  });
4702
4797
  };
@@ -4775,7 +4870,7 @@ const _import = definePlugin((editor) => {
4775
4870
  return addElement((await Promise.all(files.map((file) => load(file)))).flat(), {
4776
4871
  ...options,
4777
4872
  sizeToFit: true,
4778
- position: "fit"
4873
+ position: "right"
4779
4874
  });
4780
4875
  };
4781
4876
  return {
@@ -4869,9 +4964,7 @@ const _json = definePlugin((editor) => {
4869
4964
  elements = selection.value;
4870
4965
  }
4871
4966
  if (elements.length === 0 && root.value) {
4872
- if (root.value.meta.id) {
4873
- id = root.value.meta.id;
4874
- }
4967
+ id = root.value.id;
4875
4968
  elements = root.value.children;
4876
4969
  }
4877
4970
  }
@@ -4898,6 +4991,7 @@ const _json = definePlugin((editor) => {
4898
4991
  }),
4899
4992
  meta: {
4900
4993
  inPptIs: "Pptx",
4994
+ inEditorIs: "Doc",
4901
4995
  inCanvasIs: "Element2D",
4902
4996
  ...getTimeRange(elements)
4903
4997
  }
@@ -5411,7 +5505,7 @@ const _text = definePlugin((editor) => {
5411
5505
  const { style, ...restOptions } = options;
5412
5506
  return addElement(createTextElement(content, style), {
5413
5507
  sizeToFit: true,
5414
- position: "fit",
5508
+ position: "right",
5415
5509
  ...restOptions
5416
5510
  });
5417
5511
  };
@@ -6364,7 +6458,7 @@ const _sfc_main$v = /* @__PURE__ */ defineComponent({
6364
6458
  const style = computed(() => {
6365
6459
  return {
6366
6460
  ...floatingStyles.value,
6367
- zIndex: 2e3 + overlayItem.index.value
6461
+ zIndex: 1500 + overlayItem.index.value
6368
6462
  };
6369
6463
  });
6370
6464
  const activatorProps = computed(() => {
@@ -8323,7 +8417,7 @@ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
8323
8417
  const { zoom, position } = camera.value;
8324
8418
  return {
8325
8419
  transformOrigin: "left top",
8326
- transform: `translate(${position.x}px, ${position.y}px) scale(${zoom.x}, ${zoom.y})`
8420
+ transform: `translate(${-position.x}px, ${-position.y}px) scale(${zoom.x}, ${zoom.y})`
8327
8421
  };
8328
8422
  });
8329
8423
  const textEditorStyle = computed(() => {
@@ -30,9 +30,6 @@ declare global {
30
30
  localDb: boolean;
31
31
  screenCenterOffset: ScreenCenterOffset;
32
32
  }
33
- interface Editor {
34
- getScreenCenterOffset: () => Required<ScreenCenterOffset>;
35
- }
36
33
  }
37
34
  }
38
35
  declare const _default: import("../..").Mixin;
@@ -0,0 +1,22 @@
1
+ declare global {
2
+ namespace Mce {
3
+ type Tblock = 'top' | 'bottom';
4
+ type Tinline = 'start' | 'end' | 'left' | 'right';
5
+ type Anchor = Tblock | Tinline | 'center' | 'center center' | `${Tblock} ${Tinline | 'center'}` | `${Tinline} ${Tblock | 'center'}`;
6
+ type ParsedAnchor = {
7
+ side: 'center';
8
+ align: 'center';
9
+ } | {
10
+ side: Tblock;
11
+ align: 'left' | 'right' | 'center';
12
+ } | {
13
+ side: 'left' | 'right';
14
+ align: Tblock | 'center';
15
+ };
16
+ interface Editor {
17
+ parseAnchor: (anchor: Anchor, isRtl?: boolean) => ParsedAnchor;
18
+ }
19
+ }
20
+ }
21
+ declare const _default: import("..").Mixin;
22
+ export default _default;
@@ -0,0 +1,13 @@
1
+ declare global {
2
+ namespace Mce {
3
+ interface Editor {
4
+ getScreenCenterOffset: () => Required<ScreenCenterOffset>;
5
+ getScreenCenter: () => {
6
+ x: number;
7
+ y: number;
8
+ };
9
+ }
10
+ }
11
+ }
12
+ declare const _default: import("..").Mixin;
13
+ export default _default;
@@ -3,10 +3,12 @@ import type { Element } from 'modern-idoc';
3
3
  import type { AxisAlignedBoundingBox } from '../types';
4
4
  declare global {
5
5
  namespace Mce {
6
+ type AddElementPosition = Vector2Data | Anchor | 'screenCenter' | 'pointer';
6
7
  interface AddElementOptions {
7
- frame?: Element2D;
8
+ parent?: Element2D;
9
+ position?: AddElementPosition;
10
+ append?: boolean;
8
11
  sizeToFit?: boolean;
9
- position?: Vector2Data | 'fit' | 'screenCenter' | 'pointer';
10
12
  active?: boolean;
11
13
  regenId?: boolean;
12
14
  }
@@ -2,14 +2,22 @@ import type { Document, Element } from 'modern-idoc';
2
2
  import { Doc } from '../models';
3
3
  declare global {
4
4
  namespace Mce {
5
+ interface InternalDocument extends Document {
6
+ id: string;
7
+ meta: {
8
+ [key: string]: any;
9
+ inEditorIs: 'Doc';
10
+ };
11
+ }
12
+ type DocumentSource = InternalDocument | Element[] | string;
5
13
  interface Editor {
6
14
  getDoc: () => JsonData;
7
- setDoc: (doc: Document | Element[] | string) => Promise<Doc>;
15
+ setDoc: (doc: DocumentSource) => Promise<Doc>;
8
16
  loadDoc: (source: any) => Promise<Doc>;
9
17
  clearDoc: () => void;
10
18
  }
11
19
  interface Options {
12
- doc?: Document | string;
20
+ doc?: DocumentSource;
13
21
  }
14
22
  interface Events {
15
23
  setDoc: [doc: Doc];
@@ -12,7 +12,8 @@ declare global {
12
12
  children: NormalizedElement[];
13
13
  meta: {
14
14
  inPptIs: 'Pptx';
15
- inCanvasIs: 'Node2D';
15
+ inEditorIs: 'Doc';
16
+ inCanvasIs: 'Element2D';
16
17
  startTime: number;
17
18
  endTime: number;
18
19
  };
@@ -8,9 +8,11 @@ import './mixins/0.config/base'
8
8
  import './mixins/0.context'
9
9
  import './mixins/0.element'
10
10
  import './mixins/0.font'
11
+ import './mixins/0.helper'
11
12
  import './mixins/0.locale'
12
13
  import './mixins/1.frame'
13
14
  import './mixins/1.hotkey'
15
+ import './mixins/1.screen'
14
16
  import './mixins/1.timeline'
15
17
  import './mixins/1.upload'
16
18
  import './mixins/2.box'
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mce",
3
3
  "type": "module",
4
- "version": "0.12.1",
4
+ "version": "0.12.2",
5
5
  "description": "The headless canvas editor framework. only the ESM.",
6
6
  "author": "wxm",
7
7
  "license": "MIT",