@node-projects/web-component-designer 0.0.130 → 0.0.132

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.
Files changed (29) hide show
  1. package/dist/commandHandling/IUiCommand.d.ts +3 -0
  2. package/dist/elements/helper/ITextWriter.d.ts +11 -0
  3. package/dist/elements/helper/ITextWriter.js +1 -0
  4. package/dist/elements/helper/IndentedTextWriter copy.d.ts +14 -0
  5. package/dist/elements/helper/IndentedTextWriter copy.js +34 -0
  6. package/dist/elements/helper/IndentedTextWriter.d.ts +2 -1
  7. package/dist/elements/helper/SimpleTextWriter copy.d.ts +12 -0
  8. package/dist/elements/helper/SimpleTextWriter copy.js +26 -0
  9. package/dist/elements/helper/SimpleTextWriter.d.ts +13 -0
  10. package/dist/elements/helper/SimpleTextWriter.js +26 -0
  11. package/dist/elements/helper/SwitchContainerHelper.d.ts +2 -0
  12. package/dist/elements/helper/SwitchContainerHelper.js +45 -0
  13. package/dist/elements/services/copyPasteService/CopyPasteService.d.ts +3 -1
  14. package/dist/elements/services/copyPasteService/CopyPasteService.js +25 -4
  15. package/dist/elements/services/copyPasteService/ICopyPasteService.d.ts +2 -1
  16. package/dist/elements/services/htmlWriterService/AbstractHtmlWriterService.d.ts +4 -4
  17. package/dist/elements/services/htmlWriterService/IHtmlWriterService.d.ts +2 -2
  18. package/dist/elements/services/undoService/ChangeGroup.d.ts +1 -0
  19. package/dist/elements/services/undoService/ChangeGroup.js +3 -0
  20. package/dist/elements/services/undoService/UndoService.js +9 -3
  21. package/dist/elements/widgets/designerView/DomConverter.d.ts +1 -1
  22. package/dist/elements/widgets/designerView/DomConverter.js +4 -3
  23. package/dist/elements/widgets/designerView/IDesignerCanvas.d.ts +4 -0
  24. package/dist/elements/widgets/designerView/designerCanvas.d.ts +5 -1
  25. package/dist/elements/widgets/designerView/designerCanvas.js +30 -12
  26. package/dist/elements/widgets/designerView/extensions/ResizeExtension.js +4 -4
  27. package/dist/elements/widgets/designerView/extensions/contextMenu/MultipleItemsSelectedContextMenu.js +6 -32
  28. package/dist/elements/widgets/treeView/treeViewExtended.js +14 -77
  29. package/package.json +1 -1
@@ -3,4 +3,7 @@ export interface IUiCommand {
3
3
  type: CommandType;
4
4
  special?: string;
5
5
  parameter?: any;
6
+ altKey?: boolean;
7
+ ctrlKey?: boolean;
8
+ shiftKey?: boolean;
6
9
  }
@@ -0,0 +1,11 @@
1
+ export interface ITextWriter {
2
+ get position(): number;
3
+ isLastCharNewline(): boolean;
4
+ levelRaise(): void;
5
+ levelShrink(): void;
6
+ write(text: string): void;
7
+ writeLine(text: string): void;
8
+ writeIndent(): void;
9
+ writeNewline(): void;
10
+ getString(): string;
11
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,14 @@
1
+ export declare class IndentedTextWriter {
2
+ private _textHolder;
3
+ readonly indent: number;
4
+ level: number;
5
+ get position(): number;
6
+ isLastCharNewline(): boolean;
7
+ levelRaise(): void;
8
+ levelShrink(): void;
9
+ write(text: string): void;
10
+ writeLine(text: string): void;
11
+ writeIndent(): void;
12
+ writeNewline(): void;
13
+ getString(): string;
14
+ }
@@ -0,0 +1,34 @@
1
+ export class IndentedTextWriter {
2
+ _textHolder = '';
3
+ indent = 4;
4
+ level = 0;
5
+ get position() {
6
+ return this._textHolder.length;
7
+ }
8
+ isLastCharNewline() {
9
+ return this._textHolder[this._textHolder.length - 1] === '\n';
10
+ }
11
+ levelRaise() {
12
+ this.level++;
13
+ }
14
+ levelShrink() {
15
+ this.level--;
16
+ }
17
+ write(text) {
18
+ this._textHolder += text;
19
+ }
20
+ writeLine(text) {
21
+ this.writeIndent();
22
+ this._textHolder += text;
23
+ this.writeNewline();
24
+ }
25
+ writeIndent() {
26
+ this._textHolder += ''.padEnd(this.level * this.indent, ' ');
27
+ }
28
+ writeNewline() {
29
+ this._textHolder += '\n';
30
+ }
31
+ getString() {
32
+ return this._textHolder;
33
+ }
34
+ }
@@ -1,4 +1,5 @@
1
- export declare class IndentedTextWriter {
1
+ import { ITextWriter } from './ITextWriter';
2
+ export declare class IndentedTextWriter implements ITextWriter {
2
3
  private _textHolder;
3
4
  readonly indent: number;
4
5
  level: number;
@@ -0,0 +1,12 @@
1
+ export declare class SimpleTextWriter {
2
+ private _textHolder;
3
+ get position(): number;
4
+ isLastCharNewline(): boolean;
5
+ levelRaise(): void;
6
+ levelShrink(): void;
7
+ write(text: string): void;
8
+ writeLine(text: string): void;
9
+ writeIndent(): void;
10
+ writeNewline(): void;
11
+ getString(): string;
12
+ }
@@ -0,0 +1,26 @@
1
+ export class SimpleTextWriter {
2
+ _textHolder = '';
3
+ get position() {
4
+ return this._textHolder.length;
5
+ }
6
+ isLastCharNewline() {
7
+ return this._textHolder[this._textHolder.length - 1] === '\n';
8
+ }
9
+ levelRaise() {
10
+ }
11
+ levelShrink() {
12
+ }
13
+ write(text) {
14
+ this._textHolder += text;
15
+ }
16
+ writeLine(text) {
17
+ this._textHolder += text;
18
+ }
19
+ writeIndent() {
20
+ }
21
+ writeNewline() {
22
+ }
23
+ getString() {
24
+ return this._textHolder;
25
+ }
26
+ }
@@ -0,0 +1,13 @@
1
+ import { ITextWriter } from './ITextWriter';
2
+ export declare class SimpleTextWriter implements ITextWriter {
3
+ private _textHolder;
4
+ get position(): number;
5
+ isLastCharNewline(): boolean;
6
+ levelRaise(): void;
7
+ levelShrink(): void;
8
+ write(text: string): void;
9
+ writeLine(text: string): void;
10
+ writeIndent(): void;
11
+ writeNewline(): void;
12
+ getString(): string;
13
+ }
@@ -0,0 +1,26 @@
1
+ export class SimpleTextWriter {
2
+ _textHolder = '';
3
+ get position() {
4
+ return this._textHolder.length;
5
+ }
6
+ isLastCharNewline() {
7
+ return this._textHolder[this._textHolder.length - 1] === '\n';
8
+ }
9
+ levelRaise() {
10
+ }
11
+ levelShrink() {
12
+ }
13
+ write(text) {
14
+ this._textHolder += text;
15
+ }
16
+ writeLine(text) {
17
+ this._textHolder += text;
18
+ }
19
+ writeIndent() {
20
+ }
21
+ writeNewline() {
22
+ }
23
+ getString() {
24
+ return this._textHolder;
25
+ }
26
+ }
@@ -0,0 +1,2 @@
1
+ import { IDesignItem } from "../item/IDesignItem";
2
+ export declare function switchContainer(items: IDesignItem[], newContainer: IDesignItem, resizeNewContainer?: boolean, newContainerOffset?: number): void;
@@ -0,0 +1,45 @@
1
+ export function switchContainer(items, newContainer, resizeNewContainer = false, newContainerOffset = 0) {
2
+ //todo...
3
+ //- switch to other containers? like grid, flexbox, ...
4
+ //- position non absolute, or absolute from bottom or right
5
+ const firstItem = items[0];
6
+ const grp = firstItem.openGroup('switchContainerHelper');
7
+ const designerCanvas = firstItem.instanceServiceContainer.designerCanvas;
8
+ let minX = Number.MAX_VALUE;
9
+ let minY = Number.MAX_VALUE;
10
+ let maxX = 0;
11
+ let maxY = 0;
12
+ for (let e of items) {
13
+ let rect = designerCanvas.getNormalizedElementCoordinates(e.element);
14
+ if (rect.x < minX)
15
+ minX = rect.x;
16
+ if (rect.y < minY)
17
+ minY = rect.y;
18
+ if (rect.x + rect.width > maxX)
19
+ maxX = rect.x + rect.width;
20
+ if (rect.y + rect.height > maxY)
21
+ maxY = rect.y + rect.height;
22
+ }
23
+ let rectNewContainer = designerCanvas.getNormalizedElementCoordinates(newContainer.element);
24
+ for (let e of items) {
25
+ let rect = designerCanvas.getNormalizedElementCoordinates(e.element);
26
+ e.remove();
27
+ if (resizeNewContainer) {
28
+ e.setStyle('left', (rect.x - minX + newContainerOffset).toString() + 'px');
29
+ e.setStyle('top', (rect.y - minY + newContainerOffset).toString() + 'px');
30
+ }
31
+ else {
32
+ e.setStyle('left', (rect.x - rectNewContainer.x).toString() + 'px');
33
+ e.setStyle('top', (rect.y - rectNewContainer.y).toString() + 'px');
34
+ }
35
+ newContainer.insertChild(e);
36
+ }
37
+ if (resizeNewContainer) {
38
+ newContainer.setStyle('position', 'absolute');
39
+ newContainer.setStyle('left', (minX - newContainerOffset).toString() + 'px');
40
+ newContainer.setStyle('top', (minY - newContainerOffset).toString() + 'px');
41
+ newContainer.setStyle('width', (maxX - minX + 2 * newContainerOffset).toString() + 'px');
42
+ newContainer.setStyle('height', (maxY - minY + 2 * newContainerOffset).toString() + 'px');
43
+ }
44
+ grp.commit();
45
+ }
@@ -2,7 +2,9 @@ import { IDesignItem } from "../../item/IDesignItem.js";
2
2
  import { ICopyPasteService } from "./ICopyPasteService.js";
3
3
  import { ServiceContainer } from '../ServiceContainer';
4
4
  import { InstanceServiceContainer } from '../InstanceServiceContainer';
5
+ import { IRect } from "../../../interfaces/IRect.js";
6
+ export declare const positionsJsonMime = "web text/positions";
5
7
  export declare class CopyPasteService implements ICopyPasteService {
6
8
  copyItems(designItems: IDesignItem[]): Promise<void>;
7
- getPasteItems(serviceContainer: ServiceContainer, instanceServiceContainer: InstanceServiceContainer): Promise<IDesignItem[]>;
9
+ getPasteItems(serviceContainer: ServiceContainer, instanceServiceContainer: InstanceServiceContainer): Promise<[designItems: IDesignItem[], positions?: IRect[]]>;
8
10
  }
@@ -1,12 +1,33 @@
1
1
  import { DomConverter } from "../../widgets/designerView/DomConverter.js";
2
+ export const positionsJsonMime = 'web text/positions';
2
3
  export class CopyPasteService {
3
4
  async copyItems(designItems) {
4
- const copyText = DomConverter.ConvertToString(designItems, null);
5
- await navigator.clipboard.writeText(copyText);
5
+ const copyText = DomConverter.ConvertToString(designItems, null, false);
6
+ const positions = designItems.map(x => x.instanceServiceContainer.designerCanvas.getNormalizedElementCoordinates(x.element));
7
+ const data = [new ClipboardItem({ ["text/html"]: new Blob([copyText], { type: 'text/html' }), [positionsJsonMime]: new Blob([JSON.stringify(positions)], { type: positionsJsonMime }) })];
8
+ try {
9
+ await navigator.clipboard.write(data);
10
+ }
11
+ catch (err) {
12
+ await navigator.clipboard.writeText(copyText);
13
+ }
6
14
  }
7
15
  async getPasteItems(serviceContainer, instanceServiceContainer) {
8
- const text = await navigator.clipboard.readText();
16
+ const items = await navigator.clipboard.read();
17
+ let html = '';
18
+ try {
19
+ html = await (await items[0].getType('text/html'))?.text();
20
+ }
21
+ catch { }
22
+ if (!html)
23
+ html = await (await items[0].getType('text/plain'))?.text();
24
+ let positions = null;
25
+ try {
26
+ let positionsJson = await (await items[0].getType(positionsJsonMime))?.text();
27
+ positions = JSON.parse(positionsJson);
28
+ }
29
+ catch { }
9
30
  const parserService = serviceContainer.htmlParserService;
10
- return await parserService.parse(text, serviceContainer, instanceServiceContainer);
31
+ return [await parserService.parse(html, serviceContainer, instanceServiceContainer), positions];
11
32
  }
12
33
  }
@@ -1,7 +1,8 @@
1
+ import { IRect } from "../../../interfaces/IRect.js";
1
2
  import { IDesignItem } from "../../item/IDesignItem.js";
2
3
  import { InstanceServiceContainer } from "../InstanceServiceContainer.js";
3
4
  import { ServiceContainer } from "../ServiceContainer.js";
4
5
  export interface ICopyPasteService {
5
6
  copyItems(designItems: IDesignItem[]): Promise<void>;
6
- getPasteItems(serviceContainer: ServiceContainer, instanceServiceContainer: InstanceServiceContainer): Promise<IDesignItem[]>;
7
+ getPasteItems(serviceContainer: ServiceContainer, instanceServiceContainer: InstanceServiceContainer): Promise<[designItems: IDesignItem[], positions?: IRect[]]>;
7
8
  }
@@ -1,10 +1,10 @@
1
1
  import { IDesignItem } from '../../item/IDesignItem.js';
2
2
  import { IHtmlWriterService } from './IHtmlWriterService.js';
3
3
  import { IHtmlWriterOptions } from './IHtmlWriterOptions.js';
4
- import { IndentedTextWriter } from '../../helper/IndentedTextWriter.js';
5
4
  import { IStringPosition } from './IStringPosition.js';
5
+ import { ITextWriter } from '../../helper/ITextWriter.js';
6
6
  export declare abstract class AbstractHtmlWriterService implements IHtmlWriterService {
7
- abstract write(indentedTextWriter: IndentedTextWriter, designItems: IDesignItem[], rootContainerKeepInline: boolean, options: IHtmlWriterOptions, designItemsAssignmentList?: Map<IDesignItem, IStringPosition>): any;
8
- writeAttributes(indentedTextWriter: IndentedTextWriter, designItem: IDesignItem, options: IHtmlWriterOptions): void;
9
- writeStyles(indentedTextWriter: IndentedTextWriter, designItem: IDesignItem, options: IHtmlWriterOptions): void;
7
+ abstract write(indentedTextWriter: ITextWriter, designItems: IDesignItem[], rootContainerKeepInline: boolean, options: IHtmlWriterOptions, designItemsAssignmentList?: Map<IDesignItem, IStringPosition>): any;
8
+ writeAttributes(indentedTextWriter: ITextWriter, designItem: IDesignItem, options: IHtmlWriterOptions): void;
9
+ writeStyles(indentedTextWriter: ITextWriter, designItem: IDesignItem, options: IHtmlWriterOptions): void;
10
10
  }
@@ -1,7 +1,7 @@
1
1
  import { IDesignItem } from '../../item/IDesignItem.js';
2
2
  import { IHtmlWriterOptions } from './IHtmlWriterOptions.js';
3
- import { IndentedTextWriter } from '../../helper/IndentedTextWriter.js';
3
+ import { ITextWriter } from '../../helper/ITextWriter.js';
4
4
  import { IStringPosition } from './IStringPosition.js';
5
5
  export interface IHtmlWriterService {
6
- write(indentedTextWriter: IndentedTextWriter, designItems: IDesignItem[], rootContainerKeepInline: boolean, options: IHtmlWriterOptions, designItemsAssignmentList?: Map<IDesignItem, IStringPosition>): any;
6
+ write(textWriter: ITextWriter, designItems: IDesignItem[], rootContainerKeepInline: boolean, options: IHtmlWriterOptions, designItemsAssignmentList?: Map<IDesignItem, IStringPosition>): any;
7
7
  }
@@ -11,6 +11,7 @@ export declare class ChangeGroup implements ITransactionItem {
11
11
  commit(): void;
12
12
  abort(): void;
13
13
  mergeWith(other: ITransactionItem): boolean;
14
+ addCommitedSubchangeGroup(changeGroup: ChangeGroup): void;
14
15
  undoStack: ITransactionItem[];
15
16
  redoStack: ITransactionItem[];
16
17
  execute(item: ITransactionItem): void;
@@ -51,6 +51,9 @@ export class ChangeGroup {
51
51
  mergeWith(other) {
52
52
  return false;
53
53
  }
54
+ addCommitedSubchangeGroup(changeGroup) {
55
+ this.undoStack.push(changeGroup);
56
+ }
54
57
  undoStack = [];
55
58
  redoStack = [];
56
59
  execute(item) {
@@ -21,9 +21,15 @@ export class UndoService {
21
21
  this.clear();
22
22
  throw "UndoService - Commited Transaction was not the last";
23
23
  }
24
- if (itm.undoStack.length)
25
- this._undoStack.push(itm);
26
- this._redoStack = [];
24
+ if (itm.undoStack.length) {
25
+ if (this._transactionStack.length > 0) {
26
+ this._transactionStack[this._transactionStack.length - 1].addCommitedSubchangeGroup(itm);
27
+ }
28
+ else {
29
+ this._undoStack.push(itm);
30
+ this._redoStack = [];
31
+ }
32
+ }
27
33
  }
28
34
  abortTransactionItem(transactionItem) {
29
35
  let itm = this._transactionStack.pop();
@@ -4,5 +4,5 @@ export declare class DomConverter {
4
4
  static normalizeAttributeValue(value: string | number, useSingleQuotes?: boolean): string;
5
5
  static normalizeContentValue(value: string): string;
6
6
  static IsSelfClosingElement(tag: string): boolean;
7
- static ConvertToString(designItems: IDesignItem[], designItemsAssignmentList?: Map<IDesignItem, IStringPosition>): string;
7
+ static ConvertToString(designItems: IDesignItem[], designItemsAssignmentList?: Map<IDesignItem, IStringPosition>, beautifyOutput?: boolean): string;
8
8
  }
@@ -1,4 +1,5 @@
1
1
  import { IndentedTextWriter } from "../../helper/IndentedTextWriter.js";
2
+ import { SimpleTextWriter } from "../../helper/SimpleTextWriter.js";
2
3
  export class DomConverter {
3
4
  static normalizeAttributeValue(value, useSingleQuotes = false) {
4
5
  if (typeof value === 'number')
@@ -32,9 +33,9 @@ export class DomConverter {
32
33
  tag === 'track' ||
33
34
  tag === 'wbr';
34
35
  }
35
- static ConvertToString(designItems, designItemsAssignmentList) {
36
- let itw = new IndentedTextWriter();
37
- let options = { beautifyOutput: true, writeDesignerProperties: true, compressCssToShorthandProperties: true, parseJsonInAttributes: true, jsonWriteMode: 'beauty' };
36
+ static ConvertToString(designItems, designItemsAssignmentList, beautifyOutput) {
37
+ let itw = beautifyOutput !== false ? new IndentedTextWriter() : new SimpleTextWriter();
38
+ let options = { beautifyOutput: beautifyOutput !== false, writeDesignerProperties: true, compressCssToShorthandProperties: true, parseJsonInAttributes: true, jsonWriteMode: 'beauty' };
38
39
  designItems[0].serviceContainer.htmlWriterService.write(itw, designItems, true, options, designItemsAssignmentList);
39
40
  return itw.getString();
40
41
  }
@@ -33,6 +33,10 @@ export interface IDesignerCanvas extends IPlacementView, IUiCommandHandler {
33
33
  getNormalizedEventCoordinates(event: MouseEvent): IPoint;
34
34
  getViewportCoordinates(event: MouseEvent): IPoint;
35
35
  getNormalizedElementCoordinates(element: Element): IRect;
36
+ getNormalizedElementCoordinatesAndRealSizes(element: Element): IRect & {
37
+ realWidth: number;
38
+ realHeight: number;
39
+ };
36
40
  captureActiveTool(tool: ITool): any;
37
41
  releaseActiveTool(): any;
38
42
  getDesignSurfaceDimensions(): ISize;
@@ -73,7 +73,7 @@ export declare class DesignerCanvas extends BaseCustomWebComponentLazyAppend imp
73
73
  canExecuteCommand(command: IUiCommand): boolean;
74
74
  handleSelectAll(): void;
75
75
  handleCopyCommand(): Promise<void>;
76
- handlePasteCommand(): Promise<void>;
76
+ handlePasteCommand(disableRestoreOfPositions: boolean): Promise<void>;
77
77
  handleDeleteCommand(): void;
78
78
  initialize(serviceContainer: ServiceContainer): void;
79
79
  connectedCallback(): void;
@@ -100,6 +100,10 @@ export declare class DesignerCanvas extends BaseCustomWebComponentLazyAppend imp
100
100
  */
101
101
  getViewportCoordinates(event: MouseEvent): IPoint;
102
102
  getNormalizedElementCoordinates(element: Element): IRect;
103
+ getNormalizedElementCoordinatesAndRealSizes(element: Element): IRect & {
104
+ realWidth: number;
105
+ realHeight: number;
106
+ };
103
107
  getNormalizedOffsetInElement(event: MouseEvent, element: Element): IPoint;
104
108
  elementFromPoint(x: number, y: number): Element;
105
109
  elementsFromPoint(x: number, y: number): Element[];
@@ -295,7 +295,7 @@ export class DesignerCanvas extends BaseCustomWebComponentLazyAppend {
295
295
  this.handleDeleteCommand();
296
296
  break;
297
297
  case CommandType.paste:
298
- this.handlePasteCommand();
298
+ this.handlePasteCommand(command.altKey == true);
299
299
  break;
300
300
  case CommandType.selectAll:
301
301
  this.handleSelectAll();
@@ -363,8 +363,8 @@ export class DesignerCanvas extends BaseCustomWebComponentLazyAppend {
363
363
  async handleCopyCommand() {
364
364
  await this.serviceContainer.copyPasteService.copyItems(this.instanceServiceContainer.selectionService.selectedElements);
365
365
  }
366
- async handlePasteCommand() {
367
- const designItems = await this.serviceContainer.copyPasteService.getPasteItems(this.serviceContainer, this.instanceServiceContainer);
366
+ async handlePasteCommand(disableRestoreOfPositions) {
367
+ const [designItems, positions] = await this.serviceContainer.copyPasteService.getPasteItems(this.serviceContainer, this.instanceServiceContainer);
368
368
  let grp = this.rootDesignItem.openGroup("Insert");
369
369
  let pasteContainer = this.rootDesignItem;
370
370
  let pCon = this.instanceServiceContainer.selectionService.primarySelection;
@@ -384,8 +384,15 @@ export class DesignerCanvas extends BaseCustomWebComponentLazyAppend {
384
384
  }
385
385
  }
386
386
  if (designItems) {
387
- for (let di of designItems) {
387
+ let containerPos = this.getNormalizedElementCoordinates(pasteContainer.element);
388
+ for (let i = 0; i < designItems.length; i++) {
389
+ let di = designItems[i];
390
+ let pos = positions ? positions[i] : null;
388
391
  this.instanceServiceContainer.undoService.execute(new InsertAction(pasteContainer, pasteContainer.childCount, di));
392
+ if (!disableRestoreOfPositions && pos) {
393
+ di.setStyle('left', (pos.x - containerPos.x) + 'px');
394
+ di.setStyle('top', (pos.y - containerPos.y) + 'px');
395
+ }
389
396
  }
390
397
  const intializationService = this.serviceContainer.intializationService;
391
398
  if (intializationService) {
@@ -656,19 +663,19 @@ export class DesignerCanvas extends BaseCustomWebComponentLazyAppend {
656
663
  if (event.composedPath().indexOf(this.eatEvents) >= 0)
657
664
  return;
658
665
  if ((event.ctrlKey || event.metaKey) && event.key === 'z' && !event.shiftKey)
659
- this.executeCommand({ type: CommandType.undo });
666
+ this.executeCommand({ type: CommandType.undo, ctrlKey: event.ctrlKey, altKey: event.altKey, shiftKey: event.shiftKey });
660
667
  else if ((event.ctrlKey || event.metaKey) && event.key === 'z' && event.shiftKey)
661
- this.executeCommand({ type: CommandType.redo });
668
+ this.executeCommand({ type: CommandType.redo, ctrlKey: event.ctrlKey, altKey: event.altKey, shiftKey: event.shiftKey });
662
669
  else if ((event.ctrlKey || event.metaKey) && event.key === 'y')
663
- this.executeCommand({ type: CommandType.redo });
670
+ this.executeCommand({ type: CommandType.redo, ctrlKey: event.ctrlKey, altKey: event.altKey, shiftKey: event.shiftKey });
664
671
  else if ((event.ctrlKey || event.metaKey) && event.key === 'a')
665
- this.executeCommand({ type: CommandType.selectAll });
672
+ this.executeCommand({ type: CommandType.selectAll, ctrlKey: event.ctrlKey, altKey: event.altKey, shiftKey: event.shiftKey });
666
673
  else if ((event.ctrlKey || event.metaKey) && event.key === 'c')
667
- this.executeCommand({ type: CommandType.copy });
674
+ this.executeCommand({ type: CommandType.copy, ctrlKey: event.ctrlKey, altKey: event.altKey, shiftKey: event.shiftKey });
668
675
  else if ((event.ctrlKey || event.metaKey) && event.key === 'v')
669
- this.executeCommand({ type: CommandType.paste });
676
+ this.executeCommand({ type: CommandType.paste, ctrlKey: event.ctrlKey, altKey: event.altKey, shiftKey: event.shiftKey });
670
677
  else if ((event.ctrlKey || event.metaKey) && event.key === 'x')
671
- this.executeCommand({ type: CommandType.cut });
678
+ this.executeCommand({ type: CommandType.cut, ctrlKey: event.ctrlKey, altKey: event.altKey, shiftKey: event.shiftKey });
672
679
  else {
673
680
  let primarySelection = this.instanceServiceContainer.selectionService.primarySelection;
674
681
  if (!primarySelection) {
@@ -680,7 +687,7 @@ export class DesignerCanvas extends BaseCustomWebComponentLazyAppend {
680
687
  switch (event.key) {
681
688
  case 'Delete':
682
689
  case 'Backspace':
683
- this.executeCommand({ type: CommandType.delete });
690
+ this.executeCommand({ type: CommandType.delete, ctrlKey: event.ctrlKey, altKey: event.altKey, shiftKey: event.shiftKey });
684
691
  break;
685
692
  case 'ArrowUp':
686
693
  {
@@ -736,6 +743,17 @@ export class DesignerCanvas extends BaseCustomWebComponentLazyAppend {
736
743
  const targetRect = element.getBoundingClientRect();
737
744
  return { x: (targetRect.x - this.containerBoundingRect.x) / this.scaleFactor, y: (targetRect.y - this.containerBoundingRect.y) / this.scaleFactor, width: targetRect.width / this.scaleFactor, height: targetRect.height / this.scaleFactor };
738
745
  }
746
+ getNormalizedElementCoordinatesAndRealSizes(element) {
747
+ let ret = this.getNormalizedElementCoordinates(element);
748
+ const st = getComputedStyle(element);
749
+ let realWidth = ret.width;
750
+ let realHeight = ret.height;
751
+ if (st.boxSizing != 'border-box') {
752
+ realWidth = realWidth - (parseFloat(st.borderLeft) + parseFloat(st.paddingLeft) + parseFloat(st.paddingRight) + parseFloat(st.borderRight));
753
+ realHeight = realHeight - (parseFloat(st.borderTop) + parseFloat(st.paddingTop) + parseFloat(st.paddingBottom) + parseFloat(st.borderBottom));
754
+ }
755
+ return { ...ret, realWidth, realHeight };
756
+ }
739
757
  getNormalizedOffsetInElement(event, element) {
740
758
  const normEvt = this.getNormalizedEventCoordinates(event);
741
759
  const normEl = this.getNormalizedElementCoordinates(element);
@@ -72,12 +72,12 @@ export class ResizeExtension extends AbstractExtension {
72
72
  this._initialPoint = currentPoint;
73
73
  this._initialSizes = [];
74
74
  this._actionModeStarted = actionMode;
75
- let rect = this.extendedItem.element.getBoundingClientRect();
76
- this._initialSizes.push({ width: rect.width / this.designerCanvas.scaleFactor, height: rect.height / this.designerCanvas.scaleFactor });
75
+ let rect = this.designerCanvas.getNormalizedElementCoordinatesAndRealSizes(this.extendedItem.element);
76
+ this._initialSizes.push({ width: rect.realWidth, height: rect.realHeight });
77
77
  if (this.resizeAllSelected) {
78
78
  for (const designItem of this.designerCanvas.instanceServiceContainer.selectionService.selectedElements) {
79
- rect = designItem.element.getBoundingClientRect();
80
- this._initialSizes.push({ width: rect.width / this.designerCanvas.scaleFactor, height: rect.height / this.designerCanvas.scaleFactor });
79
+ rect = this.designerCanvas.getNormalizedElementCoordinatesAndRealSizes(designItem.element);
80
+ this._initialSizes.push({ width: rect.realWidth, height: rect.realHeight });
81
81
  }
82
82
  }
83
83
  if (this.designerCanvas.alignOnSnap)
@@ -1,3 +1,4 @@
1
+ import { switchContainer } from "../../../../helper/SwitchContainerHelper";
1
2
  import { DesignItem } from "../../../../item/DesignItem";
2
3
  export class MultipleItemsSelectedContextMenu {
3
4
  orderIndex = 60;
@@ -17,39 +18,12 @@ export class MultipleItemsSelectedContextMenu {
17
18
  action: () => {
18
19
  const grp = designItem.openGroup("wrap in Div");
19
20
  let elements = designItem.instanceServiceContainer.selectionService.selectedElements;
20
- let div = document.createElement('div');
21
- const divDesignItem = DesignItem.createDesignItemFromInstance(div, designItem.serviceContainer, designItem.instanceServiceContainer);
22
- designItem.insertAdjacentElement(divDesignItem, 'beforebegin');
23
- let offset = 10;
24
- let minX = Number.MAX_VALUE;
25
- let minY = Number.MAX_VALUE;
26
- let maxX = 0;
27
- let maxY = 0;
28
- for (let e of elements) {
29
- let rect = designerCanvas.getNormalizedElementCoordinates(e.element);
30
- if (rect.x < minX)
31
- minX = rect.x;
32
- if (rect.y < minY)
33
- minY = rect.y;
34
- if (rect.x + rect.width > maxX)
35
- maxX = rect.x + rect.width;
36
- if (rect.y + rect.height > maxY)
37
- maxY = rect.y + rect.height;
38
- }
39
- for (let e of elements) {
40
- let rect = designerCanvas.getNormalizedElementCoordinates(e.element);
41
- e.remove();
42
- e.setStyle('left', (rect.x - minX + offset).toString() + 'px');
43
- e.setStyle('top', (rect.y - minY + offset).toString() + 'px');
44
- divDesignItem.insertChild(e);
45
- }
46
- divDesignItem.setStyle('position', 'absolute');
47
- divDesignItem.setStyle('left', (minX - offset).toString() + 'px');
48
- divDesignItem.setStyle('top', (minY - offset).toString() + 'px');
49
- divDesignItem.setStyle('width', (maxX - minX + 2 * offset).toString() + 'px');
50
- divDesignItem.setStyle('height', (maxY - minY + 2 * offset).toString() + 'px');
21
+ let newContainer = document.createElement('div');
22
+ const newContainerDesignItem = DesignItem.createDesignItemFromInstance(newContainer, designItem.serviceContainer, designItem.instanceServiceContainer);
23
+ elements[0].insertAdjacentElement(newContainerDesignItem, 'beforebegin');
24
+ switchContainer(elements, newContainerDesignItem, true, 10);
51
25
  grp.commit();
52
- designItem.instanceServiceContainer.selectionService.setSelectedElements([divDesignItem]);
26
+ designItem.instanceServiceContainer.selectionService.setSelectedElements([newContainerDesignItem]);
53
27
  }
54
28
  }
55
29
  ]
@@ -2,6 +2,7 @@ import { css, html, BaseCustomWebComponentConstructorAppend } from '@node-projec
2
2
  import { NodeType } from '../../item/NodeType';
3
3
  import { assetsPath } from '../../../Constants';
4
4
  import { ContextMenu } from '../../helper/contextMenu/ContextMenu';
5
+ import { switchContainer } from '../../helper/SwitchContainerHelper';
5
6
  export class TreeViewExtended extends BaseCustomWebComponentConstructorAppend {
6
7
  _treeDiv;
7
8
  _tree;
@@ -169,7 +170,7 @@ export class TreeViewExtended extends BaseCustomWebComponentConstructorAppend {
169
170
  quicksearch: true,
170
171
  source: [],
171
172
  table: {
172
- indentation: 20,
173
+ indentation: 10,
173
174
  nodeColumnIdx: 0,
174
175
  checkboxColumnIdx: 0, // render the checkboxes into the 1st column
175
176
  },
@@ -216,96 +217,32 @@ export class TreeViewExtended extends BaseCustomWebComponentConstructorAppend {
216
217
  preventVoidMoves: false,
217
218
  dropMarkerOffsetX: -24,
218
219
  dropMarkerInsertOffsetX: -16,
220
+ multiSource: true,
219
221
  dragStart: (node, data) => {
220
- /* This function MUST be defined to enable dragging for the tree.
221
- *
222
- * Return false to cancel dragging of node.
223
- * data.dataTransfer.setData() and .setDragImage() is available
224
- * here.
225
- */
226
- // Set the allowed effects (i.e. override the 'effectAllowed' option)
227
222
  data.effectAllowed = "all";
228
- // Set a drop effect (i.e. override the 'dropEffectDefault' option)
229
- // data.dropEffect = "link";
230
- data.dropEffect = "copy";
231
- // We could use a custom image here:
232
- // data.dataTransfer.setDragImage($("<div>TEST</div>").appendTo("body")[0], -10, -10);
233
- // data.useDefaultImage = false;
234
- // Return true to allow the drag operation
223
+ data.dropEffect = "move";
235
224
  return true;
236
225
  },
237
- // dragDrag: function(node, data) {
238
- // logLazy("dragDrag", null, 2000,
239
- // "T1: dragDrag: " + "data: " + data.dropEffect + "/" + data.effectAllowed +
240
- // ", dataTransfer: " + data.dataTransfer.dropEffect + "/" + data.dataTransfer.effectAllowed );
241
- // },
242
- // dragEnd: function(node, data) {
243
- // node.debug( "T1: dragEnd: " + "data: " + data.dropEffect + "/" + data.effectAllowed +
244
- // ", dataTransfer: " + data.dataTransfer.dropEffect + "/" + data.dataTransfer.effectAllowed, data);
245
- // alert("T1: dragEnd")
246
- // },
247
- // --- Drop-support:
248
226
  dragEnter: (node, data) => {
249
- // data.dropEffect = "copy";
227
+ data.dropEffect = data.originalEvent.ctrlKey ? 'copy' : 'move';
250
228
  return true;
251
229
  },
252
230
  dragOver: (node, data) => {
253
- // Assume typical mapping for modifier keys
254
- data.dropEffect = data.dropEffectSuggested;
255
- // data.dropEffect = "move";
231
+ data.dropEffect = data.originalEvent.ctrlKey ? 'copy' : 'move';
232
+ return true;
256
233
  },
257
234
  dragDrop: (node, data) => {
258
- /* This function MUST be defined to enable dropping of items on
259
- * the tree.
260
- */
261
- let newNode, transfer = data.dataTransfer, sourceNodes = data.otherNodeList, mode = data.dropEffect;
262
- if (data.hitMode === "after") {
263
- // If node are inserted directly after tagrget node one-by-one,
264
- // this would reverse them. So we compensate:
265
- sourceNodes.reverse();
266
- }
267
- if (data.otherNode) {
268
- // Drop another Fancytree node from same frame (maybe a different tree however)
269
- //let sameTree = (data.otherNode.tree === data.tree);
270
- if (mode === "move") {
271
- data.otherNode.moveTo(node, data.hitMode);
235
+ const sourceDesignitems = data.otherNodeList.map(x => x.data.ref);
236
+ const targetDesignitem = node.data.ref;
237
+ if (data.dropEffectSuggested == 'move') {
238
+ if (data.hitMode == 'over') {
239
+ switchContainer(sourceDesignitems, targetDesignitem);
272
240
  }
273
- else {
274
- newNode = data.otherNode.copyTo(node, data.hitMode);
275
- if (mode === "link") {
276
- newNode.setTitle("Link to " + newNode.title);
277
- }
278
- else {
279
- newNode.setTitle("Copy of " + newNode.title);
280
- }
241
+ else if (data.hitMode == 'before') {
281
242
  }
282
- }
283
- else if (data.otherNodeData) {
284
- // Drop Fancytree node from different frame or window, so we only have
285
- // JSON representation available
286
- //@ts-ignore
287
- node.addChild(data.otherNodeData, data.hitMode);
288
- }
289
- else if (data.files.length) {
290
- // Drop files
291
- for (let i = 0; i < data.files.length; i++) {
292
- let file = data.files[i];
293
- node.addNode({ title: "'" + file.name + "' (" + file.size + " bytes)" }, data.hitMode);
294
- // var url = "'https://example.com/upload",
295
- // formData = new FormData();
296
- // formData.append("file", transfer.files[0])
297
- // fetch(url, {
298
- // method: "POST",
299
- // body: formData
300
- // }).then(function() { /* Done. Inform the user */ })
301
- // .catch(function() { /* Error. Inform the user */ });
243
+ else if (data.hitMode == 'after') {
302
244
  }
303
245
  }
304
- else {
305
- // Drop a non-node
306
- node.addNode({ title: transfer.getData("text") }, data.hitMode);
307
- }
308
- node.setExpanded();
309
246
  },
310
247
  },
311
248
  multi: {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "description": "A UI designer for Polymer apps",
3
3
  "name": "@node-projects/web-component-designer",
4
- "version": "0.0.130",
4
+ "version": "0.0.132",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "author": "",