p-elements-core 1.2.32-rc6 → 1.2.32-rc8
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/.editorconfig +17 -17
- package/.gitlab-ci.yml +18 -18
- package/CHANGELOG.md +201 -201
- package/demo/sample.js +1 -1
- package/demo/screen.css +16 -16
- package/dist/p-elements-core-modern.js +1 -1
- package/dist/p-elements-core.js +1 -1
- package/docs/package-lock.json +6897 -6897
- package/docs/package.json +27 -27
- package/docs/src/404.md +8 -8
- package/docs/src/_data/demos/hello-world/hello-world.tsx +35 -35
- package/docs/src/_data/demos/hello-world/index.html +10 -10
- package/docs/src/_data/demos/hello-world/project.json +7 -7
- package/docs/src/_data/demos/timer/demo-timer.tsx +120 -120
- package/docs/src/_data/demos/timer/icons.tsx +62 -62
- package/docs/src/_data/demos/timer/index.html +12 -12
- package/docs/src/_data/demos/timer/project.json +8 -8
- package/docs/src/_data/global.js +13 -13
- package/docs/src/_data/helpers.js +19 -19
- package/docs/src/_includes/layouts/base.njk +30 -30
- package/docs/src/_includes/layouts/playground.njk +40 -40
- package/docs/src/_includes/partials/app-header.njk +8 -8
- package/docs/src/_includes/partials/head.njk +14 -14
- package/docs/src/_includes/partials/nav.njk +19 -19
- package/docs/src/_includes/partials/top-nav.njk +51 -51
- package/docs/src/documentation/custom-element.md +221 -221
- package/docs/src/documentation/decorators/bind.md +71 -71
- package/docs/src/documentation/decorators/custom-element-config.md +63 -63
- package/docs/src/documentation/decorators/property.md +83 -83
- package/docs/src/documentation/decorators/query.md +66 -66
- package/docs/src/documentation/decorators/render-property-on-set.md +60 -60
- package/docs/src/documentation/decorators.md +9 -9
- package/docs/src/documentation/reactive-properties.md +53 -53
- package/docs/src/index.d.ts +25 -25
- package/docs/src/index.md +3 -3
- package/docs/src/scripts/components/app-mode-switch/app-mode-switch.css +78 -78
- package/docs/src/scripts/components/app-mode-switch/app-mode-switch.tsx +166 -166
- package/docs/src/scripts/components/app-playground/app-playground.tsx +189 -189
- package/docs/tsconfig.json +22 -22
- package/package.json +2 -2
- package/readme.md +206 -206
- package/src/custom-element-controller.ts +31 -31
- package/src/custom-element.test.ts +906 -906
- package/src/custom-element.ts +27 -15
- package/src/decorators/bind.test.ts +163 -163
- package/src/decorators/bind.ts +46 -46
- package/src/decorators/custom-element-config.ts +17 -17
- package/src/decorators/property.test.ts +279 -279
- package/src/decorators/property.ts +0 -1
- package/src/decorators/query.test.ts +146 -146
- package/src/decorators/query.ts +12 -12
- package/src/decorators/render-property-on-set.ts +3 -3
- package/src/helpers/css.ts +71 -71
- package/src/maquette/cache.ts +35 -35
- package/src/maquette/dom.ts +115 -115
- package/src/maquette/h.ts +100 -100
- package/src/maquette/index.ts +12 -12
- package/src/maquette/interfaces.ts +536 -536
- package/src/maquette/jsx.ts +61 -61
- package/src/maquette/mapping.ts +56 -56
- package/src/maquette/projection.ts +666 -666
- package/src/maquette/projector.ts +205 -200
- package/src/sample/mixin/highlight.tsx +33 -33
package/src/custom-element.ts
CHANGED
|
@@ -131,7 +131,7 @@ export abstract class CustomElement extends HTMLElement {
|
|
|
131
131
|
*
|
|
132
132
|
* @returns {readonly PropertyOptionsWithName[]} Array of property metadata
|
|
133
133
|
*/
|
|
134
|
-
get properties()
|
|
134
|
+
get properties(): readonly PropertyOptionsWithName[] {
|
|
135
135
|
const ctor = this.constructor as ComponentConstructor;
|
|
136
136
|
if (!ctor._propertyInfo) {
|
|
137
137
|
return [];
|
|
@@ -374,11 +374,10 @@ export abstract class CustomElement extends HTMLElement {
|
|
|
374
374
|
this.#initStylesheet(styleElement.textContent);
|
|
375
375
|
styleElement.remove();
|
|
376
376
|
}
|
|
377
|
-
|
|
377
|
+
window.addEventListener("updatecssapply", () => {
|
|
378
378
|
this.#polyfillCssApply();
|
|
379
379
|
});
|
|
380
380
|
|
|
381
|
-
|
|
382
381
|
return fragment;
|
|
383
382
|
}
|
|
384
383
|
|
|
@@ -389,10 +388,17 @@ export abstract class CustomElement extends HTMLElement {
|
|
|
389
388
|
this.addStylesheetToRootNode(css, root);
|
|
390
389
|
}
|
|
391
390
|
|
|
392
|
-
protected createProjector(
|
|
391
|
+
protected async createProjector(
|
|
393
392
|
element: Element,
|
|
394
393
|
render: () => VNode,
|
|
395
394
|
): Promise<Projector> {
|
|
395
|
+
await new Promise((resolve) =>
|
|
396
|
+
requestAnimationFrame(() => requestAnimationFrame(resolve)),
|
|
397
|
+
);
|
|
398
|
+
return await this.#createProjector(element, render);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
#createProjector(element: Element, render: () => VNode): Promise<Projector> {
|
|
396
402
|
return new Promise<Projector>((resolve, reject) => {
|
|
397
403
|
let projector: Projector;
|
|
398
404
|
const mode = this.#projectorMode ? this.#projectorMode : "append";
|
|
@@ -402,7 +408,7 @@ export abstract class CustomElement extends HTMLElement {
|
|
|
402
408
|
if (eventName === "renderStart" || eventName === "renderDone") {
|
|
403
409
|
this.#invokeRenderLifecycleFn(eventName);
|
|
404
410
|
}
|
|
405
|
-
}
|
|
411
|
+
},
|
|
406
412
|
});
|
|
407
413
|
projector[mode](element, render.bind(this));
|
|
408
414
|
this.#projector = projector;
|
|
@@ -425,13 +431,21 @@ export abstract class CustomElement extends HTMLElement {
|
|
|
425
431
|
}
|
|
426
432
|
|
|
427
433
|
#invokeRenderLifecycleFn(eventName: string) {
|
|
428
|
-
if (this[eventName]){
|
|
429
|
-
this[eventName](
|
|
434
|
+
if (this[eventName]) {
|
|
435
|
+
this[eventName](
|
|
436
|
+
eventName === "renderStart"
|
|
437
|
+
? this.#isFirstRenderStart
|
|
438
|
+
: this.#isFirstRenderDone,
|
|
439
|
+
);
|
|
430
440
|
}
|
|
431
441
|
const controllerEventName = `host${eventName.charAt(0).toUpperCase()}${eventName.slice(1)}`;
|
|
432
442
|
this.#controllers.forEach((controller) => {
|
|
433
443
|
if (controller[controllerEventName]) {
|
|
434
|
-
controller[controllerEventName](
|
|
444
|
+
controller[controllerEventName](
|
|
445
|
+
eventName === "renderStart"
|
|
446
|
+
? this.#isFirstRenderStart
|
|
447
|
+
: this.#isFirstRenderDone,
|
|
448
|
+
);
|
|
435
449
|
}
|
|
436
450
|
});
|
|
437
451
|
if (eventName === "renderStart") {
|
|
@@ -488,18 +502,17 @@ export abstract class CustomElement extends HTMLElement {
|
|
|
488
502
|
const div = document.createElement("div");
|
|
489
503
|
this.shadowRoot.appendChild(div);
|
|
490
504
|
requestAnimationFrame(() => {
|
|
491
|
-
this
|
|
505
|
+
this.#createProjector(div, (this as any).render).then(() => {
|
|
492
506
|
this.#upgradeProperties();
|
|
493
|
-
})
|
|
507
|
+
});
|
|
494
508
|
});
|
|
495
|
-
|
|
509
|
+
window.addEventListener("updatecssapply", () => {
|
|
496
510
|
this.#polyfillCssApply();
|
|
497
511
|
});
|
|
498
|
-
|
|
499
512
|
}
|
|
500
513
|
}
|
|
501
514
|
|
|
502
|
-
#polyfillCssApply(): string {
|
|
515
|
+
#polyfillCssApply(): string {
|
|
503
516
|
let style = replaceApplyToCssVars(this.#cssText);
|
|
504
517
|
if (this.#cssText !== style) {
|
|
505
518
|
this.#cssText = style;
|
|
@@ -510,14 +523,13 @@ export abstract class CustomElement extends HTMLElement {
|
|
|
510
523
|
URL.revokeObjectURL(this.#linkElement.href);
|
|
511
524
|
}
|
|
512
525
|
this.#linkElement.href = URL.createObjectURL(
|
|
513
|
-
new Blob([style], { type: "text/css" })
|
|
526
|
+
new Blob([style], { type: "text/css" }),
|
|
514
527
|
);
|
|
515
528
|
}
|
|
516
529
|
}
|
|
517
530
|
return style;
|
|
518
531
|
}
|
|
519
532
|
|
|
520
|
-
|
|
521
533
|
#initStylesheet(style: string) {
|
|
522
534
|
this.#cssText = style;
|
|
523
535
|
if (this.#useShadowRoot && this.shadowRoot) {
|
|
@@ -1,163 +1,163 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for @bind decorator
|
|
3
|
-
* Covers method binding to preserve 'this' context
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { describe, it, expect } from 'vitest';
|
|
7
|
-
import '../test-setup.js';
|
|
8
|
-
import { bind } from './bind.js';
|
|
9
|
-
import { CustomElement } from '../custom-element.js';
|
|
10
|
-
import { customElementConfig } from './custom-element-config.js';
|
|
11
|
-
import { generateUniqueTagName } from '../test-setup.js';
|
|
12
|
-
import { waitForRender } from '../test-utils.js';
|
|
13
|
-
|
|
14
|
-
describe('@bind decorator', () => {
|
|
15
|
-
it('should bind method to instance', async () => {
|
|
16
|
-
const tagName = generateUniqueTagName('bind-test');
|
|
17
|
-
|
|
18
|
-
@customElementConfig({ tagName })
|
|
19
|
-
class BindTest extends CustomElement {
|
|
20
|
-
static style = ':host { display: block; }';
|
|
21
|
-
value = 'bound';
|
|
22
|
-
|
|
23
|
-
@bind
|
|
24
|
-
getValue() {
|
|
25
|
-
return this.value;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
render() {
|
|
29
|
-
return { vnodeSelector: 'div', properties: {}, children: [], text: undefined, domNode: null };
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const el = document.createElement(tagName) as BindTest;
|
|
34
|
-
document.body.appendChild(el);
|
|
35
|
-
await waitForRender(el);
|
|
36
|
-
|
|
37
|
-
const method = el.getValue;
|
|
38
|
-
expect(method()).toBe('bound');
|
|
39
|
-
|
|
40
|
-
document.body.removeChild(el);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('should preserve this context when method is extracted', async () => {
|
|
44
|
-
const tagName = generateUniqueTagName('bind-test');
|
|
45
|
-
|
|
46
|
-
@customElementConfig({ tagName })
|
|
47
|
-
class BindTest extends CustomElement {
|
|
48
|
-
static style = ':host { display: block; }';
|
|
49
|
-
name = 'test-element';
|
|
50
|
-
|
|
51
|
-
@bind
|
|
52
|
-
getName() {
|
|
53
|
-
return this.name;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
render() {
|
|
57
|
-
return { vnodeSelector: 'div', properties: {}, children: [], text: undefined, domNode: null };
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const el = document.createElement(tagName) as BindTest;
|
|
62
|
-
document.body.appendChild(el);
|
|
63
|
-
await waitForRender(el);
|
|
64
|
-
|
|
65
|
-
const { getName } = el;
|
|
66
|
-
expect(getName()).toBe('test-element');
|
|
67
|
-
|
|
68
|
-
document.body.removeChild(el);
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it('should work with callbacks', async () => {
|
|
72
|
-
const tagName = generateUniqueTagName('bind-test');
|
|
73
|
-
let result: string;
|
|
74
|
-
|
|
75
|
-
@customElementConfig({ tagName })
|
|
76
|
-
class BindTest extends CustomElement {
|
|
77
|
-
static style = ':host { display: block; }';
|
|
78
|
-
message = 'callback test';
|
|
79
|
-
|
|
80
|
-
@bind
|
|
81
|
-
handleCallback() {
|
|
82
|
-
return this.message;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
render() {
|
|
86
|
-
return { vnodeSelector: 'div', properties: {}, children: [], text: undefined, domNode: null };
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const el = document.createElement(tagName) as BindTest;
|
|
91
|
-
document.body.appendChild(el);
|
|
92
|
-
await waitForRender(el);
|
|
93
|
-
|
|
94
|
-
const callback = el.handleCallback;
|
|
95
|
-
result = callback();
|
|
96
|
-
|
|
97
|
-
expect(result).toBe('callback test');
|
|
98
|
-
|
|
99
|
-
document.body.removeChild(el);
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
it('should handle methods with arguments', async () => {
|
|
103
|
-
const tagName = generateUniqueTagName('bind-test');
|
|
104
|
-
|
|
105
|
-
@customElementConfig({ tagName })
|
|
106
|
-
class BindTest extends CustomElement {
|
|
107
|
-
static style = ':host { display: block; }';
|
|
108
|
-
|
|
109
|
-
prefixValue = 'Hello';
|
|
110
|
-
|
|
111
|
-
@bind
|
|
112
|
-
greet(name: string) {
|
|
113
|
-
return `${this.prefixValue}, ${name}!`;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
render() {
|
|
117
|
-
return { vnodeSelector: 'div', properties: {}, children: [], text: undefined, domNode: null };
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
const el = document.createElement(tagName) as BindTest;
|
|
122
|
-
document.body.appendChild(el);
|
|
123
|
-
await waitForRender(el);
|
|
124
|
-
|
|
125
|
-
const extracted = el.greet;
|
|
126
|
-
expect(extracted('World')).toBe('Hello, World!');
|
|
127
|
-
|
|
128
|
-
document.body.removeChild(el);
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
it('should preserve bound method reference', async () => {
|
|
132
|
-
const tagName = generateUniqueTagName('bind-test');
|
|
133
|
-
|
|
134
|
-
@customElementConfig({ tagName })
|
|
135
|
-
class BindTest extends CustomElement {
|
|
136
|
-
static style = ':host { display: block; }';
|
|
137
|
-
|
|
138
|
-
valueNum = 42;
|
|
139
|
-
|
|
140
|
-
@bind
|
|
141
|
-
getValue() {
|
|
142
|
-
return this.valueNum;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
render() {
|
|
146
|
-
return { vnodeSelector: 'div', properties: {}, children: [], text: undefined, domNode: null };
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
const el = document.createElement(tagName) as BindTest;
|
|
151
|
-
document.body.appendChild(el);
|
|
152
|
-
await waitForRender(el);
|
|
153
|
-
|
|
154
|
-
const bound1 = el.getValue;
|
|
155
|
-
const bound2 = el.getValue;
|
|
156
|
-
|
|
157
|
-
// Should return the same bound function
|
|
158
|
-
expect(bound1).toBe(bound2);
|
|
159
|
-
expect(bound1()).toBe(42);
|
|
160
|
-
|
|
161
|
-
document.body.removeChild(el);
|
|
162
|
-
});
|
|
163
|
-
});
|
|
1
|
+
/**
|
|
2
|
+
* Tests for @bind decorator
|
|
3
|
+
* Covers method binding to preserve 'this' context
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { describe, it, expect } from 'vitest';
|
|
7
|
+
import '../test-setup.js';
|
|
8
|
+
import { bind } from './bind.js';
|
|
9
|
+
import { CustomElement } from '../custom-element.js';
|
|
10
|
+
import { customElementConfig } from './custom-element-config.js';
|
|
11
|
+
import { generateUniqueTagName } from '../test-setup.js';
|
|
12
|
+
import { waitForRender } from '../test-utils.js';
|
|
13
|
+
|
|
14
|
+
describe('@bind decorator', () => {
|
|
15
|
+
it('should bind method to instance', async () => {
|
|
16
|
+
const tagName = generateUniqueTagName('bind-test');
|
|
17
|
+
|
|
18
|
+
@customElementConfig({ tagName })
|
|
19
|
+
class BindTest extends CustomElement {
|
|
20
|
+
static style = ':host { display: block; }';
|
|
21
|
+
value = 'bound';
|
|
22
|
+
|
|
23
|
+
@bind
|
|
24
|
+
getValue() {
|
|
25
|
+
return this.value;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
render() {
|
|
29
|
+
return { vnodeSelector: 'div', properties: {}, children: [], text: undefined, domNode: null };
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const el = document.createElement(tagName) as BindTest;
|
|
34
|
+
document.body.appendChild(el);
|
|
35
|
+
await waitForRender(el);
|
|
36
|
+
|
|
37
|
+
const method = el.getValue;
|
|
38
|
+
expect(method()).toBe('bound');
|
|
39
|
+
|
|
40
|
+
document.body.removeChild(el);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should preserve this context when method is extracted', async () => {
|
|
44
|
+
const tagName = generateUniqueTagName('bind-test');
|
|
45
|
+
|
|
46
|
+
@customElementConfig({ tagName })
|
|
47
|
+
class BindTest extends CustomElement {
|
|
48
|
+
static style = ':host { display: block; }';
|
|
49
|
+
name = 'test-element';
|
|
50
|
+
|
|
51
|
+
@bind
|
|
52
|
+
getName() {
|
|
53
|
+
return this.name;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
render() {
|
|
57
|
+
return { vnodeSelector: 'div', properties: {}, children: [], text: undefined, domNode: null };
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const el = document.createElement(tagName) as BindTest;
|
|
62
|
+
document.body.appendChild(el);
|
|
63
|
+
await waitForRender(el);
|
|
64
|
+
|
|
65
|
+
const { getName } = el;
|
|
66
|
+
expect(getName()).toBe('test-element');
|
|
67
|
+
|
|
68
|
+
document.body.removeChild(el);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('should work with callbacks', async () => {
|
|
72
|
+
const tagName = generateUniqueTagName('bind-test');
|
|
73
|
+
let result: string;
|
|
74
|
+
|
|
75
|
+
@customElementConfig({ tagName })
|
|
76
|
+
class BindTest extends CustomElement {
|
|
77
|
+
static style = ':host { display: block; }';
|
|
78
|
+
message = 'callback test';
|
|
79
|
+
|
|
80
|
+
@bind
|
|
81
|
+
handleCallback() {
|
|
82
|
+
return this.message;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
render() {
|
|
86
|
+
return { vnodeSelector: 'div', properties: {}, children: [], text: undefined, domNode: null };
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const el = document.createElement(tagName) as BindTest;
|
|
91
|
+
document.body.appendChild(el);
|
|
92
|
+
await waitForRender(el);
|
|
93
|
+
|
|
94
|
+
const callback = el.handleCallback;
|
|
95
|
+
result = callback();
|
|
96
|
+
|
|
97
|
+
expect(result).toBe('callback test');
|
|
98
|
+
|
|
99
|
+
document.body.removeChild(el);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('should handle methods with arguments', async () => {
|
|
103
|
+
const tagName = generateUniqueTagName('bind-test');
|
|
104
|
+
|
|
105
|
+
@customElementConfig({ tagName })
|
|
106
|
+
class BindTest extends CustomElement {
|
|
107
|
+
static style = ':host { display: block; }';
|
|
108
|
+
|
|
109
|
+
prefixValue = 'Hello';
|
|
110
|
+
|
|
111
|
+
@bind
|
|
112
|
+
greet(name: string) {
|
|
113
|
+
return `${this.prefixValue}, ${name}!`;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
render() {
|
|
117
|
+
return { vnodeSelector: 'div', properties: {}, children: [], text: undefined, domNode: null };
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const el = document.createElement(tagName) as BindTest;
|
|
122
|
+
document.body.appendChild(el);
|
|
123
|
+
await waitForRender(el);
|
|
124
|
+
|
|
125
|
+
const extracted = el.greet;
|
|
126
|
+
expect(extracted('World')).toBe('Hello, World!');
|
|
127
|
+
|
|
128
|
+
document.body.removeChild(el);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('should preserve bound method reference', async () => {
|
|
132
|
+
const tagName = generateUniqueTagName('bind-test');
|
|
133
|
+
|
|
134
|
+
@customElementConfig({ tagName })
|
|
135
|
+
class BindTest extends CustomElement {
|
|
136
|
+
static style = ':host { display: block; }';
|
|
137
|
+
|
|
138
|
+
valueNum = 42;
|
|
139
|
+
|
|
140
|
+
@bind
|
|
141
|
+
getValue() {
|
|
142
|
+
return this.valueNum;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
render() {
|
|
146
|
+
return { vnodeSelector: 'div', properties: {}, children: [], text: undefined, domNode: null };
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const el = document.createElement(tagName) as BindTest;
|
|
151
|
+
document.body.appendChild(el);
|
|
152
|
+
await waitForRender(el);
|
|
153
|
+
|
|
154
|
+
const bound1 = el.getValue;
|
|
155
|
+
const bound2 = el.getValue;
|
|
156
|
+
|
|
157
|
+
// Should return the same bound function
|
|
158
|
+
expect(bound1).toBe(bound2);
|
|
159
|
+
expect(bound1()).toBe(42);
|
|
160
|
+
|
|
161
|
+
document.body.removeChild(el);
|
|
162
|
+
});
|
|
163
|
+
});
|
package/src/decorators/bind.ts
CHANGED
|
@@ -1,46 +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
|
-
};
|
|
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
|
+
};
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
export interface IElementConfig {
|
|
2
|
-
tagName: string;
|
|
3
|
-
options?: {
|
|
4
|
-
extends: string;
|
|
5
|
-
};
|
|
6
|
-
}
|
|
7
|
-
export const customElementConfig = (config: IElementConfig) => {
|
|
8
|
-
return (Element) => {
|
|
9
|
-
if (customElements.get(config.tagName)) {
|
|
10
|
-
console.warn(
|
|
11
|
-
`Custom element with tag name ${config.tagName} already exists.`
|
|
12
|
-
);
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
|
-
customElements.define(config.tagName, Element, config.options);
|
|
16
|
-
};
|
|
17
|
-
};
|
|
1
|
+
export interface IElementConfig {
|
|
2
|
+
tagName: string;
|
|
3
|
+
options?: {
|
|
4
|
+
extends: string;
|
|
5
|
+
};
|
|
6
|
+
}
|
|
7
|
+
export const customElementConfig = (config: IElementConfig) => {
|
|
8
|
+
return (Element) => {
|
|
9
|
+
if (customElements.get(config.tagName)) {
|
|
10
|
+
console.warn(
|
|
11
|
+
`Custom element with tag name ${config.tagName} already exists.`
|
|
12
|
+
);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
customElements.define(config.tagName, Element, config.options);
|
|
16
|
+
};
|
|
17
|
+
};
|