@node-projects/web-component-designer 0.0.209 → 0.0.210

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/commandHandling/CommandType.d.ts +2 -0
  2. package/dist/commandHandling/CommandType.js +2 -0
  3. package/dist/commandHandling/IUiCommand.d.ts +1 -0
  4. package/dist/elements/documentContainer.d.ts +1 -0
  5. package/dist/elements/documentContainer.js +9 -2
  6. package/dist/elements/item/DesignItem.js +24 -5
  7. package/dist/elements/services/propertiesService/services/AbstractPropertiesService.js +2 -2
  8. package/dist/elements/services/stylesheetService/AbstractStylesheetService.d.ts +23 -3
  9. package/dist/elements/services/stylesheetService/AbstractStylesheetService.js +109 -0
  10. package/dist/elements/services/stylesheetService/CssToolsStylesheetService.d.ts +1 -3
  11. package/dist/elements/services/stylesheetService/CssToolsStylesheetService.js +13 -50
  12. package/dist/elements/services/stylesheetService/CssTreeStylesheetService.d.ts +2 -4
  13. package/dist/elements/services/stylesheetService/CssTreeStylesheetService.js +21 -35
  14. package/dist/elements/services/stylesheetService/IStylesheetService.d.ts +7 -1
  15. package/dist/elements/services/undoService/transactionItems/AttributeChangeAction copy.d.ts +15 -0
  16. package/dist/elements/services/undoService/transactionItems/AttributeChangeAction copy.js +70 -0
  17. package/dist/elements/services/undoService/transactionItems/ContentChangeAction.d.ts +13 -0
  18. package/dist/elements/services/undoService/transactionItems/ContentChangeAction.js +38 -0
  19. package/dist/elements/widgets/demoView/IDemoView.d.ts +3 -1
  20. package/dist/elements/widgets/demoView/demoView.d.ts +7 -1
  21. package/dist/elements/widgets/demoView/demoView.js +4 -0
  22. package/dist/elements/widgets/designerView/designerCanvas.d.ts +1 -3
  23. package/dist/elements/widgets/designerView/designerCanvas.js +13 -47
  24. package/dist/elements/widgets/designerView/designerView.d.ts +1 -1
  25. package/dist/elements/widgets/designerView/designerView.js +7 -2
  26. package/dist/elements/widgets/propertyGrid/PropertyGridWithHeader.js +1 -7
  27. package/package.json +1 -1
@@ -5,6 +5,8 @@ export declare enum CommandType {
5
5
  'delete' = "delete",
6
6
  'undo' = "undo",
7
7
  'redo' = "redo",
8
+ 'holdUndo' = "holdUndo",
9
+ 'holdRedo' = "holdRedo",
8
10
  'rotateCounterClockwise' = "rotateCounterClockwise",
9
11
  'rotateClockwise' = "rotateClockwise",
10
12
  'selectAll' = "selectAll",
@@ -6,6 +6,8 @@ export var CommandType;
6
6
  CommandType["delete"] = "delete";
7
7
  CommandType["undo"] = "undo";
8
8
  CommandType["redo"] = "redo";
9
+ CommandType["holdUndo"] = "holdUndo";
10
+ CommandType["holdRedo"] = "holdRedo";
9
11
  CommandType["rotateCounterClockwise"] = "rotateCounterClockwise";
10
12
  CommandType["rotateClockwise"] = "rotateClockwise";
11
13
  CommandType["selectAll"] = "selectAll";
@@ -1,6 +1,7 @@
1
1
  import { CommandType } from './CommandType.js';
2
2
  export interface IUiCommand {
3
3
  type: CommandType;
4
+ event?: Event;
4
5
  special?: string;
5
6
  parameter?: any;
6
7
  altKey?: boolean;
@@ -14,6 +14,7 @@ export declare class DocumentContainer extends BaseCustomWebComponentLazyAppend
14
14
  codeView: ICodeView & HTMLElement;
15
15
  demoView: IDemoView & HTMLElement;
16
16
  additionalData: any;
17
+ private _firstLoad;
17
18
  private _additionalStyle;
18
19
  set additionalStyleString(style: string);
19
20
  get additionalStyleString(): string;
@@ -7,6 +7,7 @@ export class DocumentContainer extends BaseCustomWebComponentLazyAppend {
7
7
  codeView;
8
8
  demoView;
9
9
  additionalData;
10
+ _firstLoad = true;
10
11
  _additionalStyle;
11
12
  set additionalStyleString(style) {
12
13
  this._additionalStyle = style;
@@ -155,19 +156,23 @@ export class DocumentContainer extends BaseCustomWebComponentLazyAppend {
155
156
  this.designerView.executeCommand(command);
156
157
  else if (this._tabControl.selectedIndex === 1)
157
158
  this.codeView.executeCommand(command);
159
+ else if (this._tabControl.selectedIndex === 3)
160
+ this.demoView.executeCommand(command);
158
161
  }
159
162
  canExecuteCommand(command) {
160
163
  if (this._tabControl.selectedIndex === 0 || this._tabControl.selectedIndex === 2)
161
164
  return this.designerView.canExecuteCommand(command);
162
165
  else if (this._tabControl.selectedIndex === 1)
163
166
  return this.codeView.canExecuteCommand(command);
167
+ else if (this._tabControl.selectedIndex === 3)
168
+ return this.demoView.canExecuteCommand(command);
164
169
  return false;
165
170
  }
166
171
  set content(value) {
167
172
  this._content = value;
168
173
  if (this._tabControl) {
169
174
  if (this._tabControl.selectedIndex === 0)
170
- this.designerView.parseHTML(this._content);
175
+ this.designerView.parseHTML(this._content, this._firstLoad);
171
176
  else if (this._tabControl.selectedIndex === 1)
172
177
  this.codeView.update(this._content);
173
178
  else if (this._tabControl.selectedIndex === 2) {
@@ -221,8 +226,10 @@ export class DocumentContainer extends BaseCustomWebComponentLazyAppend {
221
226
  this.demoView.display(this._serviceContainer, this.designerView.instanceServiceContainer, this._content, this.additionalStyleString);
222
227
  }
223
228
  });
224
- if (this._content)
229
+ if (this._content) {
225
230
  this.content = this._content;
231
+ this._firstLoad = false;
232
+ }
226
233
  }
227
234
  get instanceServiceContainer() {
228
235
  return this.designerView.instanceServiceContainer;
@@ -179,16 +179,35 @@ export class DesignItem {
179
179
  return this.node.textContent;
180
180
  }
181
181
  set content(value) {
182
- //undo
183
- this.node.textContent = value;
182
+ const grp = this.openGroup('set innerHTML');
183
+ this.clearChildren();
184
+ let t = document.createTextNode(value);
185
+ let di = DesignItem.GetOrCreateDesignItem(t, this.serviceContainer, this.instanceServiceContainer);
186
+ if (this.nodeType == NodeType.TextNode) {
187
+ const idx = this.parent.indexOf(this);
188
+ const parent = this.parent;
189
+ this.remove();
190
+ parent.insertChild(di, idx);
191
+ }
192
+ else
193
+ this.insertChild(di);
194
+ grp.commit();
184
195
  }
185
196
  get innerHTML() {
186
197
  return this.element.innerHTML;
187
198
  }
188
199
  set innerHTML(value) {
189
- //undo
190
- this.element.innerHTML = value;
191
- this.updateChildrenFromNodesChildren();
200
+ if (this.nodeType != NodeType.TextNode) {
201
+ const grp = this.openGroup('set innerHTML');
202
+ const range = document.createRange();
203
+ range.selectNode(document.body);
204
+ const fragment = range.createContextualFragment(value);
205
+ for (const n of fragment.childNodes) {
206
+ let di = DesignItem.GetOrCreateDesignItem(n, this.serviceContainer, this.instanceServiceContainer);
207
+ this.insertChild(di);
208
+ }
209
+ grp.commit();
210
+ }
192
211
  }
193
212
  get isEmptyTextNode() {
194
213
  return this.nodeType === NodeType.TextNode && this.content?.trim() == '';
@@ -15,7 +15,7 @@ export class AbstractPropertiesService {
15
15
  return properties.find(x => x.name == name);
16
16
  }
17
17
  setValue(designItems, property, value) {
18
- const cg = designItems[0].openGroup("properties changed");
18
+ const cg = designItems[0].openGroup("property changed: " + property.name + " to " + value);
19
19
  for (let d of designItems) {
20
20
  if (property.propertyType == PropertyType.cssValue) {
21
21
  d.updateStyleInSheetOrLocal(property.name, value);
@@ -61,7 +61,7 @@ export class AbstractPropertiesService {
61
61
  return BindingTarget.property;
62
62
  }
63
63
  clearValue(designItems, property) {
64
- const cg = designItems[0].openGroup("properties cleared");
64
+ const cg = designItems[0].openGroup("property cleared: " + property.name);
65
65
  for (let d of designItems) {
66
66
  if (property.propertyType == PropertyType.cssValue) {
67
67
  d.removeStyle(property.name);
@@ -1,9 +1,27 @@
1
1
  import { TypedEvent } from "@node-projects/base-custom-webcomponent";
2
2
  import { IDesignItem } from "../../item/IDesignItem";
3
- import { IStyleDeclaration, IStyleRule, IStylesheet, IStylesheetService } from "./IStylesheetService";
3
+ import { IDocumentStylesheet, IStyleDeclaration, IStyleRule, IStylesheet, IStylesheetService } from "./IStylesheetService";
4
4
  export declare abstract class AbstractStylesheetService implements IStylesheetService {
5
- abstract setStylesheets(stylesheets: IStylesheet[]): void;
6
- abstract getStylesheets(): IStylesheet[];
5
+ protected _stylesheets: Map<string, {
6
+ stylesheet: IStylesheet;
7
+ ast: any;
8
+ }>;
9
+ protected _documentStylesheets: Map<string, {
10
+ stylesheet: IDocumentStylesheet;
11
+ ast: any;
12
+ }>;
13
+ protected _allStylesheets: Map<string, {
14
+ stylesheet: IStylesheet | IDocumentStylesheet;
15
+ ast: any;
16
+ }>;
17
+ setStylesheets(stylesheets: IStylesheet[]): Promise<void>;
18
+ setDocumentStylesheets(stylesheets: IDocumentStylesheet[]): Promise<void>;
19
+ internalSetStylesheets(stylesheets: IStylesheet[], targetMap: Map<string, {
20
+ stylesheet: IStylesheet;
21
+ ast: any;
22
+ }>): Promise<void>;
23
+ protected abstract internalParse(style: string): Promise<any>;
24
+ getStylesheets(): IStylesheet[];
7
25
  abstract getAppliedRules(designItem: IDesignItem): IStyleRule[];
8
26
  abstract getDeclarations(designItem: IDesignItem, styleName: string): IStyleDeclaration[];
9
27
  abstract updateDeclarationValue(declaration: IStyleDeclaration, value: string, important: boolean): boolean;
@@ -18,4 +36,6 @@ export declare abstract class AbstractStylesheetService implements IStylesheetSe
18
36
  }>;
19
37
  stylesheetsChanged: TypedEvent<void>;
20
38
  protected elementMatchesASelector(designItem: IDesignItem, selectors: string[]): boolean;
39
+ static buildPatchedStyleSheet(value: CSSStyleSheet[]): string;
40
+ private static traverseAndCollectRules;
21
41
  }
@@ -1,5 +1,71 @@
1
1
  import { TypedEvent } from "@node-projects/base-custom-webcomponent";
2
+ import { DesignerCanvas } from "../../widgets/designerView/designerCanvas";
2
3
  export class AbstractStylesheetService {
4
+ _stylesheets = new Map();
5
+ _documentStylesheets = new Map();
6
+ _allStylesheets = new Map();
7
+ async setStylesheets(stylesheets) {
8
+ await this.internalSetStylesheets(stylesheets, this._stylesheets);
9
+ }
10
+ async setDocumentStylesheets(stylesheets) {
11
+ await this.internalSetStylesheets(stylesheets, this._documentStylesheets);
12
+ }
13
+ async internalSetStylesheets(stylesheets, targetMap) {
14
+ if (targetMap != null && stylesheets != null && targetMap.size == stylesheets.length && stylesheets.every(x => targetMap.has(x.name))) {
15
+ for (let stylesheet of stylesheets) {
16
+ const old = targetMap.get(stylesheet.name);
17
+ if (old.stylesheet.content != stylesheet.content) {
18
+ try {
19
+ targetMap.set(stylesheet.name, {
20
+ stylesheet: stylesheet,
21
+ ast: await this.internalParse(stylesheet.content)
22
+ });
23
+ }
24
+ catch (err) {
25
+ console.warn("error parsing stylesheet", stylesheet, err);
26
+ }
27
+ this.stylesheetChanged.emit({ name: stylesheet.name, newStyle: stylesheet.content, oldStyle: old.stylesheet.content, changeSource: 'extern' });
28
+ }
29
+ }
30
+ }
31
+ else if (stylesheets != null) {
32
+ targetMap.clear();
33
+ for (let stylesheet of stylesheets) {
34
+ try {
35
+ targetMap.set(stylesheet.name, {
36
+ stylesheet: stylesheet,
37
+ ast: await this.internalParse(stylesheet.content)
38
+ });
39
+ }
40
+ catch (err) {
41
+ console.warn("error parsing stylesheet", stylesheet, err);
42
+ }
43
+ }
44
+ this.stylesheetsChanged.emit();
45
+ }
46
+ else {
47
+ targetMap.clear();
48
+ }
49
+ this._allStylesheets.clear();
50
+ for (let s of this._documentStylesheets) {
51
+ this._allStylesheets.set(s[0], s[1]);
52
+ }
53
+ for (let s of this._stylesheets) {
54
+ this._allStylesheets.set(s[0], s[1]);
55
+ }
56
+ }
57
+ getStylesheets() {
58
+ let stylesheets = [];
59
+ for (let item of this._stylesheets) {
60
+ stylesheets.push(item[1].stylesheet);
61
+ }
62
+ ;
63
+ for (let item of this._documentStylesheets) {
64
+ stylesheets.push(item[1].stylesheet);
65
+ }
66
+ ;
67
+ return stylesheets;
68
+ }
3
69
  stylesheetChanged = new TypedEvent();
4
70
  stylesheetsChanged = new TypedEvent();
5
71
  elementMatchesASelector(designItem, selectors) {
@@ -8,4 +74,47 @@ export class AbstractStylesheetService {
8
74
  return true;
9
75
  return false;
10
76
  }
77
+ static buildPatchedStyleSheet(value) {
78
+ let style = '';
79
+ for (let s of value) {
80
+ style += this.traverseAndCollectRules(s);
81
+ }
82
+ return style;
83
+ }
84
+ static traverseAndCollectRules(ruleContainer) {
85
+ let t = '';
86
+ for (let rule of ruleContainer.cssRules) {
87
+ if ((rule instanceof CSSContainerRule
88
+ || rule instanceof CSSSupportsRule
89
+ || rule instanceof CSSMediaRule)
90
+ && rule.cssRules) {
91
+ t += rule.cssText.split(rule.conditionText)[0] + rule.conditionText + " { " + this.traverseAndCollectRules(rule) + " }";
92
+ }
93
+ if (rule instanceof CSSStyleRule) {
94
+ let parts = rule.selectorText.split(',');
95
+ let sel = "";
96
+ for (let p of parts) {
97
+ if (p.includes(DesignerCanvas.cssprefixConstant)) {
98
+ sel += p;
99
+ continue;
100
+ }
101
+ if (sel)
102
+ sel += ',';
103
+ sel += DesignerCanvas.cssprefixConstant + p.trimStart();
104
+ }
105
+ t += sel;
106
+ let cssText = rule.style.cssText;
107
+ //bugfix for chrome issue: https://bugs.chromium.org/p/chromium/issues/detail?id=1394353
108
+ if (rule.styleMap && rule.styleMap.get('grid-template') && rule.styleMap.get('grid-template').toString().includes('repeat(')) {
109
+ let entr = rule.styleMap.entries();
110
+ cssText = '';
111
+ for (let e of entr) {
112
+ cssText += e[0] + ':' + e[1].toString() + ';';
113
+ }
114
+ }
115
+ t += '{' + cssText + '}';
116
+ }
117
+ }
118
+ return t;
119
+ }
11
120
  }
@@ -14,7 +14,6 @@ interface IDeclarationWithAST extends IStyleDeclaration {
14
14
  ast: CssDeclarationAST;
15
15
  }
16
16
  export declare class CssToolsStylesheetService extends AbstractStylesheetService {
17
- private _stylesheets;
18
17
  _tools: {
19
18
  parse: (css: string, options?: {
20
19
  source?: string;
@@ -26,8 +25,7 @@ export declare class CssToolsStylesheetService extends AbstractStylesheetService
26
25
  emptyDeclarations?: boolean;
27
26
  }) => string;
28
27
  };
29
- setStylesheets(stylesheets: IStylesheet[]): Promise<void>;
30
- getStylesheets(): IStylesheet[];
28
+ internalParse(style: string): Promise<any>;
31
29
  getAppliedRules(designItem: IDesignItem): IRuleWithAST[];
32
30
  private getRulesFromAst;
33
31
  getDeclarations(designItem: IDesignItem, styleName: string): IStyleDeclaration[];
@@ -1,57 +1,14 @@
1
1
  import { AbstractStylesheetService } from "./AbstractStylesheetService.js";
2
2
  export class CssToolsStylesheetService extends AbstractStylesheetService {
3
- _stylesheets = new Map();
4
3
  _tools;
5
- async setStylesheets(stylesheets) {
4
+ async internalParse(style) {
6
5
  if (!this._tools)
7
6
  this._tools = await import('@adobe/css-tools');
8
- if (this._stylesheets != null && stylesheets != null && this._stylesheets.size == stylesheets.length && stylesheets.every(x => this._stylesheets.has(x.name))) {
9
- for (let stylesheet of stylesheets) {
10
- const old = this._stylesheets.get(stylesheet.name);
11
- if (old.stylesheet.content != stylesheet.content) {
12
- try {
13
- this._stylesheets.set(stylesheet.name, {
14
- stylesheet: stylesheet,
15
- ast: this._tools.parse(stylesheet.content)
16
- });
17
- }
18
- catch (err) {
19
- console.warn("error parsing stylesheet", stylesheet, err);
20
- }
21
- this.stylesheetChanged.emit({ name: stylesheet.name, newStyle: stylesheet.content, oldStyle: old.stylesheet.content, changeSource: 'extern' });
22
- }
23
- }
24
- }
25
- else if (stylesheets != null) {
26
- this._stylesheets = new Map();
27
- for (let stylesheet of stylesheets) {
28
- try {
29
- this._stylesheets.set(stylesheet.name, {
30
- stylesheet: stylesheet,
31
- ast: this._tools.parse(stylesheet.content)
32
- });
33
- }
34
- catch (err) {
35
- console.warn("error parsing stylesheet", stylesheet, err);
36
- }
37
- }
38
- this.stylesheetsChanged.emit();
39
- }
40
- else {
41
- this._stylesheets = null;
42
- }
43
- }
44
- getStylesheets() {
45
- let stylesheets = [];
46
- for (let item of this._stylesheets) {
47
- stylesheets.push(item[1].stylesheet);
48
- }
49
- ;
50
- return stylesheets;
7
+ return this._tools.parse(style);
51
8
  }
52
9
  getAppliedRules(designItem) {
53
10
  let rules = [];
54
- for (let item of this._stylesheets.entries()) {
11
+ for (let item of this._allStylesheets.entries()) {
55
12
  if (!item[1].ast?.stylesheet?.rules)
56
13
  continue;
57
14
  let rs = Array.from(this.getRulesFromAst(item[1].ast?.stylesheet?.rules, item[1].stylesheet, designItem))
@@ -94,7 +51,7 @@ export class CssToolsStylesheetService extends AbstractStylesheetService {
94
51
  }
95
52
  updateDeclarationValue(declaration, value, important) {
96
53
  declaration.ast.value = important ? value + ' !important' : value;
97
- let ss = this._stylesheets.get(declaration.parent.stylesheetName);
54
+ let ss = this._allStylesheets.get(declaration.parent.stylesheetName);
98
55
  this.updateStylesheet(ss);
99
56
  return true;
100
57
  }
@@ -104,7 +61,7 @@ export class CssToolsStylesheetService extends AbstractStylesheetService {
104
61
  property: property,
105
62
  value: important ? value + ' !important' : value
106
63
  });
107
- this.updateStylesheet(this._stylesheets.get(rule.stylesheetName));
64
+ this.updateStylesheet(this._allStylesheets.get(rule.stylesheetName));
108
65
  return true;
109
66
  }
110
67
  removeDeclarationFromRule(rule, property) {
@@ -112,19 +69,25 @@ export class CssToolsStylesheetService extends AbstractStylesheetService {
112
69
  if (idx == -1)
113
70
  return false;
114
71
  rule.ast.declarations.splice(idx, 1);
115
- this.updateStylesheet(this._stylesheets.get(rule.stylesheetName));
72
+ this.updateStylesheet(this._allStylesheets.get(rule.stylesheetName));
116
73
  return true;
117
74
  }
118
75
  updateStylesheet(ss) {
119
76
  const old = ss.stylesheet.content;
120
77
  ss.stylesheet.content = this._tools.stringify(ss.ast, { indent: ' ', compress: false, emptyDeclarations: true });
78
+ if (ss.stylesheet.designItem) {
79
+ ss.stylesheet.designItem.content = ss.stylesheet.content;
80
+ }
121
81
  this.stylesheetChanged.emit({ name: ss.stylesheet.name, newStyle: ss.stylesheet.content, oldStyle: old, changeSource: 'styleupdate' });
122
82
  }
123
83
  updateCompleteStylesheet(name, newStyle) {
124
- const ss = this._stylesheets.get(name);
84
+ const ss = this._allStylesheets.get(name);
125
85
  if (ss.stylesheet.content != newStyle) {
126
86
  const old = ss.stylesheet.content;
127
87
  ss.stylesheet.content = newStyle;
88
+ if (ss.stylesheet.designItem) {
89
+ ss.stylesheet.designItem.content = ss.stylesheet.content;
90
+ }
128
91
  this.stylesheetChanged.emit({ name: ss.stylesheet.name, newStyle: ss.stylesheet.content, oldStyle: old, changeSource: 'styleupdate' });
129
92
  }
130
93
  }
@@ -1,5 +1,5 @@
1
1
  import { IDesignItem } from "../../item/IDesignItem.js";
2
- import { IStyleDeclaration, IStyleRule, IStylesheet } from "./IStylesheetService.js";
2
+ import { IStyleDeclaration, IStyleRule } from "./IStylesheetService.js";
3
3
  import { AbstractStylesheetService } from "./AbstractStylesheetService.js";
4
4
  declare namespace csstree {
5
5
  type CssNodePlain = any;
@@ -33,9 +33,7 @@ interface IDeclarationWithAST extends IStyleDeclaration {
33
33
  ast: csstree.DeclarationPlain;
34
34
  }
35
35
  export declare class CssTreeStylesheetService extends AbstractStylesheetService {
36
- private _stylesheets;
37
- setStylesheets(stylesheets: IStylesheet[]): void;
38
- getStylesheets(): IStylesheet[];
36
+ internalParse(style: string): Promise<any>;
39
37
  private getAppliedRulesInternal;
40
38
  getAppliedRules(designItem: IDesignItem): IRuleWithAST[];
41
39
  private getDeclarationInternal;
@@ -1,39 +1,13 @@
1
1
  import { calculate as calculateSpecifity } from "./SpecificityCalculator.js";
2
2
  import { AbstractStylesheetService } from "./AbstractStylesheetService.js";
3
3
  export class CssTreeStylesheetService extends AbstractStylesheetService {
4
- _stylesheets = new Map();
5
- setStylesheets(stylesheets) {
6
- if (stylesheets != null) {
7
- this._stylesheets = new Map();
8
- for (let stylesheet of stylesheets) {
9
- try {
10
- this._stylesheets.set(stylesheet.name, {
11
- stylesheet: stylesheet,
12
- ast: window.csstree.toPlainObject((window.csstree.parse(stylesheet.content, { positions: true, parseValue: false })))
13
- });
14
- }
15
- catch (err) {
16
- console.warn("error parsing stylesheet", stylesheet, err);
17
- }
18
- }
19
- this.stylesheetsChanged.emit();
20
- }
21
- else {
22
- this._stylesheets = null;
23
- }
24
- }
25
- getStylesheets() {
26
- let stylesheets = [];
27
- for (let item of this._stylesheets) {
28
- stylesheets.push(item[1].stylesheet);
29
- }
30
- ;
31
- return stylesheets;
4
+ async internalParse(style) {
5
+ return window.csstree.toPlainObject((window.csstree.parse(style, { positions: true, parseValue: false })));
32
6
  }
33
7
  /* Section covers the retrieval of rules and declarations */
34
8
  getAppliedRulesInternal(designItem) {
35
9
  let styles = [];
36
- for (let item of this._stylesheets) {
10
+ for (let item of this._allStylesheets) {
37
11
  if (!item[1].ast || !this.astHasChildren(item[1].ast))
38
12
  continue;
39
13
  styles = styles.concat(Array.from(this.rulesFromAST(item[1].ast, item[1].stylesheet.content, item[0], designItem)));
@@ -91,22 +65,28 @@ export class CssTreeStylesheetService extends AbstractStylesheetService {
91
65
  }
92
66
  /* Section covers the update of rules and declarations */
93
67
  updateDeclarationValue(declaration, value, important) {
94
- let sourceNode = this._stylesheets.get(declaration.parent.stylesheetName);
68
+ let sourceNode = this._allStylesheets.get(declaration.parent.stylesheetName);
95
69
  declaration.ast.value = window.csstree.toPlainObject(window.csstree.parse(declaration.name + ": " + value + (important ? " !important" : ""), { context: 'declaration', parseValue: false })).value;
96
70
  const old = sourceNode.stylesheet.content;
97
71
  sourceNode.stylesheet.content = window.csstree.generate(window.csstree.fromPlainObject(sourceNode.ast));
98
72
  // After generating the stylesheet, parse again (so line numbers are correct)
99
73
  sourceNode.ast = window.csstree.toPlainObject((window.csstree.parse(sourceNode.stylesheet.content, { positions: true, parseValue: false })));
74
+ if (sourceNode.stylesheet.designItem) {
75
+ sourceNode.stylesheet.designItem.content = sourceNode.stylesheet.content;
76
+ }
100
77
  this.stylesheetChanged.emit({ name: sourceNode.stylesheet.name, newStyle: sourceNode.stylesheet.content, oldStyle: old, changeSource: 'styleupdate' });
101
78
  return true;
102
79
  }
103
80
  insertDeclarationIntoRule(rule, property, value, important) {
104
- let sourceNode = this._stylesheets.get(rule.stylesheetName);
81
+ let sourceNode = this._allStylesheets.get(rule.stylesheetName);
105
82
  rule.ast.block.children.push(window.csstree.toPlainObject(window.csstree.parse(property + ": " + value + (important ? " !important" : ""), { context: 'declaration', parseValue: false })));
106
83
  const old = sourceNode.stylesheet.content;
107
84
  sourceNode.stylesheet.content = window.csstree.generate(window.csstree.fromPlainObject(sourceNode.ast));
108
85
  // After generating the stylesheet, parse again (so line numbers are correct)
109
86
  sourceNode.ast = window.csstree.toPlainObject((window.csstree.parse(sourceNode.stylesheet.content, { positions: true, parseValue: false })));
87
+ if (sourceNode.stylesheet.designItem) {
88
+ sourceNode.stylesheet.designItem.content = sourceNode.stylesheet.content;
89
+ }
110
90
  this.stylesheetChanged.emit({ name: sourceNode.stylesheet.name, newStyle: sourceNode.stylesheet.content, oldStyle: old, changeSource: 'styleupdate' });
111
91
  return true;
112
92
  }
@@ -115,19 +95,25 @@ export class CssTreeStylesheetService extends AbstractStylesheetService {
115
95
  if (index == -1)
116
96
  return false;
117
97
  rule.ast.block.children.splice(index, 1);
118
- const ss = this._stylesheets.get(rule.stylesheetName);
98
+ const ss = this._allStylesheets.get(rule.stylesheetName);
119
99
  const old = ss.stylesheet.content;
120
- ss.stylesheet.content = window.csstree.generate(window.csstree.fromPlainObject(this._stylesheets.get(rule.stylesheetName).ast));
100
+ ss.stylesheet.content = window.csstree.generate(window.csstree.fromPlainObject(this._allStylesheets.get(rule.stylesheetName).ast));
121
101
  // After generating the stylesheet, parse again (so line numbers are correct)
122
- ss.ast = window.csstree.toPlainObject((window.csstree.parse(this._stylesheets.get(rule.stylesheetName).stylesheet.content, { positions: true, parseValue: false })));
102
+ ss.ast = window.csstree.toPlainObject((window.csstree.parse(this._allStylesheets.get(rule.stylesheetName).stylesheet.content, { positions: true, parseValue: false })));
103
+ if (ss.stylesheet.designItem) {
104
+ ss.stylesheet.designItem.content = ss.stylesheet.content;
105
+ }
123
106
  this.stylesheetChanged.emit({ name: ss.stylesheet.name, newStyle: ss.stylesheet.content, oldStyle: old, changeSource: 'styleupdate' });
124
107
  return true;
125
108
  }
126
109
  updateCompleteStylesheet(name, newStyle) {
127
- const ss = this._stylesheets.get(name);
110
+ const ss = this._allStylesheets.get(name);
128
111
  if (ss.stylesheet.content != newStyle) {
129
112
  const old = ss.stylesheet.content;
130
113
  ss.stylesheet.content = newStyle;
114
+ if (ss.stylesheet.designItem) {
115
+ ss.stylesheet.designItem.content = ss.stylesheet.content;
116
+ }
131
117
  this.stylesheetChanged.emit({ name: ss.stylesheet.name, newStyle: ss.stylesheet.content, oldStyle: old, changeSource: 'styleupdate' });
132
118
  }
133
119
  }
@@ -16,9 +16,15 @@ export interface IStylesheet {
16
16
  content: string;
17
17
  name: string;
18
18
  }
19
+ export interface IDocumentStylesheet {
20
+ content: string;
21
+ name: string;
22
+ designItem: IDesignItem;
23
+ }
19
24
  export interface IStylesheetService {
20
- setStylesheets(stylesheets: IStylesheet[]): void;
25
+ setStylesheets(stylesheets: IStylesheet[]): Promise<void>;
21
26
  getStylesheets(): IStylesheet[];
27
+ setDocumentStylesheets(stylesheets: IDocumentStylesheet[]): Promise<void>;
22
28
  getAppliedRules(designItem: IDesignItem): IStyleRule[];
23
29
  getDeclarations(designItem: IDesignItem, styleName: string): IStyleDeclaration[];
24
30
  updateDeclarationValue(declaration: IStyleDeclaration, value: string, important: boolean): boolean;
@@ -0,0 +1,15 @@
1
+ import { ITransactionItem } from '../ITransactionItem.js';
2
+ import { IDesignItem } from '../../../item/IDesignItem.js';
3
+ import { IBinding } from '../../../item/IBinding.js';
4
+ export declare class AttributeChangeAction implements ITransactionItem {
5
+ constructor(designItem: IDesignItem, name: string, newValue: string | IBinding | null, oldValue: string | IBinding | null);
6
+ title?: string;
7
+ get affectedItems(): IDesignItem[];
8
+ undo(): void;
9
+ do(): void;
10
+ designItem: IDesignItem;
11
+ name: string;
12
+ newValue: any;
13
+ oldValue: any;
14
+ mergeWith(other: ITransactionItem): boolean;
15
+ }
@@ -0,0 +1,70 @@
1
+ export class AttributeChangeAction {
2
+ constructor(designItem, name, newValue, oldValue) {
3
+ this.title = "Change Attribute " + name + " of &lt;" + designItem.name + "&gt;";
4
+ this.designItem = designItem;
5
+ this.name = name;
6
+ this.newValue = newValue;
7
+ this.oldValue = oldValue;
8
+ }
9
+ title;
10
+ get affectedItems() {
11
+ return [this.designItem];
12
+ }
13
+ undo() {
14
+ if (this.oldValue == null) {
15
+ this.designItem._withoutUndoRemoveAttribute(this.name);
16
+ try {
17
+ this.designItem.element.removeAttribute(this.name);
18
+ }
19
+ catch (e) {
20
+ console.warn(e);
21
+ }
22
+ }
23
+ else {
24
+ this.designItem._withoutUndoSetAttribute(this.name, this.oldValue);
25
+ if (this.name != "draggable") {
26
+ try {
27
+ if (typeof this.oldValue === 'string')
28
+ this.designItem.element.setAttribute(this.name, this.oldValue);
29
+ }
30
+ catch (e) {
31
+ console.warn(e);
32
+ }
33
+ }
34
+ }
35
+ }
36
+ do() {
37
+ if (this.newValue == null) {
38
+ this.designItem._withoutUndoRemoveAttribute(this.name);
39
+ try {
40
+ this.designItem.element.removeAttribute(this.name);
41
+ }
42
+ catch (e) {
43
+ console.warn(e);
44
+ }
45
+ }
46
+ else {
47
+ this.designItem._withoutUndoSetAttribute(this.name, this.newValue);
48
+ if (this.name != "draggable") {
49
+ try {
50
+ if (typeof this.newValue === 'string')
51
+ this.designItem.element.setAttribute(this.name, this.newValue);
52
+ }
53
+ catch (e) {
54
+ console.warn(e);
55
+ }
56
+ }
57
+ }
58
+ }
59
+ designItem;
60
+ name;
61
+ newValue;
62
+ oldValue;
63
+ mergeWith(other) {
64
+ if (other instanceof AttributeChangeAction && this.designItem === other.designItem && this.name === other.name) {
65
+ this.newValue = other.newValue;
66
+ return true;
67
+ }
68
+ return false;
69
+ }
70
+ }
@@ -0,0 +1,13 @@
1
+ import { ITransactionItem } from '../ITransactionItem.js';
2
+ import { IDesignItem } from '../../../item/IDesignItem.js';
3
+ export declare class ContentChangeAction implements ITransactionItem {
4
+ constructor(designItem: IDesignItem, newValue: string);
5
+ title?: string;
6
+ get affectedItems(): IDesignItem[];
7
+ undo(): void;
8
+ do(): void;
9
+ designItem: IDesignItem;
10
+ newValue: any;
11
+ oldValue: any;
12
+ mergeWith(other: ITransactionItem): boolean;
13
+ }
@@ -0,0 +1,38 @@
1
+ import { NodeType } from '../../../item/NodeType.js';
2
+ export class ContentChangeAction {
3
+ constructor(designItem, newValue) {
4
+ this.title = "Change Content of " + designItem.name + " to " + newValue;
5
+ this.designItem = designItem;
6
+ this.newValue = newValue;
7
+ }
8
+ title;
9
+ get affectedItems() {
10
+ return [this.designItem];
11
+ }
12
+ undo() {
13
+ if (this.designItem.nodeType == NodeType.TextNode || this.designItem.nodeType == NodeType.Comment) {
14
+ this.designItem.element.textContent = this.oldValue;
15
+ }
16
+ else {
17
+ this.designItem.element.innerHTML = this.oldValue;
18
+ }
19
+ this.affectedItems[0].instanceServiceContainer.contentService.onContentChanged.emit({ changeType: 'edited', designItems: [this.designItem] });
20
+ }
21
+ do() {
22
+ if (this.designItem.nodeType == NodeType.TextNode || this.designItem.nodeType == NodeType.Comment) {
23
+ this.oldValue = this.designItem.element.textContent;
24
+ this.designItem.element.textContent = this.newValue;
25
+ }
26
+ else {
27
+ this.oldValue = this.designItem.element.innerHTML;
28
+ this.designItem.element.innerHTML = this.newValue;
29
+ }
30
+ this.affectedItems[0].instanceServiceContainer.contentService.onContentChanged.emit({ changeType: 'edited', designItems: [this.designItem] });
31
+ }
32
+ designItem;
33
+ newValue;
34
+ oldValue;
35
+ mergeWith(other) {
36
+ return false;
37
+ }
38
+ }
@@ -1,5 +1,7 @@
1
+ import { IUiCommandHandler } from '../../../commandHandling/IUiCommandHandler.js';
2
+ import { IDisposable } from '../../../interfaces/IDisposable.js';
1
3
  import { InstanceServiceContainer } from '../../services/InstanceServiceContainer.js';
2
4
  import { ServiceContainer } from '../../services/ServiceContainer.js';
3
- export interface IDemoView {
5
+ export interface IDemoView extends IUiCommandHandler, IDisposable {
4
6
  display(serviceContainer: ServiceContainer, instanceServiceContainer: InstanceServiceContainer, code: string, style: string): any;
5
7
  }
@@ -2,10 +2,16 @@ import { IDemoView } from './IDemoView.js';
2
2
  import { BaseCustomWebComponentLazyAppend } from '@node-projects/base-custom-webcomponent';
3
3
  import { ServiceContainer } from '../../services/ServiceContainer.js';
4
4
  import { InstanceServiceContainer } from '../../services/InstanceServiceContainer.js';
5
- export declare class DemoView extends BaseCustomWebComponentLazyAppend implements IDemoView {
5
+ import { IUiCommandHandler } from '../../../commandHandling/IUiCommandHandler.js';
6
+ import { IUiCommand } from '../../../commandHandling/IUiCommand.js';
7
+ import { IDisposable } from '../../../interfaces/IDisposable.js';
8
+ export declare class DemoView extends BaseCustomWebComponentLazyAppend implements IDemoView, IUiCommandHandler, IDisposable {
6
9
  private _placeholder;
7
10
  private _loading;
8
11
  static readonly style: CSSStyleSheet;
9
12
  constructor();
13
+ dispose(): void;
14
+ executeCommand: (command: IUiCommand) => void;
15
+ canExecuteCommand: (command: IUiCommand) => boolean;
10
16
  display(serviceContainer: ServiceContainer, instanceServiceContainer: InstanceServiceContainer, code: string, style: string): Promise<void>;
11
17
  }
@@ -29,6 +29,10 @@ export class DemoView extends BaseCustomWebComponentLazyAppend {
29
29
  this._loading.textContent = '🛀 Hold on, loading...';
30
30
  this.shadowRoot.appendChild(this._loading);
31
31
  }
32
+ dispose() {
33
+ }
34
+ executeCommand;
35
+ canExecuteCommand;
32
36
  async display(serviceContainer, instanceServiceContainer, code, style) {
33
37
  this._loading.hidden = false;
34
38
  await serviceContainer.demoProviderService.provideDemo(this._placeholder, serviceContainer, instanceServiceContainer, code, style);
@@ -51,7 +51,7 @@ export declare class DesignerCanvas extends BaseCustomWebComponentLazyAppend imp
51
51
  private _outercanvas2;
52
52
  private _lastHoverDesignItem;
53
53
  private _firstConnect;
54
- private cssprefixConstant;
54
+ static cssprefixConstant: string;
55
55
  static readonly style: CSSStyleSheet;
56
56
  static readonly template: HTMLTemplateElement;
57
57
  extensionManager: IExtensionManager;
@@ -125,6 +125,4 @@ export declare class DesignerCanvas extends BaseCustomWebComponentLazyAppend imp
125
125
  zoomPoint(canvasPoint: IPoint, newZoom: number): void;
126
126
  private zoomConvertEventToViewPortCoordinates;
127
127
  zoomTowardsPoint(canvasPoint: IPoint, newZoom: number): void;
128
- private buildPatchedStyleSheet;
129
- private traverseAndCollectRules;
130
128
  }
@@ -20,6 +20,7 @@ import { ContextMenu } from '../../helper/contextMenu/ContextMenu.js';
20
20
  import { NodeType } from '../../item/NodeType.js';
21
21
  import { StylesheetChangedAction } from '../../services/undoService/transactionItems/StylesheetChangedAction.js';
22
22
  import { SetDesignItemsAction } from '../../services/undoService/transactionItems/SetDesignItemsAction.js';
23
+ import { AbstractStylesheetService } from '../../services/stylesheetService/AbstractStylesheetService.js';
23
24
  export class DesignerCanvas extends BaseCustomWebComponentLazyAppend {
24
25
  // Public Properties
25
26
  serviceContainer;
@@ -77,7 +78,7 @@ export class DesignerCanvas extends BaseCustomWebComponentLazyAppend {
77
78
  _outercanvas2;
78
79
  _lastHoverDesignItem;
79
80
  _firstConnect;
80
- cssprefixConstant = '#node-projects-designer-canvas-canvas ';
81
+ static cssprefixConstant = '#node-projects-designer-canvas-canvas ';
81
82
  static style = css `
82
83
  :host {
83
84
  display: block;
@@ -216,11 +217,11 @@ export class DesignerCanvas extends BaseCustomWebComponentLazyAppend {
216
217
  applyAllStyles() {
217
218
  let styles = [this.constructor.style];
218
219
  if (this._additionalStyle)
219
- styles.push(cssFromString(this.buildPatchedStyleSheet(this._additionalStyle)));
220
+ styles.push(cssFromString(AbstractStylesheetService.buildPatchedStyleSheet(this._additionalStyle)));
220
221
  if (this.instanceServiceContainer.stylesheetService) {
221
222
  styles.push(...this.instanceServiceContainer.stylesheetService
222
223
  .getStylesheets()
223
- .map(x => cssFromString(this.buildPatchedStyleSheet([cssFromString(x.content)]))));
224
+ .map(x => cssFromString(AbstractStylesheetService.buildPatchedStyleSheet([cssFromString(x.content)]))));
224
225
  }
225
226
  this.shadowRoot.adoptedStyleSheets = styles;
226
227
  }
@@ -529,12 +530,18 @@ export class DesignerCanvas extends BaseCustomWebComponentLazyAppend {
529
530
  }
530
531
  _internalSetDesignItems(designItems) {
531
532
  this._fillCalculationrects();
532
- //this.instanceServiceContainer.undoService.clear();
533
533
  this.overlayLayer.removeAllOverlays();
534
534
  DomHelper.removeAllChildnodes(this.overlayLayer);
535
535
  for (let i of [...this.rootDesignItem.children()])
536
536
  this.rootDesignItem._removeChildInternal(i);
537
537
  this.addDesignItems(designItems);
538
+ if (this.instanceServiceContainer.stylesheetService) {
539
+ const styleElements = this.rootDesignItem.element.querySelectorAll('style');
540
+ let i = 1;
541
+ const intStyleSheets = [...styleElements].map(x => ({ name: '&lt;style&gt; #' + (x.id ? x.id + '(' + i++ + ')' : i++), content: x.textContent, designItem: DesignItem.GetDesignItem(x) }));
542
+ //TODO: clear out style elements so they don't interfer with designer
543
+ this.instanceServiceContainer.stylesheetService.setDocumentStylesheets(intStyleSheets);
544
+ }
538
545
  this.instanceServiceContainer.contentService.onContentChanged.emit({ changeType: 'parsed' });
539
546
  this.instanceServiceContainer.selectionService._withoutUndoSetSelectedElements(null);
540
547
  setTimeout(() => this.extensionManager.refreshAllAppliedExtentions(), 50);
@@ -914,6 +921,8 @@ export class DesignerCanvas extends BaseCustomWebComponentLazyAppend {
914
921
  }
915
922
  }
916
923
  _pointerEventHandler(event, forceElement = null) {
924
+ if (!this.serviceContainer)
925
+ return;
917
926
  this._fillCalculationrects();
918
927
  if (this._pointerextensions) {
919
928
  for (let pe of this._pointerextensions)
@@ -1017,48 +1026,5 @@ export class DesignerCanvas extends BaseCustomWebComponentLazyAppend {
1017
1026
  this.zoomFactor = newZoom;
1018
1027
  this.canvasOffsetUnzoomed = newCanvasOffset;
1019
1028
  }
1020
- buildPatchedStyleSheet(value) {
1021
- let style = '';
1022
- for (let s of value) {
1023
- style += this.traverseAndCollectRules(s);
1024
- }
1025
- return style;
1026
- }
1027
- traverseAndCollectRules(ruleContainer) {
1028
- let t = '';
1029
- for (let rule of ruleContainer.cssRules) {
1030
- if ((rule instanceof CSSContainerRule
1031
- || rule instanceof CSSSupportsRule
1032
- || rule instanceof CSSMediaRule)
1033
- && rule.cssRules) {
1034
- t += rule.cssText.split(rule.conditionText)[0] + rule.conditionText + " { " + this.traverseAndCollectRules(rule) + " }";
1035
- }
1036
- if (rule instanceof CSSStyleRule) {
1037
- let parts = rule.selectorText.split(',');
1038
- let sel = "";
1039
- for (let p of parts) {
1040
- if (p.includes(this.cssprefixConstant)) {
1041
- sel += p;
1042
- continue;
1043
- }
1044
- if (sel)
1045
- sel += ',';
1046
- sel += this.cssprefixConstant + p.trimStart();
1047
- }
1048
- t += sel;
1049
- let cssText = rule.style.cssText;
1050
- //bugfix for chrome issue: https://bugs.chromium.org/p/chromium/issues/detail?id=1394353
1051
- if (rule.styleMap && rule.styleMap.get('grid-template') && rule.styleMap.get('grid-template').toString().includes('repeat(')) {
1052
- let entr = rule.styleMap.entries();
1053
- cssText = '';
1054
- for (let e of entr) {
1055
- cssText += e[0] + ':' + e[1].toString() + ';';
1056
- }
1057
- }
1058
- t += '{' + cssText + '}';
1059
- }
1060
- }
1061
- return t;
1062
- }
1063
1029
  }
1064
1030
  customElements.define('node-projects-designer-canvas', DesignerCanvas);
@@ -35,6 +35,6 @@ export declare class DesignerView extends BaseCustomWebComponentConstructorAppen
35
35
  canExecuteCommand(command: IUiCommand): boolean;
36
36
  initialize(serviceContainer: ServiceContainer): void;
37
37
  getHTML(designItemsAssignmentList?: Map<IDesignItem, IStringPosition>): string;
38
- parseHTML(html: string): Promise<void>;
38
+ parseHTML(html: string, disableUndo?: boolean): Promise<void>;
39
39
  static wrapInDesigner(elements: HTMLCollection | HTMLElement[], serviceContainer: ServiceContainer): DesignerCanvas;
40
40
  }
@@ -307,7 +307,7 @@ export class DesignerView extends BaseCustomWebComponentConstructorAppend {
307
307
  return DomConverter.ConvertToString(Array.from(this._designerCanvas.rootDesignItem.children()), designItemsAssignmentList);
308
308
  return '';
309
309
  }
310
- async parseHTML(html) {
310
+ async parseHTML(html, disableUndo = false) {
311
311
  const parserService = this.serviceContainer.htmlParserService;
312
312
  if (!html) {
313
313
  this.instanceServiceContainer.undoService.clear();
@@ -317,7 +317,12 @@ export class DesignerView extends BaseCustomWebComponentConstructorAppend {
317
317
  }
318
318
  else {
319
319
  const designItems = await parserService.parse(html, this.serviceContainer, this.instanceServiceContainer);
320
- this._designerCanvas.setDesignItems(designItems);
320
+ if (disableUndo) {
321
+ this._designerCanvas._internalSetDesignItems(designItems);
322
+ }
323
+ else {
324
+ this._designerCanvas.setDesignItems(designItems);
325
+ }
321
326
  }
322
327
  }
323
328
  static wrapInDesigner(elements, serviceContainer) {
@@ -1,6 +1,5 @@
1
1
  import { BaseCustomWebComponentLazyAppend, css, html } from '@node-projects/base-custom-webcomponent';
2
2
  import { sleep } from '../../helper/Helper.js';
3
- import { DesignItem } from '../../item/DesignItem.js';
4
3
  import { NodeType } from '../../item/NodeType.js';
5
4
  export class PropertyGridWithHeader extends BaseCustomWebComponentLazyAppend {
6
5
  static style = css `
@@ -73,12 +72,7 @@ export class PropertyGridWithHeader extends BaseCustomWebComponentLazyAppend {
73
72
  };
74
73
  this._content.onkeydown = e => {
75
74
  if (e.key == 'Enter') {
76
- const grp = this._instanceServiceContainer.selectionService.primarySelection.openGroup('set content');
77
- this._instanceServiceContainer.selectionService.primarySelection.clearChildren();
78
- let t = document.createTextNode(this._content.value);
79
- let di = DesignItem.GetOrCreateDesignItem(t, this._instanceServiceContainer.selectionService.primarySelection.serviceContainer, this._instanceServiceContainer);
80
- this._instanceServiceContainer.selectionService.primarySelection.insertAdjacentElement(di, 'afterbegin');
81
- grp.commit();
75
+ this._instanceServiceContainer.selectionService.primarySelection.content = this._content.value;
82
76
  this._content.title = this._content.value;
83
77
  }
84
78
  else if (e.key == 'Escape') {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "description": "A UI designer for Polymer apps",
3
3
  "name": "@node-projects/web-component-designer",
4
- "version": "0.0.209",
4
+ "version": "0.0.210",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "author": "",