@node-projects/web-component-designer 0.1.180 → 0.1.182

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.
@@ -9,6 +9,7 @@ export interface IContextMenuOptions {
9
9
  export declare class ContextMenu implements IContextMenu {
10
10
  private static _contextMenuCss;
11
11
  static count: number;
12
+ private static _openedContextMenus;
12
13
  menu: IContextMenuItem[];
13
14
  options: IContextMenuOptions;
14
15
  context: any;
@@ -23,4 +24,5 @@ export declare class ContextMenu implements IContextMenu {
23
24
  _windowKeyUp(e: KeyboardEvent): void;
24
25
  static show(menu: IContextMenuItem[], event: MouseEvent, options?: IContextMenuOptions, context?: any): ContextMenu;
25
26
  close(): void;
27
+ static closeAll(): void;
26
28
  }
@@ -121,6 +121,7 @@ export class ContextMenu {
121
121
  background-color: #5ebdec;
122
122
  }`;
123
123
  static count = 0;
124
+ static _openedContextMenus = new Set();
124
125
  menu;
125
126
  options;
126
127
  context;
@@ -292,6 +293,7 @@ export class ContextMenu {
292
293
  window.addEventListener("mousedown", this._windowDown);
293
294
  window.addEventListener("resize", this._windowResize);
294
295
  setTimeout(() => window.addEventListener("contextmenu", this._windowDown), 100);
296
+ ContextMenu._openedContextMenus.add(this);
295
297
  }
296
298
  _windowResize() {
297
299
  this.close();
@@ -319,6 +321,11 @@ export class ContextMenu {
319
321
  window.removeEventListener("mousedown", this._windowDown);
320
322
  window.removeEventListener("resize", this._windowResize);
321
323
  setTimeout(() => window.removeEventListener("contextmenu", this._windowDown), 10);
324
+ ContextMenu._openedContextMenus.delete(this);
325
+ }
326
+ static closeAll() {
327
+ for (const c of ContextMenu._openedContextMenus.values())
328
+ c.close();
322
329
  }
323
330
  }
324
331
  class ContextUtil {
@@ -605,14 +605,14 @@ export class DesignItem {
605
605
  try {
606
606
  const rules = this.instanceServiceContainer.stylesheetService?.getAppliedRules(this);
607
607
  if (rules) {
608
- return [{ selector: null, declarations: localStyles, specificity: -1 }, ...rules];
608
+ return [{ selector: null, declarations: localStyles, specificity: null }, ...rules];
609
609
  }
610
610
  }
611
611
  catch (err) {
612
612
  console.warn('getAppliedRules', err);
613
613
  }
614
614
  }
615
- styles = [{ selector: null, declarations: localStyles, specificity: -1 }];
615
+ styles = [{ selector: null, declarations: localStyles, specificity: null }];
616
616
  this._stylesCache = styles;
617
617
  clearTimeout(this._cacheClearTimer);
618
618
  this._cacheClearTimer = setTimeout(() => this._stylesCache = null, 30);
@@ -23,9 +23,17 @@ export class CssCurrentPropertiesService extends AbstractCssPropertiesService {
23
23
  async getProperties(designItem) {
24
24
  if (!designItem || designItem.nodeType != NodeType.Element)
25
25
  return [];
26
- let styles = designItem.getAllStyles();
26
+ let styles = designItem.getAllStyles().toReversed().sort((a, b) => {
27
+ if (a.specificity == null)
28
+ return -1;
29
+ if (b.specificity == null)
30
+ return 1;
31
+ if (a.specificity.A > b.specificity.A || a.specificity.B > b.specificity.B || a.specificity.C > b.specificity.C)
32
+ return -1;
33
+ return 0;
34
+ });
27
35
  let arr = styles.map(x => ({
28
- name: x.selector ?? localName, description: x.stylesheetName ?? '', properties: [
36
+ name: (x.selector ?? localName) + (x.specificity ? ' (' + x.specificity.A + '-' + x.specificity.B + '-' + x.specificity.C + ')' : ''), description: x.stylesheetName ?? '', properties: [
29
37
  ...x.declarations.map(y => ({
30
38
  name: y.name,
31
39
  renamable: true,
@@ -3,6 +3,7 @@ import { IDesignItem } from '../../item/IDesignItem.js';
3
3
  import { IDocumentStylesheet, IStyleDeclaration, IStyleRule, IStylesheet, IStylesheetService } from './IStylesheetService.js';
4
4
  import { InstanceServiceContainer } from "../InstanceServiceContainer.js";
5
5
  import { IDesignerCanvas } from "../../widgets/designerView/IDesignerCanvas.js";
6
+ import { Specificity } from "./SpecifityCalculator.js";
6
7
  export declare abstract class AbstractStylesheetService implements IStylesheetService {
7
8
  protected _stylesheets: Map<string, {
8
9
  stylesheet: IStylesheet;
@@ -45,5 +46,5 @@ export declare abstract class AbstractStylesheetService implements IStylesheetSe
45
46
  }>;
46
47
  stylesheetsChanged: TypedEvent<void>;
47
48
  static patchStylesheetSelectorForDesigner(text: string): string;
48
- protected elementMatchesASelector(designItem: IDesignItem, selectors: string[]): boolean;
49
+ protected elementMatchesASelector(designItem: IDesignItem, selectors: string[]): false | Specificity;
49
50
  }
@@ -1,5 +1,6 @@
1
1
  import { TypedEvent } from "@node-projects/base-custom-webcomponent";
2
2
  import { forceActiveAttributeName, forceFocusAttributeName, forceFocusVisibleAttributeName, forceFocusWithinAttributeName, forceHoverAttributeName, forceVisitedAttributeName } from "../../item/DesignItem.js";
3
+ import { calculateSpecifity } from "./SpecifityCalculator.js";
3
4
  export class AbstractStylesheetService {
4
5
  _stylesheets = new Map();
5
6
  _documentStylesheets = new Map();
@@ -110,17 +111,21 @@ export class AbstractStylesheetService {
110
111
  }
111
112
  elementMatchesASelector(designItem, selectors) {
112
113
  if (designItem == null)
113
- return true;
114
+ return false;
115
+ let s = null;
114
116
  for (let selector of selectors) {
115
117
  const patched = AbstractStylesheetService.patchStylesheetSelectorForDesigner(selector);
116
118
  try {
117
- if (designItem.element.matches(patched))
118
- return true;
119
+ if (designItem.element.matches(patched)) {
120
+ let spec = calculateSpecifity(selector);
121
+ if (s === null || spec.A > s.A || spec.B > s.B || spec.C > s.C)
122
+ s = spec;
123
+ }
119
124
  }
120
125
  catch (err) {
121
126
  console.warn("invalid selector: ", selector, "patched: " + patched);
122
127
  }
123
128
  }
124
- return false;
129
+ return s === null ? false : s;
125
130
  }
126
131
  }
@@ -0,0 +1 @@
1
+ "use strict";
@@ -1,9 +1,10 @@
1
1
  import { TypedEvent } from "@node-projects/base-custom-webcomponent";
2
2
  import { IDesignItem } from "../../item/IDesignItem.js";
3
+ import { Specificity } from "./SpecifityCalculator.js";
3
4
  export interface IStyleRule {
4
5
  selector: string;
5
6
  declarations: IStyleDeclaration[];
6
- specificity: number;
7
+ specificity: Specificity;
7
8
  stylesheetName?: string;
8
9
  }
9
10
  export interface IStyleDeclaration {
@@ -0,0 +1,3 @@
1
+ export type Level = "A" | "B" | "C";
2
+ export type Specificity = Record<Level, number>;
3
+ export declare function calculateSpecifity(selector: string): Specificity;
@@ -0,0 +1,72 @@
1
+ var ParseState;
2
+ (function (ParseState) {
3
+ ParseState[ParseState["none"] = 0] = "none";
4
+ ParseState[ParseState["parseName"] = 1] = "parseName";
5
+ ParseState[ParseState["parseAttribute"] = 2] = "parseAttribute";
6
+ ParseState[ParseState["parseInFunc"] = 3] = "parseInFunc";
7
+ })(ParseState || (ParseState = {}));
8
+ //todo special cases:
9
+ //:not :is :has = inner selector specifity
10
+ //:where = 0 specifity
11
+ //:nth-child :nth-last-child = inner sel. ?
12
+ export function calculateSpecifity(selector) {
13
+ let s = { A: 0, B: 0, C: 0 };
14
+ let parseState = ParseState.none;
15
+ for (let n = 0; n < selector.length; n++) {
16
+ let c = selector[n];
17
+ if (parseState === ParseState.parseInFunc) {
18
+ if (c == ')') {
19
+ parseState = ParseState.none;
20
+ }
21
+ }
22
+ else if (parseState === ParseState.parseAttribute) {
23
+ if (c == ']') {
24
+ parseState = ParseState.none;
25
+ }
26
+ }
27
+ else {
28
+ switch (c) {
29
+ case '#':
30
+ s.A++;
31
+ parseState = ParseState.parseName;
32
+ break;
33
+ case '.':
34
+ s.B++;
35
+ parseState = ParseState.parseName;
36
+ break;
37
+ case '[':
38
+ s.B++;
39
+ parseState = ParseState.parseAttribute;
40
+ break;
41
+ case '(':
42
+ parseState = ParseState.parseInFunc;
43
+ break;
44
+ case ':':
45
+ if (selector[n + 1] !== ':') {
46
+ s.B++;
47
+ parseState = ParseState.parseName;
48
+ }
49
+ else {
50
+ s.C++;
51
+ parseState = ParseState.parseName;
52
+ n++;
53
+ }
54
+ break;
55
+ case '>':
56
+ case ' ':
57
+ case '~':
58
+ case '+':
59
+ parseState = ParseState.none;
60
+ break;
61
+ case '*':
62
+ break;
63
+ default:
64
+ if (parseState === ParseState.none) {
65
+ s.C++;
66
+ parseState = ParseState.parseName;
67
+ }
68
+ }
69
+ }
70
+ }
71
+ return s;
72
+ }
package/jsr.json ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "name": "@node-projects/web-component-designer",
3
+ "version": "0.1.180",
4
+ "exports": "./src/index.ts"
5
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "description": "A WYSIWYG designer webcomponent for html components",
3
3
  "name": "@node-projects/web-component-designer",
4
- "version": "0.1.180",
4
+ "version": "0.1.182",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "author": "jochen.kuehner@gmx.de",
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M280-80v-640h120v640H280Zm280-240v-400h120v400H560ZM80-800v-80h800v80H80Z"/></svg>