@node-projects/web-component-designer 0.0.161 → 0.0.164
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/elements/helper/ElementHelper.js +6 -0
- package/dist/elements/helper/GridHelper.d.ts +2 -0
- package/dist/elements/helper/GridHelper.js +4 -4
- package/dist/elements/services/htmlParserService/AbstractClassElementParserService.d.ts +12 -0
- package/dist/elements/services/htmlParserService/AbstractClassElementParserService.js +120 -0
- package/dist/elements/services/htmlParserService/LitElementParserService copy.d.ts +12 -0
- package/dist/elements/services/htmlParserService/LitElementParserService copy.js +120 -0
- package/dist/elements/widgets/designerView/IDesignerCanvas.d.ts +1 -1
- package/dist/elements/widgets/designerView/designerCanvas.js +9 -6
- package/dist/elements/widgets/designerView/extensions/GridExtension.d.ts +18 -0
- package/dist/elements/widgets/designerView/extensions/GridExtension.js +216 -13
- package/dist/elements/widgets/designerView/extensions/GridExtensionProvider.js +1 -0
- package/package.json +1 -1
|
@@ -70,6 +70,12 @@ export function getElementsWindowOffsetWithoutSelfAndParentTransformations(eleme
|
|
|
70
70
|
offsetTop += bbox.y;
|
|
71
71
|
element = element.ownerSVGElement;
|
|
72
72
|
}
|
|
73
|
+
else if (element instanceof HTMLBodyElement) {
|
|
74
|
+
element = element.parentElement;
|
|
75
|
+
}
|
|
76
|
+
else if (element instanceof HTMLHtmlElement) {
|
|
77
|
+
element = element.parentElement;
|
|
78
|
+
}
|
|
73
79
|
else {
|
|
74
80
|
offsetLeft += element.offsetLeft;
|
|
75
81
|
offsetTop += element.offsetTop;
|
|
@@ -85,13 +85,13 @@ export function CalculateGridInformation(designItem) {
|
|
|
85
85
|
retVal.cells.push(cellList);
|
|
86
86
|
for (let yIdx = 0; yIdx < columns.length; yIdx++) {
|
|
87
87
|
const c = columns[yIdx];
|
|
88
|
-
if (x > 0
|
|
89
|
-
retVal.gaps.push({ x: x + xOffset + paddingLeft, y: y + yOffset + paddingTop, width: xGap, height: currY });
|
|
88
|
+
if (x > 0) {
|
|
89
|
+
retVal.gaps.push({ x: x + xOffset + paddingLeft, y: y + yOffset + paddingTop, width: xGap, height: currY, column: yIdx, row: xIdx });
|
|
90
90
|
x += xGap;
|
|
91
91
|
}
|
|
92
92
|
const currX = Number.parseFloat(c.replace('px', ''));
|
|
93
|
-
if (y > 0
|
|
94
|
-
retVal.gaps.push({ x: x + xOffset + paddingLeft, y: y + yOffset - yGap + paddingTop, width: currX, height: yGap });
|
|
93
|
+
if (y > 0) {
|
|
94
|
+
retVal.gaps.push({ x: x + xOffset + paddingLeft, y: y + yOffset - yGap + paddingTop, width: currX, height: yGap, column: yIdx, row: xIdx });
|
|
95
95
|
}
|
|
96
96
|
let name = null;
|
|
97
97
|
if (areas && areas[cl]) {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { InstanceServiceContainer } from '../InstanceServiceContainer.js';
|
|
2
|
+
import { ServiceContainer } from '../ServiceContainer.js';
|
|
3
|
+
import { IHtmlParserService } from './IHtmlParserService.js';
|
|
4
|
+
import { IDesignItem } from '../../item/IDesignItem.js';
|
|
5
|
+
export declare abstract class AbstractClassElementParserService implements IHtmlParserService {
|
|
6
|
+
private _parserUrl;
|
|
7
|
+
private _esprimaUrl;
|
|
8
|
+
constructor(parserUrl?: string, esprimaUrl?: string);
|
|
9
|
+
parse(module: string, serviceContainer: ServiceContainer, instanceServiceContainer: InstanceServiceContainer): Promise<IDesignItem[]>;
|
|
10
|
+
private _parseDiv;
|
|
11
|
+
_createDesignItemsRecursive(item: any, serviceContainer: ServiceContainer, instanceServiceContainer: InstanceServiceContainer, namespace: string): IDesignItem;
|
|
12
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { DesignItem } from '../../item/DesignItem.js';
|
|
2
|
+
import { CssAttributeParser } from '../../helper/CssAttributeParser.js';
|
|
3
|
+
import { newElementFromString } from '../../helper/ElementHelper.js';
|
|
4
|
+
import * as esprima from "esprima-next/dist/esm/esprima";
|
|
5
|
+
function* getChildNodes(node) {
|
|
6
|
+
switch (node.type) {
|
|
7
|
+
case esprima.Syntax.Program:
|
|
8
|
+
yield node.body;
|
|
9
|
+
break;
|
|
10
|
+
case esprima.Syntax.ClassDeclaration:
|
|
11
|
+
yield node.body;
|
|
12
|
+
break;
|
|
13
|
+
case esprima.Syntax.MethodDefinition:
|
|
14
|
+
yield node.value;
|
|
15
|
+
break;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
// Alternative Parser, cause when you use the Browser, it instanciates the CusomElements, and some Elemnts remove
|
|
19
|
+
// attributes from their DOM, so you loose Data
|
|
20
|
+
export class AbstractClassElementParserService {
|
|
21
|
+
_parserUrl;
|
|
22
|
+
_esprimaUrl;
|
|
23
|
+
constructor(parserUrl = '../../../../../node-html-parser-esm/dist/index.js', esprimaUrl = '../../../../../esprima-next/dist/esm/esprima.js') {
|
|
24
|
+
this._parserUrl = parserUrl;
|
|
25
|
+
this._esprimaUrl = esprimaUrl;
|
|
26
|
+
}
|
|
27
|
+
async parse(module, serviceContainer, instanceServiceContainer) {
|
|
28
|
+
let esprima = await import(this._esprimaUrl);
|
|
29
|
+
const parsedModule = esprima.parseModule(module);
|
|
30
|
+
const classDecl = parsedModule.body.find(x => x.type == esprima.Syntax.ClassDeclaration);
|
|
31
|
+
const renderMethod = classDecl.body.body.find(x => x.type == esprima.Syntax.MethodDefinition && x.key.name == 'render');
|
|
32
|
+
const renderMethodStatement = renderMethod.value.body.body[0];
|
|
33
|
+
const taggedTemplate = renderMethodStatement.argument;
|
|
34
|
+
const templateLiteral = taggedTemplate.quasi;
|
|
35
|
+
const html = templateLiteral.quasis.map(x => x.value.raw).join();
|
|
36
|
+
//@ts-ignore
|
|
37
|
+
let parser = await import(this._parserUrl);
|
|
38
|
+
const parsed = parser.parse(html, { comment: true });
|
|
39
|
+
let designItems = [];
|
|
40
|
+
for (let p of parsed.childNodes) {
|
|
41
|
+
let di = this._createDesignItemsRecursive(p, serviceContainer, instanceServiceContainer, null);
|
|
42
|
+
if (di != null)
|
|
43
|
+
designItems.push(di);
|
|
44
|
+
else
|
|
45
|
+
console.warn("NodeHtmlParserService - could not parse element", p);
|
|
46
|
+
}
|
|
47
|
+
return designItems;
|
|
48
|
+
}
|
|
49
|
+
_parseDiv = document.createElement("div");
|
|
50
|
+
_createDesignItemsRecursive(item, serviceContainer, instanceServiceContainer, namespace) {
|
|
51
|
+
let designItem = null;
|
|
52
|
+
if (item.nodeType == 1) {
|
|
53
|
+
let element;
|
|
54
|
+
let manualCreatedElement = false;
|
|
55
|
+
if (!namespace)
|
|
56
|
+
element = newElementFromString('<' + item.rawTagName + ' ' + item.rawAttrs + '></' + item.rawTagName + '>'); // some custom elements only parse attributes during constructor call
|
|
57
|
+
if (!element) {
|
|
58
|
+
if (namespace)
|
|
59
|
+
element = document.createElementNS(namespace, item.rawTagName);
|
|
60
|
+
else
|
|
61
|
+
element = document.createElement(item.rawTagName);
|
|
62
|
+
manualCreatedElement = true;
|
|
63
|
+
}
|
|
64
|
+
designItem = new DesignItem(element, item, serviceContainer, instanceServiceContainer);
|
|
65
|
+
let hideAtDesignTime = false;
|
|
66
|
+
let hideAtRunTime = false;
|
|
67
|
+
let lockAtDesignTime = false;
|
|
68
|
+
let style = '';
|
|
69
|
+
let attr = item.attributes;
|
|
70
|
+
for (let a in attr) {
|
|
71
|
+
if (a !== 'style') {
|
|
72
|
+
designItem._withoutUndoSetAttribute(a, attr[a]);
|
|
73
|
+
if (manualCreatedElement) {
|
|
74
|
+
element.setAttribute(a, attr[a]);
|
|
75
|
+
}
|
|
76
|
+
if (a === 'node-projects-hide-at-design-time')
|
|
77
|
+
hideAtDesignTime = true;
|
|
78
|
+
else if (a === 'node-projects-hide-at-run-time')
|
|
79
|
+
hideAtRunTime = true;
|
|
80
|
+
else if (a === 'node-projects-lock-at-design-time')
|
|
81
|
+
lockAtDesignTime = true;
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
style = attr[a];
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if ((element instanceof HTMLElement || element instanceof SVGElement) && style) {
|
|
88
|
+
let styleParser = new CssAttributeParser();
|
|
89
|
+
styleParser.parse(style);
|
|
90
|
+
for (let s of styleParser.entries) {
|
|
91
|
+
designItem._withoutUndoSetStyle(s.name, s.value);
|
|
92
|
+
if (manualCreatedElement) {
|
|
93
|
+
element.style[s.name] = s.value;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (!lockAtDesignTime && (element instanceof HTMLElement || element instanceof SVGElement)) {
|
|
98
|
+
requestAnimationFrame(() => element.style.pointerEvents = 'auto');
|
|
99
|
+
}
|
|
100
|
+
designItem.hideAtDesignTime = hideAtDesignTime;
|
|
101
|
+
designItem.hideAtRunTime = hideAtRunTime;
|
|
102
|
+
designItem.lockAtDesignTime = lockAtDesignTime;
|
|
103
|
+
element.draggable = false; //even if it should be true, for better designer exp.
|
|
104
|
+
for (let c of item.childNodes) {
|
|
105
|
+
let di = this._createDesignItemsRecursive(c, serviceContainer, instanceServiceContainer, element instanceof SVGElement ? 'http://www.w3.org/2000/svg' : null);
|
|
106
|
+
designItem._insertChildInternal(di);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
else if (item.nodeType == 3) {
|
|
110
|
+
this._parseDiv.innerHTML = item.rawText;
|
|
111
|
+
let element = this._parseDiv.childNodes[0];
|
|
112
|
+
designItem = new DesignItem(element, item, serviceContainer, instanceServiceContainer);
|
|
113
|
+
}
|
|
114
|
+
else if (item.nodeType == 8) {
|
|
115
|
+
let element = document.createComment(item.rawText);
|
|
116
|
+
designItem = new DesignItem(element, item, serviceContainer, instanceServiceContainer);
|
|
117
|
+
}
|
|
118
|
+
return designItem;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { InstanceServiceContainer } from '../InstanceServiceContainer.js';
|
|
2
|
+
import { ServiceContainer } from '../ServiceContainer.js';
|
|
3
|
+
import { IHtmlParserService } from './IHtmlParserService.js';
|
|
4
|
+
import { IDesignItem } from '../../item/IDesignItem.js';
|
|
5
|
+
export declare class LitElementParserService implements IHtmlParserService {
|
|
6
|
+
private _parserUrl;
|
|
7
|
+
private _esprimaUrl;
|
|
8
|
+
constructor(parserUrl?: string, esprimaUrl?: string);
|
|
9
|
+
parse(module: string, serviceContainer: ServiceContainer, instanceServiceContainer: InstanceServiceContainer): Promise<IDesignItem[]>;
|
|
10
|
+
private _parseDiv;
|
|
11
|
+
_createDesignItemsRecursive(item: any, serviceContainer: ServiceContainer, instanceServiceContainer: InstanceServiceContainer, namespace: string): IDesignItem;
|
|
12
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { DesignItem } from '../../item/DesignItem.js';
|
|
2
|
+
import { CssAttributeParser } from '../../helper/CssAttributeParser.js';
|
|
3
|
+
import { newElementFromString } from '../../helper/ElementHelper.js';
|
|
4
|
+
import * as esprima from "esprima-next/dist/esm/esprima";
|
|
5
|
+
function* getChildNodes(node) {
|
|
6
|
+
switch (node.type) {
|
|
7
|
+
case esprima.Syntax.Program:
|
|
8
|
+
yield node.body;
|
|
9
|
+
break;
|
|
10
|
+
case esprima.Syntax.ClassDeclaration:
|
|
11
|
+
yield node.body;
|
|
12
|
+
break;
|
|
13
|
+
case esprima.Syntax.MethodDefinition:
|
|
14
|
+
yield node.value;
|
|
15
|
+
break;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
// Alternative Parser, cause when you use the Browser, it instanciates the CusomElements, and some Elemnts remove
|
|
19
|
+
// attributes from their DOM, so you loose Data
|
|
20
|
+
export class LitElementParserService {
|
|
21
|
+
_parserUrl;
|
|
22
|
+
_esprimaUrl;
|
|
23
|
+
constructor(parserUrl = '../../../../../node-html-parser-esm/dist/index.js', esprimaUrl = '../../../../../esprima-next/dist/esm/esprima.js') {
|
|
24
|
+
this._parserUrl = parserUrl;
|
|
25
|
+
this._esprimaUrl = esprimaUrl;
|
|
26
|
+
}
|
|
27
|
+
async parse(module, serviceContainer, instanceServiceContainer) {
|
|
28
|
+
let esprima = await import(this._esprimaUrl);
|
|
29
|
+
const parsedModule = esprima.parseModule(module);
|
|
30
|
+
const classDecl = parsedModule.body.find(x => x.type == esprima.Syntax.ClassDeclaration);
|
|
31
|
+
const renderMethod = classDecl.body.body.find(x => x.type == esprima.Syntax.MethodDefinition && x.key.name == 'render');
|
|
32
|
+
const renderMethodStatement = renderMethod.value.body.body[0];
|
|
33
|
+
const taggedTemplate = renderMethodStatement.argument;
|
|
34
|
+
const templateLiteral = taggedTemplate.quasi;
|
|
35
|
+
const html = templateLiteral.quasis.map(x => x.value.raw).join();
|
|
36
|
+
//@ts-ignore
|
|
37
|
+
let parser = await import(this._parserUrl);
|
|
38
|
+
const parsed = parser.parse(html, { comment: true });
|
|
39
|
+
let designItems = [];
|
|
40
|
+
for (let p of parsed.childNodes) {
|
|
41
|
+
let di = this._createDesignItemsRecursive(p, serviceContainer, instanceServiceContainer, null);
|
|
42
|
+
if (di != null)
|
|
43
|
+
designItems.push(di);
|
|
44
|
+
else
|
|
45
|
+
console.warn("NodeHtmlParserService - could not parse element", p);
|
|
46
|
+
}
|
|
47
|
+
return designItems;
|
|
48
|
+
}
|
|
49
|
+
_parseDiv = document.createElement("div");
|
|
50
|
+
_createDesignItemsRecursive(item, serviceContainer, instanceServiceContainer, namespace) {
|
|
51
|
+
let designItem = null;
|
|
52
|
+
if (item.nodeType == 1) {
|
|
53
|
+
let element;
|
|
54
|
+
let manualCreatedElement = false;
|
|
55
|
+
if (!namespace)
|
|
56
|
+
element = newElementFromString('<' + item.rawTagName + ' ' + item.rawAttrs + '></' + item.rawTagName + '>'); // some custom elements only parse attributes during constructor call
|
|
57
|
+
if (!element) {
|
|
58
|
+
if (namespace)
|
|
59
|
+
element = document.createElementNS(namespace, item.rawTagName);
|
|
60
|
+
else
|
|
61
|
+
element = document.createElement(item.rawTagName);
|
|
62
|
+
manualCreatedElement = true;
|
|
63
|
+
}
|
|
64
|
+
designItem = new DesignItem(element, item, serviceContainer, instanceServiceContainer);
|
|
65
|
+
let hideAtDesignTime = false;
|
|
66
|
+
let hideAtRunTime = false;
|
|
67
|
+
let lockAtDesignTime = false;
|
|
68
|
+
let style = '';
|
|
69
|
+
let attr = item.attributes;
|
|
70
|
+
for (let a in attr) {
|
|
71
|
+
if (a !== 'style') {
|
|
72
|
+
designItem._withoutUndoSetAttribute(a, attr[a]);
|
|
73
|
+
if (manualCreatedElement) {
|
|
74
|
+
element.setAttribute(a, attr[a]);
|
|
75
|
+
}
|
|
76
|
+
if (a === 'node-projects-hide-at-design-time')
|
|
77
|
+
hideAtDesignTime = true;
|
|
78
|
+
else if (a === 'node-projects-hide-at-run-time')
|
|
79
|
+
hideAtRunTime = true;
|
|
80
|
+
else if (a === 'node-projects-lock-at-design-time')
|
|
81
|
+
lockAtDesignTime = true;
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
style = attr[a];
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if ((element instanceof HTMLElement || element instanceof SVGElement) && style) {
|
|
88
|
+
let styleParser = new CssAttributeParser();
|
|
89
|
+
styleParser.parse(style);
|
|
90
|
+
for (let s of styleParser.entries) {
|
|
91
|
+
designItem._withoutUndoSetStyle(s.name, s.value);
|
|
92
|
+
if (manualCreatedElement) {
|
|
93
|
+
element.style[s.name] = s.value;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (!lockAtDesignTime && (element instanceof HTMLElement || element instanceof SVGElement)) {
|
|
98
|
+
requestAnimationFrame(() => element.style.pointerEvents = 'auto');
|
|
99
|
+
}
|
|
100
|
+
designItem.hideAtDesignTime = hideAtDesignTime;
|
|
101
|
+
designItem.hideAtRunTime = hideAtRunTime;
|
|
102
|
+
designItem.lockAtDesignTime = lockAtDesignTime;
|
|
103
|
+
element.draggable = false; //even if it should be true, for better designer exp.
|
|
104
|
+
for (let c of item.childNodes) {
|
|
105
|
+
let di = this._createDesignItemsRecursive(c, serviceContainer, instanceServiceContainer, element instanceof SVGElement ? 'http://www.w3.org/2000/svg' : null);
|
|
106
|
+
designItem._insertChildInternal(di);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
else if (item.nodeType == 3) {
|
|
110
|
+
this._parseDiv.innerHTML = item.rawText;
|
|
111
|
+
let element = this._parseDiv.childNodes[0];
|
|
112
|
+
designItem = new DesignItem(element, item, serviceContainer, instanceServiceContainer);
|
|
113
|
+
}
|
|
114
|
+
else if (item.nodeType == 8) {
|
|
115
|
+
let element = document.createComment(item.rawText);
|
|
116
|
+
designItem = new DesignItem(element, item, serviceContainer, instanceServiceContainer);
|
|
117
|
+
}
|
|
118
|
+
return designItem;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
@@ -21,7 +21,7 @@ export interface IDesignerCanvas extends IPlacementView, IUiCommandHandler {
|
|
|
21
21
|
readonly extensionManager: IExtensionManager;
|
|
22
22
|
readonly clickOverlay: HTMLDivElement;
|
|
23
23
|
readonly snapLines: Snaplines;
|
|
24
|
-
readonly shadowRoot: ShadowRoot;
|
|
24
|
+
readonly shadowRoot: ShadowRoot | null;
|
|
25
25
|
readonly alignOnGrid: boolean;
|
|
26
26
|
readonly alignOnSnap: boolean;
|
|
27
27
|
readonly onContentChanged: TypedEvent<void>;
|
|
@@ -150,15 +150,15 @@ export class DesignerCanvas extends BaseCustomWebComponentLazyAppend {
|
|
|
150
150
|
}
|
|
151
151
|
`;
|
|
152
152
|
static template = html `
|
|
153
|
-
<div style="display: flex;flex-direction: column;width: 100%;height: 100%;">
|
|
154
|
-
<div style="width: 100%;height: 100%;">
|
|
155
|
-
<div id="node-projects-designer-canvas-outercanvas2" style="width:100%;height:100%;position:relative;">
|
|
153
|
+
<div style="display: flex;flex-direction: column;width: 100%;height: 100%; margin: 0 !important; padding: 0 !important; border: none !important;">
|
|
154
|
+
<div style="width: 100%;height: 100%; margin: 0 !important; padding: 0 !important; border: none !important;">
|
|
155
|
+
<div id="node-projects-designer-canvas-outercanvas2" style="width:100%;height:100%;position:relative; margin: 0 !important; padding: 0 !important; border: none !important;">
|
|
156
156
|
<div id="node-projects-designer-canvas-canvasContainer"
|
|
157
|
-
style="width: 100%;height: 100%;position: absolute;top: 0;left: 0;user-select: none;">
|
|
158
|
-
<div id="node-projects-designer-canvas-canvas" part="canvas"></div>
|
|
157
|
+
style="width: 100%;height: 100%;position: absolute;top: 0;left: 0;user-select: none; margin: 0 !important; padding: 0 !important; border: none !important;">
|
|
158
|
+
<div id="node-projects-designer-canvas-canvas" part="canvas" style=" margin: 0 !important; padding: 0 !important; border: none !important;"></div>
|
|
159
159
|
</div>
|
|
160
160
|
</div>
|
|
161
|
-
<div id="node-projects-designer-canvas-clickOverlay" tabindex="0" style="pointer-events: auto;"></div>
|
|
161
|
+
<div id="node-projects-designer-canvas-clickOverlay" tabindex="0" style="pointer-events: auto; margin: 0 !important; padding: 0 !important; border: none !important;"></div>
|
|
162
162
|
</div>
|
|
163
163
|
</div>`;
|
|
164
164
|
extensionManager;
|
|
@@ -437,6 +437,9 @@ export class DesignerCanvas extends BaseCustomWebComponentLazyAppend {
|
|
|
437
437
|
this.extensionManager = new ExtensionManager(this);
|
|
438
438
|
this.overlayLayer = new OverlayLayerView(serviceContainer);
|
|
439
439
|
this.overlayLayer.style.pointerEvents = 'none';
|
|
440
|
+
this.overlayLayer.style.setProperty('margin', '0', 'important');
|
|
441
|
+
this.overlayLayer.style.setProperty('padding', '0', 'important');
|
|
442
|
+
this.overlayLayer.style.setProperty('border', 'none', 'important');
|
|
440
443
|
this.clickOverlay.appendChild(this.overlayLayer);
|
|
441
444
|
this.snapLines = new Snaplines(this.overlayLayer);
|
|
442
445
|
this.snapLines.initialize(this.rootDesignItem);
|
|
@@ -3,8 +3,26 @@ import { IDesignerCanvas } from '../IDesignerCanvas.js';
|
|
|
3
3
|
import { AbstractExtension } from './AbstractExtension.js';
|
|
4
4
|
import { IExtensionManager } from './IExtensionManger.js';
|
|
5
5
|
export declare class GridExtension extends AbstractExtension {
|
|
6
|
+
private _initialPoint;
|
|
7
|
+
private _initialSizes;
|
|
8
|
+
private _rects;
|
|
9
|
+
private _gaps;
|
|
10
|
+
private _resizeCircles;
|
|
6
11
|
constructor(extensionManager: IExtensionManager, designerView: IDesignerCanvas, extendedItem: IDesignItem);
|
|
7
12
|
extend(): void;
|
|
8
13
|
refresh(): void;
|
|
9
14
|
dispose(): void;
|
|
15
|
+
_drawResizeCircles(gap: any, oldCircle?: SVGCircleElement): SVGCircleElement;
|
|
16
|
+
_pointerActionTypeResize(event: PointerEvent, circle: SVGCircleElement, gapColumn: any, gapRow: any): void;
|
|
17
|
+
_getInitialSizes(style: CSSStyleDeclaration): {
|
|
18
|
+
x: any[];
|
|
19
|
+
y: any[];
|
|
20
|
+
xUnit: any[];
|
|
21
|
+
yUnit: any[];
|
|
22
|
+
};
|
|
23
|
+
_parseInitValue(stringValue: string): {
|
|
24
|
+
value: number;
|
|
25
|
+
unit: string;
|
|
26
|
+
};
|
|
27
|
+
_calculateNewSize(iSizes: any, iUnits: any, diff: any, gapIndex: any, itemWidth?: number, itemHeight?: number): string;
|
|
10
28
|
}
|
|
@@ -1,30 +1,233 @@
|
|
|
1
|
+
import { EventNames } from "../../../../enums/EventNames.js";
|
|
1
2
|
import { CalculateGridInformation } from "../../../helper/GridHelper.js";
|
|
2
3
|
import { AbstractExtension } from './AbstractExtension.js';
|
|
3
4
|
import { OverlayLayer } from "./OverlayLayer.js";
|
|
4
5
|
export class GridExtension extends AbstractExtension {
|
|
6
|
+
_initialPoint;
|
|
7
|
+
_initialSizes;
|
|
8
|
+
_rects;
|
|
9
|
+
_gaps;
|
|
10
|
+
_resizeCircles;
|
|
5
11
|
constructor(extensionManager, designerView, extendedItem) {
|
|
6
12
|
super(extensionManager, designerView, extendedItem);
|
|
7
13
|
}
|
|
8
14
|
extend() {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
var gridInformation = CalculateGridInformation(this.extendedItem);
|
|
16
|
+
this._rects = new Array(gridInformation.cells.length);
|
|
17
|
+
gridInformation.cells.forEach((cellRow, i) => {
|
|
18
|
+
this._rects[i] = new Array(cellRow.length);
|
|
19
|
+
});
|
|
20
|
+
this._gaps = new Array(gridInformation.gaps.length);
|
|
21
|
+
this._resizeCircles = new Array(gridInformation.gaps.length);
|
|
22
|
+
this.refresh();
|
|
23
|
+
}
|
|
24
|
+
refresh() {
|
|
25
|
+
var gridInformation = CalculateGridInformation(this.extendedItem);
|
|
26
|
+
gridInformation.gaps.forEach((gap, i) => {
|
|
27
|
+
this._gaps[i] = this._drawRect(gap.x, gap.y, gap.width, gap.height, 'svg-grid-gap', this._gaps[i], OverlayLayer.Foregorund);
|
|
28
|
+
this._resizeCircles[i] = this._drawResizeCircles(gap, this._resizeCircles[i]);
|
|
29
|
+
});
|
|
30
|
+
gridInformation.cells.forEach((cellRow, i) => {
|
|
31
|
+
cellRow.forEach((cell, j) => {
|
|
32
|
+
this._rects[i][j] = this._drawRect(cell.x, cell.y, cell.width, cell.height, 'svg-grid', this._rects[i][j], OverlayLayer.Background);
|
|
16
33
|
if (cell.name) {
|
|
17
34
|
const text = this._drawText(cell.name, cell.x, cell.y, 'svg-grid-area', null, OverlayLayer.Background);
|
|
18
35
|
text.setAttribute("dominant-baseline", "hanging");
|
|
19
36
|
}
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
refresh() {
|
|
24
|
-
this._removeAllOverlays();
|
|
25
|
-
this.extend();
|
|
37
|
+
});
|
|
38
|
+
});
|
|
26
39
|
}
|
|
27
40
|
dispose() {
|
|
28
41
|
this._removeAllOverlays();
|
|
29
42
|
}
|
|
43
|
+
_drawResizeCircles(gap, oldCircle) {
|
|
44
|
+
var resizeCircle = this._drawCircle((gap.x + (gap.width / 2)), (gap.y + (gap.height / 2)), 1.5, 'svg-grid-reziser', oldCircle, OverlayLayer.Foregorund);
|
|
45
|
+
resizeCircle.style.pointerEvents = "all";
|
|
46
|
+
resizeCircle.style.cursor = gap.width < gap.height ? "ew-resize" : "ns-resize";
|
|
47
|
+
if (!oldCircle) {
|
|
48
|
+
resizeCircle.addEventListener(EventNames.PointerDown, event => this._pointerActionTypeResize(event, resizeCircle, gap.column, gap.row));
|
|
49
|
+
resizeCircle.addEventListener(EventNames.PointerMove, event => this._pointerActionTypeResize(event, resizeCircle, gap.column, gap.row));
|
|
50
|
+
resizeCircle.addEventListener(EventNames.PointerUp, event => this._pointerActionTypeResize(event, resizeCircle, gap.column, gap.row));
|
|
51
|
+
}
|
|
52
|
+
return resizeCircle;
|
|
53
|
+
}
|
|
54
|
+
_pointerActionTypeResize(event, circle, gapColumn, gapRow) {
|
|
55
|
+
event.stopPropagation();
|
|
56
|
+
switch (event.type) {
|
|
57
|
+
case EventNames.PointerDown:
|
|
58
|
+
circle.setPointerCapture(event.pointerId);
|
|
59
|
+
this._initialPoint = { x: event.clientX, y: event.clientY };
|
|
60
|
+
this._initialSizes = this._getInitialSizes(this.extendedItem.element.style);
|
|
61
|
+
break;
|
|
62
|
+
case EventNames.PointerMove:
|
|
63
|
+
if (this._initialPoint) {
|
|
64
|
+
var elementStyle = this.extendedItem.element.style;
|
|
65
|
+
this.extendedItem.element.getBoundingClientRect;
|
|
66
|
+
switch (circle.style.cursor) {
|
|
67
|
+
case "ew-resize":
|
|
68
|
+
elementStyle.gridTemplateColumns = this._calculateNewSize(this._initialSizes.x, this._initialSizes.xUnit, (event.clientX - this._initialPoint.x) / this.designerCanvas.zoomFactor, gapColumn, parseFloat(elementStyle.width.substring(0, elementStyle.width.length - 2)), null);
|
|
69
|
+
break;
|
|
70
|
+
case "ns-resize":
|
|
71
|
+
elementStyle.gridTemplateRows = this._calculateNewSize(this._initialSizes.y, this._initialSizes.yUnit, (event.clientY - this._initialPoint.y) / this.designerCanvas.zoomFactor, gapRow, null, parseFloat(elementStyle.height.substring(0, elementStyle.height.length - 2)));
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
this.refresh();
|
|
75
|
+
}
|
|
76
|
+
break;
|
|
77
|
+
case EventNames.PointerUp:
|
|
78
|
+
circle.releasePointerCapture(event.pointerId);
|
|
79
|
+
this._initialPoint = null;
|
|
80
|
+
this._initialSizes = null;
|
|
81
|
+
if (this.extendedItem.getStyle("grid-template-columns") != this.extendedItem.element.style.gridTemplateColumns)
|
|
82
|
+
this.extendedItem.setStyle("grid-template-columns", this.extendedItem.element.style.gridTemplateColumns);
|
|
83
|
+
if (this.extendedItem.getStyle("grid-template-rows") != this.extendedItem.element.style.gridTemplateRows)
|
|
84
|
+
this.extendedItem.setStyle("grid-template-rows", this.extendedItem.element.style.gridTemplateRows);
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
_getInitialSizes(style) {
|
|
89
|
+
var retX = [];
|
|
90
|
+
var retY = [];
|
|
91
|
+
var retXUnit = [];
|
|
92
|
+
var retYUnit = [];
|
|
93
|
+
var tmpX = style.gridTemplateColumns.split(' ');
|
|
94
|
+
tmpX.forEach(x => {
|
|
95
|
+
var r = this._parseInitValue(x);
|
|
96
|
+
retX.push(r.value);
|
|
97
|
+
retXUnit.push(r.unit);
|
|
98
|
+
});
|
|
99
|
+
var tmpY = style.gridTemplateRows.split(' ');
|
|
100
|
+
tmpY.forEach(y => {
|
|
101
|
+
var r = this._parseInitValue(y);
|
|
102
|
+
retY.push(r.value);
|
|
103
|
+
retYUnit.push(r.unit);
|
|
104
|
+
});
|
|
105
|
+
return { x: retX, y: retY, xUnit: retXUnit, yUnit: retYUnit };
|
|
106
|
+
}
|
|
107
|
+
_parseInitValue(stringValue) {
|
|
108
|
+
var i = stringValue.length;
|
|
109
|
+
while (isNaN(parseInt(stringValue.substring(i - 1, stringValue.length))))
|
|
110
|
+
i--;
|
|
111
|
+
return { value: parseFloat(stringValue.substring(0, i)), unit: stringValue.substring(i, stringValue.length) };
|
|
112
|
+
}
|
|
113
|
+
_calculateNewSize(iSizes, iUnits, diff, gapIndex, itemWidth, itemHeight) {
|
|
114
|
+
var newSizes = [];
|
|
115
|
+
var newUnits = [];
|
|
116
|
+
var unitFactors = [];
|
|
117
|
+
var edited = [];
|
|
118
|
+
for (var i = 0; i < iSizes.length; i++) {
|
|
119
|
+
if (i + 1 == gapIndex || i == gapIndex) {
|
|
120
|
+
if (iUnits[i] == "%") {
|
|
121
|
+
var percentDiff = itemWidth ? (1 - ((itemWidth - diff) / itemWidth)) * 100 : itemHeight ? (1 - ((itemHeight - diff) / itemHeight)) * 100 : null;
|
|
122
|
+
newSizes.push(i + 1 == gapIndex ? iSizes[i] + percentDiff : i == gapIndex ? iSizes[i] - percentDiff : null);
|
|
123
|
+
unitFactors.push(null);
|
|
124
|
+
edited.push(true);
|
|
125
|
+
}
|
|
126
|
+
else if (iUnits[i] == "fr") {
|
|
127
|
+
newSizes.push(iSizes[i]);
|
|
128
|
+
unitFactors.push(null);
|
|
129
|
+
edited.push(true);
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
var unitFactor;
|
|
133
|
+
switch (iUnits[i]) {
|
|
134
|
+
case "mm":
|
|
135
|
+
unitFactor = 1 / 3.78;
|
|
136
|
+
break;
|
|
137
|
+
case "cm":
|
|
138
|
+
unitFactor = 1 / 37.8;
|
|
139
|
+
break;
|
|
140
|
+
case "in":
|
|
141
|
+
unitFactor = 1 / 96;
|
|
142
|
+
break;
|
|
143
|
+
case "px":
|
|
144
|
+
unitFactor = 1;
|
|
145
|
+
break;
|
|
146
|
+
case "pt":
|
|
147
|
+
unitFactor = 3;
|
|
148
|
+
break;
|
|
149
|
+
case "pc":
|
|
150
|
+
unitFactor = 16;
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
newSizes.push(i + 1 == gapIndex ? iSizes[i] + diff * unitFactor : i == gapIndex ? iSizes[i] - diff * unitFactor : null);
|
|
154
|
+
unitFactors.push(unitFactor);
|
|
155
|
+
edited.push(true);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
newSizes.push(iSizes[i]);
|
|
160
|
+
unitFactors.push(null);
|
|
161
|
+
edited.push(false);
|
|
162
|
+
}
|
|
163
|
+
newUnits.push(iUnits[i]);
|
|
164
|
+
}
|
|
165
|
+
var retVal = "";
|
|
166
|
+
var minPixelSize = 10;
|
|
167
|
+
var minPercentSize = itemHeight ? minPixelSize / itemHeight * 100 : itemWidth ? minPixelSize / itemWidth * 100 : null;
|
|
168
|
+
for (var i = 0; i < newSizes.length; i++) {
|
|
169
|
+
if (newUnits[i] == "%" && newSizes[i] < minPercentSize) {
|
|
170
|
+
if (edited[i + 1] && newUnits[i + 1] == "%") {
|
|
171
|
+
newSizes[i + 1] = iSizes[i] + iSizes[i + 1] - minPercentSize;
|
|
172
|
+
newSizes[i] = minPercentSize;
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
else if (edited[i - 1] && newUnits[i - 1] == "%") {
|
|
176
|
+
newSizes[i - 1] = iSizes[i] + iSizes[i - 1] - minPercentSize;
|
|
177
|
+
newSizes[i] = minPercentSize;
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
else if (newUnits[i] == "fr") {
|
|
182
|
+
var editedIndex;
|
|
183
|
+
if (edited[i + 1])
|
|
184
|
+
editedIndex = i + 1;
|
|
185
|
+
else if (edited[i - 1])
|
|
186
|
+
editedIndex = i - 1;
|
|
187
|
+
else
|
|
188
|
+
continue;
|
|
189
|
+
if (newUnits[editedIndex] == "px") {
|
|
190
|
+
if (newSizes[editedIndex] < minPixelSize)
|
|
191
|
+
newSizes[editedIndex] = minPixelSize;
|
|
192
|
+
var totalSize = itemWidth ? itemWidth : itemHeight ? itemHeight : null;
|
|
193
|
+
var totalSizeExceptFr = 0;
|
|
194
|
+
newSizes.forEach(newSize => totalSizeExceptFr += newSize);
|
|
195
|
+
var totalSizeExceptEdited = 0;
|
|
196
|
+
newSizes.forEach((newSize, k) => { if (!edited[k])
|
|
197
|
+
totalSizeExceptEdited += newSize; });
|
|
198
|
+
if (totalSize - totalSizeExceptFr < minPixelSize)
|
|
199
|
+
newSizes[editedIndex] = totalSize - totalSizeExceptEdited - minPixelSize;
|
|
200
|
+
}
|
|
201
|
+
else if (newUnits[editedIndex] == "%") {
|
|
202
|
+
if (newSizes[editedIndex] < minPercentSize)
|
|
203
|
+
newSizes[editedIndex] = minPercentSize;
|
|
204
|
+
var totalSize = 100;
|
|
205
|
+
var totalSizeExceptFr = 0;
|
|
206
|
+
newSizes.forEach(newSize => totalSizeExceptFr += newSize);
|
|
207
|
+
var totalSizeExceptEdited = 0;
|
|
208
|
+
newSizes.forEach((newSize, k) => { if (!edited[k])
|
|
209
|
+
totalSizeExceptEdited += newSize; });
|
|
210
|
+
if (totalSize - totalSizeExceptFr < minPercentSize)
|
|
211
|
+
newSizes[editedIndex] = totalSize - totalSizeExceptEdited - minPercentSize;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
if (newSizes[i] / unitFactors[i] < minPixelSize) {
|
|
216
|
+
if (edited[i + 1]) {
|
|
217
|
+
newSizes[i + 1] = iSizes[i] + iSizes[i + 1] - minPixelSize * unitFactors[i + 1];
|
|
218
|
+
newSizes[i] = minPixelSize * unitFactors[i];
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
else if (edited[i - 1]) {
|
|
222
|
+
newSizes[i - 1] = iSizes[i] + iSizes[i - 1] - minPixelSize * unitFactors[i - 1];
|
|
223
|
+
newSizes[i] = minPixelSize * unitFactors[i];
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
for (var i = 0; i < newSizes.length; i++)
|
|
230
|
+
retVal += newSizes[i] + newUnits[i] + " ";
|
|
231
|
+
return retVal;
|
|
232
|
+
}
|
|
30
233
|
}
|
|
@@ -15,5 +15,6 @@ export class GridExtensionProvider {
|
|
|
15
15
|
.svg-grid { stroke: orange; stroke-dasharray: 5; fill: #ff944722; }
|
|
16
16
|
.svg-grid-area { font-size: 8px; }
|
|
17
17
|
.svg-grid-gap { stroke: orange; stroke-dasharray: 5; fill: #0000ff22; }
|
|
18
|
+
.svg-grid-reziser { background: white; border: 1px solid black; }
|
|
18
19
|
`;
|
|
19
20
|
}
|