@node-projects/web-component-designer 0.1.159 → 0.1.161

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 (30) hide show
  1. package/README.md +6 -8
  2. package/dist/elements/documentContainer.d.ts +1 -1
  3. package/dist/elements/documentContainer.js +2 -2
  4. package/dist/elements/helper/ElementHelper.d.ts +1 -1
  5. package/dist/elements/helper/ElementHelper.js +18 -14
  6. package/dist/elements/helper/LayoutHelper.js +3 -3
  7. package/dist/elements/helper/SvgHelper.js +3 -3
  8. package/dist/elements/helper/TransformHelper.js +9 -8
  9. package/dist/elements/item/DesignItem.d.ts +4 -0
  10. package/dist/elements/item/DesignItem.js +40 -11
  11. package/dist/elements/item/IDesignItem.d.ts +4 -0
  12. package/dist/elements/services/DefaultServiceBootstrap.js +5 -5
  13. package/dist/elements/services/designItemService/BaseCustomWebcomponentDesignItemService.js +1 -1
  14. package/dist/elements/services/dragDropService/DragDropService.js +1 -1
  15. package/dist/elements/services/eventsService/EventsService.js +3 -3
  16. package/dist/elements/services/htmlWriterService/HtmlWriterService.js +12 -12
  17. package/dist/elements/services/instanceService/DefaultInstanceService.js +2 -2
  18. package/dist/elements/services/placementService/SnaplinesProviderService.js +1 -1
  19. package/dist/elements/services/propertiesService/PropertyGroupsService.js +1 -1
  20. package/dist/elements/services/propertiesService/services/AbstractPropertiesService.js +1 -1
  21. package/dist/elements/services/propertiesService/services/MathMLElementsPropertiesService.js +1 -1
  22. package/dist/elements/services/refactorService/TextRefactorService.js +1 -1
  23. package/dist/elements/widgets/designerView/IDesignerCanvas.d.ts +1 -0
  24. package/dist/elements/widgets/designerView/designerCanvas.d.ts +7 -1
  25. package/dist/elements/widgets/designerView/designerCanvas.js +86 -24
  26. package/dist/elements/widgets/designerView/designerView.d.ts +1 -1
  27. package/dist/elements/widgets/designerView/designerView.js +2 -2
  28. package/dist/elements/widgets/designerView/extensions/ElementDragTitleExtension.js +7 -2
  29. package/dist/elements/widgets/designerView/tools/PointerTool.js +4 -1
  30. package/package.json +1 -1
package/README.md CHANGED
@@ -56,16 +56,14 @@ Your index.html should be extended as follows:
56
56
  <link rel="stylesheet" href="/node_modules/mobile-drag-drop/default.css">
57
57
  <script src="/node_modules/mobile-drag-drop/index.js"></script>
58
58
 
59
- ## Similar Frameworks
59
+ ## Keys
60
60
 
61
- | Name | Licence | Edit Source (split View) | Zooming | Transformations |
62
- |-------------------------|----------|--------------------------|---------|---|
63
- | web-component-designer | MIT | yes |
64
- | GrapeJS | BSD-3 | yes |
65
- | CraftJS | MIT | no |
61
+ Pointer Tool:
62
+ alt: select element behind
63
+ meta: draw selection rect
64
+ ctrl: add to selection
65
+ shift: remove from selection
66
66
 
67
- TODO:
68
- force css states via explicit class (or attr??)
69
67
 
70
68
  ## Copyright notice
71
69
 
@@ -40,7 +40,7 @@ export declare class DocumentContainer extends BaseCustomWebComponentLazyAppend
40
40
  private _disableChangeNotificationDesigner;
41
41
  private _disableChangeNotificationEditor;
42
42
  static get style(): CSSStyleSheet;
43
- constructor(serviceContainer: ServiceContainer, content?: string);
43
+ constructor(serviceContainer: ServiceContainer, content?: string, useIframe?: boolean);
44
44
  refreshInSplitView(): Promise<void>;
45
45
  get currentView(): 'designer' | 'split' | 'code' | 'preview';
46
46
  set currentView(view: 'designer' | 'split' | 'code' | 'preview');
@@ -68,7 +68,7 @@ export class DocumentContainer extends BaseCustomWebComponentLazyAppend {
68
68
  }
69
69
  `;
70
70
  }
71
- constructor(serviceContainer, content) {
71
+ constructor(serviceContainer, content, useIframe = false) {
72
72
  super();
73
73
  this.refreshInSplitViewDebounced = debounce(this.refreshInSplitView, 200);
74
74
  this._serviceContainer = serviceContainer;
@@ -77,7 +77,7 @@ export class DocumentContainer extends BaseCustomWebComponentLazyAppend {
77
77
  let div = document.createElement("div");
78
78
  this._tabControl = new DesignerTabControl();
79
79
  div.appendChild(this._tabControl);
80
- this.designerView = new DesignerView();
80
+ this.designerView = new DesignerView(useIframe);
81
81
  this.designerView.setAttribute('exportparts', 'canvas');
82
82
  this.designerView.slot = 'top';
83
83
  this._designerDiv = document.createElement("div");
@@ -3,7 +3,7 @@ import { IRect } from '../../interfaces/IRect.js';
3
3
  import { IDesignItem } from '../item/IDesignItem.js';
4
4
  import { IDesignerCanvas } from '../widgets/designerView/IDesignerCanvas.js';
5
5
  export declare function inDesigner(element: Element): boolean;
6
- export declare function newElementFromString(text: any): Element;
6
+ export declare function newElementFromString(text: any, document: Document): Element;
7
7
  export declare enum ElementDisplayType {
8
8
  none = 0,
9
9
  inline = 1,
@@ -5,7 +5,7 @@ export function inDesigner(element) {
5
5
  return true;
6
6
  return false;
7
7
  }
8
- export function newElementFromString(text) {
8
+ export function newElementFromString(text, document) {
9
9
  const range = document.createRange();
10
10
  range.selectNode(document.body);
11
11
  //@ts-ignore
@@ -19,21 +19,25 @@ export var ElementDisplayType;
19
19
  ElementDisplayType[ElementDisplayType["block"] = 2] = "block";
20
20
  })(ElementDisplayType || (ElementDisplayType = {}));
21
21
  export function isInline(element) {
22
- if (element instanceof SVGElement)
22
+ if (element == null)
23
23
  return false;
24
- return element != null && window.getComputedStyle(element).display.startsWith('inline');
24
+ if (element instanceof element.ownerDocument.defaultView.SVGElement || element instanceof element.ownerDocument.defaultView.HTMLHtmlElement || element instanceof element.ownerDocument.defaultView.HTMLHeadElement || element instanceof element.ownerDocument.defaultView.HTMLBodyElement)
25
+ return false;
26
+ return element.ownerDocument.defaultView.getComputedStyle(element).display.startsWith('inline');
25
27
  }
26
28
  export function isInlineAfter(element) {
27
- if (element instanceof SVGElement)
29
+ if (element == null)
30
+ return false;
31
+ if (element instanceof element.ownerDocument.defaultView.SVGElement || element instanceof element.ownerDocument.defaultView.HTMLHtmlElement || element instanceof element.ownerDocument.defaultView.HTMLHeadElement || element instanceof element.ownerDocument.defaultView.HTMLBodyElement)
28
32
  return false;
29
- return element != null && window.getComputedStyle(element).display.startsWith('inline');
33
+ return element.ownerDocument.defaultView.getComputedStyle(element).display.startsWith('inline');
30
34
  }
31
35
  export function getElementDisplaytype(element) {
32
- if (element instanceof SVGElement)
36
+ if (element instanceof element.ownerDocument.defaultView.SVGElement || element instanceof element.ownerDocument.defaultView.HTMLHtmlElement || element instanceof element.ownerDocument.defaultView.HTMLHeadElement || element instanceof element.ownerDocument.defaultView.HTMLBodyElement)
33
37
  return ElementDisplayType.block;
34
- if (element instanceof MathMLElement)
38
+ if (element instanceof element.ownerDocument.defaultView.MathMLElement)
35
39
  return ElementDisplayType.block;
36
- const display = window.getComputedStyle(element).display;
40
+ const display = element.ownerDocument.defaultView.getComputedStyle(element).display;
37
41
  return display == 'none' ? ElementDisplayType.none : display.startsWith('inline') ? ElementDisplayType.inline : ElementDisplayType.block;
38
42
  }
39
43
  export function isEmptyTextNode(node) {
@@ -78,18 +82,18 @@ export function getElementsWindowOffsetWithoutSelfAndParentTransformations(eleme
78
82
  break;
79
83
  }
80
84
  let nextParent = element.offsetParent ? element.offsetParent : element.getRootNode().host;
81
- if (element instanceof SVGSVGElement || element instanceof HTMLBodyElement || element instanceof HTMLHtmlElement) {
85
+ if (element instanceof element.ownerDocument.defaultView.SVGSVGElement || element instanceof element.ownerDocument.defaultView.HTMLBodyElement || element instanceof element.ownerDocument.defaultView.HTMLHtmlElement) {
82
86
  nextParent = element.parentElement ? element.parentElement : element.getRootNode().host;
83
87
  }
84
- else if (element instanceof SVGGraphicsElement) {
88
+ else if (element instanceof element.ownerDocument.defaultView.SVGGraphicsElement) {
85
89
  nextParent = element.ownerSVGElement;
86
90
  }
87
- else if (element instanceof MathMLElement) {
91
+ else if (element instanceof element.ownerDocument.defaultView.MathMLElement) {
88
92
  nextParent = element.parentElement ?? nextParent;
89
93
  }
90
94
  let scrollLeft = 0;
91
95
  let scrollTop = 0;
92
- if (element instanceof HTMLElement) {
96
+ if (element instanceof element.ownerDocument.defaultView.HTMLElement) {
93
97
  let parent = element.parentElement;
94
98
  while (parent !== null && parent !== nextParent) {
95
99
  scrollLeft += parent.scrollLeft;
@@ -103,7 +107,7 @@ export function getElementsWindowOffsetWithoutSelfAndParentTransformations(eleme
103
107
  }
104
108
  let currLeft = 0;
105
109
  let currTop = 0;
106
- if (element instanceof SVGSVGElement || element instanceof MathMLElement) {
110
+ if (element instanceof element.ownerDocument.defaultView.SVGSVGElement || element instanceof element.ownerDocument.defaultView.MathMLElement) {
107
111
  //TODO: !huge Perf impact! - fix without transformation
108
112
  let t = element.style.transform;
109
113
  element.style.transform = '';
@@ -113,7 +117,7 @@ export function getElementsWindowOffsetWithoutSelfAndParentTransformations(eleme
113
117
  currLeft = (bcEl.left - bcPar.left) / zoom;
114
118
  currTop = (bcEl.top - bcPar.top) / zoom;
115
119
  }
116
- else if (element instanceof SVGGraphicsElement) {
120
+ else if (element instanceof element.ownerDocument.defaultView.SVGGraphicsElement) {
117
121
  let bbox = element.getBBox();
118
122
  currLeft = bbox.x;
119
123
  currTop = bbox.y;
@@ -33,10 +33,10 @@ export function placeDesignItem(container, designItem, offset, mode) {
33
33
  const computedStyleMovedElement = getComputedStyle(movedElement);
34
34
  if (mode === 'position') {
35
35
  let positionedContainerElement = container.element;
36
- let computedStylePositionedContainer = getComputedStyle(container.element);
37
- if (computedStylePositionedContainer.position !== 'relative' && computedStylePositionedContainer.position !== 'absolute') {
36
+ let computedStylePositionedContainer = container.getComputedStyle();
37
+ if (computedStylePositionedContainer.position !== 'relative' && computedStylePositionedContainer.position !== 'absolute' && positionedContainerElement.offsetParent) {
38
38
  positionedContainerElement = positionedContainerElement.offsetParent;
39
- computedStylePositionedContainer = getComputedStyle(positionedContainerElement);
39
+ computedStylePositionedContainer = container.window.getComputedStyle(positionedContainerElement);
40
40
  }
41
41
  let oldLeft = null;
42
42
  let oldRight = null;
@@ -1,11 +1,11 @@
1
1
  export function isVisualSvgElement(element) {
2
2
  let el = element;
3
3
  while (el) {
4
- if (el instanceof SVGSVGElement)
4
+ if (el instanceof el.ownerDocument.defaultView.SVGSVGElement)
5
5
  return true;
6
- if (el instanceof SVGDefsElement)
6
+ if (el instanceof el.ownerDocument.defaultView.SVGDefsElement)
7
7
  return false;
8
- if (el instanceof SVGMetadataElement)
8
+ if (el instanceof el.ownerDocument.defaultView.SVGMetadataElement)
9
9
  return false;
10
10
  el = el.parentElement;
11
11
  }
@@ -187,16 +187,16 @@ export function getDesignerCanvasNormalizedTransformedPoint(element, point, desi
187
187
  export function getElementSize(element) {
188
188
  let width = element.offsetWidth;
189
189
  let height = element.offsetHeight;
190
- if (element instanceof SVGElement && element.width) {
190
+ if (element instanceof element.ownerDocument.defaultView.SVGElement && element.width) {
191
191
  width = element.width.baseVal.value;
192
192
  height = element.height.baseVal.value;
193
193
  }
194
- else if (element instanceof SVGGraphicsElement) {
194
+ else if (element instanceof element.ownerDocument.defaultView.SVGGraphicsElement) {
195
195
  let bbox = element.getBBox();
196
196
  width = bbox.width;
197
197
  height = bbox.height;
198
198
  }
199
- else if (element instanceof MathMLElement) {
199
+ else if (element instanceof element.ownerDocument.defaultView.MathMLElement) {
200
200
  let bbox = element.getBoundingClientRect();
201
201
  width = bbox.width;
202
202
  height = bbox.height;
@@ -251,11 +251,12 @@ export function getDesignerCanvasNormalizedTransformedCornerDOMPoints(element, u
251
251
  let top1Transformed = top1.matrixTransform(originalElementAndAllParentsMultipliedMatrix);
252
252
  let top2Transformed = top2.matrixTransform(originalElementAndAllParentsMultipliedMatrix);
253
253
  let top3Transformed = top3.matrixTransform(originalElementAndAllParentsMultipliedMatrix);
254
- let transformedCornerPoints = [];
255
- transformedCornerPoints[0] = new DOMPoint(designerCanvasNormalizedTransformOrigin.x + top0Transformed.x, designerCanvasNormalizedTransformOrigin.y + top0Transformed.y);
256
- transformedCornerPoints[1] = new DOMPoint(designerCanvasNormalizedTransformOrigin.x + top1Transformed.x, designerCanvasNormalizedTransformOrigin.y + top1Transformed.y);
257
- transformedCornerPoints[2] = new DOMPoint(designerCanvasNormalizedTransformOrigin.x + top2Transformed.x, designerCanvasNormalizedTransformOrigin.y + top2Transformed.y);
258
- transformedCornerPoints[3] = new DOMPoint(designerCanvasNormalizedTransformOrigin.x + top3Transformed.x, designerCanvasNormalizedTransformOrigin.y + top3Transformed.y);
254
+ const transformedCornerPoints = [];
255
+ const offset = designerCanvas.containerOffset;
256
+ transformedCornerPoints[0] = new DOMPoint(designerCanvasNormalizedTransformOrigin.x + top0Transformed.x + offset.x, designerCanvasNormalizedTransformOrigin.y + top0Transformed.y + offset.y);
257
+ transformedCornerPoints[1] = new DOMPoint(designerCanvasNormalizedTransformOrigin.x + top1Transformed.x + offset.x, designerCanvasNormalizedTransformOrigin.y + top1Transformed.y + offset.y);
258
+ transformedCornerPoints[2] = new DOMPoint(designerCanvasNormalizedTransformOrigin.x + top2Transformed.x + offset.x, designerCanvasNormalizedTransformOrigin.y + top2Transformed.y + offset.y);
259
+ transformedCornerPoints[3] = new DOMPoint(designerCanvasNormalizedTransformOrigin.x + top3Transformed.x + offset.x, designerCanvasNormalizedTransformOrigin.y + top3Transformed.y + offset.y);
259
260
  return transformedCornerPoints;
260
261
  }
261
262
  export function extractTranslationFromDOMMatrix(matrix) {
@@ -22,6 +22,9 @@ export declare class DesignItem implements IDesignItem {
22
22
  serviceContainer: ServiceContainer;
23
23
  instanceServiceContainer: InstanceServiceContainer;
24
24
  nodeReplaced: TypedEvent<void>;
25
+ get window(): Window & typeof globalThis;
26
+ get document(): Document;
27
+ get usableContainer(): Element | Document | ShadowRoot;
25
28
  clone(): Promise<IDesignItem>;
26
29
  allMatching(selectors: string): Generator<IDesignItem, void, undefined>;
27
30
  replaceNode(newNode: Node): void;
@@ -76,6 +79,7 @@ export declare class DesignItem implements IDesignItem {
76
79
  static createDesignItemFromInstance(node: Node, serviceContainer: ServiceContainer, instanceServiceContainer: InstanceServiceContainer): DesignItem;
77
80
  querySelectorAll(selectors: string): NodeListOf<HTMLElement>;
78
81
  removeDesignerAttributesAndStylesFromChildren(): void;
82
+ updateChildrenFromNodesChildren(): void;
79
83
  _internalUpdateChildrenFromNodesChildren(): any[];
80
84
  _backupWhenEditContent: any;
81
85
  _inEditContent: boolean;
@@ -27,6 +27,23 @@ export class DesignItem {
27
27
  serviceContainer;
28
28
  instanceServiceContainer;
29
29
  nodeReplaced = new TypedEvent;
30
+ get window() {
31
+ if (this.isRootItem && this.node instanceof HTMLIFrameElement)
32
+ return this.node.contentDocument.defaultView;
33
+ return this.node.ownerDocument.defaultView;
34
+ }
35
+ get document() {
36
+ if (this.isRootItem && this.node instanceof HTMLIFrameElement)
37
+ return this.node.contentDocument;
38
+ return this.node.ownerDocument;
39
+ }
40
+ get usableContainer() {
41
+ if (this.isRootItem && this.element instanceof this.element.ownerDocument.defaultView.HTMLIFrameElement)
42
+ return this.element.contentWindow.document;
43
+ else if (this.isRootItem)
44
+ return this.node.shadowRoot;
45
+ return this.element;
46
+ }
30
47
  async clone() {
31
48
  try {
32
49
  const html = DomConverter.ConvertToString([this], false);
@@ -57,9 +74,9 @@ export class DesignItem {
57
74
  this.nodeReplaced.emit();
58
75
  }
59
76
  get nodeType() {
60
- if (this.node instanceof Comment)
77
+ if (this.node instanceof this.node.ownerDocument.defaultView.Comment)
61
78
  return NodeType.Comment;
62
- if (this.node instanceof Text)
79
+ if (this.node instanceof this.node.ownerDocument.defaultView.Text)
63
80
  return NodeType.TextNode;
64
81
  return NodeType.Element;
65
82
  }
@@ -88,7 +105,7 @@ export class DesignItem {
88
105
  }
89
106
  _reparseSpecialAttributes(name) {
90
107
  if (name == hideAtDesignTimeAttributeName) {
91
- if (this.element instanceof HTMLElement || this.element instanceof SVGElement) {
108
+ if (this.element instanceof this.node.ownerDocument.defaultView.HTMLElement || this.element instanceof this.node.ownerDocument.defaultView.SVGElement) {
92
109
  if (!this._attributes.has(hideAtDesignTimeAttributeName))
93
110
  this.element.style.display = this._styles.get('display') ?? "";
94
111
  else
@@ -96,7 +113,7 @@ export class DesignItem {
96
113
  }
97
114
  }
98
115
  else if (name == hideAtRunTimeAttributeName) {
99
- if (this.element instanceof HTMLElement || this.element instanceof SVGElement) {
116
+ if (this.element instanceof this.node.ownerDocument.defaultView.HTMLElement || this.element instanceof this.node.ownerDocument.defaultView.SVGElement) {
100
117
  if (!this._attributes.has(hideAtRunTimeAttributeName))
101
118
  this.element.style.opacity = this._styles.get('opacity') ?? "";
102
119
  else
@@ -104,7 +121,7 @@ export class DesignItem {
104
121
  }
105
122
  }
106
123
  else if (name == lockAtDesignTimeAttributeName) {
107
- if (this.element instanceof HTMLElement || this.element instanceof SVGElement) {
124
+ if (this.element instanceof this.node.ownerDocument.defaultView.HTMLElement || this.element instanceof this.node.ownerDocument.defaultView.SVGElement) {
108
125
  if (!this._attributes.has(lockAtDesignTimeAttributeName))
109
126
  this.element.style.pointerEvents = 'auto';
110
127
  else
@@ -313,7 +330,7 @@ export class DesignItem {
313
330
  }
314
331
  static createDesignItemFromInstance(node, serviceContainer, instanceServiceContainer) {
315
332
  let designItem = new DesignItem(node, node, serviceContainer, instanceServiceContainer);
316
- if (node instanceof HTMLTemplateElement && node.getAttribute('shadowrootmode') == 'open') {
333
+ if (node instanceof node.ownerDocument.defaultView.HTMLTemplateElement && node.getAttribute('shadowrootmode') == 'open') {
317
334
  try {
318
335
  const shadow = node.parentNode.attachShadow({ mode: 'open' });
319
336
  shadow.appendChild(node.content.cloneNode(true));
@@ -328,7 +345,7 @@ export class DesignItem {
328
345
  designItem._attributes.set(a.name, a.value);
329
346
  }
330
347
  }
331
- if (node instanceof HTMLElement || node instanceof SVGElement) {
348
+ if (node instanceof node.ownerDocument.defaultView.HTMLElement || node instanceof node.ownerDocument.defaultView.SVGElement) {
332
349
  const cssParser = new CssAttributeParser();
333
350
  const st = node.getAttribute("style");
334
351
  if (st) {
@@ -369,15 +386,27 @@ export class DesignItem {
369
386
  e.style.pointerEvents = '';
370
387
  }
371
388
  }
389
+ updateChildrenFromNodesChildren() {
390
+ this._childArray = this._internalUpdateChildrenFromNodesChildren();
391
+ for (let c of this._childArray) {
392
+ c._parent = this;
393
+ }
394
+ }
372
395
  _internalUpdateChildrenFromNodesChildren() {
373
396
  const newChilds = [];
374
397
  if (this.nodeType == NodeType.Element) {
375
- if (this.element instanceof HTMLTemplateElement) {
398
+ if (this.element instanceof this.node.ownerDocument.defaultView.HTMLTemplateElement) {
376
399
  for (const c of this.element.content.childNodes) {
377
400
  const di = DesignItem.createDesignItemFromInstance(c, this.serviceContainer, this.instanceServiceContainer);
378
401
  newChilds.push(di);
379
402
  }
380
403
  }
404
+ else if (this.element instanceof this.node.ownerDocument.defaultView.HTMLIFrameElement) {
405
+ for (const c of this.element.contentWindow.document.childNodes) {
406
+ const di = DesignItem.createDesignItemFromInstance(c, this.serviceContainer, this.instanceServiceContainer);
407
+ newChilds.push(di);
408
+ }
409
+ }
381
410
  else {
382
411
  for (const c of this.element.childNodes) {
383
412
  const di = DesignItem.createDesignItemFromInstance(c, this.serviceContainer, this.instanceServiceContainer);
@@ -565,7 +594,7 @@ export class DesignItem {
565
594
  }
566
595
  getComputedStyle() {
567
596
  if (this.nodeType == NodeType.Element)
568
- return window.getComputedStyle(this.element);
597
+ return this.window.getComputedStyle(this.element);
569
598
  return null;
570
599
  }
571
600
  _stylesCache = null;
@@ -616,7 +645,7 @@ export class DesignItem {
616
645
  if (this.isRootItem) {
617
646
  this.node.shadowRoot.appendChild(designItem.view);
618
647
  }
619
- else if (this.view instanceof HTMLTemplateElement) {
648
+ else if (this.view instanceof this.node.ownerDocument.defaultView.HTMLTemplateElement) {
620
649
  this.view.content.appendChild(designItem.view);
621
650
  }
622
651
  else
@@ -627,7 +656,7 @@ export class DesignItem {
627
656
  if (this.isRootItem) {
628
657
  this.node.shadowRoot.insertBefore(designItem.view, el.element);
629
658
  }
630
- else if (this.view instanceof HTMLTemplateElement) {
659
+ else if (this.view instanceof this.node.ownerDocument.defaultView.HTMLTemplateElement) {
631
660
  this.view.content.insertBefore(designItem.view, el.element);
632
661
  }
633
662
  else
@@ -8,6 +8,10 @@ import { IPlacementService } from '../services/placementService/IPlacementServic
8
8
  import { TypedEvent } from '@node-projects/base-custom-webcomponent';
9
9
  export interface IDesignItem {
10
10
  lastContainerSize: ISize;
11
+ readonly window: Window & typeof globalThis;
12
+ readonly document: Document;
13
+ readonly usableContainer: ShadowRoot | Element | Document;
14
+ updateChildrenFromNodesChildren(): any;
11
15
  setView(node: Element): any;
12
16
  replaceNode(newNode: Node): any;
13
17
  nodeReplaced: TypedEvent<void>;
@@ -133,7 +133,7 @@ export function createDefaultServiceContainer() {
133
133
  new InvisibleElementExtensionProvider(),
134
134
  ]);
135
135
  serviceContainer.designerExtensions.set(ExtensionType.PrimarySelection, [
136
- new ConditionExtensionProvider(new ElementDragTitleExtensionProvider(), item => !(item.node instanceof SVGElement) || item.node instanceof SVGSVGElement),
136
+ new ConditionExtensionProvider(new ElementDragTitleExtensionProvider(), item => !(item.node instanceof item.window.SVGElement) || item.node instanceof item.window.SVGSVGElement),
137
137
  new PreviousElementSelectExtensionProvider(),
138
138
  new TransformOriginExtensionProvider(true),
139
139
  new MarginExtensionProvider(),
@@ -142,7 +142,7 @@ export function createDefaultServiceContainer() {
142
142
  new SvgElementExtensionProvider(),
143
143
  new ApplyFirstMachingExtensionProvider(new GridChildResizeExtensionProvider(), new ResizeExtensionProvider(true)),
144
144
  new RotateExtensionProvider(),
145
- new ConditionExtensionProvider(new MultipleSelectionRectExtensionProvider(), item => !(item.node instanceof SVGElement) || item.node instanceof SVGSVGElement),
145
+ new ConditionExtensionProvider(new MultipleSelectionRectExtensionProvider(), item => !(item.node instanceof item.window.SVGElement) || item.node instanceof item.window.SVGSVGElement),
146
146
  ]);
147
147
  serviceContainer.designerExtensions.set(ExtensionType.PrimarySelectionRefreshed, [
148
148
  new GridChildToolbarExtensionProvider(),
@@ -156,7 +156,7 @@ export function createDefaultServiceContainer() {
156
156
  new FlexboxExtensionProvider(),
157
157
  ]);
158
158
  serviceContainer.designerExtensions.set(ExtensionType.Selection, [
159
- new ConditionExtensionProvider(new SelectionDefaultExtensionProvider(), item => !(item.node instanceof SVGElement) || item.node instanceof SVGSVGElement),
159
+ new ConditionExtensionProvider(new SelectionDefaultExtensionProvider(), item => !(item.node instanceof item.window.SVGElement) || item.node instanceof item.window.SVGSVGElement),
160
160
  ]);
161
161
  serviceContainer.designerExtensions.set(ExtensionType.PrimarySelectionContainerAndCanBeEntered, [
162
162
  new DisplayGridExtensionProvider('lightgray', '#8080802b'),
@@ -165,8 +165,8 @@ export function createDefaultServiceContainer() {
165
165
  ]);
166
166
  serviceContainer.designerExtensions.set(ExtensionType.MouseOver, [
167
167
  new HighlightElementExtensionProvider(),
168
- new ConditionExtensionProvider(new ElementDragTitleExtensionProvider(), item => item.instanceServiceContainer.selectionService.primarySelection !== item && !(item.node instanceof SVGElement) || item.node instanceof SVGSVGElement),
169
- new ConditionExtensionProvider(new PreviousElementSelectExtensionProvider(), item => item.instanceServiceContainer.selectionService.primarySelection !== item && !(item.node instanceof SVGElement) || item.node instanceof SVGSVGElement),
168
+ new ConditionExtensionProvider(new ElementDragTitleExtensionProvider(), item => item.instanceServiceContainer.selectionService.primarySelection !== item && !(item.node instanceof item.window.SVGElement) || item.node instanceof item.window.SVGSVGElement),
169
+ new ConditionExtensionProvider(new PreviousElementSelectExtensionProvider(), item => item.instanceServiceContainer.selectionService.primarySelection !== item && !(item.node instanceof item.window.SVGElement) || item.node instanceof item.window.SVGSVGElement),
170
170
  ]);
171
171
  serviceContainer.designerExtensions.set(ExtensionType.Placement, [
172
172
  new PlacementExtensionProvider()
@@ -2,7 +2,7 @@ import { DesignItem } from "../../item/DesignItem.js";
2
2
  export class BaseCustomWebcomponentDesignItemService {
3
3
  createDesignItem(node, parsedNode, serviceContainer, instanceServiceContainer) {
4
4
  const di = new DesignItem(node, parsedNode, serviceContainer, instanceServiceContainer);
5
- if (node instanceof HTMLTemplateElement) {
5
+ if (node instanceof node.ownerDocument.defaultView.HTMLTemplateElement) {
6
6
  requestAnimationFrame(() => {
7
7
  let repeatCount = 1;
8
8
  const attr = node.getAttribute('sample-repeat-count');
@@ -74,7 +74,7 @@ export class DragDropService {
74
74
  newContainerService = designerCanvas.serviceContainer.getLastServiceWhere('containerService', x => x.serviceForContainer(newContainerElementDesignItem, containerStyle));
75
75
  if (newContainerService) {
76
76
  //TODO: Maybe the check for SVG Element should be in "canEnterByDrop"?
77
- if (newContainerService.isEnterableContainer(newContainerElementDesignItem) && !(newContainerElementDesignItem.element instanceof SVGElement)) {
77
+ if (newContainerService.isEnterableContainer(newContainerElementDesignItem) && !(newContainerElementDesignItem.element instanceof newContainerElementDesignItem.window.SVGElement)) {
78
78
  break;
79
79
  }
80
80
  else {
@@ -89,9 +89,9 @@ export class EventsService {
89
89
  return true;
90
90
  }
91
91
  getPossibleEvents(designItem) {
92
- if (designItem.element instanceof HTMLInputElement ||
93
- designItem.element instanceof HTMLTextAreaElement ||
94
- designItem.element instanceof HTMLSelectElement) {
92
+ if (designItem.element instanceof designItem.window.HTMLInputElement ||
93
+ designItem.element instanceof designItem.window.HTMLTextAreaElement ||
94
+ designItem.element instanceof designItem.window.HTMLSelectElement) {
95
95
  let events = [...this._simpleForm, ...this._simpleMouseEvents, ...this._form, ...this._pointerEvents, ...this._allElements, ...this._focusableEvents];
96
96
  return events;
97
97
  }
@@ -7,22 +7,22 @@ export class HtmlWriterService extends AbstractHtmlWriterService {
7
7
  super(options);
8
8
  }
9
9
  _conditionalyWriteIndent(indentedTextWriter, designItem) {
10
- if ((designItem.element instanceof HTMLElement && !isInlineAfter(designItem.element)) ||
11
- (designItem.element.previousElementSibling instanceof HTMLElement && !isInline(designItem.element.previousElementSibling)) ||
10
+ if ((designItem.element instanceof designItem.window.HTMLElement && !isInlineAfter(designItem.element)) ||
11
+ (designItem.element.previousElementSibling instanceof designItem.window.HTMLElement && !isInline(designItem.element.previousElementSibling)) ||
12
12
  (designItem.element.previousElementSibling == null && !isInline(designItem.element.parentElement) && (designItem.element.previousSibling == null || isEmptyTextNode(designItem.element.previousSibling))) ||
13
- (designItem.element instanceof SVGElement))
13
+ (designItem.element instanceof designItem.window.SVGElement))
14
14
  indentedTextWriter.writeIndent();
15
15
  }
16
16
  _conditionalyWriteIndentBefore(indentedTextWriter, designItem) {
17
- if ((designItem.element.previousElementSibling instanceof HTMLElement && !isInline(designItem.element.previousElementSibling)) ||
17
+ if ((designItem.element.previousElementSibling instanceof designItem.window.HTMLElement && !isInline(designItem.element.previousElementSibling)) ||
18
18
  (designItem.element.previousElementSibling == null && !isInline(designItem.element.parentElement) && (designItem.element.previousSibling == null || isEmptyTextNode(designItem.element.previousSibling))) ||
19
- (designItem.element instanceof SVGElement))
19
+ (designItem.element instanceof designItem.window.SVGElement))
20
20
  indentedTextWriter.writeIndent();
21
21
  }
22
22
  _conditionalyWriteNewline(indentedTextWriter, designItem) {
23
- if ((designItem.element instanceof HTMLElement && !isInlineAfter(designItem.element)) ||
24
- (designItem.element.nextElementSibling instanceof HTMLElement && !isInline(designItem.element.nextElementSibling)) ||
25
- (designItem.element instanceof SVGElement))
23
+ if ((designItem.element instanceof designItem.window.HTMLElement && !isInlineAfter(designItem.element)) ||
24
+ (designItem.element.nextElementSibling instanceof designItem.window.HTMLElement && !isInline(designItem.element.nextElementSibling)) ||
25
+ (designItem.element instanceof designItem.window.SVGElement))
26
26
  indentedTextWriter.writeNewline();
27
27
  }
28
28
  write(indentedTextWriter, designItems, rootContainerKeepInline, updatePositions = false) {
@@ -36,8 +36,8 @@ export class HtmlWriterService extends AbstractHtmlWriterService {
36
36
  let end = indentedTextWriter.position;
37
37
  if (designItem.nodeType == NodeType.TextNode) {
38
38
  if (isEmptyTextNode(designItem.element) &&
39
- ((designItem.element.previousSibling instanceof HTMLElement && !isInlineAfter(designItem.element.previousSibling)) ||
40
- (designItem.element.nextSibling instanceof HTMLElement && !isInline(designItem.element.nextSibling)))) {
39
+ ((designItem.element.previousSibling instanceof designItem.window.HTMLElement && !isInlineAfter(designItem.element.previousSibling)) ||
40
+ (designItem.element.nextSibling instanceof designItem.window.HTMLElement && !isInline(designItem.element.nextSibling)))) {
41
41
  }
42
42
  else
43
43
  this.writeTextNode(indentedTextWriter, designItem, true);
@@ -66,7 +66,7 @@ export class HtmlWriterService extends AbstractHtmlWriterService {
66
66
  this.writeTextNode(indentedTextWriter, designItem, false, !notrim);
67
67
  }
68
68
  else {
69
- if (designItem.element instanceof HTMLElement && !isInlineAfter(designItem.element) || (designItem.element instanceof SVGElement)) {
69
+ if (designItem.element instanceof designItem.window.HTMLElement && !isInlineAfter(designItem.element) || (designItem.element instanceof designItem.window.SVGElement)) {
70
70
  indentedTextWriter.writeNewline();
71
71
  indentedTextWriter.levelRaise();
72
72
  }
@@ -77,7 +77,7 @@ export class HtmlWriterService extends AbstractHtmlWriterService {
77
77
  if (!indentedTextWriter.isLastCharNewline())
78
78
  this._conditionalyWriteNewline(indentedTextWriter, c);
79
79
  }
80
- if (designItem.element instanceof HTMLElement && !isInlineAfter(designItem.element) || (designItem.element instanceof SVGElement)) {
80
+ if (designItem.element instanceof designItem.window.HTMLElement && !isInlineAfter(designItem.element) || (designItem.element instanceof designItem.window.SVGElement)) {
81
81
  indentedTextWriter.levelShrink();
82
82
  if (!indentedTextWriter.isLastCharNewline())
83
83
  indentedTextWriter.writeNewline();
@@ -45,7 +45,7 @@ export class DefaultInstanceService {
45
45
  }
46
46
  }
47
47
  const elementString = '<' + definition.tag + attr + '></' + definition.tag + '>';
48
- const element = newElementFromString(elementString);
48
+ const element = newElementFromString(elementString, instanceServiceContainer.designerCanvas.rootDesignItem.document);
49
49
  element._inNodeProjectsDesignerView = true;
50
50
  if (definition.defaultWidth)
51
51
  element.style.width = definition.defaultWidth;
@@ -58,7 +58,7 @@ export class DefaultInstanceService {
58
58
  }
59
59
  if (definition.defaultContent) {
60
60
  if (typeof definition.defaultContent === "string") {
61
- const parser = new DOMParser();
61
+ const parser = new instanceServiceContainer.designerCanvas.rootDesignItem.window.DOMParser();
62
62
  //@ts-ignore
63
63
  const doc = parser.parseFromString(definition.defaultContent, 'text/html', { includeShadowRoots: true });
64
64
  element.append(...doc.head.childNodes);
@@ -12,7 +12,7 @@ export class SnaplinesProviderService {
12
12
  const positionsMiddleH = [];
13
13
  const positionsV = [];
14
14
  const positionsMiddleV = [];
15
- const tw = document.createTreeWalker(containerItem.isRootItem ? containerItem.element.shadowRoot : containerItem.element, NodeFilter.SHOW_ELEMENT);
15
+ const tw = containerItem.document.createTreeWalker(containerItem.usableContainer, NodeFilter.SHOW_ELEMENT);
16
16
  let n = tw.nextNode();
17
17
  while (n != null) {
18
18
  if (ignMap.has(n)) {
@@ -60,7 +60,7 @@ export class PropertyGroupsService {
60
60
  this._pgList[0].propertiesService = designItems[0].serviceContainer.getLastServiceWhere('propertyService', x => x.isHandledElement(designItems[0]));
61
61
  this._svgPgList[0].propertiesService = designItems[0].serviceContainer.getLastServiceWhere('propertyService', x => x.isHandledElement(designItems[0]));
62
62
  let lst = this._pgList;
63
- if (designItems[0].element instanceof SVGElement)
63
+ if (designItems[0].element instanceof designItems[0].window.SVGElement)
64
64
  lst = this._svgPgList;
65
65
  const style = designItems[0].getComputedStyle();
66
66
  if (style.display.includes('grid'))
@@ -262,7 +262,7 @@ export class AbstractPropertiesService {
262
262
  txt += a.name + '="' + a.value.replaceAll('"', '&quot;') + '" ';
263
263
  }
264
264
  txt += '></' + d.name + '>';
265
- let element = newElementFromString(txt); // some custom elements only parse attributes during constructor call
265
+ let element = newElementFromString(txt, designItems[0].document); // some custom elements only parse attributes during constructor call
266
266
  for (let c of [...d.element.childNodes])
267
267
  element.appendChild(c);
268
268
  element.style.pointerEvents = 'auto';
@@ -50,7 +50,7 @@ export class MathMLElementsPropertiesService extends CommonPropertiesService {
50
50
  return RefreshMode.full;
51
51
  }
52
52
  isHandledElement(designItem) {
53
- return designItem.element instanceof MathMLElement;
53
+ return designItem.element instanceof designItem.window.MathMLElement;
54
54
  }
55
55
  getProperty(designItem, name) {
56
56
  return this.getProperties(designItem).find(x => x.name == name);
@@ -2,7 +2,7 @@ export class TextRefactorService {
2
2
  getRefactorings(designItems) {
3
3
  let refactorings = [];
4
4
  for (let d of designItems) {
5
- if (d.element instanceof HTMLInputElement || d.element instanceof HTMLTextAreaElement) {
5
+ if (d.element instanceof d.window.HTMLInputElement || d.element instanceof d.window.HTMLTextAreaElement) {
6
6
  if (d.element.value)
7
7
  refactorings.push({ service: this, name: d.element.value, itemType: 'text', designItem: d, type: 'attribute', sourceObject: d, display: 'attribute' + '/' + 'value' });
8
8
  }
@@ -30,6 +30,7 @@ export interface IDesignerCanvas extends IPlacementView, IUiCommandHandler {
30
30
  designerOffsetHeight: number;
31
31
  readonly scaleFactor: number;
32
32
  canvasOffset: IPoint;
33
+ readonly containerOffset: IPoint;
33
34
  canvas: HTMLElement;
34
35
  additionalStyles: CSSStyleSheet[];
35
36
  ignoreEvent(event: Event): any;
@@ -48,6 +48,8 @@ export declare class DesignerCanvas extends BaseCustomWebComponentLazyAppend imp
48
48
  set canvasOffset(value: IPoint);
49
49
  get canvasOffsetUnzoomed(): IPoint;
50
50
  set canvasOffsetUnzoomed(value: IPoint);
51
+ /** Offset when using an iframe as container */
52
+ get containerOffset(): IPoint;
51
53
  onContentChanged: TypedEvent<void>;
52
54
  onZoomFactorChanged: TypedEvent<number>;
53
55
  get canvas(): HTMLElement;
@@ -64,7 +66,10 @@ export declare class DesignerCanvas extends BaseCustomWebComponentLazyAppend imp
64
66
  private _pointerextensions;
65
67
  private _lastCopiedPrimaryItem;
66
68
  private _ignoreEvent;
67
- constructor();
69
+ private _useIframe;
70
+ private _iframe;
71
+ private _window;
72
+ constructor(useIframe?: boolean);
68
73
  get designerWidth(): string;
69
74
  set designerWidth(value: string);
70
75
  get designerHeight(): string;
@@ -124,6 +129,7 @@ export declare class DesignerCanvas extends BaseCustomWebComponentLazyAppend imp
124
129
  realHeight: number;
125
130
  };
126
131
  getNormalizedOffsetInElement(event: MouseEvent, element: Element): IPoint;
132
+ private transformPoint;
127
133
  elementsFromPoint(x: number, y: number): Element[];
128
134
  getElementAtPoint(point: IPoint, ignoreElementCallback?: (element: HTMLElement) => boolean): HTMLElement;
129
135
  _patchStylesheetForDesigner(text: string): string;
@@ -1,7 +1,7 @@
1
1
  import { EventNames } from '../../../enums/EventNames.js';
2
2
  import { InstanceServiceContainer } from '../../services/InstanceServiceContainer.js';
3
3
  import { DesignItem, forceActiveAttributeName, forceFocusAttributeName, forceFocusVisibleAttributeName, forceFocusWithinAttributeName, forceHoverAttributeName, forceVisitedAttributeName } from '../../item/DesignItem.js';
4
- import { BaseCustomWebComponentLazyAppend, css, html, TypedEvent, cssFromString } from '@node-projects/base-custom-webcomponent';
4
+ import { BaseCustomWebComponentLazyAppend, css, html, TypedEvent } from '@node-projects/base-custom-webcomponent';
5
5
  import { dragDropFormatNameBindingObject } from '../../../Constants.js';
6
6
  import { InsertAction } from '../../services/undoService/transactionItems/InsertAction.js';
7
7
  import { Snaplines } from './Snaplines.js';
@@ -21,6 +21,7 @@ import { StylesheetChangedAction } from '../../services/undoService/transactionI
21
21
  import { SetDesignItemsAction } from '../../services/undoService/transactionItems/SetDesignItemsAction.js';
22
22
  import { filterChildPlaceItems } from '../../helper/LayoutHelper.js';
23
23
  import { TouchGestureHelper } from '../../helper/TouchGestureHelper.js';
24
+ import { stylesheetFromString } from '../../helper/StylesheetHelper.js';
24
25
  export class DesignerCanvas extends BaseCustomWebComponentLazyAppend {
25
26
  // Public Properties
26
27
  serviceContainer;
@@ -91,6 +92,14 @@ export class DesignerCanvas extends BaseCustomWebComponentLazyAppend {
91
92
  set canvasOffsetUnzoomed(value) {
92
93
  this.canvasOffset = { x: value.x / this.zoomFactor, y: value.y / this.zoomFactor };
93
94
  }
95
+ /** Offset when using an iframe as container */
96
+ get containerOffset() {
97
+ if (this._useIframe) {
98
+ const rect = this._outercanvas2.getBoundingClientRect();
99
+ return rect;
100
+ }
101
+ return { x: 0, y: 0 };
102
+ }
94
103
  onContentChanged = new TypedEvent();
95
104
  onZoomFactorChanged = new TypedEvent();
96
105
  get canvas() {
@@ -158,6 +167,15 @@ export class DesignerCanvas extends BaseCustomWebComponentLazyAppend {
158
167
  user-select: none;
159
168
  -webkit-user-select: none;
160
169
  }
170
+
171
+ #node-projects-designer-canvas-canvas iframe {
172
+ cursor: pointer;
173
+ user-select: none;
174
+ -webkit-user-select: none;
175
+ border: none;
176
+ width: 100%;
177
+ height: 100%;
178
+ }
161
179
 
162
180
  #node-projects-designer-canvas-clickOverlay {
163
181
  position: absolute;
@@ -275,11 +293,27 @@ export class DesignerCanvas extends BaseCustomWebComponentLazyAppend {
275
293
  _pointerextensions;
276
294
  _lastCopiedPrimaryItem;
277
295
  _ignoreEvent;
278
- constructor() {
296
+ _useIframe = true;
297
+ _iframe;
298
+ _window;
299
+ constructor(useIframe = false) {
279
300
  super();
301
+ this._useIframe = useIframe;
280
302
  this._restoreCachedInititalValues();
281
303
  this._canvas = this._getDomElement('node-projects-designer-canvas-canvas');
282
- this._canvasShadowRoot = this._canvas.attachShadow({ mode: 'open' });
304
+ if (this._useIframe) {
305
+ this._iframe = document.createElement('iframe');
306
+ this._iframe.setAttribute("sandbox", "allow-same-origin");
307
+ this._canvas.appendChild(this._iframe);
308
+ requestAnimationFrame(() => {
309
+ this._window = this._iframe.contentWindow;
310
+ this._canvasShadowRoot = this._iframe.contentWindow.document;
311
+ });
312
+ }
313
+ else {
314
+ this._window = window;
315
+ this._canvasShadowRoot = this._canvas.attachShadow({ mode: 'open' });
316
+ }
283
317
  this._canvasContainer = this._getDomElement('node-projects-designer-canvas-canvasContainer');
284
318
  this._outercanvas2 = this._getDomElement('node-projects-designer-canvas-outercanvas2');
285
319
  this.clickOverlay = this._getDomElement('node-projects-designer-canvas-clickOverlay');
@@ -333,15 +367,25 @@ export class DesignerCanvas extends BaseCustomWebComponentLazyAppend {
333
367
  return this._additionalStyle;
334
368
  }
335
369
  applyAllStyles() {
336
- let styles = [];
337
- if (this._additionalStyle)
338
- styles.push(...this._additionalStyle);
339
- if (this.instanceServiceContainer.stylesheetService) {
340
- styles.push(...this.instanceServiceContainer.stylesheetService
341
- .getStylesheets()
342
- .map(x => cssFromString(this._patchStylesheetForDesigner(x.content))));
370
+ if (this._window) {
371
+ let styles = [];
372
+ if (this._additionalStyle)
373
+ styles.push(...this._additionalStyle);
374
+ if (this.instanceServiceContainer.stylesheetService) {
375
+ styles.push(...this.instanceServiceContainer.stylesheetService
376
+ .getStylesheets()
377
+ .map(x => stylesheetFromString(this._window, this._patchStylesheetForDesigner(x.content))));
378
+ }
379
+ if (this._useIframe) {
380
+ this._iframe.contentWindow.document.adoptedStyleSheets = styles;
381
+ }
382
+ else {
383
+ this._canvasShadowRoot.adoptedStyleSheets = styles;
384
+ }
385
+ }
386
+ else {
387
+ requestAnimationFrame(() => this.applyAllStyles());
343
388
  }
344
- this._canvasShadowRoot.adoptedStyleSheets = styles;
345
389
  }
346
390
  ignoreEvent(event) {
347
391
  this._ignoreEvent = event;
@@ -489,7 +533,7 @@ export class DesignerCanvas extends BaseCustomWebComponentLazyAppend {
489
533
  this.canvasOffset = { x: 0, y: 0 };
490
534
  this.zoomFactor = 1;
491
535
  for (let n of this.rootDesignItem.querySelectorAll('*')) {
492
- if (n instanceof Element) {
536
+ if (n instanceof n.ownerDocument.defaultView.Element) {
493
537
  const rect = n.getBoundingClientRect();
494
538
  minX = minX < rect.x ? minX : rect.x;
495
539
  minY = minY < rect.y ? minY : rect.y;
@@ -598,8 +642,15 @@ export class DesignerCanvas extends BaseCustomWebComponentLazyAppend {
598
642
  if (designItemDocumentPositionService) {
599
643
  this.instanceServiceContainer.register("designItemDocumentPositionService", designItemDocumentPositionService(this));
600
644
  }
601
- this.rootDesignItem = DesignItem.GetOrCreateDesignItem(this._canvas, this._canvas, this.serviceContainer, this.instanceServiceContainer);
602
- //this.rootDesignItem.setView(<any>this._canvasShadowRoot);
645
+ if (this._useIframe) {
646
+ this.rootDesignItem = DesignItem.GetOrCreateDesignItem(this._iframe, this._iframe, this.serviceContainer, this.instanceServiceContainer);
647
+ requestAnimationFrame(() => {
648
+ this.rootDesignItem.updateChildrenFromNodesChildren();
649
+ });
650
+ }
651
+ else {
652
+ this.rootDesignItem = DesignItem.GetOrCreateDesignItem(this._canvas, this._canvas, this.serviceContainer, this.instanceServiceContainer);
653
+ }
603
654
  const contentService = this.serviceContainer.getLastService('contentService');
604
655
  if (contentService) {
605
656
  this.instanceServiceContainer.register("contentService", contentService(this));
@@ -998,14 +1049,16 @@ export class DesignerCanvas extends BaseCustomWebComponentLazyAppend {
998
1049
  let range = document.createRange();
999
1050
  range.selectNodeContents(element);
1000
1051
  let targetRect = range.getBoundingClientRect();
1001
- return { x: (targetRect.x - this.containerBoundingRect.x) / (ignoreScalefactor ? 1 : this.scaleFactor), y: (targetRect.y - this.containerBoundingRect.y) / (ignoreScalefactor ? 1 : this.scaleFactor), width: targetRect.width / (ignoreScalefactor ? 1 : this.scaleFactor), height: targetRect.height / (ignoreScalefactor ? 1 : this.scaleFactor) };
1052
+ const offset = this.containerOffset;
1053
+ return { x: offset.x + (targetRect.x - this.containerBoundingRect.x) / (ignoreScalefactor ? 1 : this.scaleFactor), y: offset.y + (targetRect.y - this.containerBoundingRect.y) / (ignoreScalefactor ? 1 : this.scaleFactor), width: targetRect.width / (ignoreScalefactor ? 1 : this.scaleFactor), height: targetRect.height / (ignoreScalefactor ? 1 : this.scaleFactor) };
1002
1054
  }
1003
1055
  getNormalizedElementCoordinates(element, ignoreScalefactor) {
1004
1056
  if (element.nodeType == NodeType.TextNode) {
1005
1057
  return this.getNormalizedTextNodeCoordinates(element, ignoreScalefactor);
1006
1058
  }
1007
1059
  const targetRect = element.getBoundingClientRect();
1008
- return { x: (targetRect.x - this.containerBoundingRect.x) / (ignoreScalefactor ? 1 : this.scaleFactor), y: (targetRect.y - this.containerBoundingRect.y) / (ignoreScalefactor ? 1 : this.scaleFactor), width: targetRect.width / (ignoreScalefactor ? 1 : this.scaleFactor), height: targetRect.height / (ignoreScalefactor ? 1 : this.scaleFactor) };
1060
+ const offset = this.containerOffset;
1061
+ return { x: offset.x + (targetRect.x - this.containerBoundingRect.x) / (ignoreScalefactor ? 1 : this.scaleFactor), y: offset.y + (targetRect.y - this.containerBoundingRect.y) / (ignoreScalefactor ? 1 : this.scaleFactor), width: targetRect.width / (ignoreScalefactor ? 1 : this.scaleFactor), height: targetRect.height / (ignoreScalefactor ? 1 : this.scaleFactor) };
1009
1062
  }
1010
1063
  getNormalizedElementCoordinatesAndRealSizes(element) {
1011
1064
  let ret = this.getNormalizedElementCoordinates(element);
@@ -1023,9 +1076,17 @@ export class DesignerCanvas extends BaseCustomWebComponentLazyAppend {
1023
1076
  const normEl = this.getNormalizedElementCoordinates(element);
1024
1077
  return { x: normEvt.x - normEl.x, y: normEvt.y - normEl.y };
1025
1078
  }
1079
+ transformPoint(point) {
1080
+ if (this._useIframe) {
1081
+ const rect = this._canvasContainer.getBoundingClientRect();
1082
+ return { x: point.x - rect.x, y: point.y - rect.y };
1083
+ }
1084
+ return point;
1085
+ }
1026
1086
  elementsFromPoint(x, y) {
1027
1087
  let retVal = [];
1028
- let elements = this._canvasShadowRoot.elementsFromPoint(x, y);
1088
+ const t = this.transformPoint({ x, y });
1089
+ const elements = this._canvasShadowRoot.elementsFromPoint(t.x, t.y);
1029
1090
  for (let e of elements) {
1030
1091
  if (e.getRootNode() !== this._canvasShadowRoot)
1031
1092
  continue;
@@ -1034,7 +1095,8 @@ export class DesignerCanvas extends BaseCustomWebComponentLazyAppend {
1034
1095
  return retVal;
1035
1096
  }
1036
1097
  getElementAtPoint(point, ignoreElementCallback) {
1037
- const elements = this._canvasShadowRoot.elementsFromPoint(point.x, point.y);
1098
+ const t = this.transformPoint(point);
1099
+ const elements = this._canvasShadowRoot.elementsFromPoint(t.x, t.y);
1038
1100
  let currentElement = null;
1039
1101
  for (let i = 0; i < elements.length; i++) {
1040
1102
  currentElement = elements[i];
@@ -1055,12 +1117,12 @@ export class DesignerCanvas extends BaseCustomWebComponentLazyAppend {
1055
1117
  return currentElement;
1056
1118
  }
1057
1119
  _patchStylesheetForDesigner(text) {
1058
- return text.replace(':hover', '[' + forceHoverAttributeName + ']')
1059
- .replace(':active', '[' + forceActiveAttributeName + ']')
1060
- .replace(':visited', '[' + forceVisitedAttributeName + ']')
1061
- .replace(':focus', '[' + forceFocusAttributeName + ']')
1062
- .replace(':focus-within', '[' + forceFocusWithinAttributeName + ']')
1063
- .replace(':focus-visible', '[' + forceFocusVisibleAttributeName + ']');
1120
+ return text.replaceAll(':hover', '[' + forceHoverAttributeName + ']')
1121
+ .replaceAll(':active', '[' + forceActiveAttributeName + ']')
1122
+ .replaceAll(':visited', '[' + forceVisitedAttributeName + ']')
1123
+ .replaceAll(':focus', '[' + forceFocusAttributeName + ']')
1124
+ .replaceAll(':focus-within', '[' + forceFocusWithinAttributeName + ']')
1125
+ .replaceAll(':focus-visible', '[' + forceFocusVisibleAttributeName + ']');
1064
1126
  }
1065
1127
  _hoverElement;
1066
1128
  showHoverExtension(element, event) {
@@ -19,7 +19,7 @@ export declare class DesignerView extends BaseCustomWebComponentConstructorAppen
19
19
  private _toolbar;
20
20
  static readonly style: CSSStyleSheet;
21
21
  static readonly template: HTMLTemplateElement;
22
- constructor();
22
+ constructor(useIframe?: boolean);
23
23
  zoomReset(): void;
24
24
  zoomToFit(): void;
25
25
  private _onScrollbar;
@@ -150,13 +150,13 @@ export class DesignerView extends BaseCustomWebComponentConstructorAppend {
150
150
  <div title="snap to elements" id="alignSnap" class="toolbar-control snap-guide"></div>
151
151
  </div>
152
152
  </div>`;
153
- constructor() {
153
+ constructor(useIframe = false) {
154
154
  super();
155
155
  this._restoreCachedInititalValues();
156
156
  this._sVert = this._getDomElement('s-vert');
157
157
  this._sHor = this._getDomElement('s-hor');
158
158
  const outer = this._getDomElement('outer');
159
- this._designerCanvas = new DesignerCanvas();
159
+ this._designerCanvas = new DesignerCanvas(useIframe);
160
160
  this._designerCanvas.id = "canvas";
161
161
  this._designerCanvas.appendChild(document.createElement("slot"));
162
162
  outer.insertAdjacentElement('afterbegin', this._designerCanvas);
@@ -24,11 +24,15 @@ export class ElementDragTitleExtension extends AbstractExtension {
24
24
  this._rect = this._drawRect(transformedCornerPoints[0].x, transformedCornerPoints[0].y, this._width, 15, 'svg-primary-selection-move', this._rect);
25
25
  this._clickRect = this._drawRect(transformedCornerPoints[0].x, transformedCornerPoints[0].y, this._width, 18, 'svg-invisible', this._clickRect);
26
26
  this._clickRect.style.background = 'transparent';
27
- 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; padding-left: 2px;">' + text + '</span></div>', (boundRect.x - this.designerCanvas.containerBoundingRect.x) / this.designerCanvas.scaleFactor, transformedCornerPoints[0].y - 16, this._width, 15, 'svg-text-primary', this._text);
27
+ this._text = this._drawHTML('<div style="position:relative; pointer-events: none;"><span style="width: 100%; position: absolute; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; transform-origin: 0 0; padding-left: 2px;">' + text + '</span></div>', (boundRect.x - this.designerCanvas.containerBoundingRect.x) / this.designerCanvas.scaleFactor, transformedCornerPoints[0].y - 16, this._width, 15, 'svg-text-primary', this._text);
28
28
  this._text.style.overflow = 'visible';
29
29
  this._clickRect.addEventListener('pointerdown', (e) => this._pointerEvent(e));
30
30
  this._clickRect.addEventListener('pointermove', (e) => this._pointerEvent(e));
31
31
  this._clickRect.addEventListener('pointerup', (e) => this._pointerEvent(e));
32
+ this._clickRect.addEventListener('contextmenu', (e) => {
33
+ e.preventDefault();
34
+ this.designerCanvas.showDesignItemContextMenu(this.extendedItem, e);
35
+ });
32
36
  this.refresh(cache, event);
33
37
  }
34
38
  }
@@ -67,7 +71,8 @@ export class ElementDragTitleExtension extends AbstractExtension {
67
71
  _pointerEvent(event) {
68
72
  event.preventDefault();
69
73
  event.stopPropagation();
70
- this.designerCanvas.serviceContainer.designerTools.get(NamedTools.Pointer).pointerEventHandler(this.designerCanvas, event, this.extendedItem.element);
74
+ if (event.button != 2)
75
+ this.designerCanvas.serviceContainer.designerTools.get(NamedTools.Pointer).pointerEventHandler(this.designerCanvas, event, this.extendedItem.element);
71
76
  }
72
77
  dispose() {
73
78
  this._removeAllOverlays();
@@ -103,7 +103,10 @@ export class PointerTool {
103
103
  if (this._actionType == null) {
104
104
  this._initialPoint = currentPoint;
105
105
  this._initialOffset = designerCanvas.getNormalizedOffsetInElement(event, currentElement);
106
- if (event.type == EventNames.PointerDown) {
106
+ if (event.metaKey) {
107
+ this._actionType = PointerActionType.DrawSelection;
108
+ }
109
+ else if (event.type == EventNames.PointerDown) {
107
110
  this._actionStartedDesignItem = currentDesignItem;
108
111
  this._actionStartedDesignItems = [...designerCanvas.instanceServiceContainer.selectionService.selectedElements];
109
112
  designerCanvas.snapLines.clearSnaplines();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "description": "A WYSIWYG designer webcomponent for html components",
3
3
  "name": "@node-projects/web-component-designer",
4
- "version": "0.1.159",
4
+ "version": "0.1.161",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "author": "jochen.kuehner@gmx.de",