@node-projects/web-component-designer 0.1.91 → 0.1.92

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 (27) hide show
  1. package/dist/elements/helper/ElementHelper.js +6 -1
  2. package/dist/elements/helper/SelectionHelper.d.ts +2 -0
  3. package/dist/elements/helper/SelectionHelper.js +51 -0
  4. package/dist/elements/helper/TransformHelper.js +5 -0
  5. package/dist/elements/services/DefaultServiceBootstrap.js +1 -1
  6. package/dist/elements/services/dragDropService/DragDropService.js +1 -2
  7. package/dist/elements/services/placementService/AbsolutePlacementService.d.ts +19 -0
  8. package/dist/elements/services/placementService/AbsolutePlacementService.js +153 -0
  9. package/dist/elements/services/placementService/DefaultPlacementService copy.d.ts +19 -0
  10. package/dist/elements/services/placementService/DefaultPlacementService copy.js +151 -0
  11. package/dist/elements/services/placementService/DefaultPlacementService.d.ts +1 -1
  12. package/dist/elements/services/placementService/DefaultPlacementService.js +3 -1
  13. package/dist/elements/services/placementService/FlexBoxPlacementService.d.ts +1 -1
  14. package/dist/elements/services/placementService/FlexBoxPlacementService.js +1 -1
  15. package/dist/elements/services/placementService/GridPlacementService.d.ts +1 -1
  16. package/dist/elements/services/placementService/GridPlacementService.js +1 -1
  17. package/dist/elements/services/placementService/IPlacementService.d.ts +1 -1
  18. package/dist/elements/services/propertiesService/propertyEditors/FontPropertyEditor.d.ts +2 -1
  19. package/dist/elements/services/propertiesService/propertyEditors/FontPropertyEditor.js +9 -6
  20. package/dist/elements/widgets/designerView/extensions/EditText/EditTextExtension.d.ts +1 -1
  21. package/dist/elements/widgets/designerView/extensions/EditText/EditTextExtension.js +35 -9
  22. package/dist/elements/widgets/designerView/extensions/ElementDragTitleExtension.js +3 -3
  23. package/dist/elements/widgets/designerView/tools/PointerTool.js +1 -1
  24. package/dist/elements/widgets/designerView/tools/toolBar/popups/DrawToolPopup.js +4 -0
  25. package/dist/index.d.ts +2 -0
  26. package/dist/index.js +2 -0
  27. package/package.json +1 -1
@@ -31,6 +31,8 @@ export function isInlineAfter(element) {
31
31
  export function getElementDisplaytype(element) {
32
32
  if (element instanceof SVGElement)
33
33
  return ElementDisplayType.block;
34
+ if (element instanceof MathMLElement)
35
+ return ElementDisplayType.block;
34
36
  const display = window.getComputedStyle(element).display;
35
37
  return display == 'none' ? ElementDisplayType.none : display.startsWith('inline') ? ElementDisplayType.inline : ElementDisplayType.block;
36
38
  }
@@ -82,6 +84,9 @@ export function getElementsWindowOffsetWithoutSelfAndParentTransformations(eleme
82
84
  else if (element instanceof SVGGraphicsElement) {
83
85
  nextParent = element.ownerSVGElement;
84
86
  }
87
+ else if (element instanceof MathMLElement) {
88
+ nextParent = element.parentElement;
89
+ }
85
90
  let scrollLeft = 0;
86
91
  let scrollTop = 0;
87
92
  if (nextParent) {
@@ -90,7 +95,7 @@ export function getElementsWindowOffsetWithoutSelfAndParentTransformations(eleme
90
95
  }
91
96
  let currLeft = 0;
92
97
  let currTop = 0;
93
- if (element instanceof SVGSVGElement) {
98
+ if (element instanceof SVGSVGElement || element instanceof MathMLElement) {
94
99
  //TODO: !huge Perf impact! - fix without transformation
95
100
  let t = element.style.transform;
96
101
  element.style.transform = '';
@@ -0,0 +1,2 @@
1
+ export declare function shadowrootGetSelection(shadowRoot: ShadowRoot): Selection;
2
+ export declare function wrapSelectionInSpans(selection: Selection): HTMLSpanElement[];
@@ -0,0 +1,51 @@
1
+ export function shadowrootGetSelection(shadowRoot) {
2
+ let selection = document.getSelection();
3
+ if (selection.getComposedRanges)
4
+ selection = selection.getComposedRanges(shadowRoot);
5
+ else if (shadowRoot.getSelection)
6
+ selection = shadowRoot.getSelection();
7
+ return selection;
8
+ }
9
+ function wrapTextNodesInSpan(range, spans) {
10
+ function wrapNode(node) {
11
+ const span = document.createElement('span');
12
+ spans.push(span);
13
+ node.parentNode.insertBefore(span, node);
14
+ span.appendChild(node);
15
+ }
16
+ function processNode(node) {
17
+ switch (node.nodeType) {
18
+ case Node.TEXT_NODE:
19
+ wrapNode(node);
20
+ break;
21
+ case Node.DOCUMENT_FRAGMENT_NODE:
22
+ case Node.ELEMENT_NODE:
23
+ Array.from(node.childNodes).forEach(processNode);
24
+ break;
25
+ }
26
+ }
27
+ const fragment = range.extractContents();
28
+ processNode(fragment);
29
+ range.insertNode(fragment);
30
+ }
31
+ function staticRangeToRange(staticRange) {
32
+ const range = document.createRange();
33
+ range.setStart(staticRange.startContainer, staticRange.startOffset);
34
+ range.setEnd(staticRange.endContainer, staticRange.endOffset);
35
+ return range;
36
+ }
37
+ export function wrapSelectionInSpans(selection) {
38
+ const spans = [];
39
+ if (selection[0] instanceof StaticRange) {
40
+ wrapTextNodesInSpan(staticRangeToRange(selection[0]), spans);
41
+ }
42
+ else {
43
+ if (!selection.rangeCount)
44
+ return spans;
45
+ const range = selection.getRangeAt(0);
46
+ wrapTextNodesInSpan(range, spans);
47
+ }
48
+ if (selection.removeAllRanges)
49
+ selection.removeAllRanges();
50
+ return spans;
51
+ }
@@ -196,6 +196,11 @@ export function getElementSize(element) {
196
196
  width = bbox.width;
197
197
  height = bbox.height;
198
198
  }
199
+ else if (element instanceof MathMLElement) {
200
+ let bbox = element.getBoundingClientRect();
201
+ width = bbox.width;
202
+ height = bbox.height;
203
+ }
199
204
  return { width, height };
200
205
  }
201
206
  export function getDesignerCanvasNormalizedTransformedCornerDOMPoints(element, untransformedCornerPointsOffset, designerCanvas, cache) {
@@ -121,7 +121,7 @@ export function createDefaultServiceContainer() {
121
121
  ]);
122
122
  serviceContainer.designerExtensions.set(ExtensionType.PrimarySelection, [
123
123
  new ElementDragTitleExtensionProvider(),
124
- new TransformOriginExtensionProvider(),
124
+ new TransformOriginExtensionProvider(true),
125
125
  new CanvasExtensionProvider(),
126
126
  new PositionExtensionProvider(),
127
127
  new EllipsisExtensionProvider(),
@@ -40,9 +40,8 @@ export class DragDropService {
40
40
  const elementDefinition = JSON.parse(transferData);
41
41
  const di = await designerCanvas.serviceContainer.forSomeServicesTillResult("instanceService", (service) => service.getElement(elementDefinition, designerCanvas.serviceContainer, designerCanvas.instanceServiceContainer));
42
42
  const grp = di.openGroup("Insert of <" + di.name + ">");
43
- di.setStyle('position', 'absolute');
44
43
  const containerService = designerCanvas.serviceContainer.getLastServiceWhere('containerService', x => x.serviceForContainer(newContainer, newContainer.getComputedStyle()));
45
- containerService.enterContainer(newContainer, [di]);
44
+ containerService.enterContainer(newContainer, [di], 'drop');
46
45
  const containerPos = designerCanvas.getNormalizedElementCoordinates(newContainer.element);
47
46
  const evCoord = designerCanvas.getNormalizedEventCoordinates(event);
48
47
  const pos = { x: evCoord.x - containerPos.x, y: evCoord.y - containerPos.y };
@@ -0,0 +1,19 @@
1
+ import type { IPoint } from '../../../interfaces/IPoint.js';
2
+ import type { IPlacementService } from './IPlacementService.js';
3
+ import type { IDesignItem } from '../../item/IDesignItem.js';
4
+ import { IPlacementView } from '../../widgets/designerView/IPlacementView.js';
5
+ export declare class AbsolutePlacementService implements IPlacementService {
6
+ serviceForContainer(container: IDesignItem, containerStyle: CSSStyleDeclaration): boolean;
7
+ isEnterableContainer(container: IDesignItem): boolean;
8
+ canEnter(container: IDesignItem, items: IDesignItem[]): boolean;
9
+ canLeave(container: IDesignItem, items: IDesignItem[]): boolean;
10
+ getElementOffset(container: IDesignItem, designItem?: IDesignItem): IPoint;
11
+ private calculateTrack;
12
+ placePoint(event: MouseEvent, placementView: IPlacementView, container: IDesignItem, startPoint: IPoint, offsetInControl: IPoint, newPoint: IPoint, items: IDesignItem[]): IPoint;
13
+ startPlace(event: MouseEvent, placementView: IPlacementView, container: IDesignItem, startPoint: IPoint, offsetInControl: IPoint, newPoint: IPoint, items: IDesignItem[]): void;
14
+ place(event: MouseEvent, placementView: IPlacementView, container: IDesignItem, startPoint: IPoint, offsetInControl: IPoint, newPoint: IPoint, items: IDesignItem[]): void;
15
+ moveElements(designItems: IDesignItem[], position: IPoint, absolute: boolean): void;
16
+ enterContainer(container: IDesignItem, items: IDesignItem[], mode: 'normal' | 'drop'): void;
17
+ leaveContainer(container: IDesignItem, items: IDesignItem[]): void;
18
+ finishPlace(event: MouseEvent, placementView: IPlacementView, container: IDesignItem, startPoint: IPoint, offsetInControl: IPoint, newPoint: IPoint, items: IDesignItem[]): void;
19
+ }
@@ -0,0 +1,153 @@
1
+ import { DomConverter } from '../../widgets/designerView/DomConverter.js';
2
+ import { combineTransforms, extractTranslationFromDOMMatrix, getResultingTransformationBetweenElementAndAllAncestors } from '../../helper/TransformHelper.js';
3
+ import { filterChildPlaceItems, getDesignItemCurrentPos, placeDesignItem } from '../../helper/LayoutHelper.js';
4
+ import { ExtensionType } from '../../widgets/designerView/extensions/ExtensionType.js';
5
+ import { straightenLine } from '../../helper/PathDataPolyfill.js';
6
+ export class AbsolutePlacementService {
7
+ serviceForContainer(container, containerStyle) {
8
+ if (containerStyle.display === 'grid' || containerStyle.display === 'inline-grid' ||
9
+ containerStyle.display === 'flex' || containerStyle.display === 'inline-flex')
10
+ return false;
11
+ return true;
12
+ }
13
+ isEnterableContainer(container) {
14
+ if (DomConverter.IsSelfClosingElement(container.element.localName))
15
+ return false;
16
+ if (!container.isRootItem && container.element.shadowRoot && container.element.shadowRoot.querySelector('slot') == null)
17
+ return false;
18
+ return true;
19
+ }
20
+ canEnter(container, items) {
21
+ if (!this.isEnterableContainer(container))
22
+ return false;
23
+ if (!items.every(x => !x.element.contains(container.element) && x !== container))
24
+ return false;
25
+ return true;
26
+ }
27
+ canLeave(container, items) {
28
+ return true;
29
+ }
30
+ getElementOffset(container, designItem) {
31
+ return container.instanceServiceContainer.designerCanvas.getNormalizedElementCoordinates(container.element);
32
+ }
33
+ calculateTrack(event, placementView, startPoint, offsetInControl, newPoint, item) {
34
+ let trackX = newPoint.x - startPoint.x;
35
+ let trackY = newPoint.y - startPoint.y;
36
+ if (!event.ctrlKey) {
37
+ if (placementView.alignOnGrid) {
38
+ let p = getDesignItemCurrentPos(item, 'position');
39
+ p.x = p.x % placementView.gridSize;
40
+ p.y = p.y % placementView.gridSize;
41
+ trackX = Math.round(trackX / placementView.gridSize) * placementView.gridSize - p.x;
42
+ trackY = Math.round(trackY / placementView.gridSize) * placementView.gridSize - p.y;
43
+ }
44
+ else if (placementView.alignOnSnap) {
45
+ let rect = item.element.getBoundingClientRect();
46
+ let newPos = placementView.snapLines.snapToPosition({ x: (newPoint.x - offsetInControl.x), y: (newPoint.y - offsetInControl.y) }, { width: rect.width / placementView.scaleFactor, height: rect.height / placementView.scaleFactor }, { x: trackX > 0 ? 1 : -1, y: trackY > 0 ? 1 : -1 });
47
+ if (newPos.x !== null) {
48
+ trackX = newPos.x - Math.round(startPoint.x) + Math.round(offsetInControl.x);
49
+ }
50
+ else {
51
+ trackX = Math.round(trackX);
52
+ }
53
+ if (newPos.y !== null) {
54
+ trackY = newPos.y - Math.round(startPoint.y) + Math.round(offsetInControl.y);
55
+ }
56
+ else {
57
+ trackY = Math.round(trackY);
58
+ }
59
+ }
60
+ }
61
+ return { x: trackX, y: trackY };
62
+ }
63
+ placePoint(event, placementView, container, startPoint, offsetInControl, newPoint, items) {
64
+ let trackX = newPoint.x;
65
+ let trackY = newPoint.y;
66
+ if (!event.ctrlKey) {
67
+ if (placementView.alignOnGrid) {
68
+ trackX = Math.round(trackX / placementView.gridSize) * placementView.gridSize;
69
+ trackY = Math.round(trackY / placementView.gridSize) * placementView.gridSize;
70
+ }
71
+ else if (placementView.alignOnSnap) {
72
+ let newPos = placementView.snapLines.snapToPosition({ x: newPoint.x - offsetInControl.x, y: newPoint.y - offsetInControl.y }, null, { x: trackX > 0 ? 1 : -1, y: trackY > 0 ? 1 : -1 });
73
+ if (newPos.x !== null) {
74
+ trackX = newPos.x;
75
+ }
76
+ else {
77
+ trackX = Math.round(trackX);
78
+ }
79
+ if (newPos.y !== null) {
80
+ trackY = newPos.y;
81
+ }
82
+ else {
83
+ trackY = Math.round(trackY);
84
+ }
85
+ }
86
+ }
87
+ return { x: trackX, y: trackY };
88
+ }
89
+ startPlace(event, placementView, container, startPoint, offsetInControl, newPoint, items) {
90
+ }
91
+ place(event, placementView, container, startPoint, offsetInControl, newPoint, items) {
92
+ //TODO: this should revert all undo actions while active
93
+ //maybe a undo actions returns itself or an id so it could be changed?
94
+ let track = this.calculateTrack(event, placementView, startPoint, offsetInControl, newPoint, items[0]);
95
+ if (event.shiftKey) {
96
+ track = straightenLine({ x: 0, y: 0 }, track, true);
97
+ }
98
+ let filteredItems = filterChildPlaceItems(items);
99
+ for (const designItem of filteredItems) {
100
+ const canvas = designItem.instanceServiceContainer.designerCanvas.rootDesignItem.element;
101
+ let originalElementAndAllAncestorsMultipliedMatrix = getResultingTransformationBetweenElementAndAllAncestors(designItem.parent.element, canvas, true);
102
+ let transformMatrixParentTransformsCompensated = null;
103
+ if (originalElementAndAllAncestorsMultipliedMatrix) {
104
+ transformMatrixParentTransformsCompensated = new DOMPoint(track.x, track.y, 0, 0).matrixTransform(originalElementAndAllAncestorsMultipliedMatrix.inverse());
105
+ }
106
+ else {
107
+ transformMatrixParentTransformsCompensated = new DOMPoint(track.x, track.y, 0, 0);
108
+ }
109
+ const translationMatrix = new DOMMatrix().translate(transformMatrixParentTransformsCompensated.x, transformMatrixParentTransformsCompensated.y);
110
+ combineTransforms(designItem.element, designItem.getStyle('transform'), translationMatrix.toString());
111
+ }
112
+ }
113
+ moveElements(designItems, position, absolute) {
114
+ //TODO: Check if we set left or right
115
+ //TODO: Use CSS units
116
+ for (let d of designItems) {
117
+ if (position.x)
118
+ d.setStyle('left', parseInt(d.element.style.left) - position.x + 'px');
119
+ if (position.y)
120
+ d.setStyle('top', parseInt(d.element.style.top) - position.y + 'px');
121
+ }
122
+ designItems[0].instanceServiceContainer.designerCanvas.extensionManager.refreshExtensions(designItems);
123
+ }
124
+ enterContainer(container, items, mode) {
125
+ let filterdItems = filterChildPlaceItems(items);
126
+ for (let i of filterdItems) {
127
+ if (mode == 'drop')
128
+ i.setStyle('position', 'absolute');
129
+ container.insertChild(i);
130
+ if (i.lastContainerSize) {
131
+ if (!i.hasStyle('width'))
132
+ i.setStyle('width', i.lastContainerSize.width + 'px');
133
+ if (!i.hasStyle('height'))
134
+ i.setStyle('height', i.lastContainerSize.height + 'px');
135
+ }
136
+ }
137
+ }
138
+ leaveContainer(container, items) {
139
+ }
140
+ finishPlace(event, placementView, container, startPoint, offsetInControl, newPoint, items) {
141
+ let filterdItems = filterChildPlaceItems(items);
142
+ for (const designItem of filterdItems) {
143
+ let translation = extractTranslationFromDOMMatrix(new DOMMatrix(designItem.element.style.transform));
144
+ const stylesMapOffset = extractTranslationFromDOMMatrix(new DOMMatrix(designItem.getStyle('transform') ?? ''));
145
+ designItem.element.style.transform = designItem.getStyle('transform') ?? '';
146
+ let track = { x: translation.x, y: translation.y };
147
+ placeDesignItem(container, designItem, { x: track.x - stylesMapOffset.x, y: track.y - stylesMapOffset.y }, 'position');
148
+ }
149
+ for (const item of items) {
150
+ placementView.extensionManager.removeExtension(item, ExtensionType.Placement);
151
+ }
152
+ }
153
+ }
@@ -0,0 +1,19 @@
1
+ import type { IPoint } from '../../../interfaces/IPoint.js';
2
+ import type { IPlacementService } from './IPlacementService.js';
3
+ import type { IDesignItem } from '../../item/IDesignItem.js';
4
+ import { IPlacementView } from '../../widgets/designerView/IPlacementView.js';
5
+ export declare class DefaultPlacementService implements IPlacementService {
6
+ serviceForContainer(container: IDesignItem, containerStyle: CSSStyleDeclaration): boolean;
7
+ isEnterableContainer(container: IDesignItem): boolean;
8
+ canEnter(container: IDesignItem, items: IDesignItem[]): boolean;
9
+ canLeave(container: IDesignItem, items: IDesignItem[]): boolean;
10
+ getElementOffset(container: IDesignItem, designItem?: IDesignItem): IPoint;
11
+ private calculateTrack;
12
+ placePoint(event: MouseEvent, placementView: IPlacementView, container: IDesignItem, startPoint: IPoint, offsetInControl: IPoint, newPoint: IPoint, items: IDesignItem[]): IPoint;
13
+ startPlace(event: MouseEvent, placementView: IPlacementView, container: IDesignItem, startPoint: IPoint, offsetInControl: IPoint, newPoint: IPoint, items: IDesignItem[]): void;
14
+ place(event: MouseEvent, placementView: IPlacementView, container: IDesignItem, startPoint: IPoint, offsetInControl: IPoint, newPoint: IPoint, items: IDesignItem[]): void;
15
+ moveElements(designItems: IDesignItem[], position: IPoint, absolute: boolean): void;
16
+ enterContainer(container: IDesignItem, items: IDesignItem[]): void;
17
+ leaveContainer(container: IDesignItem, items: IDesignItem[]): void;
18
+ finishPlace(event: MouseEvent, placementView: IPlacementView, container: IDesignItem, startPoint: IPoint, offsetInControl: IPoint, newPoint: IPoint, items: IDesignItem[]): void;
19
+ }
@@ -0,0 +1,151 @@
1
+ import { DomConverter } from '../../widgets/designerView/DomConverter.js';
2
+ import { combineTransforms, extractTranslationFromDOMMatrix, getResultingTransformationBetweenElementAndAllAncestors } from '../../helper/TransformHelper.js';
3
+ import { filterChildPlaceItems, getDesignItemCurrentPos, placeDesignItem } from '../../helper/LayoutHelper.js';
4
+ import { ExtensionType } from '../../widgets/designerView/extensions/ExtensionType.js';
5
+ import { straightenLine } from '../../helper/PathDataPolyfill.js';
6
+ export class DefaultPlacementService {
7
+ serviceForContainer(container, containerStyle) {
8
+ if (containerStyle.display === 'grid' || containerStyle.display === 'inline-grid' ||
9
+ containerStyle.display === 'flex' || containerStyle.display === 'inline-flex')
10
+ return false;
11
+ return true;
12
+ }
13
+ isEnterableContainer(container) {
14
+ if (DomConverter.IsSelfClosingElement(container.element.localName))
15
+ return false;
16
+ if (!container.isRootItem && container.element.shadowRoot && container.element.shadowRoot.querySelector('slot') == null)
17
+ return false;
18
+ return true;
19
+ }
20
+ canEnter(container, items) {
21
+ if (!this.isEnterableContainer(container))
22
+ return false;
23
+ if (!items.every(x => !x.element.contains(container.element) && x !== container))
24
+ return false;
25
+ return true;
26
+ }
27
+ canLeave(container, items) {
28
+ return true;
29
+ }
30
+ getElementOffset(container, designItem) {
31
+ return container.instanceServiceContainer.designerCanvas.getNormalizedElementCoordinates(container.element);
32
+ }
33
+ calculateTrack(event, placementView, startPoint, offsetInControl, newPoint, item) {
34
+ let trackX = newPoint.x - startPoint.x;
35
+ let trackY = newPoint.y - startPoint.y;
36
+ if (!event.ctrlKey) {
37
+ if (placementView.alignOnGrid) {
38
+ let p = getDesignItemCurrentPos(item, 'position');
39
+ p.x = p.x % placementView.gridSize;
40
+ p.y = p.y % placementView.gridSize;
41
+ trackX = Math.round(trackX / placementView.gridSize) * placementView.gridSize - p.x;
42
+ trackY = Math.round(trackY / placementView.gridSize) * placementView.gridSize - p.y;
43
+ }
44
+ else if (placementView.alignOnSnap) {
45
+ let rect = item.element.getBoundingClientRect();
46
+ let newPos = placementView.snapLines.snapToPosition({ x: (newPoint.x - offsetInControl.x), y: (newPoint.y - offsetInControl.y) }, { width: rect.width / placementView.scaleFactor, height: rect.height / placementView.scaleFactor }, { x: trackX > 0 ? 1 : -1, y: trackY > 0 ? 1 : -1 });
47
+ if (newPos.x !== null) {
48
+ trackX = newPos.x - Math.round(startPoint.x) + Math.round(offsetInControl.x);
49
+ }
50
+ else {
51
+ trackX = Math.round(trackX);
52
+ }
53
+ if (newPos.y !== null) {
54
+ trackY = newPos.y - Math.round(startPoint.y) + Math.round(offsetInControl.y);
55
+ }
56
+ else {
57
+ trackY = Math.round(trackY);
58
+ }
59
+ }
60
+ }
61
+ return { x: trackX, y: trackY };
62
+ }
63
+ placePoint(event, placementView, container, startPoint, offsetInControl, newPoint, items) {
64
+ let trackX = newPoint.x;
65
+ let trackY = newPoint.y;
66
+ if (!event.ctrlKey) {
67
+ if (placementView.alignOnGrid) {
68
+ trackX = Math.round(trackX / placementView.gridSize) * placementView.gridSize;
69
+ trackY = Math.round(trackY / placementView.gridSize) * placementView.gridSize;
70
+ }
71
+ else if (placementView.alignOnSnap) {
72
+ let newPos = placementView.snapLines.snapToPosition({ x: newPoint.x - offsetInControl.x, y: newPoint.y - offsetInControl.y }, null, { x: trackX > 0 ? 1 : -1, y: trackY > 0 ? 1 : -1 });
73
+ if (newPos.x !== null) {
74
+ trackX = newPos.x;
75
+ }
76
+ else {
77
+ trackX = Math.round(trackX);
78
+ }
79
+ if (newPos.y !== null) {
80
+ trackY = newPos.y;
81
+ }
82
+ else {
83
+ trackY = Math.round(trackY);
84
+ }
85
+ }
86
+ }
87
+ return { x: trackX, y: trackY };
88
+ }
89
+ startPlace(event, placementView, container, startPoint, offsetInControl, newPoint, items) {
90
+ }
91
+ place(event, placementView, container, startPoint, offsetInControl, newPoint, items) {
92
+ //TODO: this should revert all undo actions while active
93
+ //maybe a undo actions returns itself or an id so it could be changed?
94
+ let track = this.calculateTrack(event, placementView, startPoint, offsetInControl, newPoint, items[0]);
95
+ if (event.shiftKey) {
96
+ track = straightenLine({ x: 0, y: 0 }, track, true);
97
+ }
98
+ let filteredItems = filterChildPlaceItems(items);
99
+ for (const designItem of filteredItems) {
100
+ const canvas = designItem.instanceServiceContainer.designerCanvas.rootDesignItem.element;
101
+ let originalElementAndAllAncestorsMultipliedMatrix = getResultingTransformationBetweenElementAndAllAncestors(designItem.parent.element, canvas, true);
102
+ let transformMatrixParentTransformsCompensated = null;
103
+ if (originalElementAndAllAncestorsMultipliedMatrix) {
104
+ transformMatrixParentTransformsCompensated = new DOMPoint(track.x, track.y, 0, 0).matrixTransform(originalElementAndAllAncestorsMultipliedMatrix.inverse());
105
+ }
106
+ else {
107
+ transformMatrixParentTransformsCompensated = new DOMPoint(track.x, track.y, 0, 0);
108
+ }
109
+ const translationMatrix = new DOMMatrix().translate(transformMatrixParentTransformsCompensated.x, transformMatrixParentTransformsCompensated.y);
110
+ combineTransforms(designItem.element, designItem.getStyle('transform'), translationMatrix.toString());
111
+ }
112
+ }
113
+ moveElements(designItems, position, absolute) {
114
+ //TODO: Check if we set left or right
115
+ //TODO: Use CSS units
116
+ for (let d of designItems) {
117
+ if (position.x)
118
+ d.setStyle('left', parseInt(d.element.style.left) - position.x + 'px');
119
+ if (position.y)
120
+ d.setStyle('top', parseInt(d.element.style.top) - position.y + 'px');
121
+ }
122
+ designItems[0].instanceServiceContainer.designerCanvas.extensionManager.refreshExtensions(designItems);
123
+ }
124
+ enterContainer(container, items) {
125
+ let filterdItems = filterChildPlaceItems(items);
126
+ for (let i of filterdItems) {
127
+ container.insertChild(i);
128
+ if (i.lastContainerSize) {
129
+ if (!i.hasStyle('width'))
130
+ i.setStyle('width', i.lastContainerSize.width + 'px');
131
+ if (!i.hasStyle('height'))
132
+ i.setStyle('height', i.lastContainerSize.height + 'px');
133
+ }
134
+ }
135
+ }
136
+ leaveContainer(container, items) {
137
+ }
138
+ finishPlace(event, placementView, container, startPoint, offsetInControl, newPoint, items) {
139
+ let filterdItems = filterChildPlaceItems(items);
140
+ for (const designItem of filterdItems) {
141
+ let translation = extractTranslationFromDOMMatrix(new DOMMatrix(designItem.element.style.transform));
142
+ const stylesMapOffset = extractTranslationFromDOMMatrix(new DOMMatrix(designItem.getStyle('transform') ?? ''));
143
+ designItem.element.style.transform = designItem.getStyle('transform') ?? '';
144
+ let track = { x: translation.x, y: translation.y };
145
+ placeDesignItem(container, designItem, { x: track.x - stylesMapOffset.x, y: track.y - stylesMapOffset.y }, 'position');
146
+ }
147
+ for (const item of items) {
148
+ placementView.extensionManager.removeExtension(item, ExtensionType.Placement);
149
+ }
150
+ }
151
+ }
@@ -13,7 +13,7 @@ export declare class DefaultPlacementService implements IPlacementService {
13
13
  startPlace(event: MouseEvent, placementView: IPlacementView, container: IDesignItem, startPoint: IPoint, offsetInControl: IPoint, newPoint: IPoint, items: IDesignItem[]): void;
14
14
  place(event: MouseEvent, placementView: IPlacementView, container: IDesignItem, startPoint: IPoint, offsetInControl: IPoint, newPoint: IPoint, items: IDesignItem[]): void;
15
15
  moveElements(designItems: IDesignItem[], position: IPoint, absolute: boolean): void;
16
- enterContainer(container: IDesignItem, items: IDesignItem[]): void;
16
+ enterContainer(container: IDesignItem, items: IDesignItem[], mode: 'normal' | 'drop'): void;
17
17
  leaveContainer(container: IDesignItem, items: IDesignItem[]): void;
18
18
  finishPlace(event: MouseEvent, placementView: IPlacementView, container: IDesignItem, startPoint: IPoint, offsetInControl: IPoint, newPoint: IPoint, items: IDesignItem[]): void;
19
19
  }
@@ -121,9 +121,11 @@ export class DefaultPlacementService {
121
121
  }
122
122
  designItems[0].instanceServiceContainer.designerCanvas.extensionManager.refreshExtensions(designItems);
123
123
  }
124
- enterContainer(container, items) {
124
+ enterContainer(container, items, mode) {
125
125
  let filterdItems = filterChildPlaceItems(items);
126
126
  for (let i of filterdItems) {
127
+ if (mode == 'drop')
128
+ i.setStyle('position', 'absolute');
127
129
  container.insertChild(i);
128
130
  if (i.lastContainerSize) {
129
131
  if (!i.hasStyle('width'))
@@ -5,7 +5,7 @@ import { IPlacementService } from './IPlacementService.js';
5
5
  export declare class FlexBoxPlacementService implements IPlacementService {
6
6
  private _basePlacementService;
7
7
  constructor(basePlacementService: IPlacementService);
8
- enterContainer(container: IDesignItem, items: IDesignItem[]): void;
8
+ enterContainer(container: IDesignItem, items: IDesignItem[], mode: 'normal' | 'drop'): void;
9
9
  leaveContainer(container: IDesignItem, items: IDesignItem[]): void;
10
10
  serviceForContainer(container: IDesignItem, containerStyle: CSSStyleDeclaration): boolean;
11
11
  isEnterableContainer(container: IDesignItem): any;
@@ -4,7 +4,7 @@ export class FlexBoxPlacementService {
4
4
  constructor(basePlacementService) {
5
5
  this._basePlacementService = basePlacementService ?? new DefaultPlacementService();
6
6
  }
7
- enterContainer(container, items) {
7
+ enterContainer(container, items, mode) {
8
8
  for (let i of items) {
9
9
  container.insertChild(i);
10
10
  i.removeStyle("position");
@@ -5,7 +5,7 @@ import { IPlacementView } from '../../widgets/designerView/IPlacementView.js';
5
5
  export declare class GridPlacementService implements IPlacementService {
6
6
  private _basePlacementService;
7
7
  constructor(basePlacementService: IPlacementService);
8
- enterContainer(container: IDesignItem, items: IDesignItem[]): void;
8
+ enterContainer(container: IDesignItem, items: IDesignItem[], mode: 'normal' | 'drop'): void;
9
9
  leaveContainer(container: IDesignItem, items: IDesignItem[]): void;
10
10
  serviceForContainer(container: IDesignItem, containerStyle: CSSStyleDeclaration): boolean;
11
11
  isEnterableContainer(container: IDesignItem): any;
@@ -6,7 +6,7 @@ export class GridPlacementService {
6
6
  constructor(basePlacementService) {
7
7
  this._basePlacementService = basePlacementService ?? new DefaultPlacementService();
8
8
  }
9
- enterContainer(container, items) {
9
+ enterContainer(container, items, mode) {
10
10
  for (let i of items) {
11
11
  container.insertChild(i);
12
12
  i.removeStyle("position");
@@ -7,7 +7,7 @@ export interface IPlacementService extends IService {
7
7
  isEnterableContainer(container: IDesignItem): boolean;
8
8
  canEnter(container: IDesignItem, items: IDesignItem[]): boolean;
9
9
  canLeave(container: IDesignItem, items: IDesignItem[]): boolean;
10
- enterContainer(container: IDesignItem, items: IDesignItem[]): any;
10
+ enterContainer(container: IDesignItem, items: IDesignItem[], mode: 'normal' | 'drop'): any;
11
11
  leaveContainer(container: IDesignItem, items: IDesignItem[]): any;
12
12
  getElementOffset(container: IDesignItem, designItem?: IDesignItem): IPoint;
13
13
  placePoint(event: MouseEvent, placementView: IPlacementView, container: IDesignItem, startPoint: IPoint, offsetInControl: IPoint, newPoint: IPoint, items: IDesignItem[]): IPoint;
@@ -4,6 +4,7 @@ import { ValueType } from '../ValueType.js';
4
4
  export declare class FontPropertyEditor extends BasePropertyEditor<HTMLSelectElement> {
5
5
  static fontList: string[];
6
6
  constructor(property: IProperty);
7
- parseFontList(): void;
7
+ static addFontsToSelect(select: HTMLSelectElement): void;
8
+ private static parseFontList;
8
9
  refreshValue(valueType: ValueType, value: any): void;
9
10
  }
@@ -5,8 +5,12 @@ export class FontPropertyEditor extends BasePropertyEditor {
5
5
  super(property);
6
6
  let element = document.createElement("select");
7
7
  this.element = element;
8
+ FontPropertyEditor.addFontsToSelect(element);
9
+ this.element.onchange = (e) => this._valueChanged(this.element.value);
10
+ }
11
+ static addFontsToSelect(select) {
8
12
  if (FontPropertyEditor.fontList) {
9
- this.parseFontList();
13
+ FontPropertyEditor.parseFontList(select);
10
14
  //@ts-ignore
11
15
  }
12
16
  else if (window.queryLocalFonts) {
@@ -14,22 +18,21 @@ export class FontPropertyEditor extends BasePropertyEditor {
14
18
  window.queryLocalFonts().then(x => {
15
19
  //@ts-ignore
16
20
  FontPropertyEditor.fontList = [...new Set(x.map(y => y.family))];
17
- this.parseFontList();
21
+ FontPropertyEditor.parseFontList(select);
18
22
  });
19
23
  }
20
24
  else {
21
25
  FontPropertyEditor.fontList = ["Verdana", "Arial", "Tahoma", "Trebuchet MS", "Times New Roman", "Georgia", "Garamond", "Courier New", "Brush Script MT"];
22
- this.parseFontList();
26
+ FontPropertyEditor.parseFontList(select);
23
27
  }
24
28
  }
25
- parseFontList() {
29
+ static parseFontList(select) {
26
30
  for (let v of FontPropertyEditor.fontList) {
27
31
  let option = document.createElement("option");
28
32
  option.value = v;
29
33
  option.text = v;
30
- this.element.appendChild(option);
34
+ select.appendChild(option);
31
35
  }
32
- this.element.onchange = (e) => this._valueChanged(this.element.value);
33
36
  }
34
37
  refreshValue(valueType, value) {
35
38
  this.element.value = value;
@@ -14,5 +14,5 @@ export declare class EditTextExtension extends AbstractExtension implements hand
14
14
  refresh(): void;
15
15
  dispose(): void;
16
16
  handlesPointerEvent(designerCanvas: IDesignerCanvas, event: PointerEvent, currentElement: Element): boolean;
17
- _formatSelection(type: string): void;
17
+ _formatSelection(type: string, value?: string): void;
18
18
  }
@@ -2,13 +2,34 @@ import { html } from "@node-projects/base-custom-webcomponent";
2
2
  import { AbstractExtension } from "../AbstractExtension.js";
3
3
  import { OverlayLayer } from "../OverlayLayer.js";
4
4
  import { getDesignerCanvasNormalizedTransformedCornerDOMPoints } from "../../../../helper/TransformHelper.js";
5
+ import { shadowrootGetSelection, wrapSelectionInSpans } from "../../../../helper/SelectionHelper.js";
6
+ import { FontPropertyEditor } from "../../../../services/propertiesService/propertyEditors/FontPropertyEditor.js";
5
7
  export class EditTextExtension extends AbstractExtension {
6
8
  static template = html `
7
9
  <div style="height: 24px; display: flex; gap: 2px;">
8
- <button data-command="bold" style="pointer-events: all; height: 24px; width: 24px; padding: 0; font-weight: 900;">b</button>
9
- <button data-command="italic" style="pointer-events: all; height: 24px; width: 24px; padding: 0;"><em>i</em></button>
10
- <button data-command="underline" style="pointer-events: all; height: 24px; width: 24px; padding: 0;"><ins>u</ins></button>
11
- <button data-command="strikeThrough" style="pointer-events: all; height: 24px; width: 24px; padding: 0;"><del>s</del></button>
10
+ <button data-command="font-weight" data-command-parameter="800" style="pointer-events: all; height: 24px; width: 24px; padding: 0; font-weight: 900;">b</button>
11
+ <button data-command="font-style" data-command-parameter="italic" style="pointer-events: all; height: 24px; width: 24px; padding: 0;"><em>i</em></button>
12
+ <button data-command="text-decoration" data-command-parameter="underline" style="pointer-events: all; height: 24px; width: 24px; padding: 0;"><ins>u</ins></button>
13
+ <button data-command="text-decoration" data-command-parameter="line-through" style="pointer-events: all; height: 24px; width: 24px; padding: 0;"><del>s</del></button>
14
+ <button data-command="text-decoration" data-command-parameter="overline" style="pointer-events: all; height: 24px; width: 24px; padding: 0;"><span style="text-decoration: overline">o</span></button>
15
+ <select data-command="fontSize" style="pointer-events: all; height: 24px; width: 60px; padding: 0;">
16
+ <option>8px</option>
17
+ <option>9px</option>
18
+ <option>10px</option>
19
+ <option>11px</option>
20
+ <option>12px</option>
21
+ <option>14px</option>
22
+ <option>16px</option>
23
+ <option>18px</option>
24
+ <option>20px</option>
25
+ <option>24px</option>
26
+ <option>28px</option>
27
+ <option>32px</option>
28
+ <option>36px</option>
29
+ </select>
30
+ <select id="fontFamily" data-command="font-family" style="pointer-events: all; height: 24px; width: 90px; padding: 0;">
31
+
32
+ </select>
12
33
  </div>
13
34
  `;
14
35
  _foreignObject;
@@ -25,13 +46,15 @@ export class EditTextExtension extends AbstractExtension {
25
46
  this.extendedItem.element.focus();
26
47
  let itemRect = this.extendedItem.element.getBoundingClientRect();
27
48
  const elements = EditTextExtension.template.content.cloneNode(true);
28
- elements.querySelectorAll('button').forEach(x => x.onpointerdown = () => this._formatSelection(x.dataset['command']));
49
+ FontPropertyEditor.addFontsToSelect(elements.querySelector('#fontFamily'));
50
+ elements.querySelectorAll('button').forEach(x => x.onpointerdown = () => this._formatSelection(x.dataset['command'], x.dataset['commandParameter']));
51
+ elements.querySelectorAll('select').forEach(x => x.onchange = () => this._formatSelection(x.dataset['command'], x.value));
29
52
  //Button overlay
30
53
  const foreignObject = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject');
31
54
  this._foreignObject = foreignObject;
32
55
  foreignObject.setAttribute('x', '' + (itemRect.x - this.designerCanvas.containerBoundingRect.x) / this.designerCanvas.scaleFactor);
33
56
  foreignObject.setAttribute('y', '' + ((itemRect.y - this.designerCanvas.containerBoundingRect.y) / this.designerCanvas.scaleFactor - 30));
34
- foreignObject.setAttribute('width', '96');
57
+ foreignObject.setAttribute('width', '300');
35
58
  foreignObject.setAttribute('height', '24');
36
59
  foreignObject.appendChild(elements);
37
60
  this._addOverlay(foreignObject, OverlayLayer.Foreground);
@@ -66,12 +89,15 @@ export class EditTextExtension extends AbstractExtension {
66
89
  this.designerCanvas.clickOverlay.style.pointerEvents = 'auto';
67
90
  }
68
91
  handlesPointerEvent(designerCanvas, event, currentElement) {
69
- let p = event.composedPath();
92
+ const p = event.composedPath();
70
93
  const stylo = this._foreignObject.querySelector('stylo-editor');
71
94
  return p.indexOf(stylo) >= 0;
72
95
  }
73
- _formatSelection(type) {
74
- document.execCommand(type, false, null);
96
+ _formatSelection(type, value) {
97
+ const selection = shadowrootGetSelection(this.designerCanvas.rootDesignItem.element.shadowRoot);
98
+ const spans = wrapSelectionInSpans(selection);
99
+ for (const span of spans)
100
+ span.style[type] = value;
75
101
  this.extendedItem.element.focus();
76
102
  }
77
103
  }
@@ -19,7 +19,8 @@ export class ElementDragTitleExtension extends AbstractExtension {
19
19
  let text = this.extendedItem.name;
20
20
  this._width = Math.max(Math.min(elementWidth, w), extensionWidth);
21
21
  this._rect = this._drawRect(transformedCornerPoints[0].x, transformedCornerPoints[0].y - 16, this._width, 15, 'svg-primary-selection-move', this._rect);
22
- this._text = this._drawHTML('<span style="width: 100%; position: absolute; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">' + text + '</span>', (boundRect.x - this.designerCanvas.containerBoundingRect.x) / this.designerCanvas.scaleFactor, transformedCornerPoints[0].y - 16, this._width, 15, 'svg-text-primary', this._text);
22
+ this._text = this._drawHTML('<div style="position:relative"><span style="width: 100%; position: absolute; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; transform-origin: 0 0;">' + text + '</span></div>', (boundRect.x - this.designerCanvas.containerBoundingRect.x) / this.designerCanvas.scaleFactor, transformedCornerPoints[0].y - 16, this._width, 15, 'svg-text-primary', this._text);
23
+ this._text.style.overflow = 'visible';
23
24
  this._rect.addEventListener('pointerdown', (e) => this._pointerEvent(e));
24
25
  this._rect.addEventListener('pointermove', (e) => this._pointerEvent(e));
25
26
  this._rect.addEventListener('pointerup', (e) => this._pointerEvent(e));
@@ -47,8 +48,7 @@ export class ElementDragTitleExtension extends AbstractExtension {
47
48
  this._text.style.fontSize = (10 / this.designerCanvas.scaleFactor) + 'px';
48
49
  this._text.setAttribute('height', '' + h);
49
50
  this._text.setAttribute('width', '' + w);
50
- this._text.style.transformBox = 'fill-box';
51
- this._text.style.rotate = angle + 'deg';
51
+ this._text.children[0].children[0].style.rotate = angle + 'deg';
52
52
  }
53
53
  }
54
54
  }
@@ -282,7 +282,7 @@ export class PointerTool {
282
282
  this._moveItemsOffset = { x: newOffset.x - oldOffset.x + this._moveItemsOffset.x, y: newOffset.y - oldOffset.y + this._moveItemsOffset.y };
283
283
  currentContainerService.leaveContainer(this._actionStartedDesignItem.parent, this._actionStartedDesignItems);
284
284
  const cp = { x: currentPoint.x - this._moveItemsOffset.x, y: currentPoint.y - this._moveItemsOffset.y };
285
- newContainerService.enterContainer(newContainerElementDesignItem, this._actionStartedDesignItems);
285
+ newContainerService.enterContainer(newContainerElementDesignItem, this._actionStartedDesignItems, 'normal');
286
286
  newContainerService.place(event, designerCanvas, this._actionStartedDesignItem.parent, this._initialPoint, this._initialOffset, cp, this._actionStartedDesignItems);
287
287
  designerCanvas.extensionManager.removeExtension(this._dragParentExtensionItem, ExtensionType.ContainerDrag);
288
288
  designerCanvas.extensionManager.applyExtension(newContainerElementDesignItem, ExtensionType.ContainerDrag, event);
@@ -3,6 +3,10 @@ import { assetsPath } from "../../../../../../Constants.js";
3
3
  import { AbstractBaseToolPopup } from './AbstractBaseToolPopup.js';
4
4
  export class DrawToolPopup extends AbstractBaseToolPopup {
5
5
  static style = [super.style, css `
6
+ .container {
7
+ width: 220px;
8
+ min-height: 300px;
9
+ }
6
10
  .inputs{
7
11
  float: left;
8
12
  margin-top: 5px;
package/dist/index.d.ts CHANGED
@@ -16,6 +16,7 @@ export * from "./elements/helper/Helper.js";
16
16
  export * from "./elements/helper/SwitchContainerHelper.js";
17
17
  export * from "./elements/helper/NpmPackageLoader.js";
18
18
  export * from "./elements/helper/LayoutHelper.js";
19
+ export * from "./elements/helper/SelectionHelper.js";
19
20
  export type { IContextMenuItem, IContextMenu } from "./elements/helper/contextMenu/IContextMenuItem.js";
20
21
  export * from "./elements/item/DesignItem.js";
21
22
  export type { IDesignItem } from "./elements/item/IDesignItem.js";
@@ -29,6 +30,7 @@ export type { IBindableObjectsService } from "./elements/services/bindableObject
29
30
  export type { IBindableObjectDragDropService } from "./elements/services/bindableObjectsService/IBindableObjectDragDropService.js";
30
31
  export type { IBindingService } from "./elements/services/bindingsService/IBindingService.js";
31
32
  export * from "./elements/services/bindingsService/BaseCustomWebcomponentBindingsService.js";
33
+ export * from "./elements/services/placementService/AbsolutePlacementService.js";
32
34
  export * from "./elements/services/placementService/DefaultPlacementService.js";
33
35
  export * from "./elements/services/placementService/FlexBoxPlacementService.js";
34
36
  export * from "./elements/services/placementService/GridPlacementService.js";
package/dist/index.js CHANGED
@@ -15,12 +15,14 @@ export * from "./elements/helper/Helper.js";
15
15
  export * from "./elements/helper/SwitchContainerHelper.js";
16
16
  export * from "./elements/helper/NpmPackageLoader.js";
17
17
  export * from "./elements/helper/LayoutHelper.js";
18
+ export * from "./elements/helper/SelectionHelper.js";
18
19
  export * from "./elements/item/DesignItem.js";
19
20
  export * from "./elements/item/BindingMode.js";
20
21
  export * from "./elements/item/BindingTarget.js";
21
22
  export * from "./elements/item/NodeType.js";
22
23
  export * from "./elements/services/bindableObjectsService/BindableObjectType.js";
23
24
  export * from "./elements/services/bindingsService/BaseCustomWebcomponentBindingsService.js";
25
+ export * from "./elements/services/placementService/AbsolutePlacementService.js";
24
26
  export * from "./elements/services/placementService/DefaultPlacementService.js";
25
27
  export * from "./elements/services/placementService/FlexBoxPlacementService.js";
26
28
  export * from "./elements/services/placementService/GridPlacementService.js";
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.1.91",
4
+ "version": "0.1.92",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "author": "jochen.kuehner@gmx.de",