p-elements-core 1.2.2 → 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 +3 -3
- package/p-elements-core.d.ts +16 -10
- package/package.json +1 -1
- package/src/custom-element.ts +142 -162
- package/src/decorators/bind.ts +46 -0
- package/src/decorators/custom-element-config.ts +10 -0
- package/src/decorators/render-property-on-set.ts +46 -0
- package/src/sample.tsx +13 -8
package/p-elements-core.d.ts
CHANGED
|
@@ -166,13 +166,21 @@ declare const CustomElementConfig: (
|
|
|
166
166
|
config: IElementConfig
|
|
167
167
|
) => (Element: any) => void;
|
|
168
168
|
|
|
169
|
+
declare type ElementProjectorMode = "append" | "merge" | "replace";
|
|
170
|
+
|
|
169
171
|
declare abstract class CustomElement extends HTMLElement {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
172
|
+
private _projector;
|
|
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;
|
|
182
|
+
protected adoptStyle(root: Document | ShadowRoot, css: string): string | void;
|
|
183
|
+
protected createProjector(element: Element, render: () => VNode): Promise<Projector>;
|
|
176
184
|
protected renderNow(): void;
|
|
177
185
|
}
|
|
178
186
|
|
|
@@ -182,8 +190,6 @@ declare const Bind: (
|
|
|
182
190
|
descriptor: any
|
|
183
191
|
) => void;
|
|
184
192
|
|
|
185
|
-
declare
|
|
186
|
-
|
|
187
|
-
declare function RenderOnSet(target: object, propertyKey: string): void;
|
|
193
|
+
declare const PropertyRenderOnSet: (target: object, propertyKey: string) => void;
|
|
188
194
|
|
|
189
|
-
declare
|
|
195
|
+
declare const RenderOnSet: (target: object, propertyKey: string) => void;
|
package/package.json
CHANGED
package/src/custom-element.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import { bind } from "./decorators/bind";
|
|
2
|
+
import { customElementConfig } from "./decorators/custom-element-config";
|
|
3
|
+
import { propertyRenderOnSet } from "./decorators/render-property-on-set";
|
|
4
|
+
|
|
5
|
+
export type ElementProjectorMode = "append" | "merge" | "replace";
|
|
6
|
+
|
|
1
7
|
declare var HTMLElement: {
|
|
2
8
|
prototype: HTMLElement;
|
|
3
9
|
new (param?): HTMLElement;
|
|
@@ -10,112 +16,9 @@ export interface IElementConfig {
|
|
|
10
16
|
};
|
|
11
17
|
}
|
|
12
18
|
|
|
13
|
-
export const Bind =
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
if (typeof fn !== "function") {
|
|
17
|
-
throw new Error(
|
|
18
|
-
`@Bind decorator can only be applied to methods not: ${typeof fn}`
|
|
19
|
-
);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// In IE11 calling Object.defineProperty has a side-effect of evaluating the
|
|
23
|
-
// getter for the property which is being replaced. This causes infinite
|
|
24
|
-
// recursion and an "Out of stack space" error.
|
|
25
|
-
let definingProperty = false;
|
|
26
|
-
|
|
27
|
-
return {
|
|
28
|
-
configurable: true,
|
|
29
|
-
get() {
|
|
30
|
-
if (
|
|
31
|
-
definingProperty ||
|
|
32
|
-
this === target.prototype ||
|
|
33
|
-
this.hasOwnProperty(key) ||
|
|
34
|
-
typeof fn !== "function"
|
|
35
|
-
) {
|
|
36
|
-
return fn;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
let boundFn = fn.bind(this);
|
|
40
|
-
definingProperty = true;
|
|
41
|
-
Object.defineProperty(this, key, {
|
|
42
|
-
configurable: true,
|
|
43
|
-
get() {
|
|
44
|
-
return boundFn;
|
|
45
|
-
},
|
|
46
|
-
set(value) {
|
|
47
|
-
fn = value;
|
|
48
|
-
delete this[key];
|
|
49
|
-
},
|
|
50
|
-
});
|
|
51
|
-
definingProperty = false;
|
|
52
|
-
return boundFn;
|
|
53
|
-
},
|
|
54
|
-
set(value) {
|
|
55
|
-
fn = value;
|
|
56
|
-
},
|
|
57
|
-
};
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
export const CustomElementConfig = (config: IElementConfig) => {
|
|
61
|
-
return (Element) => {
|
|
62
|
-
setTimeout(() => {
|
|
63
|
-
customElements.define(config.tagName, Element, config.options);
|
|
64
|
-
}, 10);
|
|
65
|
-
const camelCased = config.tagName.replace(/-([a-z])/g, function (g) {
|
|
66
|
-
return g[1].toUpperCase();
|
|
67
|
-
});
|
|
68
|
-
(<any>window)[camelCased.charAt(0).toUpperCase() + camelCased.slice(1)] =
|
|
69
|
-
Element;
|
|
70
|
-
};
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
export function PropertyRenderOnSet(target, key) {
|
|
74
|
-
if (!Reflect.get(target, "_dp_" + key)) {
|
|
75
|
-
Reflect.defineProperty(target, "_dp_" + key, {
|
|
76
|
-
configurable: true,
|
|
77
|
-
enumerable: true,
|
|
78
|
-
get: function () {
|
|
79
|
-
return this["_" + key + "_value"];
|
|
80
|
-
},
|
|
81
|
-
set: function (value) {
|
|
82
|
-
this["_" + key + "_value"] = value;
|
|
83
|
-
},
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
if (!target["_dp_setters_" + key]) {
|
|
88
|
-
target["_dp_setters_" + key] = [];
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const propertyRenderOnSetFunction = (o, v) => {
|
|
92
|
-
if (o && o.renderNow) {
|
|
93
|
-
o.renderNow();
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
target["_dp_setters_" + key].push(propertyRenderOnSetFunction);
|
|
98
|
-
|
|
99
|
-
const getter = function () {
|
|
100
|
-
return this["_" + key + "_value"];
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
const setter = function (newVal) {
|
|
104
|
-
this["_dp_" + key] = newVal;
|
|
105
|
-
if (target["_dp_setters_" + key]) {
|
|
106
|
-
target["_dp_setters_" + key].forEach((fn) => {
|
|
107
|
-
fn(this, newVal);
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
Object.defineProperty(target, key, {
|
|
113
|
-
configurable: true,
|
|
114
|
-
enumerable: true,
|
|
115
|
-
get: getter,
|
|
116
|
-
set: setter,
|
|
117
|
-
});
|
|
118
|
-
}
|
|
19
|
+
export const Bind = bind;
|
|
20
|
+
export const CustomElementConfig = customElementConfig;
|
|
21
|
+
export const PropertyRenderOnSet = propertyRenderOnSet;
|
|
119
22
|
|
|
120
23
|
declare var HTMLElement: {
|
|
121
24
|
prototype: HTMLElement;
|
|
@@ -133,45 +36,88 @@ if (!isNative((document as any).registerElement)) {
|
|
|
133
36
|
// cssMap contain css string processed by ShadyCSS
|
|
134
37
|
const cssMap = new Map();
|
|
135
38
|
|
|
39
|
+
// documentAdoptedStyleSheets contain hash of css string
|
|
40
|
+
const documentAdoptedStyleSheets: number[] = [];
|
|
41
|
+
|
|
136
42
|
export abstract class CustomElement extends HTMLElement {
|
|
137
43
|
constructor(self) {
|
|
138
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() {
|
|
139
55
|
if (typeof (this as any).init === "function") {
|
|
140
56
|
(this as any).init();
|
|
141
57
|
}
|
|
142
|
-
return self;
|
|
143
58
|
}
|
|
144
59
|
|
|
145
|
-
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
|
+
}
|
|
146
68
|
|
|
147
|
-
|
|
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
|
+
}
|
|
96
|
+
|
|
97
|
+
protected templateFromString(html: string, useShadow = true): any {
|
|
148
98
|
// attach shadow dom if not already attached
|
|
149
|
-
if (!this.shadowRoot) {
|
|
99
|
+
if (useShadow && !this.shadowRoot) {
|
|
150
100
|
this.attachShadow({ mode: "open" });
|
|
151
101
|
}
|
|
152
|
-
this.shadowRoot.innerHTML = "";
|
|
153
|
-
const supportReplaceCssSync = (this.shadowRoot as any).adoptedStyleSheets && CSSStyleSheet;
|
|
102
|
+
useShadow ? (this.shadowRoot.innerHTML = "") : (this.innerHTML = "");
|
|
154
103
|
|
|
155
|
-
// find css style in template
|
|
104
|
+
// find css style in template
|
|
156
105
|
let style = "<style></style>";
|
|
157
106
|
const styleMatch = html.match(/<style[^>]*>([\s\S]*?)<\/style>/);
|
|
158
107
|
if (styleMatch) {
|
|
159
108
|
style = styleMatch[0];
|
|
160
|
-
if (
|
|
109
|
+
if (useShadow && this._supportsAdoptedStyleSheets) {
|
|
161
110
|
html = html.replace(styleMatch[0], "");
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
} else {
|
|
167
|
-
// add link to stylesheet with object uri from css processed by ShadyCSS or the css match from template
|
|
168
|
-
const blob = new Blob([ cssMap.get(this.tagName) ? cssMap.get(this.tagName) : styleMatch[1]], { type: "text/css" });
|
|
169
|
-
html = html.replace(
|
|
111
|
+
this._shadowRootAdoptMapStyle(styleMatch[1]);
|
|
112
|
+
} else if (useShadow) {
|
|
113
|
+
html = this._shadowRootReplaceStyleWithLink(
|
|
114
|
+
html,
|
|
170
115
|
styleMatch[0],
|
|
171
|
-
|
|
172
|
-
blob
|
|
173
|
-
)}" data-tmp="true">`
|
|
116
|
+
styleMatch[1]
|
|
174
117
|
);
|
|
118
|
+
} else {
|
|
119
|
+
html = html.replace(styleMatch[0], "");
|
|
120
|
+
this.adoptStyle(document, styleMatch[1]);
|
|
175
121
|
}
|
|
176
122
|
}
|
|
177
123
|
|
|
@@ -180,12 +126,11 @@ export abstract class CustomElement extends HTMLElement {
|
|
|
180
126
|
myElementTemplate.innerHTML = html;
|
|
181
127
|
let template = document.importNode(myElementTemplate.content, true);
|
|
182
128
|
|
|
183
|
-
// process css with ShadyCSS function
|
|
129
|
+
// process css with ShadyCSS function
|
|
184
130
|
const textContentForShadyStyle = () => {
|
|
185
131
|
if (cssMap.has(this.tagName)) {
|
|
186
132
|
return cssMap.get(this.tagName);
|
|
187
133
|
}
|
|
188
|
-
|
|
189
134
|
const t = document.createElement("template");
|
|
190
135
|
t.innerHTML = style;
|
|
191
136
|
const p = (window as any).ShadyCSS.prepareTemplate(t, "x-tmp");
|
|
@@ -195,7 +140,7 @@ export abstract class CustomElement extends HTMLElement {
|
|
|
195
140
|
return s;
|
|
196
141
|
};
|
|
197
142
|
|
|
198
|
-
// create object uri from css processed by ShadyCSS function
|
|
143
|
+
// create object uri from css processed by ShadyCSS function
|
|
199
144
|
const creatObjectUrlForShadyStyle = () => {
|
|
200
145
|
if (cssMap.has(this.tagName)) {
|
|
201
146
|
return cssMap.get(this.tagName);
|
|
@@ -211,56 +156,92 @@ export abstract class CustomElement extends HTMLElement {
|
|
|
211
156
|
return url;
|
|
212
157
|
};
|
|
213
158
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
if (link) {
|
|
226
|
-
if (link.hasAttribute("data-tmp")) {
|
|
227
|
-
URL.revokeObjectURL(link.href);
|
|
228
|
-
link.removeAttribute("data-tmp");
|
|
229
|
-
}
|
|
230
|
-
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);
|
|
231
170
|
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
171
|
+
}, 300);
|
|
172
|
+
});
|
|
173
|
+
setTimeout(() => {
|
|
174
|
+
this._revokeAndUpdateLinkUrl(creatObjectUrlForShadyStyle);
|
|
175
|
+
}, 100);
|
|
176
|
+
}
|
|
177
|
+
return template;
|
|
178
|
+
}
|
|
236
179
|
|
|
237
|
-
|
|
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");
|
|
186
|
+
}
|
|
187
|
+
link.href = creatObjectUrlForShadyStyle();
|
|
188
|
+
}
|
|
189
|
+
}
|
|
238
190
|
|
|
239
|
-
|
|
240
|
-
|
|
191
|
+
private _getHashCode(s: string) {
|
|
192
|
+
for (var i = 0, h = 0; i < s.length; i++)
|
|
193
|
+
h = (Math.imul(31, h) + s.charCodeAt(i)) | 0;
|
|
194
|
+
return h;
|
|
195
|
+
}
|
|
241
196
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
197
|
+
protected adoptStyle(
|
|
198
|
+
root: Document | ShadowRoot,
|
|
199
|
+
css: string
|
|
200
|
+
): string | void {
|
|
201
|
+
let hash = 0;
|
|
202
|
+
if (root instanceof Document) {
|
|
203
|
+
hash = this._getHashCode(css);
|
|
204
|
+
if (documentAdoptedStyleSheets.indexOf(hash) !== -1) {
|
|
205
|
+
return;
|
|
247
206
|
}
|
|
207
|
+
}
|
|
248
208
|
|
|
249
|
-
|
|
209
|
+
if (this._supportsAdoptedStyleSheets) {
|
|
210
|
+
const sheet = new CSSStyleSheet();
|
|
211
|
+
(sheet as any).replaceSync(css);
|
|
212
|
+
(root as any).adoptedStyleSheets = [
|
|
213
|
+
...(root as any).adoptedStyleSheets,
|
|
214
|
+
sheet,
|
|
215
|
+
];
|
|
216
|
+
} else {
|
|
217
|
+
const blob = new Blob([css], { type: "text/css" });
|
|
218
|
+
const url = URL.createObjectURL(blob);
|
|
250
219
|
|
|
251
|
-
|
|
220
|
+
const link = document.createElement("link");
|
|
221
|
+
link.setAttribute("rel", "stylesheet");
|
|
222
|
+
link.setAttribute("href", url);
|
|
223
|
+
if (root instanceof Document) {
|
|
224
|
+
root.head.appendChild(link);
|
|
225
|
+
} else {
|
|
226
|
+
root.appendChild(link);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
if (hash !== 0) {
|
|
230
|
+
documentAdoptedStyleSheets.push(hash);
|
|
231
|
+
}
|
|
252
232
|
}
|
|
253
233
|
|
|
234
|
+
|
|
254
235
|
protected createProjector(
|
|
255
236
|
element: Element,
|
|
256
237
|
render: () => VNode
|
|
257
238
|
): Promise<Projector> {
|
|
258
239
|
return new Promise<Projector>((resolve, reject) => {
|
|
259
240
|
let projector: Projector;
|
|
260
|
-
|
|
241
|
+
const mode = this._projectorMode;
|
|
261
242
|
setTimeout(() => {
|
|
262
243
|
projector = (window as any).Maquette.createProjector();
|
|
263
|
-
projector
|
|
244
|
+
projector[mode](element, render);
|
|
264
245
|
this._projector = projector;
|
|
265
246
|
resolve(projector);
|
|
266
247
|
this.dispatchEvent(new CustomEvent("firstRender", {}));
|
|
@@ -273,5 +254,4 @@ export abstract class CustomElement extends HTMLElement {
|
|
|
273
254
|
this._projector.renderNow();
|
|
274
255
|
}
|
|
275
256
|
}
|
|
276
|
-
|
|
277
257
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export const bind = (target, key, descriptor) => {
|
|
2
|
+
let fn = descriptor.value;
|
|
3
|
+
console.warn("@Bind decorator is deprecated, use arrow function expression");
|
|
4
|
+
if (typeof fn !== "function") {
|
|
5
|
+
throw new Error(
|
|
6
|
+
`@Bind decorator can only be applied to methods not: ${typeof fn}`
|
|
7
|
+
);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// In IE11 calling Object.defineProperty has a side-effect of evaluating the
|
|
11
|
+
// getter for the property which is being replaced. This causes infinite
|
|
12
|
+
// recursion and an "Out of stack space" error.
|
|
13
|
+
let definingProperty = false;
|
|
14
|
+
|
|
15
|
+
return {
|
|
16
|
+
configurable: true,
|
|
17
|
+
get() {
|
|
18
|
+
if (
|
|
19
|
+
definingProperty ||
|
|
20
|
+
this === target.prototype ||
|
|
21
|
+
this.hasOwnProperty(key) ||
|
|
22
|
+
typeof fn !== "function"
|
|
23
|
+
) {
|
|
24
|
+
return fn;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let boundFn = fn.bind(this);
|
|
28
|
+
definingProperty = true;
|
|
29
|
+
Object.defineProperty(this, key, {
|
|
30
|
+
configurable: true,
|
|
31
|
+
get() {
|
|
32
|
+
return boundFn;
|
|
33
|
+
},
|
|
34
|
+
set(value) {
|
|
35
|
+
fn = value;
|
|
36
|
+
delete this[key];
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
definingProperty = false;
|
|
40
|
+
return boundFn;
|
|
41
|
+
},
|
|
42
|
+
set(value) {
|
|
43
|
+
fn = value;
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export const customElementConfig = (config: IElementConfig) => {
|
|
2
|
+
return (Element) => {
|
|
3
|
+
customElements.define(config.tagName, Element, config.options);
|
|
4
|
+
const camelCased = config.tagName.replace(/-([a-z])/g, function (g) {
|
|
5
|
+
return g[1].toUpperCase();
|
|
6
|
+
});
|
|
7
|
+
(<any>window)[camelCased.charAt(0).toUpperCase() + camelCased.slice(1)] =
|
|
8
|
+
Element;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export const propertyRenderOnSet = (target, key) => {
|
|
2
|
+
if (!Reflect.get(target, "_dp_" + key)) {
|
|
3
|
+
Reflect.defineProperty(target, "_dp_" + key, {
|
|
4
|
+
configurable: true,
|
|
5
|
+
enumerable: true,
|
|
6
|
+
get: function () {
|
|
7
|
+
return this["_" + key + "_value"];
|
|
8
|
+
},
|
|
9
|
+
set: function (value) {
|
|
10
|
+
this["_" + key + "_value"] = value;
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (!target["_dp_setters_" + key]) {
|
|
16
|
+
target["_dp_setters_" + key] = [];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const propertyRenderOnSetFunction = (o, v) => {
|
|
20
|
+
if (o && o.renderNow) {
|
|
21
|
+
o.renderNow();
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
target["_dp_setters_" + key].push(propertyRenderOnSetFunction);
|
|
26
|
+
|
|
27
|
+
const getter = function () {
|
|
28
|
+
return this["_" + key + "_value"];
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const setter = function (newVal) {
|
|
32
|
+
this["_dp_" + key] = newVal;
|
|
33
|
+
if (target["_dp_setters_" + key]) {
|
|
34
|
+
target["_dp_setters_" + key].forEach((fn) => {
|
|
35
|
+
fn(this, newVal);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
Object.defineProperty(target, key, {
|
|
41
|
+
configurable: true,
|
|
42
|
+
enumerable: true,
|
|
43
|
+
get: getter,
|
|
44
|
+
set: setter,
|
|
45
|
+
});
|
|
46
|
+
}
|
package/src/sample.tsx
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
PropertyRenderOnSet,
|
|
3
3
|
CustomElement,
|
|
4
4
|
CustomElementConfig,
|
|
5
|
-
|
|
5
|
+
ElementProjectorMode,
|
|
6
6
|
} from "./custom-element";
|
|
7
7
|
import * as anime from "animejs";
|
|
8
8
|
|
|
@@ -199,16 +199,21 @@ class MyGreetings extends CustomElement {
|
|
|
199
199
|
tagName: "p-foo",
|
|
200
200
|
})
|
|
201
201
|
class PFoo extends CustomElement {
|
|
202
|
-
|
|
202
|
+
constructor(args) {
|
|
203
|
+
super(args);
|
|
203
204
|
const template = this.templateFromString(
|
|
204
|
-
`<style
|
|
205
|
+
`<style>.foo{color: red}</style><div></div>`, false
|
|
205
206
|
);
|
|
206
|
-
this.
|
|
207
|
-
|
|
208
|
-
this.shadowRoot.querySelector(".root").innerHTML = `
|
|
209
|
-
<div>P-FOO</div>
|
|
210
|
-
`;
|
|
207
|
+
this.appendChild(template);
|
|
208
|
+
this.createProjector(this.querySelector("div"), this.render);
|
|
211
209
|
}
|
|
210
|
+
|
|
211
|
+
static projectorMode: ElementProjectorMode = "replace";
|
|
212
|
+
|
|
213
|
+
private render = () => {
|
|
214
|
+
return <div class="foo">Foo</div>;
|
|
215
|
+
};
|
|
216
|
+
|
|
212
217
|
}
|
|
213
218
|
|
|
214
219
|
class SuperAnchorElement extends HTMLAnchorElement {
|