@playcanvas/web-components 0.8.2 → 0.9.0

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 (71) hide show
  1. package/dist/app.d.ts +10 -2
  2. package/dist/asset.d.ts +18 -3
  3. package/dist/async-element.d.ts +51 -4
  4. package/dist/components/button-component.d.ts +10 -4
  5. package/dist/components/camera-component.d.ts +9 -4
  6. package/dist/components/collision-component.d.ts +9 -4
  7. package/dist/components/component.d.ts +7 -1
  8. package/dist/components/element-component.d.ts +17 -12
  9. package/dist/components/gsplat-component.d.ts +6 -1
  10. package/dist/components/layoutchild-component.d.ts +6 -1
  11. package/dist/components/layoutgroup-component.d.ts +21 -15
  12. package/dist/components/light-component.d.ts +12 -6
  13. package/dist/components/listener-component.d.ts +6 -1
  14. package/dist/components/particlesystem-component.d.ts +6 -1
  15. package/dist/components/render-component.d.ts +13 -4
  16. package/dist/components/rigidbody-component.d.ts +9 -4
  17. package/dist/components/screen-component.d.ts +6 -1
  18. package/dist/components/script-component.d.ts +116 -16
  19. package/dist/components/script.d.ts +72 -8
  20. package/dist/components/scrollbar-component.d.ts +10 -4
  21. package/dist/components/scrollview-component.d.ts +17 -10
  22. package/dist/components/sound-component.d.ts +6 -1
  23. package/dist/components/sound-slot.d.ts +8 -3
  24. package/dist/entity.d.ts +26 -2
  25. package/dist/index.d.ts +3 -2
  26. package/dist/material.d.ts +10 -0
  27. package/dist/model.d.ts +5 -0
  28. package/dist/module.d.ts +5 -0
  29. package/dist/pwc.cjs +1574 -853
  30. package/dist/pwc.cjs.map +1 -1
  31. package/dist/pwc.js +1574 -853
  32. package/dist/pwc.js.map +1 -1
  33. package/dist/pwc.min.js +1 -1
  34. package/dist/pwc.min.js.map +1 -1
  35. package/dist/pwc.mjs +1575 -855
  36. package/dist/pwc.mjs.map +1 -1
  37. package/dist/scene.d.ts +14 -5
  38. package/dist/sky.d.ts +6 -0
  39. package/dist/utils.d.ts +81 -23
  40. package/package.json +7 -7
  41. package/src/app.ts +38 -12
  42. package/src/asset.ts +61 -8
  43. package/src/async-element.ts +86 -5
  44. package/src/components/button-component.ts +26 -19
  45. package/src/components/camera-component.ts +29 -23
  46. package/src/components/collision-component.ts +19 -13
  47. package/src/components/component.ts +32 -13
  48. package/src/components/element-component.ts +58 -52
  49. package/src/components/gsplat-component.ts +14 -7
  50. package/src/components/layoutchild-component.ts +16 -9
  51. package/src/components/layoutgroup-component.ts +38 -31
  52. package/src/components/light-component.ts +33 -31
  53. package/src/components/listener-component.ts +8 -2
  54. package/src/components/particlesystem-component.ts +8 -2
  55. package/src/components/render-component.ts +19 -8
  56. package/src/components/rigidbody-component.ts +21 -15
  57. package/src/components/screen-component.ts +15 -9
  58. package/src/components/script-component.ts +512 -125
  59. package/src/components/script.ts +116 -16
  60. package/src/components/scrollbar-component.ts +19 -12
  61. package/src/components/scrollview-component.ts +37 -29
  62. package/src/components/sound-component.ts +16 -9
  63. package/src/components/sound-slot.ts +23 -14
  64. package/src/entity.ts +61 -71
  65. package/src/index.ts +5 -2
  66. package/src/material.ts +34 -1
  67. package/src/model.ts +6 -0
  68. package/src/module.ts +6 -0
  69. package/src/scene.ts +25 -12
  70. package/src/sky.ts +34 -16
  71. package/src/utils.ts +180 -40
@@ -2,9 +2,9 @@ import { BUTTON_TRANSITION_MODE_SPRITE_CHANGE, BUTTON_TRANSITION_MODE_TINT, Butt
2
2
 
3
3
  import { AssetElement } from '../asset';
4
4
  import { ComponentElement } from './component';
5
- import { getEntity, parseColor, parseEnum, parseVec4 } from '../utils';
5
+ import { getEntity, parseBool, parseColor, parseEnum, parseNumber, parseVec4 } from '../utils';
6
6
 
7
- const transitionModes = new Map<string, number>([
7
+ const transitionModes = new Map<'tint' | 'sprite', number>([
8
8
  ['tint', BUTTON_TRANSITION_MODE_TINT],
9
9
  ['sprite', BUTTON_TRANSITION_MODE_SPRITE_CHANGE]
10
10
  ]);
@@ -24,7 +24,7 @@ class ButtonComponentElement extends ComponentElement {
24
24
 
25
25
  private _hitPadding = new Vec4(0, 0, 0, 0);
26
26
 
27
- private _transitionMode: number = BUTTON_TRANSITION_MODE_TINT;
27
+ private _transitionMode: 'tint' | 'sprite' = 'tint';
28
28
 
29
29
  private _hoverTint = new Color(1, 1, 1, 1);
30
30
 
@@ -55,7 +55,7 @@ class ButtonComponentElement extends ComponentElement {
55
55
  const data: Record<string, any> = {
56
56
  active: this._active,
57
57
  hitPadding: this._hitPadding,
58
- transitionMode: this._transitionMode,
58
+ transitionMode: transitionModes.get(this._transitionMode),
59
59
  hoverTint: this._hoverTint,
60
60
  pressedTint: this._pressedTint,
61
61
  inactiveTint: this._inactiveTint,
@@ -94,8 +94,8 @@ class ButtonComponentElement extends ComponentElement {
94
94
  * Gets the underlying PlayCanvas button component.
95
95
  * @returns The button component.
96
96
  */
97
- get component(): ButtonComponent | null {
98
- return super.component as ButtonComponent | null;
97
+ get component(): ButtonComponent {
98
+ return super.component as ButtonComponent;
99
99
  }
100
100
 
101
101
  /**
@@ -158,13 +158,14 @@ class ButtonComponentElement extends ComponentElement {
158
158
  }
159
159
 
160
160
  /**
161
- * Sets how the button reacts to being hovered/pressed. Can be `tint` (0) or `sprite` (1).
161
+ * Sets how the button reacts to being hovered/pressed. Can be `tint` or `sprite`. Defaults to
162
+ * `tint`.
162
163
  * @param value - The transition mode.
163
164
  */
164
- set transitionMode(value: number) {
165
+ set transitionMode(value: 'tint' | 'sprite') {
165
166
  this._transitionMode = value;
166
167
  if (this.component) {
167
- this.component.transitionMode = value;
168
+ this.component.transitionMode = transitionModes.get(value) ?? BUTTON_TRANSITION_MODE_TINT;
168
169
  }
169
170
  }
170
171
 
@@ -400,46 +401,46 @@ class ButtonComponentElement extends ComponentElement {
400
401
 
401
402
  switch (name) {
402
403
  case 'active':
403
- this.active = newValue !== 'false';
404
+ this.active = parseBool(newValue, true);
404
405
  break;
405
406
  case 'image':
406
407
  this.image = newValue;
407
408
  break;
408
409
  case 'hit-padding':
409
- this.hitPadding = parseVec4(newValue);
410
+ this.hitPadding = parseVec4(newValue, Vec4.ZERO, name);
410
411
  break;
411
412
  case 'transition-mode':
412
- this.transitionMode = parseEnum(newValue, transitionModes, BUTTON_TRANSITION_MODE_TINT);
413
+ this.transitionMode = parseEnum(newValue, transitionModes, 'tint', name);
413
414
  break;
414
415
  case 'hover-tint':
415
- this.hoverTint = parseColor(newValue);
416
+ this.hoverTint = parseColor(newValue, Color.WHITE, name);
416
417
  break;
417
418
  case 'pressed-tint':
418
- this.pressedTint = parseColor(newValue);
419
+ this.pressedTint = parseColor(newValue, Color.WHITE, name);
419
420
  break;
420
421
  case 'inactive-tint':
421
- this.inactiveTint = parseColor(newValue);
422
+ this.inactiveTint = parseColor(newValue, Color.WHITE, name);
422
423
  break;
423
424
  case 'fade-duration':
424
- this.fadeDuration = Number(newValue);
425
+ this.fadeDuration = parseNumber(newValue, 0, name);
425
426
  break;
426
427
  case 'hover-sprite-asset':
427
428
  this.hoverSpriteAsset = newValue;
428
429
  break;
429
430
  case 'hover-sprite-frame':
430
- this.hoverSpriteFrame = Number(newValue);
431
+ this.hoverSpriteFrame = parseNumber(newValue, 0, name);
431
432
  break;
432
433
  case 'pressed-sprite-asset':
433
434
  this.pressedSpriteAsset = newValue;
434
435
  break;
435
436
  case 'pressed-sprite-frame':
436
- this.pressedSpriteFrame = Number(newValue);
437
+ this.pressedSpriteFrame = parseNumber(newValue, 0, name);
437
438
  break;
438
439
  case 'inactive-sprite-asset':
439
440
  this.inactiveSpriteAsset = newValue;
440
441
  break;
441
442
  case 'inactive-sprite-frame':
442
- this.inactiveSpriteFrame = Number(newValue);
443
+ this.inactiveSpriteFrame = parseNumber(newValue, 0, name);
443
444
  break;
444
445
  }
445
446
  }
@@ -447,4 +448,10 @@ class ButtonComponentElement extends ComponentElement {
447
448
 
448
449
  customElements.define('pc-button', ButtonComponentElement);
449
450
 
451
+ declare global {
452
+ interface HTMLElementTagNameMap {
453
+ 'pc-button': ButtonComponentElement;
454
+ }
455
+ }
456
+
450
457
  export { ButtonComponentElement };
@@ -1,9 +1,9 @@
1
1
  import { CameraComponent, Color, Vec4, GAMMA_NONE, GAMMA_SRGB, PROJECTION_ORTHOGRAPHIC, PROJECTION_PERSPECTIVE, TONEMAP_LINEAR, TONEMAP_FILMIC, TONEMAP_NEUTRAL, TONEMAP_ACES2, TONEMAP_ACES, TONEMAP_HEJL, TONEMAP_NONE, XRTYPE_VR } from 'playcanvas';
2
2
 
3
3
  import { ComponentElement } from './component';
4
- import { parseColor, parseVec4 } from '../utils';
4
+ import { parseBool, parseColor, parseEnum, parseNumber, parseVec4 } from '../utils';
5
5
 
6
- const tonemaps = new Map([
6
+ const tonemaps = new Map<'none' | 'linear' | 'filmic' | 'hejl' | 'aces' | 'aces2' | 'neutral', number>([
7
7
  ['none', TONEMAP_NONE],
8
8
  ['linear', TONEMAP_LINEAR],
9
9
  ['filmic', TONEMAP_FILMIC],
@@ -77,7 +77,7 @@ class CameraComponentElement extends ComponentElement {
77
77
  gammaCorrection: this._gamma === 'srgb' ? GAMMA_SRGB : GAMMA_NONE,
78
78
  horizontalFov: this._horizontalFov,
79
79
  nearClip: this._nearClip,
80
- orthographic: this._orthographic,
80
+ projection: this._orthographic ? PROJECTION_ORTHOGRAPHIC : PROJECTION_PERSPECTIVE,
81
81
  orthoHeight: this._orthoHeight,
82
82
  priority: this._priority,
83
83
  rect: this._rect,
@@ -119,8 +119,8 @@ class CameraComponentElement extends ComponentElement {
119
119
  * Gets the underlying PlayCanvas camera component.
120
120
  * @returns The camera component.
121
121
  */
122
- get component(): CameraComponent | null {
123
- return super.component as CameraComponent | null;
122
+ get component(): CameraComponent {
123
+ return super.component as CameraComponent;
124
124
  }
125
125
 
126
126
  /**
@@ -495,58 +495,58 @@ class CameraComponentElement extends ComponentElement {
495
495
 
496
496
  switch (name) {
497
497
  case 'clear-color':
498
- this.clearColor = parseColor(newValue);
498
+ this.clearColor = parseColor(newValue, new Color(0.75, 0.75, 0.75, 1), name);
499
499
  break;
500
500
  case 'clear-color-buffer':
501
- this.clearColorBuffer = newValue !== 'false';
501
+ this.clearColorBuffer = parseBool(newValue, true);
502
502
  break;
503
503
  case 'clear-depth-buffer':
504
- this.clearDepthBuffer = newValue !== 'false';
504
+ this.clearDepthBuffer = parseBool(newValue, true);
505
505
  break;
506
506
  case 'clear-stencil-buffer':
507
- this.clearStencilBuffer = newValue !== 'false';
507
+ this.clearStencilBuffer = parseBool(newValue, false);
508
508
  break;
509
509
  case 'cull-faces':
510
- this.cullFaces = newValue !== 'false';
510
+ this.cullFaces = parseBool(newValue, true);
511
511
  break;
512
512
  case 'far-clip':
513
- this.farClip = parseFloat(newValue);
513
+ this.farClip = parseNumber(newValue, 1000, name);
514
514
  break;
515
515
  case 'flip-faces':
516
- this.flipFaces = newValue !== 'false';
516
+ this.flipFaces = parseBool(newValue, false);
517
517
  break;
518
518
  case 'fov':
519
- this.fov = parseFloat(newValue);
519
+ this.fov = parseNumber(newValue, 45, name);
520
520
  break;
521
521
  case 'frustum-culling':
522
- this.frustumCulling = newValue !== 'false';
522
+ this.frustumCulling = parseBool(newValue, true);
523
523
  break;
524
524
  case 'gamma':
525
- this.gamma = newValue as 'linear' | 'srgb';
525
+ this.gamma = parseEnum(newValue, ['linear', 'srgb'], 'srgb', name);
526
526
  break;
527
527
  case 'horizontal-fov':
528
- this.horizontalFov = this.hasAttribute('horizontal-fov');
528
+ this.horizontalFov = parseBool(newValue, false);
529
529
  break;
530
530
  case 'near-clip':
531
- this.nearClip = parseFloat(newValue);
531
+ this.nearClip = parseNumber(newValue, 0.1, name);
532
532
  break;
533
533
  case 'orthographic':
534
- this.orthographic = this.hasAttribute('orthographic');
534
+ this.orthographic = parseBool(newValue, false);
535
535
  break;
536
536
  case 'ortho-height':
537
- this.orthoHeight = parseFloat(newValue);
537
+ this.orthoHeight = parseNumber(newValue, 10, name);
538
538
  break;
539
539
  case 'priority':
540
- this.priority = parseFloat(newValue);
540
+ this.priority = parseNumber(newValue, 0, name);
541
541
  break;
542
542
  case 'rect':
543
- this.rect = parseVec4(newValue);
543
+ this.rect = parseVec4(newValue, new Vec4(0, 0, 1, 1), name);
544
544
  break;
545
545
  case 'scissor-rect':
546
- this.scissorRect = parseVec4(newValue);
546
+ this.scissorRect = parseVec4(newValue, new Vec4(0, 0, 1, 1), name);
547
547
  break;
548
548
  case 'tonemap':
549
- this.tonemap = newValue as 'none' | 'linear' | 'filmic' | 'hejl' | 'aces' | 'aces2' | 'neutral';
549
+ this.tonemap = parseEnum(newValue, tonemaps, 'none', name);
550
550
  break;
551
551
  }
552
552
  }
@@ -554,4 +554,10 @@ class CameraComponentElement extends ComponentElement {
554
554
 
555
555
  customElements.define('pc-camera', CameraComponentElement);
556
556
 
557
+ declare global {
558
+ interface HTMLElementTagNameMap {
559
+ 'pc-camera': CameraComponentElement;
560
+ }
561
+ }
562
+
557
563
  export { CameraComponentElement };
@@ -1,7 +1,7 @@
1
1
  import { CollisionComponent, Quat, Vec3 } from 'playcanvas';
2
2
 
3
3
  import { ComponentElement } from './component';
4
- import { parseQuat, parseVec3 } from '../utils';
4
+ import { parseBool, parseEnum, parseNumber, parseQuat, parseVec3 } from '../utils';
5
5
 
6
6
  /**
7
7
  * The CollisionComponentElement interface provides properties and methods for manipulating
@@ -26,7 +26,7 @@ class CollisionComponentElement extends ComponentElement {
26
26
 
27
27
  private _radius: number = 0.5;
28
28
 
29
- private _type: string = 'box';
29
+ private _type: 'box' | 'capsule' | 'compound' | 'cone' | 'cylinder' | 'mesh' | 'sphere' = 'box';
30
30
 
31
31
  /** @ignore */
32
32
  constructor() {
@@ -50,8 +50,8 @@ class CollisionComponentElement extends ComponentElement {
50
50
  * Gets the underlying PlayCanvas collision component.
51
51
  * @returns The collision component.
52
52
  */
53
- get component(): CollisionComponent | null {
54
- return super.component as CollisionComponent | null;
53
+ get component(): CollisionComponent {
54
+ return super.component as CollisionComponent;
55
55
  }
56
56
 
57
57
  set angularOffset(value: Quat) {
@@ -131,7 +131,7 @@ class CollisionComponentElement extends ComponentElement {
131
131
  return this._radius;
132
132
  }
133
133
 
134
- set type(value: string) {
134
+ set type(value: 'box' | 'capsule' | 'compound' | 'cone' | 'cylinder' | 'mesh' | 'sphere') {
135
135
  this._type = value;
136
136
  if (this.component) {
137
137
  this.component.type = value;
@@ -151,28 +151,28 @@ class CollisionComponentElement extends ComponentElement {
151
151
 
152
152
  switch (name) {
153
153
  case 'angular-offset':
154
- this.angularOffset = parseQuat(newValue);
154
+ this.angularOffset = parseQuat(newValue, Quat.IDENTITY, name);
155
155
  break;
156
156
  case 'axis':
157
- this.axis = parseInt(newValue, 10);
157
+ this.axis = parseNumber(newValue, 1, name);
158
158
  break;
159
159
  case 'convex-hull':
160
- this.convexHull = this.hasAttribute('convex-hull');
160
+ this.convexHull = parseBool(newValue, false);
161
161
  break;
162
162
  case 'half-extents':
163
- this.halfExtents = parseVec3(newValue);
163
+ this.halfExtents = parseVec3(newValue, new Vec3(0.5, 0.5, 0.5), name);
164
164
  break;
165
165
  case 'height':
166
- this.height = parseFloat(newValue);
166
+ this.height = parseNumber(newValue, 2, name);
167
167
  break;
168
168
  case 'linear-offset':
169
- this.linearOffset = parseVec3(newValue);
169
+ this.linearOffset = parseVec3(newValue, Vec3.ZERO, name);
170
170
  break;
171
171
  case 'radius':
172
- this.radius = parseFloat(newValue);
172
+ this.radius = parseNumber(newValue, 0.5, name);
173
173
  break;
174
174
  case 'type':
175
- this.type = newValue;
175
+ this.type = parseEnum(newValue, ['box', 'capsule', 'compound', 'cone', 'cylinder', 'mesh', 'sphere'], 'box', name);
176
176
  break;
177
177
  }
178
178
  }
@@ -180,4 +180,10 @@ class CollisionComponentElement extends ComponentElement {
180
180
 
181
181
  customElements.define('pc-collision', CollisionComponentElement);
182
182
 
183
+ declare global {
184
+ interface HTMLElementTagNameMap {
185
+ 'pc-collision': CollisionComponentElement;
186
+ }
187
+ }
188
+
183
189
  export { CollisionComponentElement };
@@ -1,6 +1,8 @@
1
1
  import { Component } from 'playcanvas';
2
2
 
3
+ import { AppElement } from '../app';
3
4
  import { AsyncElement } from '../async-element';
5
+ import { parseBool } from '../utils';
4
6
 
5
7
  /**
6
8
  * Represents a component in the PlayCanvas engine.
@@ -14,6 +16,8 @@ class ComponentElement extends AsyncElement {
14
16
 
15
17
  private _component: Component | null = null;
16
18
 
19
+ private _appElement: AppElement | null = null;
20
+
17
21
  /**
18
22
  * Creates a new ComponentElement instance.
19
23
  *
@@ -33,33 +37,48 @@ class ComponentElement extends AsyncElement {
33
37
 
34
38
  async addComponent() {
35
39
  const entityElement = this.closestEntity;
36
- if (entityElement) {
37
- await entityElement.ready();
38
- // Add the component to the entity
39
- const data = this.getInitialComponentData();
40
- this._component = entityElement.entity!.addComponent(this._componentName, data);
40
+ if (!entityElement) {
41
+ // A component can only exist on an entity, so an element placed outside one is inert.
42
+ // It still becomes ready (with a null `component`), so warn rather than fail silently
43
+ const label = this.id ? ` '${this.id}'` : '';
44
+ console.warn(`${this.tagName.toLowerCase()}${label} must be a descendant of pc-entity - component not added`);
45
+ return;
41
46
  }
47
+
48
+ await entityElement.ready();
49
+ // Add the component to the entity
50
+ const data = this.getInitialComponentData();
51
+ this._component = entityElement.entity!.addComponent(this._componentName, data);
42
52
  }
43
53
 
44
54
  initComponent() {}
45
55
 
46
56
  async connectedCallback() {
47
- await this.closestApp?.ready();
57
+ this._appElement = this.closestApp ?? null;
58
+ await this._appElement?.ready();
48
59
  await this.addComponent();
49
60
  this.initComponent();
50
61
  this._onReady();
51
62
  }
52
63
 
53
64
  disconnectedCallback() {
54
- // Remove the component when the element is disconnected
55
- if (this.component && this.component.entity) {
56
- this._component!.entity.removeComponent(this._componentName);
57
- this._component = null;
65
+ // Remove the component when the element is disconnected. Skip this when the owning
66
+ // application has already been destroyed — removing a <pc-app> disconnects it before
67
+ // its children, taking the component systems with it.
68
+ if (this._appElement?.app && this._component?.entity) {
69
+ this._component.entity.removeComponent(this._componentName);
58
70
  }
71
+ this._component = null;
72
+ this._appElement = null;
59
73
  }
60
74
 
61
- get component(): Component | null {
62
- return this._component;
75
+ /**
76
+ * The PlayCanvas component instance. Available once the element is ready — await
77
+ * {@link whenReady} or the element's `ready()` promise before accessing it.
78
+ * @returns The component instance.
79
+ */
80
+ get component(): Component {
81
+ return this._component!;
63
82
  }
64
83
 
65
84
  /**
@@ -88,7 +107,7 @@ class ComponentElement extends AsyncElement {
88
107
  attributeChangedCallback(name: string, _oldValue: string, newValue: string) {
89
108
  switch (name) {
90
109
  case 'enabled':
91
- this.enabled = newValue !== 'false';
110
+ this.enabled = parseBool(newValue, true);
92
111
  break;
93
112
  }
94
113
  }
@@ -2,7 +2,7 @@ import { Color, ElementComponent, Vec2, Vec4 } from 'playcanvas';
2
2
 
3
3
  import { AssetElement } from '../asset';
4
4
  import { ComponentElement } from './component';
5
- import { parseColor, parseVec2, parseVec4 } from '../utils';
5
+ import { parseBool, parseColor, parseEnum, parseNumber, parseVec2, parseVec4 } from '../utils';
6
6
 
7
7
  /**
8
8
  * The ElementComponentElement interface provides properties and methods for manipulating
@@ -15,8 +15,6 @@ import { parseColor, parseVec2, parseVec4 } from '../utils';
15
15
  class ElementComponentElement extends ComponentElement {
16
16
  private _anchor: Vec4 = new Vec4(0.5, 0.5, 0.5, 0.5);
17
17
 
18
- private _asset: string = '';
19
-
20
18
  private _autoWidth: boolean = true;
21
19
 
22
20
  private _autoHeight: boolean = true;
@@ -29,6 +27,8 @@ class ElementComponentElement extends ComponentElement {
29
27
 
30
28
  private _enableMarkup: boolean = false;
31
29
 
30
+ private _fontAsset: string = '';
31
+
32
32
  private _fontSize: number = 32;
33
33
 
34
34
  private _maxFontSize: number = 32;
@@ -116,7 +116,7 @@ class ElementComponentElement extends ComponentElement {
116
116
 
117
117
  // Asset references are resolved from `<pc-asset>` element ids to engine asset ids. They are
118
118
  // only included when they resolve, so image/group elements (with no font) don't error.
119
- const fontAsset = AssetElement.get(this._asset);
119
+ const fontAsset = AssetElement.get(this._fontAsset);
120
120
  if (fontAsset) {
121
121
  data.fontAsset = fontAsset.id;
122
122
  }
@@ -148,8 +148,8 @@ class ElementComponentElement extends ComponentElement {
148
148
  * Gets the underlying PlayCanvas element component.
149
149
  * @returns The element component.
150
150
  */
151
- get component(): ElementComponent | null {
152
- return super.component as ElementComponent | null;
151
+ get component(): ElementComponent {
152
+ return super.component as ElementComponent;
153
153
  }
154
154
 
155
155
  /**
@@ -171,26 +171,6 @@ class ElementComponentElement extends ComponentElement {
171
171
  return this._anchor;
172
172
  }
173
173
 
174
- /**
175
- * Sets the id of the `pc-asset` to use for the font (text elements).
176
- * @param value - The asset ID.
177
- */
178
- set asset(value: string) {
179
- this._asset = value;
180
- const asset = AssetElement.get(value);
181
- if (this.component && asset) {
182
- this.component.fontAsset = asset.id;
183
- }
184
- }
185
-
186
- /**
187
- * Gets the id of the `pc-asset` to use for the font.
188
- * @returns The asset ID.
189
- */
190
- get asset() {
191
- return this._asset;
192
- }
193
-
194
174
  /**
195
175
  * Sets whether the element component should automatically adjust its width to the text content
196
176
  * (text elements only).
@@ -269,6 +249,26 @@ class ElementComponentElement extends ComponentElement {
269
249
  return this._enableMarkup;
270
250
  }
271
251
 
252
+ /**
253
+ * Sets the id of the `pc-asset` to use for the font (text elements).
254
+ * @param value - The font asset ID.
255
+ */
256
+ set fontAsset(value: string) {
257
+ this._fontAsset = value;
258
+ const asset = AssetElement.get(value);
259
+ if (this.component && asset) {
260
+ this.component.fontAsset = asset.id;
261
+ }
262
+ }
263
+
264
+ /**
265
+ * Gets the id of the `pc-asset` to use for the font.
266
+ * @returns The font asset ID.
267
+ */
268
+ get fontAsset() {
269
+ return this._fontAsset;
270
+ }
271
+
272
272
  /**
273
273
  * Sets the font size of the element component.
274
274
  * @param value - The font size.
@@ -658,13 +658,13 @@ class ElementComponentElement extends ComponentElement {
658
658
  return [
659
659
  ...super.observedAttributes,
660
660
  'anchor',
661
- 'asset',
662
661
  'auto-width',
663
662
  'auto-height',
664
663
  'auto-fit-width',
665
664
  'auto-fit-height',
666
665
  'color',
667
666
  'enable-markup',
667
+ 'font-asset',
668
668
  'font-size',
669
669
  'max-font-size',
670
670
  'min-font-size',
@@ -691,64 +691,64 @@ class ElementComponentElement extends ComponentElement {
691
691
 
692
692
  switch (name) {
693
693
  case 'anchor':
694
- this.anchor = parseVec4(newValue);
695
- break;
696
- case 'asset':
697
- this.asset = newValue;
694
+ this.anchor = parseVec4(newValue, new Vec4(0.5, 0.5, 0.5, 0.5), name);
698
695
  break;
699
696
  case 'auto-width':
700
- this.autoWidth = newValue !== 'false';
697
+ this.autoWidth = parseBool(newValue, true);
701
698
  break;
702
699
  case 'auto-height':
703
- this.autoHeight = newValue !== 'false';
700
+ this.autoHeight = parseBool(newValue, true);
704
701
  break;
705
702
  case 'auto-fit-width':
706
- this.autoFitWidth = newValue !== 'false';
703
+ this.autoFitWidth = parseBool(newValue, false);
707
704
  break;
708
705
  case 'auto-fit-height':
709
- this.autoFitHeight = newValue !== 'false';
706
+ this.autoFitHeight = parseBool(newValue, false);
710
707
  break;
711
708
  case 'color':
712
- this.color = parseColor(newValue);
709
+ this.color = parseColor(newValue, Color.WHITE, name);
713
710
  break;
714
711
  case 'enable-markup':
715
- this.enableMarkup = this.hasAttribute(name);
712
+ this.enableMarkup = parseBool(newValue, false);
713
+ break;
714
+ case 'font-asset':
715
+ this.fontAsset = newValue;
716
716
  break;
717
717
  case 'font-size':
718
- this.fontSize = Number(newValue);
718
+ this.fontSize = parseNumber(newValue, 32, name);
719
719
  break;
720
720
  case 'max-font-size':
721
- this.maxFontSize = Number(newValue);
721
+ this.maxFontSize = parseNumber(newValue, 32, name);
722
722
  break;
723
723
  case 'min-font-size':
724
- this.minFontSize = Number(newValue);
724
+ this.minFontSize = parseNumber(newValue, 8, name);
725
725
  break;
726
726
  case 'height':
727
- this.height = Number(newValue);
727
+ this.height = parseNumber(newValue, 0, name);
728
728
  break;
729
729
  case 'line-height':
730
- this.lineHeight = Number(newValue);
730
+ this.lineHeight = parseNumber(newValue, 32, name);
731
731
  break;
732
732
  case 'margin':
733
- this.margin = parseVec4(newValue);
733
+ this.margin = parseVec4(newValue, null, name);
734
734
  break;
735
735
  case 'mask':
736
- this.mask = this.hasAttribute(name);
736
+ this.mask = parseBool(newValue, false);
737
737
  break;
738
738
  case 'opacity':
739
- this.opacity = Number(newValue);
739
+ this.opacity = parseNumber(newValue, 1, name);
740
740
  break;
741
741
  case 'pivot':
742
- this.pivot = parseVec2(newValue);
742
+ this.pivot = parseVec2(newValue, new Vec2(0.5, 0.5), name);
743
743
  break;
744
744
  case 'pixels-per-unit':
745
- this.pixelsPerUnit = Number(newValue);
745
+ this.pixelsPerUnit = parseNumber(newValue, null, name);
746
746
  break;
747
747
  case 'sprite-asset':
748
748
  this.spriteAsset = newValue;
749
749
  break;
750
750
  case 'sprite-frame':
751
- this.spriteFrame = Number(newValue);
751
+ this.spriteFrame = parseNumber(newValue, 0, name);
752
752
  break;
753
753
  case 'text':
754
754
  this.text = newValue;
@@ -757,16 +757,16 @@ class ElementComponentElement extends ComponentElement {
757
757
  this.textureAsset = newValue;
758
758
  break;
759
759
  case 'type':
760
- this.type = newValue as 'group' | 'image' | 'text';
760
+ this.type = parseEnum(newValue, ['group', 'image', 'text'], 'group', name);
761
761
  break;
762
762
  case 'use-input':
763
- this.useInput = this.hasAttribute(name);
763
+ this.useInput = parseBool(newValue, false);
764
764
  break;
765
765
  case 'width':
766
- this.width = Number(newValue);
766
+ this.width = parseNumber(newValue, 0, name);
767
767
  break;
768
768
  case 'wrap-lines':
769
- this.wrapLines = this.hasAttribute(name);
769
+ this.wrapLines = parseBool(newValue, false);
770
770
  break;
771
771
  }
772
772
  }
@@ -774,4 +774,10 @@ class ElementComponentElement extends ComponentElement {
774
774
 
775
775
  customElements.define('pc-element', ElementComponentElement);
776
776
 
777
+ declare global {
778
+ interface HTMLElementTagNameMap {
779
+ 'pc-element': ElementComponentElement;
780
+ }
781
+ }
782
+
777
783
  export { ElementComponentElement };