@node-projects/web-component-designer 0.0.175 → 0.0.177

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/dist/elements/item/DesignItem.js +3 -3
  2. package/dist/elements/services/DefaultServiceBootstrap.js +2 -0
  3. package/dist/elements/services/htmlWriterService/HtmlWriterService.js +8 -1
  4. package/dist/elements/services/propertiesService/services/CssCurrentPropertiesService.d.ts +4 -0
  5. package/dist/elements/services/propertiesService/services/CssCurrentPropertiesService.js +17 -5
  6. package/dist/elements/services/propertiesService/services/CssPropertiesService.js +11 -7
  7. package/dist/elements/services/stylesheetService/AbstractStylesheetService.d.ts +17 -0
  8. package/dist/elements/services/stylesheetService/AbstractStylesheetService.js +11 -0
  9. package/dist/elements/services/stylesheetService/CssToolsStylesheetService.d.ts +31 -11
  10. package/dist/elements/services/stylesheetService/CssToolsStylesheetService.js +72 -13
  11. package/dist/elements/services/stylesheetService/CssTreeStylesheetService.d.ts +6 -13
  12. package/dist/elements/services/stylesheetService/CssTreeStylesheetService.js +16 -20
  13. package/dist/elements/services/stylesheetService/IStylesheetService.d.ts +4 -3
  14. package/dist/elements/widgets/codeView/code-view-monaco.js +2 -0
  15. package/dist/elements/widgets/designerView/designerCanvas.d.ts +0 -4
  16. package/dist/elements/widgets/designerView/designerCanvas.js +10 -14
  17. package/dist/elements/widgets/designerView/extensions/buttons/ButtonSeperatorProvider.js +2 -1
  18. package/dist/elements/widgets/designerView/extensions/buttons/FlexboxExtensionDesignViewConfigButtons.d.ts +3 -5
  19. package/dist/elements/widgets/designerView/extensions/buttons/FlexboxExtensionDesignViewConfigButtons.js +4 -19
  20. package/dist/elements/widgets/designerView/extensions/buttons/GridExtensionDesignViewConfigButtons.d.ts +3 -5
  21. package/dist/elements/widgets/designerView/extensions/buttons/GridExtensionDesignViewConfigButtons.js +4 -19
  22. package/dist/elements/widgets/designerView/extensions/buttons/InvisibleElementExtensionDesignViewConfigButtons.d.ts +3 -5
  23. package/dist/elements/widgets/designerView/extensions/buttons/InvisibleElementExtensionDesignViewConfigButtons.js +4 -19
  24. package/dist/elements/widgets/designerView/extensions/contextMenu/JumpToElementContextMenu.d.ts +8 -0
  25. package/dist/elements/widgets/designerView/extensions/contextMenu/JumpToElementContextMenu.js +15 -0
  26. package/dist/elements/widgets/propertyGrid/PropertyGridPropertyList.js +1 -1
  27. package/dist/index.d.ts +1 -0
  28. package/dist/index.js +1 -0
  29. package/package.json +5 -5
@@ -314,7 +314,7 @@ export class DesignItem {
314
314
  let nm = PropertiesHelper.camelToDashCase(name);
315
315
  // Pre-sorted by specificity
316
316
  let declerations = this.instanceServiceContainer.stylesheetService?.getDeclarations(this, nm);
317
- if (this.hasStyle(name) || this.instanceServiceContainer.designContext.extensionOptions[enableStylesheetService] === false || !declerations) {
317
+ if (this.hasStyle(name) || this.instanceServiceContainer.designContext.extensionOptions[enableStylesheetService] === false || !declerations?.length) {
318
318
  // Set style locally
319
319
  if (this.getStyle(nm) != value) {
320
320
  this.setStyle(nm, value);
@@ -325,7 +325,7 @@ export class DesignItem {
325
325
  }
326
326
  else {
327
327
  // Set style in sheet
328
- this.instanceServiceContainer.stylesheetService.updateDeclarationWithDeclaration(declerations[0], value, important);
328
+ this.instanceServiceContainer.stylesheetService.updateDeclarationValue(declerations[0], value, important);
329
329
  }
330
330
  }
331
331
  getStyleFromSheetOrLocal(name, fallback = null) {
@@ -354,7 +354,7 @@ export class DesignItem {
354
354
  return value ?? fallback;
355
355
  }
356
356
  getAllStyles() {
357
- const localStyles = [...this._styles.entries()].map(x => ({ name: x[0], value: x[1], important: false }));
357
+ const localStyles = [...this._styles.entries()].map(x => ({ name: x[0], value: x[1], important: false, parent: null }));
358
358
  if (this.instanceServiceContainer.stylesheetService) {
359
359
  const rules = this.instanceServiceContainer.stylesheetService?.getAppliedRules(this);
360
360
  if (rules) {
@@ -76,6 +76,7 @@ import { UndoService } from './undoService/UndoService.js';
76
76
  import { SelectionService } from './selectionService/SelectionService.js';
77
77
  import { ContentService } from './contentService/ContentService.js';
78
78
  import { StylesheetServiceDesignViewConfigButtons } from '../widgets/designerView/extensions/buttons/StylesheetServiceDesignViewConfigButtons.js';
79
+ import { JumpToElementContextMenu } from '../widgets/designerView/extensions/contextMenu/JumpToElementContextMenu.js';
79
80
  export function createDefaultServiceContainer() {
80
81
  let serviceContainer = new ServiceContainer();
81
82
  serviceContainer.register("propertyService", new PolymerPropertiesService());
@@ -169,6 +170,7 @@ export function createDefaultServiceContainer() {
169
170
  new SeperatorContextMenu(),
170
171
  new RotateLeftAndRight(),
171
172
  new SeperatorContextMenu(),
173
+ new JumpToElementContextMenu(),
172
174
  new ZoomToElementContextMenu(),
173
175
  new SeperatorContextMenu(),
174
176
  new ZMoveContextMenu(),
@@ -29,6 +29,7 @@ export class HtmlWriterService extends AbstractHtmlWriterService {
29
29
  }
30
30
  internalWrite(indentedTextWriter, designItem, options, designItemsAssignmentList) {
31
31
  let start = indentedTextWriter.position;
32
+ let end = indentedTextWriter.position;
32
33
  if (designItem.nodeType == NodeType.TextNode) {
33
34
  if (isEmptyTextNode(designItem.element) &&
34
35
  ((designItem.element.previousSibling instanceof HTMLElement && !isInlineAfter(designItem.element.previousSibling)) ||
@@ -36,14 +37,18 @@ export class HtmlWriterService extends AbstractHtmlWriterService {
36
37
  }
37
38
  else
38
39
  this.writeTextNode(indentedTextWriter, designItem, true);
40
+ end = indentedTextWriter.position;
39
41
  }
40
42
  else if (designItem.nodeType == NodeType.Comment) {
41
43
  this._conditionalyWriteIndent(indentedTextWriter, designItem);
44
+ start = indentedTextWriter.position;
42
45
  indentedTextWriter.write('<!--' + designItem.content + '-->');
46
+ end = indentedTextWriter.position;
43
47
  this._conditionalyWriteNewline(indentedTextWriter, designItem);
44
48
  }
45
49
  else {
46
50
  this._conditionalyWriteIndentBefore(indentedTextWriter, designItem);
51
+ start = indentedTextWriter.position;
47
52
  indentedTextWriter.write('<' + designItem.name);
48
53
  this.writeAttributes(indentedTextWriter, designItem, options);
49
54
  this.writeStyles(indentedTextWriter, designItem, options);
@@ -79,14 +84,16 @@ export class HtmlWriterService extends AbstractHtmlWriterService {
79
84
  indentedTextWriter.write(DomConverter.normalizeContentValue(designItem.content));
80
85
  //this._conditionalyWriteNewline(indentedTextWriter, designItem);
81
86
  }
87
+ end = indentedTextWriter.position;
82
88
  if (!DomConverter.IsSelfClosingElement(designItem.name))
83
89
  indentedTextWriter.write('</' + designItem.name + '>');
90
+ end = indentedTextWriter.position;
84
91
  //if (!contentSingleTextNode)
85
92
  if (!indentedTextWriter.isLastCharNewline() && (!designItem.parent || !isInlineAfter(designItem.parent.element)))
86
93
  this._conditionalyWriteNewline(indentedTextWriter, designItem);
87
94
  }
88
95
  if (designItemsAssignmentList) {
89
- designItemsAssignmentList.set(designItem, { start: start, length: indentedTextWriter.position - start - 1 });
96
+ designItemsAssignmentList.set(designItem, { start: start, length: end - start });
90
97
  }
91
98
  }
92
99
  writeTextNode(indentedTextWriter, designItem, indentAndNewline) {
@@ -23,6 +23,10 @@ export declare class CssCurrentPropertiesService extends CommonPropertiesService
23
23
  styleRule: IStyleRule;
24
24
  styleDeclaration: IStyleDeclaration;
25
25
  }): any;
26
+ getUnsetValue(designItems: IDesignItem[], property: IProperty & {
27
+ styleRule: IStyleRule;
28
+ styleDeclaration: IStyleDeclaration;
29
+ }): any;
26
30
  isSet(designItems: IDesignItem[], property: IProperty & {
27
31
  styleRule: IStyleRule;
28
32
  styleDeclaration: IStyleDeclaration;
@@ -42,19 +42,26 @@ export class CssCurrentPropertiesService extends CommonPropertiesService {
42
42
  setValue(designItems, property, value) {
43
43
  // No selector means local style, styleDeclaration is null means new property
44
44
  if (property.styleRule?.selector !== null && property.styleDeclaration) {
45
- designItems[0].instanceServiceContainer.stylesheetService.updateDeclarationWithDeclaration(property.styleDeclaration, value, false);
45
+ designItems[0].instanceServiceContainer.stylesheetService.updateDeclarationValue(property.styleDeclaration, value, false);
46
+ this._notifyChangedProperty(designItems[0], property, value);
46
47
  return;
47
48
  }
48
49
  if (property.styleRule?.selector !== null && !property.styleDeclaration) {
49
- designItems[0].instanceServiceContainer.stylesheetService.insertDeclarationIntoRule(property.styleRule, { name: property.name, value: value, important: false }, false);
50
+ designItems[0].instanceServiceContainer.stylesheetService.insertDeclarationIntoRule(property.styleRule, property.name, value, false);
51
+ this._notifyChangedProperty(designItems[0], property, value);
50
52
  return;
51
53
  }
52
- // Local style
53
- super.setValue(designItems, { ...property, propertyType: PropertyType.cssValue }, value);
54
+ for (const d of designItems) {
55
+ // Local style
56
+ d.setStyle(property.name, value);
57
+ //unkown css property names do not trigger the mutation observer of property grid,
58
+ //fixed by assinging stle again to the attribute
59
+ d.element.setAttribute('style', d.element.getAttribute('style'));
60
+ }
54
61
  }
55
62
  clearValue(designItems, property) {
56
63
  if (property.styleRule?.selector !== null && property.styleDeclaration) {
57
- designItems[0].instanceServiceContainer.stylesheetService.removeDeclarationFromRule(property.styleRule, property.styleDeclaration);
64
+ designItems[0].instanceServiceContainer.stylesheetService.removeDeclarationFromRule(property.styleRule, property.styleDeclaration.name);
58
65
  return;
59
66
  }
60
67
  super.clearValue(designItems, property);
@@ -64,6 +71,11 @@ export class CssCurrentPropertiesService extends CommonPropertiesService {
64
71
  return property.styleDeclaration.value;
65
72
  return super.getValue(designItems, property);
66
73
  }
74
+ getUnsetValue(designItems, property) {
75
+ if (property.styleRule?.selector && property.styleDeclaration)
76
+ return property.styleDeclaration.value;
77
+ return super.getUnsetValue(designItems, property);
78
+ }
67
79
  isSet(designItems, property) {
68
80
  if (property.styleRule?.selector && property.styleDeclaration) {
69
81
  if (designItems[0].hasStyle(property.name))
@@ -3,6 +3,7 @@ import { PropertyType } from '../PropertyType.js';
3
3
  import { CommonPropertiesService } from './CommonPropertiesService.js';
4
4
  import { RefreshMode } from '../IPropertiesService.js';
5
5
  import cssProperties from './CssProperties.json' assert { type: 'json' };
6
+ import { PropertiesHelper } from './PropertiesHelper.js';
6
7
  export class CssPropertiesService extends CommonPropertiesService {
7
8
  getRefreshMode(designItem) {
8
9
  return RefreshMode.none;
@@ -57,13 +58,16 @@ export class CssPropertiesService extends CommonPropertiesService {
57
58
  }
58
59
  getProperties(designItem) {
59
60
  const propNames = this[this.name];
60
- const propertiesList = propNames.map(x => ({
61
- name: x,
62
- type: cssProperties[x]?.type ?? 'string',
63
- values: cssProperties[x]?.values ? [...cssProperties[x]?.values, 'initial', 'inherit', 'unset'] : ['initial', 'inherit', 'unset'],
64
- service: this,
65
- propertyType: PropertyType.cssValue
66
- }));
61
+ const propertiesList = propNames.map(x => {
62
+ const camelName = PropertiesHelper.dashToCamelCase(x);
63
+ return {
64
+ name: x,
65
+ type: cssProperties[camelName]?.type ?? 'string',
66
+ values: cssProperties[camelName]?.values ? [...cssProperties[camelName]?.values, 'initial', 'inherit', 'unset'] : ['initial', 'inherit', 'unset'],
67
+ service: this,
68
+ propertyType: PropertyType.cssValue
69
+ };
70
+ });
67
71
  return propertiesList;
68
72
  }
69
73
  getPropertyTarget(designItem, property) {
@@ -0,0 +1,17 @@
1
+ import { TypedEvent } from "@node-projects/base-custom-webcomponent";
2
+ import { IDesignItem } from "../../item/IDesignItem";
3
+ import { IStyleDeclaration, IStyleRule, IStylesheet, IStylesheetService } from "./IStylesheetService";
4
+ export declare abstract class AbstractStylesheetService implements IStylesheetService {
5
+ abstract setStylesheets(stylesheets: IStylesheet[]): void;
6
+ abstract getStylesheets(): IStylesheet[];
7
+ abstract getAppliedRules(designItem: IDesignItem): IStyleRule[];
8
+ abstract getDeclarations(designItem: IDesignItem, styleName: string): IStyleDeclaration[];
9
+ abstract updateDeclarationValue(declaration: IStyleDeclaration, value: string, important: boolean): boolean;
10
+ abstract insertDeclarationIntoRule(rule: IStyleRule, property: string, value: string, important: boolean): boolean;
11
+ abstract removeDeclarationFromRule(rule: IStyleRule, property: string): boolean;
12
+ stylesheetChanged: TypedEvent<{
13
+ stylesheet: IStylesheet;
14
+ }>;
15
+ stylesheetsChanged: TypedEvent<void>;
16
+ protected elementMatchesASelector(designItem: IDesignItem, selectors: string[]): boolean;
17
+ }
@@ -0,0 +1,11 @@
1
+ import { TypedEvent } from "@node-projects/base-custom-webcomponent";
2
+ export class AbstractStylesheetService {
3
+ stylesheetChanged = new TypedEvent();
4
+ stylesheetsChanged = new TypedEvent();
5
+ elementMatchesASelector(designItem, selectors) {
6
+ for (const selector of selectors)
7
+ if (designItem.element.matches(selector))
8
+ return true;
9
+ return false;
10
+ }
11
+ }
@@ -1,17 +1,37 @@
1
1
  import { IDesignItem } from "../../item/IDesignItem.js";
2
- import { IStyleDeclaration, IStyleRule, IStylesheet, IStylesheetService } from "./IStylesheetService.js";
3
- import { TypedEvent } from "@node-projects/base-custom-webcomponent";
4
- export declare class CssToolsStylesheetService implements IStylesheetService {
2
+ import { IStyleDeclaration, IStyleRule, IStylesheet } from "./IStylesheetService.js";
3
+ import type { CssDeclarationAST, CssRuleAST, CssStylesheetAST } from "@adobe/css-tools";
4
+ import { AbstractStylesheetService } from "./AbstractStylesheetService.js";
5
+ interface IRuleWithAST extends IStyleRule {
6
+ ast: CssRuleAST;
7
+ declarations: IDeclarationWithAST[];
8
+ stylesheet: IStylesheet;
9
+ stylesheetName: string;
10
+ }
11
+ interface IDeclarationWithAST extends IStyleDeclaration {
12
+ ast: CssDeclarationAST;
13
+ }
14
+ export declare class CssToolsStylesheetService extends AbstractStylesheetService {
5
15
  private _stylesheets;
6
- stylesheetChanged: TypedEvent<{
7
- stylesheet: IStylesheet;
8
- }>;
9
- stylesheetsChanged: TypedEvent<void>;
16
+ _tools: {
17
+ parse: (css: string, options?: {
18
+ source?: string;
19
+ silent?: boolean;
20
+ }) => CssStylesheetAST;
21
+ stringify: (node: CssStylesheetAST, options?: {
22
+ indent?: string;
23
+ compress?: boolean;
24
+ emptyDeclarations?: boolean;
25
+ }) => string;
26
+ };
10
27
  setStylesheets(stylesheets: IStylesheet[]): Promise<void>;
11
28
  getStylesheets(): IStylesheet[];
12
- getAppliedRules(designItem: IDesignItem): IStyleRule[];
29
+ getAppliedRules(designItem: IDesignItem): IRuleWithAST[];
30
+ private getRulesFromAst;
13
31
  getDeclarations(designItem: IDesignItem, styleName: string): IStyleDeclaration[];
14
- updateDeclarationWithDeclaration(declaration: IStyleDeclaration, value: string, important: boolean): boolean;
15
- insertDeclarationIntoRule(rule: IStyleRule, declaration: IStyleDeclaration, important: boolean): boolean;
16
- removeDeclarationFromRule(rule: IStyleRule, declaration: IStyleDeclaration): boolean;
32
+ updateDeclarationValue(declaration: IDeclarationWithAST, value: string, important: boolean): boolean;
33
+ insertDeclarationIntoRule(rule: IRuleWithAST, property: string, value: string, important: boolean): boolean;
34
+ removeDeclarationFromRule(rule: IRuleWithAST, property: string): boolean;
35
+ private updateStylesheet;
17
36
  }
37
+ export {};
@@ -1,17 +1,21 @@
1
- import { TypedEvent } from "@node-projects/base-custom-webcomponent";
2
- export class CssToolsStylesheetService {
1
+ import { AbstractStylesheetService } from "./AbstractStylesheetService.js";
2
+ export class CssToolsStylesheetService extends AbstractStylesheetService {
3
3
  _stylesheets = new Map();
4
- stylesheetChanged = new TypedEvent();
5
- stylesheetsChanged = new TypedEvent();
4
+ _tools;
6
5
  async setStylesheets(stylesheets) {
7
6
  if (stylesheets != null) {
8
- let tools = await import('@adobe/css-tools');
7
+ this._tools = await import('@adobe/css-tools');
9
8
  this._stylesheets = new Map();
10
9
  for (let stylesheet of stylesheets) {
11
- this._stylesheets.set(stylesheet.name, {
12
- stylesheet: stylesheet,
13
- ast: tools.parse(stylesheet.content)
14
- });
10
+ try {
11
+ this._stylesheets.set(stylesheet.name, {
12
+ stylesheet: stylesheet,
13
+ ast: this._tools.parse(stylesheet.content)
14
+ });
15
+ }
16
+ catch (err) {
17
+ console.warn("error parsing stylesheet", stylesheet, err);
18
+ }
15
19
  }
16
20
  this.stylesheetsChanged.emit();
17
21
  }
@@ -28,18 +32,73 @@ export class CssToolsStylesheetService {
28
32
  return stylesheets;
29
33
  }
30
34
  getAppliedRules(designItem) {
35
+ let rules = [];
36
+ for (let item of this._stylesheets.entries()) {
37
+ if (!item[1].ast?.stylesheet?.rules)
38
+ continue;
39
+ let rs = Array.from(this.getRulesFromAst(item[1].ast?.stylesheet?.rules, item[1].stylesheet, designItem))
40
+ .map(x => ({
41
+ selector: x.selectors.join(', '),
42
+ declarations: x.declarations.map(y => ({
43
+ name: y.property,
44
+ value: y.value.endsWith('!important') ? y.value.substring(0, y.value.length - 10).trimEnd() : y.value,
45
+ important: y.value.endsWith('!important'),
46
+ parent: null,
47
+ ast: y,
48
+ })),
49
+ specificity: 0,
50
+ stylesheetName: item[0],
51
+ ast: x,
52
+ }));
53
+ rs.forEach(x => x.declarations.forEach(y => y.parent = x));
54
+ rules.push(...rs);
55
+ }
56
+ ;
57
+ return rules;
58
+ }
59
+ *getRulesFromAst(cssAtRuleAst, stylesheet, designItem) {
60
+ for (const atRule of cssAtRuleAst) {
61
+ if (atRule.type == 'media') {
62
+ yield* this.getRulesFromAst(atRule.rules, stylesheet, designItem);
63
+ }
64
+ else if (atRule.type == 'supports') {
65
+ yield* this.getRulesFromAst(atRule.rules, stylesheet, designItem);
66
+ }
67
+ else if (atRule.type == 'rule') {
68
+ if (this.elementMatchesASelector(designItem, atRule.selectors))
69
+ yield atRule;
70
+ }
71
+ }
31
72
  return null;
32
73
  }
33
74
  getDeclarations(designItem, styleName) {
34
- return null;
75
+ return this.getAppliedRules(designItem).flatMap(x => x.declarations).filter(x => x.name == styleName);
35
76
  }
36
- updateDeclarationWithDeclaration(declaration, value, important) {
77
+ updateDeclarationValue(declaration, value, important) {
78
+ declaration.ast.value = important ? value + ' !important' : value;
79
+ let ss = this._stylesheets.get(declaration.parent.stylesheetName);
80
+ this.updateStylesheet(ss);
37
81
  return true;
38
82
  }
39
- insertDeclarationIntoRule(rule, declaration, important) {
83
+ insertDeclarationIntoRule(rule, property, value, important) {
84
+ rule.ast.declarations.push({
85
+ type: 'declaration',
86
+ property: property,
87
+ value: important ? value + ' !important' : value
88
+ });
89
+ this.updateStylesheet(this._stylesheets.get(rule.stylesheetName));
40
90
  return true;
41
91
  }
42
- removeDeclarationFromRule(rule, declaration) {
92
+ removeDeclarationFromRule(rule, property) {
93
+ let idx = rule.ast.declarations.findIndex(x => x.property == property);
94
+ if (idx == -1)
95
+ return false;
96
+ rule.ast.declarations.splice(idx, 1);
97
+ this.updateStylesheet(this._stylesheets.get(rule.stylesheetName));
43
98
  return true;
44
99
  }
100
+ updateStylesheet(ss) {
101
+ ss.stylesheet.content = this._tools.stringify(ss.ast, { indent: ' ', compress: false, emptyDeclarations: true });
102
+ this.stylesheetChanged.emit({ stylesheet: ss.stylesheet });
103
+ }
45
104
  }
@@ -1,7 +1,7 @@
1
1
  import { IDesignItem } from "../../item/IDesignItem.js";
2
- import { IStyleDeclaration, IStyleRule, IStylesheet, IStylesheetService } from "./IStylesheetService.js";
2
+ import { IStyleDeclaration, IStyleRule, IStylesheet } from "./IStylesheetService.js";
3
3
  import type * as csstree from 'css-tree';
4
- import { TypedEvent } from "@node-projects/base-custom-webcomponent";
4
+ import { AbstractStylesheetService } from "./AbstractStylesheetService.js";
5
5
  declare global {
6
6
  interface Window {
7
7
  csstree: {
@@ -18,30 +18,23 @@ interface IRuleWithAST extends IStyleRule {
18
18
  }
19
19
  interface IDeclarationWithAST extends IStyleDeclaration {
20
20
  ast: csstree.DeclarationPlain;
21
- parent: IStyleRule;
22
21
  }
23
- export declare class CssTreeStylesheetService implements IStylesheetService {
22
+ export declare class CssTreeStylesheetService extends AbstractStylesheetService {
24
23
  private _stylesheets;
25
- stylesheetChanged: TypedEvent<{
26
- stylesheet: IStylesheet;
27
- }>;
28
- stylesheetsChanged: TypedEvent<void>;
29
- constructor();
30
24
  setStylesheets(stylesheets: IStylesheet[]): void;
31
25
  getStylesheets(): IStylesheet[];
32
26
  private getAppliedRulesInternal;
33
27
  getAppliedRules(designItem: IDesignItem): IRuleWithAST[];
34
28
  private getDeclarationInternal;
35
29
  getDeclarations(designItem: IDesignItem, stlyeName: string): IDeclarationWithAST[];
36
- updateDeclarationWithDeclaration(declaration: IDeclarationWithAST, value: string, important: boolean): boolean;
37
- insertDeclarationIntoRule(rule: IRuleWithAST, declaration: IStyleDeclaration, important: boolean): boolean;
38
- removeDeclarationFromRule(rule: IRuleWithAST, declaration: IDeclarationWithAST): boolean;
30
+ updateDeclarationValue(declaration: IDeclarationWithAST, value: string, important: boolean): boolean;
31
+ insertDeclarationIntoRule(rule: IRuleWithAST, property: string, value: string, important: boolean): boolean;
32
+ removeDeclarationFromRule(rule: IRuleWithAST, property: string): boolean;
39
33
  private rulesFromAST;
40
34
  private astHasChildren;
41
35
  private buildSelectorString;
42
36
  private getSpecificity;
43
37
  private findDeclarationInRule;
44
- private elementMatchesASelector;
45
38
  private buildAtRuleString;
46
39
  private sortDeclarations;
47
40
  }
@@ -1,18 +1,20 @@
1
- import { TypedEvent } from "@node-projects/base-custom-webcomponent";
2
1
  import { calculate as calculateSpecifity } from "./SpecificityCalculator.js";
3
- export class CssTreeStylesheetService {
2
+ import { AbstractStylesheetService } from "./AbstractStylesheetService.js";
3
+ export class CssTreeStylesheetService extends AbstractStylesheetService {
4
4
  _stylesheets = new Map();
5
- stylesheetChanged = new TypedEvent();
6
- stylesheetsChanged = new TypedEvent();
7
- constructor() { }
8
5
  setStylesheets(stylesheets) {
9
6
  if (stylesheets != null) {
10
7
  this._stylesheets = new Map();
11
8
  for (let stylesheet of stylesheets) {
12
- this._stylesheets.set(stylesheet.name, {
13
- stylesheet: stylesheet,
14
- ast: window.csstree.toPlainObject((window.csstree.parse(stylesheet.content, { positions: true, parseValue: false })))
15
- });
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
+ }
16
18
  }
17
19
  this.stylesheetsChanged.emit();
18
20
  }
@@ -88,7 +90,7 @@ export class CssTreeStylesheetService {
88
90
  return this.sortDeclarations(declarations);
89
91
  }
90
92
  /* Section covers the update of rules and declarations */
91
- updateDeclarationWithDeclaration(declaration, value, important) {
93
+ updateDeclarationValue(declaration, value, important) {
92
94
  let sourceNode = this._stylesheets.get(declaration.parent.stylesheetName);
93
95
  declaration.ast.value = window.csstree.toPlainObject(window.csstree.parse(declaration.name + ": " + value + (important ? " !important" : ""), { context: 'declaration', parseValue: false })).value;
94
96
  sourceNode.stylesheet.content = window.csstree.generate(window.csstree.fromPlainObject(sourceNode.ast));
@@ -97,17 +99,17 @@ export class CssTreeStylesheetService {
97
99
  this.stylesheetChanged.emit({ stylesheet: sourceNode.stylesheet });
98
100
  return true;
99
101
  }
100
- insertDeclarationIntoRule(rule, declaration, important) {
102
+ insertDeclarationIntoRule(rule, property, value, important) {
101
103
  let sourceNode = this._stylesheets.get(rule.stylesheetName);
102
- rule.ast.block.children.push(window.csstree.toPlainObject(window.csstree.parse(declaration.name + ": " + declaration.value + (declaration.important ? " !important" : ""), { context: 'declaration', parseValue: false })));
104
+ rule.ast.block.children.push(window.csstree.toPlainObject(window.csstree.parse(property + ": " + value + (important ? " !important" : ""), { context: 'declaration', parseValue: false })));
103
105
  sourceNode.stylesheet.content = window.csstree.generate(window.csstree.fromPlainObject(sourceNode.ast));
104
106
  // After generating the stylesheet, parse again (so line numbers are correct)
105
107
  sourceNode.ast = window.csstree.toPlainObject((window.csstree.parse(sourceNode.stylesheet.content, { positions: true, parseValue: false })));
106
108
  this.stylesheetChanged.emit({ stylesheet: sourceNode.stylesheet });
107
109
  return true;
108
110
  }
109
- removeDeclarationFromRule(rule, declaration) {
110
- let index = rule.ast.block.children.indexOf(declaration.ast);
111
+ removeDeclarationFromRule(rule, property) {
112
+ let index = rule.ast.block.children.findIndex(x => x.property == property);
111
113
  if (index == -1)
112
114
  return false;
113
115
  rule.ast.block.children.splice(index, 1);
@@ -172,12 +174,6 @@ export class CssTreeStylesheetService {
172
174
  findDeclarationInRule(rule, styleName) {
173
175
  return rule.block.children.find(declaration => declaration.property == styleName);
174
176
  }
175
- elementMatchesASelector(designItem, selectors) {
176
- for (const selector of selectors)
177
- if (designItem.element.matches(selector))
178
- return true;
179
- return false;
180
- }
181
177
  buildAtRuleString(ast, stylesheet) {
182
178
  return {
183
179
  sel: stylesheet.slice(ast.prelude.loc.start.offset, ast.prelude.loc.end.offset),
@@ -10,6 +10,7 @@ export interface IStyleDeclaration {
10
10
  name: string;
11
11
  value: string;
12
12
  important: boolean;
13
+ parent: IStyleRule;
13
14
  }
14
15
  export interface IStylesheet {
15
16
  content: string;
@@ -20,9 +21,9 @@ export interface IStylesheetService {
20
21
  getStylesheets(): IStylesheet[];
21
22
  getAppliedRules(designItem: IDesignItem): IStyleRule[];
22
23
  getDeclarations(designItem: IDesignItem, styleName: string): IStyleDeclaration[];
23
- updateDeclarationWithDeclaration(declaration: IStyleDeclaration, value: string, important: boolean): boolean;
24
- insertDeclarationIntoRule(rule: IStyleRule, declaration: IStyleDeclaration, important: boolean): boolean;
25
- removeDeclarationFromRule(rule: IStyleRule, declaration: IStyleDeclaration): boolean;
24
+ updateDeclarationValue(declaration: IStyleDeclaration, value: string, important: boolean): boolean;
25
+ insertDeclarationIntoRule(rule: IStyleRule, property: string, value: string, important: boolean): boolean;
26
+ removeDeclarationFromRule(rule: IStyleRule, property: string): boolean;
26
27
  stylesheetChanged: TypedEvent<{
27
28
  stylesheet: IStylesheet;
28
29
  }>;
@@ -70,6 +70,8 @@ export class CodeViewMonaco extends BaseCustomWebComponentLazyAppend {
70
70
  //@ts-ignore
71
71
  this._monacoEditor = monaco.editor.create(this._editor, {
72
72
  automaticLayout: true,
73
+ wordWrapColumn: 1000,
74
+ wordWrap: 'wordWrapColumn',
73
75
  value: this.code,
74
76
  language: 'html',
75
77
  minimap: {
@@ -49,16 +49,12 @@ export declare class DesignerCanvas extends BaseCustomWebComponentLazyAppend imp
49
49
  private _canvasContainer;
50
50
  private _outercanvas2;
51
51
  private _lastHoverDesignItem;
52
- private _pointerEventHandlerBound;
53
52
  private _firstConnect;
54
- private _onKeyDownBound;
55
- private _onKeyUpBound;
56
53
  private cssprefixConstant;
57
54
  static readonly style: CSSStyleSheet;
58
55
  static readonly template: HTMLTemplateElement;
59
56
  extensionManager: IExtensionManager;
60
57
  private _pointerextensions;
61
- private _onDblClickBound;
62
58
  private _lastCopiedPrimaryItem;
63
59
  constructor();
64
60
  get designerWidth(): string;
@@ -72,10 +72,7 @@ export class DesignerCanvas extends BaseCustomWebComponentLazyAppend {
72
72
  _canvasContainer;
73
73
  _outercanvas2;
74
74
  _lastHoverDesignItem;
75
- _pointerEventHandlerBound;
76
75
  _firstConnect;
77
- _onKeyDownBound;
78
- _onKeyUpBound;
79
76
  cssprefixConstant = '#node-projects-designer-canvas-canvas ';
80
77
  static style = css `
81
78
  :host {
@@ -162,7 +159,6 @@ export class DesignerCanvas extends BaseCustomWebComponentLazyAppend {
162
159
  </div>`;
163
160
  extensionManager;
164
161
  _pointerextensions;
165
- _onDblClickBound;
166
162
  _lastCopiedPrimaryItem;
167
163
  constructor() {
168
164
  super();
@@ -171,10 +167,10 @@ export class DesignerCanvas extends BaseCustomWebComponentLazyAppend {
171
167
  this._canvasContainer = this._getDomElement('node-projects-designer-canvas-canvasContainer');
172
168
  this._outercanvas2 = this._getDomElement('node-projects-designer-canvas-outercanvas2');
173
169
  this.clickOverlay = this._getDomElement('node-projects-designer-canvas-clickOverlay');
174
- this._onKeyDownBound = this.onKeyDown.bind(this);
175
- this._onKeyUpBound = this.onKeyUp.bind(this);
176
- this._onDblClickBound = this._onDblClick.bind(this);
177
- this._pointerEventHandlerBound = this._pointerEventHandler.bind(this);
170
+ this.onKeyDown = this.onKeyDown.bind(this);
171
+ this.onKeyUp = this.onKeyUp.bind(this);
172
+ this._onDblClick = this._onDblClick.bind(this);
173
+ this._pointerEventHandler = this._pointerEventHandler.bind(this);
178
174
  this.clickOverlay.oncontextmenu = (e) => e.preventDefault();
179
175
  }
180
176
  get designerWidth() {
@@ -471,16 +467,16 @@ export class DesignerCanvas extends BaseCustomWebComponentLazyAppend {
471
467
  connectedCallback() {
472
468
  if (!this._firstConnect) {
473
469
  this._firstConnect = true;
474
- this.clickOverlay.addEventListener(EventNames.PointerDown, this._pointerEventHandlerBound);
475
- this.clickOverlay.addEventListener(EventNames.PointerMove, this._pointerEventHandlerBound);
476
- this.clickOverlay.addEventListener(EventNames.PointerUp, this._pointerEventHandlerBound);
470
+ this.clickOverlay.addEventListener(EventNames.PointerDown, this._pointerEventHandler);
471
+ this.clickOverlay.addEventListener(EventNames.PointerMove, this._pointerEventHandler);
472
+ this.clickOverlay.addEventListener(EventNames.PointerUp, this._pointerEventHandler);
477
473
  this.clickOverlay.addEventListener(EventNames.DragEnter, event => this._onDragEnter(event));
478
474
  this.clickOverlay.addEventListener(EventNames.DragLeave, event => this._onDragLeave(event));
479
475
  this.clickOverlay.addEventListener(EventNames.DragOver, event => this._onDragOver(event));
480
476
  this.clickOverlay.addEventListener(EventNames.Drop, event => this._onDrop(event));
481
- this.clickOverlay.addEventListener(EventNames.KeyDown, this._onKeyDownBound, true);
482
- this.clickOverlay.addEventListener(EventNames.KeyUp, this._onKeyUpBound, true);
483
- this.clickOverlay.addEventListener(EventNames.DblClick, this._onDblClickBound, true);
477
+ this.clickOverlay.addEventListener(EventNames.KeyDown, this.onKeyDown, true);
478
+ this.clickOverlay.addEventListener(EventNames.KeyUp, this.onKeyUp, true);
479
+ this.clickOverlay.addEventListener(EventNames.DblClick, this._onDblClick, true);
484
480
  }
485
481
  }
486
482
  _zoomFactorChanged(refreshExtensions = true) {
@@ -5,7 +5,8 @@ export class ButtonSeperatorProvider {
5
5
  }
6
6
  provideButtons(designerView, designerCanvas) {
7
7
  const div = document.createElement('div');
8
- div.style.marginLeft = this._space + 'px';
8
+ div.style.width = this._space + 'px';
9
+ div.oncontextmenu = (e) => { e.preventDefault(); };
9
10
  return [div];
10
11
  }
11
12
  }
@@ -1,6 +1,4 @@
1
- import { DesignerView } from "../../designerView.js";
2
- import { IDesignerCanvas } from '../../IDesignerCanvas.js';
3
- import { IDesignViewConfigButtonsProvider } from "./IDesignViewConfigButtonsProvider.js";
4
- export declare class FlexboxExtensionDesignViewConfigButtons implements IDesignViewConfigButtonsProvider {
5
- provideButtons(designerView: DesignerView, designerCanvas: IDesignerCanvas): HTMLElement[];
1
+ import { AbstractDesignViewConfigButton } from "./AbstractDesignViewConfigButton.js";
2
+ export declare class FlexboxExtensionDesignViewConfigButtons extends AbstractDesignViewConfigButton {
3
+ constructor();
6
4
  }
@@ -1,22 +1,7 @@
1
1
  import { flexboxExtensionShowOverlayOptionName } from "../FlexboxExtensionProvider.js";
2
- export class FlexboxExtensionDesignViewConfigButtons {
3
- provideButtons(designerView, designerCanvas) {
4
- const extensionOptions = designerCanvas.instanceServiceContainer.designContext.extensionOptions;
5
- const btn = document.createElement('div');
6
- btn.innerText = 'F';
7
- btn.title = 'show flexbox overlay';
8
- btn.className = 'toolbar-control';
9
- if (extensionOptions[flexboxExtensionShowOverlayOptionName] !== false)
10
- btn.classList.add('selected');
11
- btn.onclick = () => {
12
- const val = extensionOptions[flexboxExtensionShowOverlayOptionName];
13
- extensionOptions[flexboxExtensionShowOverlayOptionName] = val === false ? true : false;
14
- if (extensionOptions[flexboxExtensionShowOverlayOptionName] !== false)
15
- btn.classList.add('selected');
16
- else
17
- btn.classList.remove('selected');
18
- designerCanvas.extensionManager.reapplyAllAppliedExtentions();
19
- };
20
- return [btn];
2
+ import { AbstractDesignViewConfigButton } from "./AbstractDesignViewConfigButton.js";
3
+ export class FlexboxExtensionDesignViewConfigButtons extends AbstractDesignViewConfigButton {
4
+ constructor() {
5
+ super(flexboxExtensionShowOverlayOptionName, "F", "show flexbox overlay");
21
6
  }
22
7
  }
@@ -1,6 +1,4 @@
1
- import { DesignerView } from "../../designerView.js";
2
- import { IDesignerCanvas } from '../../IDesignerCanvas.js';
3
- import { IDesignViewConfigButtonsProvider } from "./IDesignViewConfigButtonsProvider.js";
4
- export declare class GridExtensionDesignViewConfigButtons implements IDesignViewConfigButtonsProvider {
5
- provideButtons(designerView: DesignerView, designerCanvas: IDesignerCanvas): HTMLElement[];
1
+ import { AbstractDesignViewConfigButton } from "./AbstractDesignViewConfigButton.js";
2
+ export declare class GridExtensionDesignViewConfigButtons extends AbstractDesignViewConfigButton {
3
+ constructor();
6
4
  }
@@ -1,22 +1,7 @@
1
1
  import { gridExtensionShowOverlayOptionName } from "../GridExtensionProvider.js";
2
- export class GridExtensionDesignViewConfigButtons {
3
- provideButtons(designerView, designerCanvas) {
4
- const extensionOptions = designerCanvas.instanceServiceContainer.designContext.extensionOptions;
5
- const btn = document.createElement('div');
6
- btn.innerText = 'G';
7
- btn.title = 'show grid overlay';
8
- btn.className = 'toolbar-control';
9
- if (extensionOptions[gridExtensionShowOverlayOptionName] !== false)
10
- btn.classList.add('selected');
11
- btn.onclick = () => {
12
- const val = extensionOptions[gridExtensionShowOverlayOptionName];
13
- extensionOptions[gridExtensionShowOverlayOptionName] = val === false ? true : false;
14
- if (extensionOptions[gridExtensionShowOverlayOptionName] !== false)
15
- btn.classList.add('selected');
16
- else
17
- btn.classList.remove('selected');
18
- designerCanvas.extensionManager.reapplyAllAppliedExtentions();
19
- };
20
- return [btn];
2
+ import { AbstractDesignViewConfigButton } from "./AbstractDesignViewConfigButton.js";
3
+ export class GridExtensionDesignViewConfigButtons extends AbstractDesignViewConfigButton {
4
+ constructor() {
5
+ super(gridExtensionShowOverlayOptionName, "G", "show grid overlay");
21
6
  }
22
7
  }
@@ -1,6 +1,4 @@
1
- import { DesignerView } from "../../designerView.js";
2
- import { IDesignerCanvas } from '../../IDesignerCanvas.js';
3
- import { IDesignViewConfigButtonsProvider } from "./IDesignViewConfigButtonsProvider.js";
4
- export declare class InvisibleElementExtensionDesignViewConfigButtons implements IDesignViewConfigButtonsProvider {
5
- provideButtons(designerView: DesignerView, designerCanvas: IDesignerCanvas): HTMLElement[];
1
+ import { AbstractDesignViewConfigButton } from "./AbstractDesignViewConfigButton.js";
2
+ export declare class InvisibleElementExtensionDesignViewConfigButtons extends AbstractDesignViewConfigButton {
3
+ constructor();
6
4
  }
@@ -1,22 +1,7 @@
1
1
  import { invisibleElementExtensionShowOverlayOptionName } from "../InvisibleElementExtensionProvider.js";
2
- export class InvisibleElementExtensionDesignViewConfigButtons {
3
- provideButtons(designerView, designerCanvas) {
4
- const extensionOptions = designerCanvas.instanceServiceContainer.designContext.extensionOptions;
5
- const btn = document.createElement('div');
6
- btn.innerText = 'I';
7
- btn.title = 'show invisible div overlay';
8
- btn.className = 'toolbar-control';
9
- if (extensionOptions[invisibleElementExtensionShowOverlayOptionName] !== false)
10
- btn.classList.add('selected');
11
- btn.onclick = () => {
12
- const val = extensionOptions[invisibleElementExtensionShowOverlayOptionName];
13
- extensionOptions[invisibleElementExtensionShowOverlayOptionName] = val === false ? true : false;
14
- if (extensionOptions[invisibleElementExtensionShowOverlayOptionName] !== false)
15
- btn.classList.add('selected');
16
- else
17
- btn.classList.remove('selected');
18
- designerCanvas.extensionManager.reapplyAllAppliedExtentions();
19
- };
20
- return [btn];
2
+ import { AbstractDesignViewConfigButton } from "./AbstractDesignViewConfigButton.js";
3
+ export class InvisibleElementExtensionDesignViewConfigButtons extends AbstractDesignViewConfigButton {
4
+ constructor() {
5
+ super(invisibleElementExtensionShowOverlayOptionName, "I", "show invisible div overlay");
21
6
  }
22
7
  }
@@ -0,0 +1,8 @@
1
+ import { IContextMenuItem } from '../../../../helper/contextMenu/IContextMenuItem.js';
2
+ import { IDesignItem } from '../../../../item/IDesignItem.js';
3
+ import { IDesignerCanvas } from '../../IDesignerCanvas.js';
4
+ import { ContextmenuInitiator, IContextMenuExtension } from './IContextMenuExtension.js';
5
+ export declare class JumpToElementContextMenu implements IContextMenuExtension {
6
+ shouldProvideContextmenu(event: MouseEvent, designerCanvas: IDesignerCanvas, designItem: IDesignItem, initiator: ContextmenuInitiator): boolean;
7
+ provideContextMenuItems(event: MouseEvent, designerCanvas: IDesignerCanvas, designItem: IDesignItem): IContextMenuItem[];
8
+ }
@@ -0,0 +1,15 @@
1
+ export class JumpToElementContextMenu {
2
+ shouldProvideContextmenu(event, designerCanvas, designItem, initiator) {
3
+ return true;
4
+ }
5
+ provideContextMenuItems(event, designerCanvas, designItem) {
6
+ return [
7
+ {
8
+ title: 'jump to', action: () => {
9
+ const coord = designerCanvas.getNormalizedElementCoordinates(designItem.element);
10
+ designerCanvas.zoomPoint({ x: coord.x + coord.width / 2, y: coord.y + coord.height / 2 }, designerCanvas.zoomFactor);
11
+ }
12
+ },
13
+ ];
14
+ }
15
+ }
@@ -113,7 +113,7 @@ export class PropertyGridPropertyList extends BaseCustomWebComponentLazyAppend {
113
113
  this._propertyMap.clear();
114
114
  if (this._propertiesService) {
115
115
  let properties = this._propertiesService.getProperties(designItem);
116
- if (properties) {
116
+ if (properties?.length) {
117
117
  if ('properties' in properties[0])
118
118
  this.createPropertyGroups(properties);
119
119
  else
package/dist/index.d.ts CHANGED
@@ -213,6 +213,7 @@ export * from "./elements/widgets/designerView/extensions/contextMenu/SelectAllC
213
213
  export * from "./elements/widgets/designerView/extensions/contextMenu/ZMoveContextMenu.js";
214
214
  export * from "./elements/widgets/designerView/extensions/contextMenu/RotateLeftAndRightContextMenu.js";
215
215
  export * from "./elements/widgets/designerView/extensions/contextMenu/ZoomToElementContextMenu.js";
216
+ export * from "./elements/widgets/designerView/extensions/contextMenu/JumpToElementContextMenu.js";
216
217
  export type { IDesignerPointerExtension } from "./elements/widgets/designerView/extensions/pointerExtensions/IDesignerPointerExtension.js";
217
218
  export type { IDesignerPointerExtensionProvider } from "./elements/widgets/designerView/extensions/pointerExtensions/IDesignerPointerExtensionProvider.js";
218
219
  export * from "./elements/widgets/designerView/extensions/pointerExtensions/AbstractDesignerPointerExtension.js";
package/dist/index.js CHANGED
@@ -166,6 +166,7 @@ export * from "./elements/widgets/designerView/extensions/contextMenu/SelectAllC
166
166
  export * from "./elements/widgets/designerView/extensions/contextMenu/ZMoveContextMenu.js";
167
167
  export * from "./elements/widgets/designerView/extensions/contextMenu/RotateLeftAndRightContextMenu.js";
168
168
  export * from "./elements/widgets/designerView/extensions/contextMenu/ZoomToElementContextMenu.js";
169
+ export * from "./elements/widgets/designerView/extensions/contextMenu/JumpToElementContextMenu.js";
169
170
  export * from "./elements/widgets/designerView/extensions/pointerExtensions/AbstractDesignerPointerExtension.js";
170
171
  export * from "./elements/widgets/designerView/extensions/pointerExtensions/CursorLinePointerExtension.js";
171
172
  export * from "./elements/widgets/designerView/extensions/pointerExtensions/CursorLinePointerExtensionProvider.js";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "description": "A UI designer for Polymer apps",
3
3
  "name": "@node-projects/web-component-designer",
4
- "version": "0.0.175",
4
+ "version": "0.0.177",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "author": "",
@@ -18,20 +18,20 @@
18
18
  "construct-style-sheets-polyfill": "^3.1.0"
19
19
  },
20
20
  "devDependencies": {
21
- "@adobe/css-tools": "^4.0.2",
21
+ "@adobe/css-tools": "^4.1.0",
22
22
  "@node-projects/lean-he-esm": "^3.3.0",
23
23
  "@node-projects/node-html-parser-esm": "^2.5.1",
24
24
  "@papyrs/stylo": "^0.0.42",
25
- "@types/codemirror": "^5.60.6",
25
+ "@types/codemirror": "^5.60.7",
26
26
  "@types/css-tree": "^2.0.1",
27
27
  "@types/jquery": "^3.5.16",
28
28
  "@types/jquery.fancytree": "0.0.7",
29
- "ace-builds": "^1.14.0",
29
+ "ace-builds": "^1.15.0",
30
30
  "codemirror": "^6.0.1",
31
31
  "css-tree": "^2.3.1",
32
32
  "esprima-next": "^5.8.4",
33
33
  "html2canvas": "*",
34
- "jest": "^29.3.1",
34
+ "jest": "^29.4.0",
35
35
  "jquery": "^3.6.3",
36
36
  "jquery.fancytree": "^2.38.2",
37
37
  "mdn-data": "^2.0.30",