@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.
- package/dist/elements/helper/contextMenu/ContextMenu.d.ts +2 -0
- package/dist/elements/helper/contextMenu/ContextMenu.js +7 -0
- package/dist/elements/item/DesignItem.js +2 -2
- package/dist/elements/services/propertiesService/services/CssCurrentPropertiesService.js +10 -2
- package/dist/elements/services/stylesheetService/AbstractStylesheetService.d.ts +2 -1
- package/dist/elements/services/stylesheetService/AbstractStylesheetService.js +9 -4
- package/dist/elements/services/stylesheetService/ISpecifity.d.ts +0 -0
- package/dist/elements/services/stylesheetService/ISpecifity.js +1 -0
- package/dist/elements/services/stylesheetService/IStylesheetService.d.ts +2 -1
- package/dist/elements/services/stylesheetService/SpecifityCalculator.d.ts +3 -0
- package/dist/elements/services/stylesheetService/SpecifityCalculator.js +72 -0
- package/jsr.json +5 -0
- package/package.json +1 -1
- package/assets/icons//303/247.svg +0 -1
|
@@ -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:
|
|
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:
|
|
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[]):
|
|
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
|
|
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
|
-
|
|
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
|
}
|
|
File without changes
|
|
@@ -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:
|
|
7
|
+
specificity: Specificity;
|
|
7
8
|
stylesheetName?: string;
|
|
8
9
|
}
|
|
9
10
|
export interface IStyleDeclaration {
|
|
@@ -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
package/package.json
CHANGED
|
@@ -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>
|