p-elements-core 1.2.3-rc1 → 1.2.3
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/demo/sample.js +2 -2
- package/dist/p-elements-core-modern.js +3 -3
- package/dist/p-elements-core.js +1 -1
- package/p-elements-core.d.ts +9 -3
- package/package.json +1 -1
- package/src/custom-element.ts +95 -68
- package/src/sample.tsx +5 -5
package/p-elements-core.d.ts
CHANGED
|
@@ -170,10 +170,16 @@ declare type ElementProjectorMode = "append" | "merge" | "replace";
|
|
|
170
170
|
|
|
171
171
|
declare abstract class CustomElement extends HTMLElement {
|
|
172
172
|
private _projector;
|
|
173
|
-
|
|
174
|
-
private
|
|
173
|
+
private _projectorMode;
|
|
174
|
+
private _callInitFunction;
|
|
175
|
+
private _initProjectorMode;
|
|
176
|
+
private get _supportsAdoptedStyleSheets();
|
|
177
|
+
private _shadowRootAdoptMapStyle;
|
|
178
|
+
private _shadowRootReplaceStyleWithLink;
|
|
179
|
+
protected templateFromString(html: string, useShadow?: boolean): any;
|
|
180
|
+
private _revokeAndUpdateLinkUrl;
|
|
181
|
+
private _getHashCode;
|
|
175
182
|
protected adoptStyle(root: Document | ShadowRoot, css: string): string | void;
|
|
176
|
-
projectorMode?: ElementProjectorMode;
|
|
177
183
|
protected createProjector(element: Element, render: () => VNode): Promise<Projector>;
|
|
178
184
|
protected renderNow(): void;
|
|
179
185
|
}
|
package/package.json
CHANGED
package/src/custom-element.ts
CHANGED
|
@@ -42,50 +42,82 @@ const documentAdoptedStyleSheets: number[] = [];
|
|
|
42
42
|
export abstract class CustomElement extends HTMLElement {
|
|
43
43
|
constructor(self) {
|
|
44
44
|
self = super(self);
|
|
45
|
+
this._callInitFunction();
|
|
46
|
+
this._initProjectorMode();
|
|
47
|
+
return self;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
private _projector: Projector;
|
|
51
|
+
|
|
52
|
+
private _projectorMode: ElementProjectorMode;
|
|
53
|
+
|
|
54
|
+
private _callInitFunction() {
|
|
45
55
|
if (typeof (this as any).init === "function") {
|
|
46
56
|
(this as any).init();
|
|
47
57
|
}
|
|
48
|
-
return self;
|
|
49
58
|
}
|
|
50
59
|
|
|
51
|
-
private
|
|
60
|
+
private _initProjectorMode() {
|
|
61
|
+
const staticProjectorMode = (this.constructor as any).projectorMode;
|
|
62
|
+
this._projectorMode = staticProjectorMode ? staticProjectorMode : "append";
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
private get _supportsAdoptedStyleSheets(): boolean {
|
|
66
|
+
return (document as any).adoptedStyleSheets && CSSStyleSheet ? true : false;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
private _shadowRootAdoptMapStyle(style: string) {
|
|
70
|
+
const styleSheet = new CSSStyleSheet();
|
|
71
|
+
// adopt stylesheet with css processed by ShadyCSS or the css match from template
|
|
72
|
+
(styleSheet as any).replaceSync(
|
|
73
|
+
cssMap.has(this.tagName) === true ? cssMap.get(this.tagName) : style
|
|
74
|
+
);
|
|
75
|
+
(this.shadowRoot as any).adoptedStyleSheets = [styleSheet];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
private _shadowRootReplaceStyleWithLink(
|
|
79
|
+
html: string,
|
|
80
|
+
search: string,
|
|
81
|
+
style: string
|
|
82
|
+
): string {
|
|
83
|
+
// add link to stylesheet with object uri from css processed by ShadyCSS or the css match from template
|
|
84
|
+
const blob = new Blob(
|
|
85
|
+
[cssMap.get(this.tagName) ? cssMap.get(this.tagName) : style],
|
|
86
|
+
{ type: "text/css" }
|
|
87
|
+
);
|
|
88
|
+
html = html.replace(
|
|
89
|
+
search,
|
|
90
|
+
`<link rel="stylesheet" href="${URL.createObjectURL(
|
|
91
|
+
blob
|
|
92
|
+
)}" data-tmp="true">`
|
|
93
|
+
);
|
|
94
|
+
return html;
|
|
95
|
+
}
|
|
52
96
|
|
|
53
|
-
protected templateFromString(html: string): any {
|
|
97
|
+
protected templateFromString(html: string, useShadow = true): any {
|
|
54
98
|
// attach shadow dom if not already attached
|
|
55
|
-
if (!this.shadowRoot) {
|
|
99
|
+
if (useShadow && !this.shadowRoot) {
|
|
56
100
|
this.attachShadow({ mode: "open" });
|
|
57
101
|
}
|
|
58
|
-
this.shadowRoot.innerHTML = "";
|
|
59
|
-
const supportReplaceCssSync =
|
|
60
|
-
(this.shadowRoot as any).adoptedStyleSheets && CSSStyleSheet;
|
|
102
|
+
useShadow ? (this.shadowRoot.innerHTML = "") : (this.innerHTML = "");
|
|
61
103
|
|
|
62
104
|
// find css style in template
|
|
63
105
|
let style = "<style></style>";
|
|
64
106
|
const styleMatch = html.match(/<style[^>]*>([\s\S]*?)<\/style>/);
|
|
65
107
|
if (styleMatch) {
|
|
66
108
|
style = styleMatch[0];
|
|
67
|
-
if (
|
|
109
|
+
if (useShadow && this._supportsAdoptedStyleSheets) {
|
|
68
110
|
html = html.replace(styleMatch[0], "");
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
? cssMap.get(this.tagName)
|
|
74
|
-
: styleMatch[1]
|
|
75
|
-
);
|
|
76
|
-
(this.shadowRoot as any).adoptedStyleSheets = [styleSheet];
|
|
77
|
-
} else {
|
|
78
|
-
// add link to stylesheet with object uri from css processed by ShadyCSS or the css match from template
|
|
79
|
-
const blob = new Blob(
|
|
80
|
-
[cssMap.get(this.tagName) ? cssMap.get(this.tagName) : styleMatch[1]],
|
|
81
|
-
{ type: "text/css" }
|
|
82
|
-
);
|
|
83
|
-
html = html.replace(
|
|
111
|
+
this._shadowRootAdoptMapStyle(styleMatch[1]);
|
|
112
|
+
} else if (useShadow) {
|
|
113
|
+
html = this._shadowRootReplaceStyleWithLink(
|
|
114
|
+
html,
|
|
84
115
|
styleMatch[0],
|
|
85
|
-
|
|
86
|
-
blob
|
|
87
|
-
)}" data-tmp="true">`
|
|
116
|
+
styleMatch[1]
|
|
88
117
|
);
|
|
118
|
+
} else {
|
|
119
|
+
html = html.replace(styleMatch[0], "");
|
|
120
|
+
this.adoptStyle(document, styleMatch[1]);
|
|
89
121
|
}
|
|
90
122
|
}
|
|
91
123
|
|
|
@@ -99,7 +131,6 @@ export abstract class CustomElement extends HTMLElement {
|
|
|
99
131
|
if (cssMap.has(this.tagName)) {
|
|
100
132
|
return cssMap.get(this.tagName);
|
|
101
133
|
}
|
|
102
|
-
|
|
103
134
|
const t = document.createElement("template");
|
|
104
135
|
t.innerHTML = style;
|
|
105
136
|
const p = (window as any).ShadyCSS.prepareTemplate(t, "x-tmp");
|
|
@@ -125,59 +156,57 @@ export abstract class CustomElement extends HTMLElement {
|
|
|
125
156
|
return url;
|
|
126
157
|
};
|
|
127
158
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
if (link.hasAttribute("data-tmp")) {
|
|
140
|
-
URL.revokeObjectURL(link.href);
|
|
141
|
-
link.removeAttribute("data-tmp");
|
|
142
|
-
}
|
|
143
|
-
link.href = creatObjectUrlForShadyStyle();
|
|
159
|
+
if (useShadow) {
|
|
160
|
+
window.addEventListener("customStyleConnected", () => {
|
|
161
|
+
setTimeout(() => {
|
|
162
|
+
if (styleMatch && this._supportsAdoptedStyleSheets) {
|
|
163
|
+
html = html.replace(styleMatch[0], "");
|
|
164
|
+
const styleSheet = new CSSStyleSheet();
|
|
165
|
+
const css = textContentForShadyStyle();
|
|
166
|
+
(styleSheet as any).replaceSync(css);
|
|
167
|
+
(this.shadowRoot as any).adoptedStyleSheets = [styleSheet];
|
|
168
|
+
} else {
|
|
169
|
+
this._revokeAndUpdateLinkUrl(creatObjectUrlForShadyStyle);
|
|
144
170
|
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
171
|
+
}, 300);
|
|
172
|
+
});
|
|
173
|
+
setTimeout(() => {
|
|
174
|
+
this._revokeAndUpdateLinkUrl(creatObjectUrlForShadyStyle);
|
|
175
|
+
}, 100);
|
|
176
|
+
}
|
|
177
|
+
return template;
|
|
178
|
+
}
|
|
148
179
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
}
|
|
156
|
-
link.href = creatObjectUrlForShadyStyle();
|
|
180
|
+
private _revokeAndUpdateLinkUrl(creatObjectUrlForShadyStyle: () => string) {
|
|
181
|
+
const link = this.shadowRoot.querySelector("link");
|
|
182
|
+
if (link) {
|
|
183
|
+
if (link.hasAttribute("data-tmp")) {
|
|
184
|
+
URL.revokeObjectURL(link.href);
|
|
185
|
+
link.removeAttribute("data-tmp");
|
|
157
186
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
return template;
|
|
187
|
+
link.href = creatObjectUrlForShadyStyle();
|
|
188
|
+
}
|
|
161
189
|
}
|
|
162
190
|
|
|
163
|
-
private
|
|
191
|
+
private _getHashCode(s: string) {
|
|
164
192
|
for (var i = 0, h = 0; i < s.length; i++)
|
|
165
193
|
h = (Math.imul(31, h) + s.charCodeAt(i)) | 0;
|
|
166
194
|
return h;
|
|
167
195
|
}
|
|
168
196
|
|
|
169
|
-
protected adoptStyle(
|
|
197
|
+
protected adoptStyle(
|
|
198
|
+
root: Document | ShadowRoot,
|
|
199
|
+
css: string
|
|
200
|
+
): string | void {
|
|
170
201
|
let hash = 0;
|
|
171
202
|
if (root instanceof Document) {
|
|
172
|
-
hash = this.
|
|
203
|
+
hash = this._getHashCode(css);
|
|
173
204
|
if (documentAdoptedStyleSheets.indexOf(hash) !== -1) {
|
|
174
205
|
return;
|
|
175
206
|
}
|
|
176
207
|
}
|
|
177
|
-
const hasAdoptedStyleSheetsSupport =
|
|
178
|
-
(root as any).adoptedStyleSheets && CSSStyleSheet;
|
|
179
208
|
|
|
180
|
-
if (
|
|
209
|
+
if (this._supportsAdoptedStyleSheets) {
|
|
181
210
|
const sheet = new CSSStyleSheet();
|
|
182
211
|
(sheet as any).replaceSync(css);
|
|
183
212
|
(root as any).adoptedStyleSheets = [
|
|
@@ -192,9 +221,8 @@ export abstract class CustomElement extends HTMLElement {
|
|
|
192
221
|
link.setAttribute("rel", "stylesheet");
|
|
193
222
|
link.setAttribute("href", url);
|
|
194
223
|
if (root instanceof Document) {
|
|
195
|
-
root.head.appendChild(link)
|
|
196
|
-
}
|
|
197
|
-
else {
|
|
224
|
+
root.head.appendChild(link);
|
|
225
|
+
} else {
|
|
198
226
|
root.appendChild(link);
|
|
199
227
|
}
|
|
200
228
|
}
|
|
@@ -203,7 +231,6 @@ export abstract class CustomElement extends HTMLElement {
|
|
|
203
231
|
}
|
|
204
232
|
}
|
|
205
233
|
|
|
206
|
-
projectorMode?: ElementProjectorMode;
|
|
207
234
|
|
|
208
235
|
protected createProjector(
|
|
209
236
|
element: Element,
|
|
@@ -211,7 +238,7 @@ export abstract class CustomElement extends HTMLElement {
|
|
|
211
238
|
): Promise<Projector> {
|
|
212
239
|
return new Promise<Projector>((resolve, reject) => {
|
|
213
240
|
let projector: Projector;
|
|
214
|
-
const mode = this.
|
|
241
|
+
const mode = this._projectorMode;
|
|
215
242
|
setTimeout(() => {
|
|
216
243
|
projector = (window as any).Maquette.createProjector();
|
|
217
244
|
projector[mode](element, render);
|
package/src/sample.tsx
CHANGED
|
@@ -202,16 +202,16 @@ class PFoo extends CustomElement {
|
|
|
202
202
|
constructor(args) {
|
|
203
203
|
super(args);
|
|
204
204
|
const template = this.templateFromString(
|
|
205
|
-
`<style
|
|
205
|
+
`<style>.foo{color: red}</style><div></div>`, false
|
|
206
206
|
);
|
|
207
|
-
this.
|
|
208
|
-
this.createProjector(this.
|
|
207
|
+
this.appendChild(template);
|
|
208
|
+
this.createProjector(this.querySelector("div"), this.render);
|
|
209
209
|
}
|
|
210
210
|
|
|
211
|
-
projectorMode: ElementProjectorMode = "replace";
|
|
211
|
+
static projectorMode: ElementProjectorMode = "replace";
|
|
212
212
|
|
|
213
213
|
private render = () => {
|
|
214
|
-
return <div>Foo</div>;
|
|
214
|
+
return <div class="foo">Foo</div>;
|
|
215
215
|
};
|
|
216
216
|
|
|
217
217
|
}
|