@tmagic/editor 1.0.4 → 1.1.0-beta.1

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.
@@ -33,9 +33,10 @@ import {
33
33
  change2Fixed,
34
34
  COPY_STORAGE_KEY,
35
35
  Fixed2Other,
36
+ fixNodeLeft,
36
37
  generatePageNameByApp,
38
+ getInitPositionStyle,
37
39
  getNodeIndex,
38
- initPosition,
39
40
  isFixed,
40
41
  setLayout,
41
42
  } from '@editor/utils/editor';
@@ -70,6 +71,7 @@ class Editor extends BaseService {
70
71
  'paste',
71
72
  'alignCenter',
72
73
  'moveLayer',
74
+ 'moveToContainer',
73
75
  'move',
74
76
  'undo',
75
77
  'redo',
@@ -274,7 +276,7 @@ class Editor extends BaseService {
274
276
  const { type, ...config } = addNode;
275
277
  const curNode = this.get<MContainer>('node');
276
278
 
277
- let parentNode: MNode | undefined;
279
+ let parentNode: MContainer | undefined;
278
280
  const isPage = type === NodeType.PAGE;
279
281
 
280
282
  if (isPage) {
@@ -291,12 +293,8 @@ class Editor extends BaseService {
291
293
  if (!parentNode) throw new Error('未找到父元素');
292
294
 
293
295
  const layout = await this.getLayout(toRaw(parentNode), addNode as MNode);
294
- const newNode = initPosition(
295
- { ...toRaw(await propsService.getPropsValue(type, config)) },
296
- layout,
297
- parentNode,
298
- this.get<StageCore>('stage'),
299
- );
296
+ const newNode = { ...toRaw(await propsService.getPropsValue(type, config)) };
297
+ newNode.style = getInitPositionStyle(newNode.style, layout, parentNode, this.get<StageCore>('stage'));
300
298
 
301
299
  if ((parentNode?.type === NodeType.ROOT || curNode.type === NodeType.ROOT) && newNode.type !== NodeType.PAGE) {
302
300
  throw new Error('app下不能添加组件');
@@ -305,8 +303,17 @@ class Editor extends BaseService {
305
303
  parentNode?.items?.push(newNode);
306
304
 
307
305
  const stage = this.get<StageCore | null>('stage');
306
+ const root = this.get<MApp>('root');
307
+
308
+ await stage?.add({ config: cloneDeep(newNode), root: cloneDeep(root) });
308
309
 
309
- await stage?.add({ config: cloneDeep(newNode), root: cloneDeep(this.get('root')) });
310
+ if (layout === Layout.ABSOLUTE) {
311
+ const fixedLeft = fixNodeLeft(newNode, parentNode, stage?.renderer.contentWindow?.document);
312
+ if (typeof fixedLeft !== 'undefined') {
313
+ newNode.style.left = fixedLeft;
314
+ await stage?.update({ config: cloneDeep(newNode), root: cloneDeep(root) });
315
+ }
316
+ }
310
317
 
311
318
  await this.select(newNode);
312
319
 
@@ -348,7 +355,7 @@ class Editor extends BaseService {
348
355
 
349
356
  parent.items?.splice(index, 1);
350
357
  const stage = this.get<StageCore | null>('stage');
351
- stage?.remove({ id: node.id, root: this.get('root') });
358
+ stage?.remove({ id: node.id, root: cloneDeep(this.get('root')) });
352
359
 
353
360
  if (node.type === NodeType.PAGE) {
354
361
  this.state.pageLength -= 1;
@@ -431,7 +438,7 @@ class Editor extends BaseService {
431
438
  this.set('node', newConfig);
432
439
  }
433
440
 
434
- this.get<StageCore | null>('stage')?.update({ config: cloneDeep(newConfig), root: this.get('root') });
441
+ this.get<StageCore | null>('stage')?.update({ config: cloneDeep(newConfig), root: cloneDeep(this.get('root')) });
435
442
 
436
443
  if (newConfig.type === NodeType.PAGE) {
437
444
  this.set('page', newConfig);
@@ -464,7 +471,7 @@ class Editor extends BaseService {
464
471
  await this.update(parent);
465
472
  await this.select(node);
466
473
 
467
- this.get<StageCore | null>('stage')?.update({ config: cloneDeep(node), root: this.get('root') });
474
+ this.get<StageCore | null>('stage')?.update({ config: cloneDeep(node), root: cloneDeep(this.get('root')) });
468
475
 
469
476
  this.addModifiedNodeId(parent.id);
470
477
  this.pushHistoryState();
@@ -544,7 +551,10 @@ class Editor extends BaseService {
544
551
  }
545
552
 
546
553
  await this.update(node);
547
- this.get<StageCore | null>('stage')?.update({ config: cloneDeep(toRaw(node)), root: this.get('root') });
554
+ this.get<StageCore | null>('stage')?.update({
555
+ config: cloneDeep(toRaw(node)),
556
+ root: cloneDeep(this.get<MApp>('root')),
557
+ });
548
558
  this.addModifiedNodeId(config.id);
549
559
  this.pushHistoryState();
550
560
 
@@ -569,7 +579,54 @@ class Editor extends BaseService {
569
579
  brothers.splice(index + parseInt(`${offset}`, 10), 0, brothers.splice(index, 1)[0]);
570
580
  }
571
581
 
572
- this.get<StageCore | null>('stage')?.update({ config: cloneDeep(toRaw(parent)), root: this.get('root') });
582
+ this.get<StageCore | null>('stage')?.update({
583
+ config: cloneDeep(toRaw(parent)),
584
+ root: cloneDeep(this.get<MApp>('root')),
585
+ });
586
+ }
587
+
588
+ /**
589
+ * 移动到指定容器中
590
+ * @param config 需要移动的节点
591
+ * @param targetId 容器ID
592
+ */
593
+ public async moveToContainer(config: MNode, targetId: Id): Promise<MNode | undefined> {
594
+ const { node, parent } = this.getNodeInfo(config.id, false);
595
+ const target = this.getNodeById(targetId, false) as MContainer;
596
+
597
+ const stage = this.get<StageCore | null>('stage');
598
+
599
+ if (node && parent && stage) {
600
+ const root = cloneDeep(this.get<MApp>('root'));
601
+ const index = getNodeIndex(node, parent);
602
+ parent.items?.splice(index, 1);
603
+
604
+ await stage.remove({ id: node.id, root });
605
+
606
+ const layout = await this.getLayout(target);
607
+
608
+ const newConfig = mergeWith(cloneDeep(node), config, (objValue, srcValue) => {
609
+ if (Array.isArray(srcValue)) {
610
+ return srcValue;
611
+ }
612
+ });
613
+ newConfig.style = getInitPositionStyle(newConfig.style, layout, target, stage);
614
+
615
+ target.items.push(newConfig);
616
+
617
+ await stage.select(targetId);
618
+
619
+ await stage.update({ config: cloneDeep(target), root });
620
+
621
+ await this.select(newConfig);
622
+ stage.select(newConfig.id);
623
+
624
+ this.addModifiedNodeId(target.id);
625
+ this.addModifiedNodeId(parent.id);
626
+ this.pushHistoryState();
627
+
628
+ return newConfig;
629
+ }
573
630
  }
574
631
 
575
632
  /**
@@ -656,13 +713,13 @@ class Editor extends BaseService {
656
713
  }
657
714
 
658
715
  private async toggleFixedPosition(dist: MNode, src: MNode, root: MApp) {
659
- let newConfig = cloneDeep(dist);
716
+ const newConfig = cloneDeep(dist);
660
717
 
661
718
  if (!isPop(src) && newConfig.style?.position) {
662
719
  if (isFixed(newConfig) && !isFixed(src)) {
663
- newConfig = change2Fixed(newConfig, root);
720
+ newConfig.style = change2Fixed(newConfig, root);
664
721
  } else if (!isFixed(newConfig) && isFixed(src)) {
665
- newConfig = await Fixed2Other(newConfig, root, this.getLayout);
722
+ newConfig.style = await Fixed2Other(newConfig, root, this.getLayout);
666
723
  }
667
724
  }
668
725
 
package/src/type.ts CHANGED
@@ -49,9 +49,12 @@ export interface Services {
49
49
  export interface StageOptions {
50
50
  runtimeUrl: string;
51
51
  autoScrollIntoView: boolean;
52
+ containerHighlightClassName: string;
53
+ containerHighlightDuration: number;
52
54
  render: () => HTMLDivElement;
53
55
  moveableOptions: MoveableOptions | ((core?: StageCore) => MoveableOptions);
54
56
  canSelect: (el: HTMLElement) => boolean | Promise<boolean>;
57
+ isContainer: (el: HTMLElement) => boolean | Promise<boolean>;
55
58
  updateDragEl: (el: HTMLDivElement) => void;
56
59
  }
57
60
 
@@ -81,21 +81,17 @@ export const getNodeIndex = (node: MNode, parent: MContainer | MApp): number =>
81
81
  return items.findIndex((item: MNode) => `${item.id}` === `${node.id}`);
82
82
  };
83
83
 
84
- export const toRelative = (node: MNode) => {
85
- node.style = {
86
- ...(node.style || {}),
87
- position: 'relative',
88
- top: 0,
89
- left: 0,
90
- };
91
- return node;
92
- };
93
-
94
- const setTop2Middle = (node: MNode, parentNode: MNode, stage: StageCore) => {
95
- const style = node.style || {};
84
+ export const getRelativeStyle = (style: Record<string, any> = {}): Record<string, any> => ({
85
+ ...style,
86
+ position: 'relative',
87
+ top: 0,
88
+ left: 0,
89
+ });
90
+
91
+ const getMiddleTop = (style: Record<string, any> = {}, parentNode: MNode, stage: StageCore) => {
96
92
  let height = style.height || 0;
97
93
 
98
- if (!stage || typeof style.top !== 'undefined' || !parentNode.style) return style;
94
+ if (!stage || typeof style.top !== 'undefined' || !parentNode.style) return style.top;
99
95
 
100
96
  if (!isNumber(height)) {
101
97
  height = 0;
@@ -105,43 +101,45 @@ const setTop2Middle = (node: MNode, parentNode: MNode, stage: StageCore) => {
105
101
 
106
102
  if (isPage(parentNode)) {
107
103
  const { scrollTop = 0, wrapperHeight } = stage.mask;
108
- style.top = (wrapperHeight - height) / 2 + scrollTop;
109
- } else {
110
- style.top = (parentHeight - height) / 2;
104
+ return (wrapperHeight - height) / 2 + scrollTop;
111
105
  }
112
-
113
- return style;
106
+ return (parentHeight - height) / 2;
114
107
  };
115
108
 
116
- export const initPosition = (node: MNode, layout: Layout, parentNode: MNode, stage: StageCore) => {
109
+ export const getInitPositionStyle = (
110
+ style: Record<string, any> = {},
111
+ layout: Layout,
112
+ parentNode: MNode,
113
+ stage: StageCore,
114
+ ) => {
117
115
  if (layout === Layout.ABSOLUTE) {
118
- node.style = {
116
+ return {
117
+ ...style,
119
118
  position: 'absolute',
120
- ...setTop2Middle(node, parentNode, stage),
119
+ top: getMiddleTop(style, parentNode, stage),
121
120
  };
122
- return node;
123
121
  }
124
122
 
125
123
  if (layout === Layout.RELATIVE) {
126
- return toRelative(node);
124
+ return getRelativeStyle(style);
127
125
  }
128
126
 
129
- return node;
127
+ return style;
130
128
  };
131
129
 
132
130
  export const setLayout = (node: MNode, layout: Layout) => {
133
131
  node.items?.forEach((child: MNode) => {
134
132
  if (isPop(child)) return;
135
133
 
136
- child.style = child.style || {};
134
+ const style = child.style || {};
137
135
 
138
136
  // 是 fixed 不做处理
139
- if (child.style.position === 'fixed') return;
137
+ if (style.position === 'fixed') return;
140
138
 
141
139
  if (layout !== Layout.RELATIVE) {
142
- child.style.position = 'absolute';
140
+ style.position = 'absolute';
143
141
  } else {
144
- toRelative(child);
142
+ child.style = getRelativeStyle(style);
145
143
  child.style.right = 'auto';
146
144
  child.style.bottom = 'auto';
147
145
  }
@@ -161,11 +159,10 @@ export const change2Fixed = (node: MNode, root: MApp) => {
161
159
  offset.top = offset.top + globalThis.parseFloat(value.style?.top || 0);
162
160
  });
163
161
 
164
- node.style = {
162
+ return {
165
163
  ...(node.style || {}),
166
164
  ...offset,
167
165
  };
168
- return node;
169
166
  };
170
167
 
171
168
  export const Fixed2Other = async (
@@ -186,23 +183,23 @@ export const Fixed2Other = async (
186
183
  offset.left = offset.left - globalThis.parseFloat(value.style?.left || 0);
187
184
  offset.top = offset.top - globalThis.parseFloat(value.style?.top || 0);
188
185
  });
186
+ const style = node.style || {};
189
187
 
190
188
  const parent = path.pop();
191
189
  if (!parent) {
192
- return toRelative(node);
190
+ return getRelativeStyle(style);
193
191
  }
194
192
 
195
193
  const layout = await getLayout(parent);
196
194
  if (layout !== Layout.RELATIVE) {
197
- node.style = {
198
- ...(node.style || {}),
195
+ return {
196
+ ...style,
199
197
  ...offset,
200
198
  position: 'absolute',
201
199
  };
202
- return node;
203
200
  }
204
201
 
205
- return toRelative(node);
202
+ return getRelativeStyle(style);
206
203
  };
207
204
 
208
205
  export const getGuideLineFromCache = (key: string): number[] => {
@@ -219,3 +216,16 @@ export const getGuideLineFromCache = (key: string): number[] => {
219
216
 
220
217
  return [];
221
218
  };
219
+
220
+ export const fixNodeLeft = (config: MNode, parent: MContainer, doc?: Document) => {
221
+ if (!doc || !config.style || !isNumber(config.style.left)) return config.style?.left;
222
+
223
+ const el = doc.getElementById(`${config.id}`);
224
+ const parentEl = doc.getElementById(`${parent.id}`);
225
+
226
+ if (el && parentEl && el.offsetWidth + config.style?.left > parentEl.offsetWidth) {
227
+ return parentEl.offsetWidth - el.offsetWidth;
228
+ }
229
+
230
+ return config.style.left;
231
+ };