p-elements-core 1.2.32-rc5 → 1.2.32-rc7

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.
Files changed (63) hide show
  1. package/.editorconfig +17 -17
  2. package/.gitlab-ci.yml +18 -18
  3. package/CHANGELOG.md +201 -201
  4. package/demo/sample.js +1 -1
  5. package/demo/screen.css +16 -16
  6. package/dist/p-elements-core-modern.js +1 -1
  7. package/dist/p-elements-core.js +1 -1
  8. package/docs/package-lock.json +6897 -6897
  9. package/docs/package.json +27 -27
  10. package/docs/src/404.md +8 -8
  11. package/docs/src/_data/demos/hello-world/hello-world.tsx +35 -35
  12. package/docs/src/_data/demos/hello-world/index.html +10 -10
  13. package/docs/src/_data/demos/hello-world/project.json +7 -7
  14. package/docs/src/_data/demos/timer/demo-timer.tsx +120 -120
  15. package/docs/src/_data/demos/timer/icons.tsx +62 -62
  16. package/docs/src/_data/demos/timer/index.html +12 -12
  17. package/docs/src/_data/demos/timer/project.json +8 -8
  18. package/docs/src/_data/global.js +13 -13
  19. package/docs/src/_data/helpers.js +19 -19
  20. package/docs/src/_includes/layouts/base.njk +30 -30
  21. package/docs/src/_includes/layouts/playground.njk +40 -40
  22. package/docs/src/_includes/partials/app-header.njk +8 -8
  23. package/docs/src/_includes/partials/head.njk +14 -14
  24. package/docs/src/_includes/partials/nav.njk +19 -19
  25. package/docs/src/_includes/partials/top-nav.njk +51 -51
  26. package/docs/src/documentation/custom-element.md +221 -221
  27. package/docs/src/documentation/decorators/bind.md +71 -71
  28. package/docs/src/documentation/decorators/custom-element-config.md +63 -63
  29. package/docs/src/documentation/decorators/property.md +83 -83
  30. package/docs/src/documentation/decorators/query.md +66 -66
  31. package/docs/src/documentation/decorators/render-property-on-set.md +60 -60
  32. package/docs/src/documentation/decorators.md +9 -9
  33. package/docs/src/documentation/reactive-properties.md +53 -53
  34. package/docs/src/index.d.ts +25 -25
  35. package/docs/src/index.md +3 -3
  36. package/docs/src/scripts/components/app-mode-switch/app-mode-switch.css +78 -78
  37. package/docs/src/scripts/components/app-mode-switch/app-mode-switch.tsx +166 -166
  38. package/docs/src/scripts/components/app-playground/app-playground.tsx +189 -189
  39. package/docs/tsconfig.json +22 -22
  40. package/package.json +2 -2
  41. package/readme.md +206 -206
  42. package/src/custom-element-controller.ts +31 -31
  43. package/src/custom-element.test.ts +906 -906
  44. package/src/custom-element.ts +9 -9
  45. package/src/decorators/bind.test.ts +163 -163
  46. package/src/decorators/bind.ts +46 -46
  47. package/src/decorators/custom-element-config.ts +17 -17
  48. package/src/decorators/property.test.ts +279 -279
  49. package/src/decorators/property.ts +1 -2
  50. package/src/decorators/query.test.ts +146 -146
  51. package/src/decorators/query.ts +12 -12
  52. package/src/decorators/render-property-on-set.ts +3 -3
  53. package/src/helpers/css.ts +71 -71
  54. package/src/maquette/cache.ts +35 -35
  55. package/src/maquette/dom.ts +115 -115
  56. package/src/maquette/h.ts +100 -100
  57. package/src/maquette/index.ts +12 -12
  58. package/src/maquette/interfaces.ts +536 -536
  59. package/src/maquette/jsx.ts +61 -61
  60. package/src/maquette/mapping.ts +56 -56
  61. package/src/maquette/projection.ts +666 -666
  62. package/src/maquette/projector.ts +200 -200
  63. package/src/sample/mixin/highlight.tsx +33 -33
@@ -1,279 +1,279 @@
1
- /**
2
- * Tests for @property decorator
3
- * Covers type conversion, attribute reflection, custom converters, and lifecycle integration
4
- */
5
-
6
- import { describe, it, expect } from 'vitest';
7
- import '../test-setup.js';
8
- import { property } from './property.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('@property decorator', () => {
15
- describe('Type: String', () => {
16
- it('should convert attribute to string property', async () => {
17
- const tagName = generateUniqueTagName('prop-string');
18
-
19
- @customElementConfig({ tagName })
20
- class StringTest extends CustomElement {
21
- static style = ':host { display: block; }';
22
- @property({ type: String })
23
- text = 'default';
24
-
25
- render() {
26
- return { vnodeSelector: 'div', properties: {}, children: [], text: undefined, domNode: null };
27
- }
28
- }
29
-
30
- const el = document.createElement(tagName) as StringTest;
31
- el.setAttribute('text', 'hello');
32
- document.body.appendChild(el);
33
- await waitForRender(el);
34
-
35
- expect(el.text).toBe('hello');
36
-
37
- document.body.removeChild(el);
38
- });
39
-
40
- it('should set property from JavaScript', async () => {
41
- const tagName = generateUniqueTagName('prop-string');
42
-
43
- @customElementConfig({ tagName })
44
- class StringTest extends CustomElement {
45
- static style = ':host { display: block; }';
46
- @property({ type: String })
47
- text = 'default';
48
-
49
- render() {
50
- return { vnodeSelector: 'div', properties: {}, children: [], text: undefined, domNode: null };
51
- }
52
- }
53
-
54
- const el = document.createElement(tagName) as StringTest;
55
- document.body.appendChild(el);
56
-
57
- el.text = 'updated';
58
- await waitForRender(el);
59
-
60
- expect(el.text).toBe('updated');
61
-
62
- document.body.removeChild(el);
63
- });
64
- });
65
-
66
- describe('Type: Number', () => {
67
- it('should convert attribute to number property', async () => {
68
- const tagName = generateUniqueTagName('prop-number');
69
-
70
- @customElementConfig({ tagName })
71
- class NumberTest extends CustomElement {
72
- static style = ':host { display: block; }';
73
- @property({ type: Number })
74
- count = 0;
75
-
76
- render() {
77
- return { vnodeSelector: 'div', properties: {}, children: [], text: undefined, domNode: null };
78
- }
79
- }
80
-
81
- const el = document.createElement(tagName) as NumberTest;
82
- el.setAttribute('count', '42');
83
- document.body.appendChild(el);
84
- await waitForRender(el);
85
-
86
- expect(el.count).toBe(42);
87
-
88
- document.body.removeChild(el);
89
- });
90
- });
91
-
92
- describe('Type: Boolean', () => {
93
- it('should convert presence of attribute to true', async () => {
94
- const tagName = generateUniqueTagName('prop-bool');
95
-
96
- @customElementConfig({ tagName })
97
- class BooleanTest extends CustomElement {
98
- static style = ':host { display: block; }';
99
- @property({ type: Boolean })
100
- active = false;
101
-
102
- render() {
103
- return { vnodeSelector: 'div', properties: {}, children: [], text: undefined, domNode: null };
104
- }
105
- }
106
-
107
- const el = document.createElement(tagName) as BooleanTest;
108
- el.setAttribute('active', '');
109
- document.body.appendChild(el);
110
- await waitForRender(el);
111
-
112
- expect(el.active).toBe(true);
113
-
114
- document.body.removeChild(el);
115
- });
116
- });
117
-
118
- describe('Attribute reflection (reflect: true)', () => {
119
- it('should reflect string property to attribute', async () => {
120
- const tagName = generateUniqueTagName('prop-reflect');
121
-
122
- @customElementConfig({ tagName })
123
- class ReflectTest extends CustomElement {
124
- static style = ':host { display: block; }';
125
- @property({ type: String, reflect: true })
126
- status = 'pending';
127
-
128
- render() {
129
- return { vnodeSelector: 'div', properties: {}, children: [], text: undefined, domNode: null };
130
- }
131
- }
132
-
133
- const el = document.createElement(tagName) as ReflectTest;
134
- document.body.appendChild(el);
135
-
136
- el.status = 'complete';
137
- await waitForRender(el);
138
-
139
- expect(el.getAttribute('status')).toBe('complete');
140
-
141
- document.body.removeChild(el);
142
- });
143
-
144
- it('should reflect boolean property to attribute', async () => {
145
- const tagName = generateUniqueTagName('prop-reflect');
146
-
147
- @customElementConfig({ tagName })
148
- class ReflectTest extends CustomElement {
149
- static style = ':host { display: block; }';
150
- @property({ type: Boolean, reflect: true })
151
- active = false;
152
-
153
- render() {
154
- return { vnodeSelector: 'div', properties: {}, children: [], text: undefined, domNode: null };
155
- }
156
- }
157
-
158
- const el = document.createElement(tagName) as ReflectTest;
159
- document.body.appendChild(el);
160
-
161
- el.active = true;
162
- await waitForRender(el);
163
- expect(el.hasAttribute('active')).toBe(true);
164
-
165
- el.active = false;
166
- await waitForRender(el);
167
- expect(el.hasAttribute('active')).toBe(false);
168
-
169
- document.body.removeChild(el);
170
- });
171
-
172
- it('should reflect number property to attribute', async () => {
173
- const tagName = generateUniqueTagName('prop-reflect');
174
-
175
- @customElementConfig({ tagName })
176
- class ReflectTest extends CustomElement {
177
- static style = ':host { display: block; }';
178
- @property({ type: Number, reflect: true })
179
- count = 0;
180
-
181
- render() {
182
- return { vnodeSelector: 'div', properties: {}, children: [], text: undefined, domNode: null };
183
- }
184
- }
185
-
186
- const el = document.createElement(tagName) as ReflectTest;
187
- document.body.appendChild(el);
188
-
189
- el.count = 42;
190
- await waitForRender(el);
191
-
192
- expect(el.getAttribute('count')).toBe('42');
193
-
194
- document.body.removeChild(el);
195
- });
196
- });
197
-
198
- describe('Property without type conversion', () => {
199
- it('should handle object properties', async () => {
200
- const tagName = generateUniqueTagName('prop-object');
201
-
202
- @customElementConfig({ tagName })
203
- class ObjectTest extends CustomElement {
204
- static style = ':host { display: block; }';
205
- @property()
206
- data: any = null;
207
-
208
- render() {
209
- return { vnodeSelector: 'div', properties: {}, children: [], text: undefined, domNode: null };
210
- }
211
- }
212
-
213
- const el = document.createElement(tagName) as ObjectTest;
214
- document.body.appendChild(el);
215
-
216
- const testData = { foo: 'bar', num: 123 };
217
- el.data = testData;
218
- await waitForRender(el);
219
-
220
- expect(el.data).toBe(testData);
221
- expect(el.data.foo).toBe('bar');
222
-
223
- document.body.removeChild(el);
224
- });
225
-
226
- it('should handle array properties', async () => {
227
- const tagName = generateUniqueTagName('prop-array');
228
-
229
- @customElementConfig({ tagName })
230
- class ArrayTest extends CustomElement {
231
- static style = ':host { display: block; }';
232
- @property()
233
- items: string[] = [];
234
-
235
- render() {
236
- return { vnodeSelector: 'div', properties: {}, children: [], text: undefined, domNode: null };
237
- }
238
- }
239
-
240
- const el = document.createElement(tagName) as ArrayTest;
241
- document.body.appendChild(el);
242
-
243
- el.items = ['a', 'b', 'c'];
244
- await waitForRender(el);
245
-
246
- expect(el.items.length).toBe(3);
247
- expect(el.items[0]).toBe('a');
248
-
249
- document.body.removeChild(el);
250
- });
251
- });
252
-
253
- describe('Custom attribute names', () => {
254
- it('should support custom attribute names', async () => {
255
- const tagName = generateUniqueTagName('prop-custom');
256
-
257
- @customElementConfig({ tagName })
258
- class CustomAttrTest extends CustomElement {
259
- static style = ':host { display: block; }';
260
- @property({ type: String, attribute: 'data-value' })
261
- value = '';
262
-
263
- render() {
264
- return { vnodeSelector: 'div', properties: {}, children: [], text: undefined, domNode: null };
265
- }
266
- }
267
-
268
- const el = document.createElement(tagName) as CustomAttrTest;
269
- document.body.appendChild(el);
270
-
271
- el.setAttribute('data-value', 'test');
272
- await new Promise(resolve => setTimeout(resolve, 10));
273
-
274
- expect(el.value).toBe('test');
275
-
276
- document.body.removeChild(el);
277
- });
278
- });
279
- });
1
+ /**
2
+ * Tests for @property decorator
3
+ * Covers type conversion, attribute reflection, custom converters, and lifecycle integration
4
+ */
5
+
6
+ import { describe, it, expect } from 'vitest';
7
+ import '../test-setup.js';
8
+ import { property } from './property.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('@property decorator', () => {
15
+ describe('Type: String', () => {
16
+ it('should convert attribute to string property', async () => {
17
+ const tagName = generateUniqueTagName('prop-string');
18
+
19
+ @customElementConfig({ tagName })
20
+ class StringTest extends CustomElement {
21
+ static style = ':host { display: block; }';
22
+ @property({ type: String })
23
+ text = 'default';
24
+
25
+ render() {
26
+ return { vnodeSelector: 'div', properties: {}, children: [], text: undefined, domNode: null };
27
+ }
28
+ }
29
+
30
+ const el = document.createElement(tagName) as StringTest;
31
+ el.setAttribute('text', 'hello');
32
+ document.body.appendChild(el);
33
+ await waitForRender(el);
34
+
35
+ expect(el.text).toBe('hello');
36
+
37
+ document.body.removeChild(el);
38
+ });
39
+
40
+ it('should set property from JavaScript', async () => {
41
+ const tagName = generateUniqueTagName('prop-string');
42
+
43
+ @customElementConfig({ tagName })
44
+ class StringTest extends CustomElement {
45
+ static style = ':host { display: block; }';
46
+ @property({ type: String })
47
+ text = 'default';
48
+
49
+ render() {
50
+ return { vnodeSelector: 'div', properties: {}, children: [], text: undefined, domNode: null };
51
+ }
52
+ }
53
+
54
+ const el = document.createElement(tagName) as StringTest;
55
+ document.body.appendChild(el);
56
+
57
+ el.text = 'updated';
58
+ await waitForRender(el);
59
+
60
+ expect(el.text).toBe('updated');
61
+
62
+ document.body.removeChild(el);
63
+ });
64
+ });
65
+
66
+ describe('Type: Number', () => {
67
+ it('should convert attribute to number property', async () => {
68
+ const tagName = generateUniqueTagName('prop-number');
69
+
70
+ @customElementConfig({ tagName })
71
+ class NumberTest extends CustomElement {
72
+ static style = ':host { display: block; }';
73
+ @property({ type: Number })
74
+ count = 0;
75
+
76
+ render() {
77
+ return { vnodeSelector: 'div', properties: {}, children: [], text: undefined, domNode: null };
78
+ }
79
+ }
80
+
81
+ const el = document.createElement(tagName) as NumberTest;
82
+ el.setAttribute('count', '42');
83
+ document.body.appendChild(el);
84
+ await waitForRender(el);
85
+
86
+ expect(el.count).toBe(42);
87
+
88
+ document.body.removeChild(el);
89
+ });
90
+ });
91
+
92
+ describe('Type: Boolean', () => {
93
+ it('should convert presence of attribute to true', async () => {
94
+ const tagName = generateUniqueTagName('prop-bool');
95
+
96
+ @customElementConfig({ tagName })
97
+ class BooleanTest extends CustomElement {
98
+ static style = ':host { display: block; }';
99
+ @property({ type: Boolean })
100
+ active = false;
101
+
102
+ render() {
103
+ return { vnodeSelector: 'div', properties: {}, children: [], text: undefined, domNode: null };
104
+ }
105
+ }
106
+
107
+ const el = document.createElement(tagName) as BooleanTest;
108
+ el.setAttribute('active', '');
109
+ document.body.appendChild(el);
110
+ await waitForRender(el);
111
+
112
+ expect(el.active).toBe(true);
113
+
114
+ document.body.removeChild(el);
115
+ });
116
+ });
117
+
118
+ describe('Attribute reflection (reflect: true)', () => {
119
+ it('should reflect string property to attribute', async () => {
120
+ const tagName = generateUniqueTagName('prop-reflect');
121
+
122
+ @customElementConfig({ tagName })
123
+ class ReflectTest extends CustomElement {
124
+ static style = ':host { display: block; }';
125
+ @property({ type: String, reflect: true })
126
+ status = 'pending';
127
+
128
+ render() {
129
+ return { vnodeSelector: 'div', properties: {}, children: [], text: undefined, domNode: null };
130
+ }
131
+ }
132
+
133
+ const el = document.createElement(tagName) as ReflectTest;
134
+ document.body.appendChild(el);
135
+
136
+ el.status = 'complete';
137
+ await waitForRender(el);
138
+
139
+ expect(el.getAttribute('status')).toBe('complete');
140
+
141
+ document.body.removeChild(el);
142
+ });
143
+
144
+ it('should reflect boolean property to attribute', async () => {
145
+ const tagName = generateUniqueTagName('prop-reflect');
146
+
147
+ @customElementConfig({ tagName })
148
+ class ReflectTest extends CustomElement {
149
+ static style = ':host { display: block; }';
150
+ @property({ type: Boolean, reflect: true })
151
+ active = false;
152
+
153
+ render() {
154
+ return { vnodeSelector: 'div', properties: {}, children: [], text: undefined, domNode: null };
155
+ }
156
+ }
157
+
158
+ const el = document.createElement(tagName) as ReflectTest;
159
+ document.body.appendChild(el);
160
+
161
+ el.active = true;
162
+ await waitForRender(el);
163
+ expect(el.hasAttribute('active')).toBe(true);
164
+
165
+ el.active = false;
166
+ await waitForRender(el);
167
+ expect(el.hasAttribute('active')).toBe(false);
168
+
169
+ document.body.removeChild(el);
170
+ });
171
+
172
+ it('should reflect number property to attribute', async () => {
173
+ const tagName = generateUniqueTagName('prop-reflect');
174
+
175
+ @customElementConfig({ tagName })
176
+ class ReflectTest extends CustomElement {
177
+ static style = ':host { display: block; }';
178
+ @property({ type: Number, reflect: true })
179
+ count = 0;
180
+
181
+ render() {
182
+ return { vnodeSelector: 'div', properties: {}, children: [], text: undefined, domNode: null };
183
+ }
184
+ }
185
+
186
+ const el = document.createElement(tagName) as ReflectTest;
187
+ document.body.appendChild(el);
188
+
189
+ el.count = 42;
190
+ await waitForRender(el);
191
+
192
+ expect(el.getAttribute('count')).toBe('42');
193
+
194
+ document.body.removeChild(el);
195
+ });
196
+ });
197
+
198
+ describe('Property without type conversion', () => {
199
+ it('should handle object properties', async () => {
200
+ const tagName = generateUniqueTagName('prop-object');
201
+
202
+ @customElementConfig({ tagName })
203
+ class ObjectTest extends CustomElement {
204
+ static style = ':host { display: block; }';
205
+ @property()
206
+ data: any = null;
207
+
208
+ render() {
209
+ return { vnodeSelector: 'div', properties: {}, children: [], text: undefined, domNode: null };
210
+ }
211
+ }
212
+
213
+ const el = document.createElement(tagName) as ObjectTest;
214
+ document.body.appendChild(el);
215
+
216
+ const testData = { foo: 'bar', num: 123 };
217
+ el.data = testData;
218
+ await waitForRender(el);
219
+
220
+ expect(el.data).toBe(testData);
221
+ expect(el.data.foo).toBe('bar');
222
+
223
+ document.body.removeChild(el);
224
+ });
225
+
226
+ it('should handle array properties', async () => {
227
+ const tagName = generateUniqueTagName('prop-array');
228
+
229
+ @customElementConfig({ tagName })
230
+ class ArrayTest extends CustomElement {
231
+ static style = ':host { display: block; }';
232
+ @property()
233
+ items: string[] = [];
234
+
235
+ render() {
236
+ return { vnodeSelector: 'div', properties: {}, children: [], text: undefined, domNode: null };
237
+ }
238
+ }
239
+
240
+ const el = document.createElement(tagName) as ArrayTest;
241
+ document.body.appendChild(el);
242
+
243
+ el.items = ['a', 'b', 'c'];
244
+ await waitForRender(el);
245
+
246
+ expect(el.items.length).toBe(3);
247
+ expect(el.items[0]).toBe('a');
248
+
249
+ document.body.removeChild(el);
250
+ });
251
+ });
252
+
253
+ describe('Custom attribute names', () => {
254
+ it('should support custom attribute names', async () => {
255
+ const tagName = generateUniqueTagName('prop-custom');
256
+
257
+ @customElementConfig({ tagName })
258
+ class CustomAttrTest extends CustomElement {
259
+ static style = ':host { display: block; }';
260
+ @property({ type: String, attribute: 'data-value' })
261
+ value = '';
262
+
263
+ render() {
264
+ return { vnodeSelector: 'div', properties: {}, children: [], text: undefined, domNode: null };
265
+ }
266
+ }
267
+
268
+ const el = document.createElement(tagName) as CustomAttrTest;
269
+ document.body.appendChild(el);
270
+
271
+ el.setAttribute('data-value', 'test');
272
+ await new Promise(resolve => setTimeout(resolve, 10));
273
+
274
+ expect(el.value).toBe('test');
275
+
276
+ document.body.removeChild(el);
277
+ });
278
+ });
279
+ });
@@ -543,13 +543,12 @@ export function property(
543
543
  if (typeof console !== "undefined" && console.info) {
544
544
  // log this once per nodeName
545
545
  logConnectedCallback(this.nodeName);
546
-
547
546
  }
548
547
  } else {
549
548
  processPendingUpdates(this);
550
549
  if (typeof console !== "undefined" && console.info) {
551
550
  console.info(
552
- `[p-elements-core] connectedCallback: called processPendingUpdates automatically for <${this.nodeName}>`,
551
+ `[p-elements-core] called processPendingUpdates automatically for <${this.nodeName}>`,
553
552
  );
554
553
  }
555
554
  }