@playcanvas/web-components 0.8.2 → 0.10.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 (79) hide show
  1. package/README.md +18 -0
  2. package/dist/app.d.ts +13 -4
  3. package/dist/asset.d.ts +33 -3
  4. package/dist/async-element.d.ts +54 -4
  5. package/dist/components/button-component.d.ts +11 -5
  6. package/dist/components/camera-component.d.ts +10 -5
  7. package/dist/components/collision-component.d.ts +10 -5
  8. package/dist/components/component.d.ts +8 -2
  9. package/dist/components/element-component.d.ts +18 -13
  10. package/dist/components/gsplat-component.d.ts +7 -2
  11. package/dist/components/layoutchild-component.d.ts +7 -2
  12. package/dist/components/layoutgroup-component.d.ts +22 -16
  13. package/dist/components/light-component.d.ts +13 -7
  14. package/dist/components/listener-component.d.ts +6 -1
  15. package/dist/components/particlesystem-component.d.ts +7 -2
  16. package/dist/components/render-component.d.ts +14 -5
  17. package/dist/components/rigidbody-component.d.ts +10 -5
  18. package/dist/components/screen-component.d.ts +7 -2
  19. package/dist/components/script-component.d.ts +116 -16
  20. package/dist/components/script.d.ts +79 -8
  21. package/dist/components/scrollbar-component.d.ts +11 -5
  22. package/dist/components/scrollview-component.d.ts +18 -11
  23. package/dist/components/sound-component.d.ts +7 -2
  24. package/dist/components/sound-slot.d.ts +17 -4
  25. package/dist/custom-elements.json +16231 -0
  26. package/dist/entity.d.ts +45 -3
  27. package/dist/index.d.ts +3 -2
  28. package/dist/material.d.ts +976 -4
  29. package/dist/model.d.ts +6 -1
  30. package/dist/module.d.ts +15 -0
  31. package/dist/parse.d.ts +144 -0
  32. package/dist/pwc.cjs +5735 -2923
  33. package/dist/pwc.cjs.map +1 -1
  34. package/dist/pwc.js +5735 -2923
  35. package/dist/pwc.js.map +1 -1
  36. package/dist/pwc.min.js +1 -1
  37. package/dist/pwc.min.js.map +1 -1
  38. package/dist/pwc.min.mjs +2 -0
  39. package/dist/pwc.min.mjs.map +1 -0
  40. package/dist/pwc.mjs +5736 -2925
  41. package/dist/pwc.mjs.map +1 -1
  42. package/dist/scene.d.ts +15 -6
  43. package/dist/sky.d.ts +7 -1
  44. package/dist/vscode.html-custom-data.json +1795 -0
  45. package/dist/web-types.json +3592 -0
  46. package/package.json +32 -14
  47. package/src/app.ts +42 -15
  48. package/src/asset.ts +78 -8
  49. package/src/async-element.ts +89 -5
  50. package/src/components/button-component.ts +31 -24
  51. package/src/components/camera-component.ts +30 -24
  52. package/src/components/collision-component.ts +20 -14
  53. package/src/components/component.ts +33 -14
  54. package/src/components/element-component.ts +62 -56
  55. package/src/components/gsplat-component.ts +16 -9
  56. package/src/components/layoutchild-component.ts +17 -10
  57. package/src/components/layoutgroup-component.ts +39 -32
  58. package/src/components/light-component.ts +34 -32
  59. package/src/components/listener-component.ts +8 -2
  60. package/src/components/particlesystem-component.ts +10 -4
  61. package/src/components/render-component.ts +28 -12
  62. package/src/components/rigidbody-component.ts +22 -16
  63. package/src/components/screen-component.ts +16 -10
  64. package/src/components/script-component.ts +512 -125
  65. package/src/components/script.ts +123 -16
  66. package/src/components/scrollbar-component.ts +21 -14
  67. package/src/components/scrollview-component.ts +42 -34
  68. package/src/components/sound-component.ts +17 -10
  69. package/src/components/sound-slot.ts +50 -19
  70. package/src/entity.ts +84 -76
  71. package/src/index.ts +5 -2
  72. package/src/material.ts +2432 -62
  73. package/src/model.ts +8 -2
  74. package/src/module.ts +16 -0
  75. package/src/parse.ts +298 -0
  76. package/src/scene.ts +26 -13
  77. package/src/sky.ts +36 -18
  78. package/dist/utils.d.ts +0 -56
  79. package/src/utils.ts +0 -119
@@ -1,23 +1,71 @@
1
+ import { Script } from 'playcanvas';
2
+
3
+ import { AsyncElement } from '../async-element';
4
+ import { parseBool } from '../parse';
5
+
1
6
  /**
2
7
  * The ScriptElement interface provides properties and methods for manipulating
3
8
  * `<pc-script>` elements. The ScriptElement interface also inherits the properties and
4
- * methods of the {@link HTMLElement} interface.
9
+ * methods of the {@link AsyncElement} interface.
10
+ *
11
+ * Script attributes can be supplied through two channels:
12
+ *
13
+ * - **Per-property attributes**: any non-reserved attribute on the element maps to the script
14
+ * attribute of the same name (kebab-case to camelCase, e.g. `focus-point` → `focusPoint`).
15
+ * Values are parsed according to the type of the attribute's current value — initially the
16
+ * script's declared default (numbers, booleans, strings, Vec2/3/4, Color, Quat as Euler
17
+ * angles) — and the `asset:`/`entity:`/`vec2:`/`vec3:`/`vec4:`/`color:` prefixes may be used
18
+ * to be explicit.
19
+ * - **The `attributes` JSON attribute**: an object supporting nested structures and attribute
20
+ * names that collide with reserved HTML attribute names (e.g. `title`).
21
+ *
22
+ * When both specify the same attribute, the per-property attribute wins — at creation and
23
+ * whenever either channel changes at runtime. The element's own `name` and `enabled`
24
+ * attributes configure the element itself and are not script attributes.
25
+ *
26
+ * Changing `name` on a live element destroys the old-name script instance and creates the
27
+ * new-name one, re-applying both attribute channels to it.
28
+ *
29
+ * The element becomes ready once its script instance has been created by the parent
30
+ * `<pc-scripts>` element.
31
+ *
32
+ * @fires {CustomEvent} scriptattributeschange - Fired when the script's attributes change. The
33
+ * `detail` carries the new `attributes` object. Bubbles.
34
+ * @fires {CustomEvent} scriptenablechange - Fired when the script's enabled state changes. The
35
+ * `detail` carries the new `enabled` state. Bubbles.
36
+ * @fires {CustomEvent} scriptnamechange - Fired when the script is renamed on a live element. The
37
+ * `detail` carries `oldName` and `newName`. Bubbles.
5
38
  */
6
- class ScriptElement extends HTMLElement {
7
- private _attributes: string = '{}';
39
+ class ScriptElement extends AsyncElement {
40
+ private _attributes: Record<string, any> = {};
8
41
 
9
42
  private _enabled: boolean = true;
10
43
 
11
- private _name: string = '';
44
+ /**
45
+ * Whether readiness has been signalled. Creation can happen more than once over an
46
+ * element's life (a runtime `name` change recreates the instance), but `ready` is a
47
+ * one-shot signal, so only the first successful creation fires it.
48
+ */
49
+ private _readySignalled: boolean = false;
12
50
 
13
51
  /**
14
- * Sets the attributes of the script.
52
+ * The Script instance created for this element by its parent `<pc-scripts>` element.
53
+ * @ignore
54
+ */
55
+ _script: Script | null = null;
56
+
57
+ /**
58
+ * Sets the attributes of the script as an object. Values are converted with the same rules
59
+ * as the `attributes` attribute: `asset:`/`entity:` references and `vec2:`/`vec3:`/`vec4:`/
60
+ * `color:` prefixed strings are resolved, and a plain numeric array is converted to the
61
+ * type of the attribute it targets when that attribute currently holds a Vec2, Vec3, Vec4
62
+ * or Color.
15
63
  * @param value - The attributes of the script.
16
64
  */
17
- set scriptAttributes(value: string) {
18
- this._attributes = value;
65
+ set scriptAttributes(value: Record<string, any>) {
66
+ this._attributes = value ?? {};
19
67
  this.dispatchEvent(new CustomEvent('scriptattributeschange', {
20
- detail: { attributes: value },
68
+ detail: { attributes: this._attributes },
21
69
  bubbles: true
22
70
  }));
23
71
  }
@@ -26,7 +74,7 @@ class ScriptElement extends HTMLElement {
26
74
  * Gets the attributes of the script.
27
75
  * @returns The attributes of the script.
28
76
  */
29
- get scriptAttributes() {
77
+ get scriptAttributes(): Record<string, any> {
30
78
  return this._attributes;
31
79
  }
32
80
 
@@ -51,11 +99,20 @@ class ScriptElement extends HTMLElement {
51
99
  }
52
100
 
53
101
  /**
54
- * Sets the name of the script to create.
102
+ * Sets the name of the script to create. The `name` attribute is the single source of truth
103
+ * (it is what the parent `<pc-scripts>` element reads when creating the instance), so the
104
+ * property writes through to it — assigning before insertion works as expected:
105
+ *
106
+ * ```js
107
+ * const script = document.createElement('pc-script');
108
+ * script.name = 'rotate';
109
+ * scriptsElement.appendChild(script);
110
+ * await script.ready();
111
+ * ```
55
112
  * @param value - The name.
56
113
  */
57
114
  set name(value: string) {
58
- this._name = value;
115
+ this.setAttribute('name', value);
59
116
  }
60
117
 
61
118
  /**
@@ -63,23 +120,67 @@ class ScriptElement extends HTMLElement {
63
120
  * @returns The name.
64
121
  */
65
122
  get name() {
66
- return this._name;
123
+ return this.getAttribute('name') ?? '';
124
+ }
125
+
126
+ /**
127
+ * Gets the {@link Script} instance created for this element. Returns `null` until the
128
+ * instance exists — await {@link whenReady} or the element's `ready()` promise before
129
+ * accessing it.
130
+ * @returns The script instance, or `null`.
131
+ */
132
+ get script(): Script | null {
133
+ return this._script;
134
+ }
135
+
136
+ connectedCallback() {
137
+ // Script instances are created by the parent pc-scripts element, so an element placed
138
+ // anywhere else is inert and never becomes ready - warn rather than hang silently
139
+ if (this.parentElement?.tagName !== 'PC-SCRIPTS') {
140
+ console.warn(`pc-script '${this.getAttribute('name')}' must be a direct child of pc-scripts - script not created`);
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Called by the parent `<pc-scripts>` element when the script instance has been created.
146
+ * @ignore
147
+ */
148
+ _onScriptCreated() {
149
+ if (this._readySignalled) return;
150
+ this._readySignalled = true;
151
+ this._onReady();
67
152
  }
68
153
 
69
154
  static get observedAttributes() {
70
155
  return ['attributes', 'enabled', 'name'];
71
156
  }
72
157
 
73
- attributeChangedCallback(name: string, _oldValue: string, newValue: string) {
158
+ attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null) {
74
159
  switch (name) {
75
160
  case 'attributes':
76
- this.scriptAttributes = newValue;
161
+ if (newValue === null) {
162
+ this.scriptAttributes = {};
163
+ break;
164
+ }
165
+ try {
166
+ this.scriptAttributes = JSON.parse(newValue);
167
+ } catch (error) {
168
+ console.warn(`Invalid 'attributes' JSON on pc-script '${this.getAttribute('name')}': ${(error as Error).message}`);
169
+ }
77
170
  break;
78
171
  case 'enabled':
79
- this.enabled = newValue !== 'false';
172
+ this.enabled = parseBool(newValue, true);
80
173
  break;
81
174
  case 'name':
82
- this.name = newValue;
175
+ // The first set is handled by the parent's creation paths (the boot query and
176
+ // the added-node mutation), so only a genuine rename is signalled here. Note
177
+ // that setAttribute fires this callback even when the value is unchanged.
178
+ if (oldValue !== null && oldValue !== newValue) {
179
+ this.dispatchEvent(new CustomEvent('scriptnamechange', {
180
+ detail: { oldName: oldValue, newName: newValue },
181
+ bubbles: true
182
+ }));
183
+ }
83
184
  break;
84
185
  }
85
186
  }
@@ -87,4 +188,10 @@ class ScriptElement extends HTMLElement {
87
188
 
88
189
  customElements.define('pc-script', ScriptElement);
89
190
 
191
+ declare global {
192
+ interface HTMLElementTagNameMap {
193
+ 'pc-script': ScriptElement;
194
+ }
195
+ }
196
+
90
197
  export { ScriptElement };
@@ -1,9 +1,9 @@
1
1
  import { ORIENTATION_HORIZONTAL, ORIENTATION_VERTICAL, ScrollbarComponent } from 'playcanvas';
2
2
 
3
3
  import { ComponentElement } from './component';
4
- import { getEntity, parseEnum } from '../utils';
4
+ import { getEntity, parseEnum, parseNumber } from '../parse';
5
5
 
6
- const orientations = new Map<string, number>([
6
+ const orientations = new Map<'horizontal' | 'vertical', number>([
7
7
  ['horizontal', ORIENTATION_HORIZONTAL],
8
8
  ['vertical', ORIENTATION_VERTICAL]
9
9
  ]);
@@ -17,7 +17,7 @@ const orientations = new Map<string, number>([
17
17
  * @category Components
18
18
  */
19
19
  class ScrollbarComponentElement extends ComponentElement {
20
- private _orientation: number = ORIENTATION_HORIZONTAL;
20
+ private _orientation: 'horizontal' | 'vertical' = 'horizontal';
21
21
 
22
22
  private _value = 0;
23
23
 
@@ -32,7 +32,7 @@ class ScrollbarComponentElement extends ComponentElement {
32
32
 
33
33
  getInitialComponentData() {
34
34
  const data: Record<string, any> = {
35
- orientation: this._orientation,
35
+ orientation: orientations.get(this._orientation),
36
36
  value: this._value,
37
37
  handleSize: this._handleSize
38
38
  };
@@ -49,18 +49,19 @@ class ScrollbarComponentElement extends ComponentElement {
49
49
  * Gets the underlying PlayCanvas scrollbar component.
50
50
  * @returns The scrollbar component.
51
51
  */
52
- get component(): ScrollbarComponent | null {
53
- return super.component as ScrollbarComponent | null;
52
+ get component(): ScrollbarComponent {
53
+ return super.component as ScrollbarComponent;
54
54
  }
55
55
 
56
56
  /**
57
- * Sets the orientation of the scrollbar. Can be `horizontal` (0) or `vertical` (1).
57
+ * Sets the orientation of the scrollbar. Can be `horizontal` or `vertical`. Defaults to
58
+ * `horizontal`.
58
59
  * @param value - The orientation.
59
60
  */
60
- set orientation(value: number) {
61
+ set orientation(value: 'horizontal' | 'vertical') {
61
62
  this._orientation = value;
62
63
  if (this.component) {
63
- this.component.orientation = value;
64
+ this.component.orientation = orientations.get(value) ?? ORIENTATION_HORIZONTAL;
64
65
  }
65
66
  }
66
67
 
@@ -141,21 +142,21 @@ class ScrollbarComponentElement extends ComponentElement {
141
142
  ];
142
143
  }
143
144
 
144
- attributeChangedCallback(name: string, _oldValue: string, newValue: string) {
145
+ attributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null) {
145
146
  super.attributeChangedCallback(name, _oldValue, newValue);
146
147
 
147
148
  switch (name) {
148
149
  case 'orientation':
149
- this.orientation = parseEnum(newValue, orientations, ORIENTATION_HORIZONTAL);
150
+ this.orientation = parseEnum(newValue, orientations, 'horizontal', name);
150
151
  break;
151
152
  case 'value':
152
- this.value = Number(newValue);
153
+ this.value = parseNumber(newValue, 0, name);
153
154
  break;
154
155
  case 'handle-size':
155
- this.handleSize = Number(newValue);
156
+ this.handleSize = parseNumber(newValue, 0.5, name);
156
157
  break;
157
158
  case 'handle':
158
- this.handle = newValue;
159
+ this.handle = newValue ?? '';
159
160
  break;
160
161
  }
161
162
  }
@@ -163,4 +164,10 @@ class ScrollbarComponentElement extends ComponentElement {
163
164
 
164
165
  customElements.define('pc-scrollbar', ScrollbarComponentElement);
165
166
 
167
+ declare global {
168
+ interface HTMLElementTagNameMap {
169
+ 'pc-scrollbar': ScrollbarComponentElement;
170
+ }
171
+ }
172
+
166
173
  export { ScrollbarComponentElement };
@@ -1,15 +1,15 @@
1
1
  import { SCROLL_MODE_BOUNCE, SCROLL_MODE_CLAMP, SCROLL_MODE_INFINITE, SCROLLBAR_VISIBILITY_SHOW_ALWAYS, SCROLLBAR_VISIBILITY_SHOW_WHEN_REQUIRED, ScrollViewComponent, Vec2 } from 'playcanvas';
2
2
 
3
3
  import { ComponentElement } from './component';
4
- import { getEntity, parseEnum, parseVec2 } from '../utils';
4
+ import { getEntity, parseBool, parseEnum, parseNumber, parseVec2 } from '../parse';
5
5
 
6
- const scrollModes = new Map<string, number>([
6
+ const scrollModes = new Map<'clamp' | 'bounce' | 'infinite', number>([
7
7
  ['clamp', SCROLL_MODE_CLAMP],
8
8
  ['bounce', SCROLL_MODE_BOUNCE],
9
9
  ['infinite', SCROLL_MODE_INFINITE]
10
10
  ]);
11
11
 
12
- const visibilities = new Map<string, number>([
12
+ const visibilities = new Map<'always' | 'when-required', number>([
13
13
  ['always', SCROLLBAR_VISIBILITY_SHOW_ALWAYS],
14
14
  ['when-required', SCROLLBAR_VISIBILITY_SHOW_WHEN_REQUIRED]
15
15
  ]);
@@ -27,7 +27,7 @@ class ScrollViewComponentElement extends ComponentElement {
27
27
 
28
28
  private _vertical = true;
29
29
 
30
- private _scrollMode: number = SCROLL_MODE_BOUNCE;
30
+ private _scrollMode: 'clamp' | 'bounce' | 'infinite' = 'bounce';
31
31
 
32
32
  private _bounceAmount = 0.1;
33
33
 
@@ -37,9 +37,9 @@ class ScrollViewComponentElement extends ComponentElement {
37
37
 
38
38
  private _mouseWheelSensitivity = new Vec2(1, 1);
39
39
 
40
- private _horizontalScrollbarVisibility: number = SCROLLBAR_VISIBILITY_SHOW_WHEN_REQUIRED;
40
+ private _horizontalScrollbarVisibility: 'always' | 'when-required' = 'when-required';
41
41
 
42
- private _verticalScrollbarVisibility: number = SCROLLBAR_VISIBILITY_SHOW_WHEN_REQUIRED;
42
+ private _verticalScrollbarVisibility: 'always' | 'when-required' = 'when-required';
43
43
 
44
44
  private _viewport = '';
45
45
 
@@ -58,13 +58,13 @@ class ScrollViewComponentElement extends ComponentElement {
58
58
  const data: Record<string, any> = {
59
59
  horizontal: this._horizontal,
60
60
  vertical: this._vertical,
61
- scrollMode: this._scrollMode,
61
+ scrollMode: scrollModes.get(this._scrollMode),
62
62
  bounceAmount: this._bounceAmount,
63
63
  friction: this._friction,
64
64
  useMouseWheel: this._useMouseWheel,
65
65
  mouseWheelSensitivity: this._mouseWheelSensitivity,
66
- horizontalScrollbarVisibility: this._horizontalScrollbarVisibility,
67
- verticalScrollbarVisibility: this._verticalScrollbarVisibility
66
+ horizontalScrollbarVisibility: visibilities.get(this._horizontalScrollbarVisibility),
67
+ verticalScrollbarVisibility: visibilities.get(this._verticalScrollbarVisibility)
68
68
  };
69
69
 
70
70
  const viewport = getEntity(this._viewport);
@@ -94,8 +94,8 @@ class ScrollViewComponentElement extends ComponentElement {
94
94
  * Gets the underlying PlayCanvas scroll view component.
95
95
  * @returns The scroll view component.
96
96
  */
97
- get component(): ScrollViewComponent | null {
98
- return super.component as ScrollViewComponent | null;
97
+ get component(): ScrollViewComponent {
98
+ return super.component as ScrollViewComponent;
99
99
  }
100
100
 
101
101
  /**
@@ -138,13 +138,13 @@ class ScrollViewComponentElement extends ComponentElement {
138
138
 
139
139
  /**
140
140
  * Sets how the scroll view should behave when the content is scrolled beyond its bounds. Can be
141
- * `clamp` (0), `bounce` (1) or `infinite` (2).
141
+ * `clamp`, `bounce` or `infinite`. Defaults to `bounce`.
142
142
  * @param value - The scroll mode.
143
143
  */
144
- set scrollMode(value: number) {
144
+ set scrollMode(value: 'clamp' | 'bounce' | 'infinite') {
145
145
  this._scrollMode = value;
146
146
  if (this.component) {
147
- this.component.scrollMode = value;
147
+ this.component.scrollMode = scrollModes.get(value) ?? SCROLL_MODE_BOUNCE;
148
148
  }
149
149
  }
150
150
 
@@ -235,13 +235,14 @@ class ScrollViewComponentElement extends ComponentElement {
235
235
  }
236
236
 
237
237
  /**
238
- * Sets the visibility of the horizontal scrollbar. Can be `always` (0) or `when-required` (1).
238
+ * Sets the visibility of the horizontal scrollbar. Can be `always` or `when-required`.
239
+ * Defaults to `when-required`.
239
240
  * @param value - The horizontal scrollbar visibility.
240
241
  */
241
- set horizontalScrollbarVisibility(value: number) {
242
+ set horizontalScrollbarVisibility(value: 'always' | 'when-required') {
242
243
  this._horizontalScrollbarVisibility = value;
243
244
  if (this.component) {
244
- this.component.horizontalScrollbarVisibility = value;
245
+ this.component.horizontalScrollbarVisibility = visibilities.get(value) ?? SCROLLBAR_VISIBILITY_SHOW_WHEN_REQUIRED;
245
246
  }
246
247
  }
247
248
 
@@ -254,13 +255,14 @@ class ScrollViewComponentElement extends ComponentElement {
254
255
  }
255
256
 
256
257
  /**
257
- * Sets the visibility of the vertical scrollbar. Can be `always` (0) or `when-required` (1).
258
+ * Sets the visibility of the vertical scrollbar. Can be `always` or `when-required`.
259
+ * Defaults to `when-required`.
258
260
  * @param value - The vertical scrollbar visibility.
259
261
  */
260
- set verticalScrollbarVisibility(value: number) {
262
+ set verticalScrollbarVisibility(value: 'always' | 'when-required') {
261
263
  this._verticalScrollbarVisibility = value;
262
264
  if (this.component) {
263
- this.component.verticalScrollbarVisibility = value;
265
+ this.component.verticalScrollbarVisibility = visibilities.get(value) ?? SCROLLBAR_VISIBILITY_SHOW_WHEN_REQUIRED;
264
266
  }
265
267
  }
266
268
 
@@ -375,48 +377,48 @@ class ScrollViewComponentElement extends ComponentElement {
375
377
  ];
376
378
  }
377
379
 
378
- attributeChangedCallback(name: string, _oldValue: string, newValue: string) {
380
+ attributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null) {
379
381
  super.attributeChangedCallback(name, _oldValue, newValue);
380
382
 
381
383
  switch (name) {
382
384
  case 'horizontal':
383
- this.horizontal = newValue !== 'false';
385
+ this.horizontal = parseBool(newValue, true);
384
386
  break;
385
387
  case 'vertical':
386
- this.vertical = newValue !== 'false';
388
+ this.vertical = parseBool(newValue, true);
387
389
  break;
388
390
  case 'scroll-mode':
389
- this.scrollMode = parseEnum(newValue, scrollModes, SCROLL_MODE_BOUNCE);
391
+ this.scrollMode = parseEnum(newValue, scrollModes, 'bounce', name);
390
392
  break;
391
393
  case 'bounce-amount':
392
- this.bounceAmount = Number(newValue);
394
+ this.bounceAmount = parseNumber(newValue, 0.1, name);
393
395
  break;
394
396
  case 'friction':
395
- this.friction = Number(newValue);
397
+ this.friction = parseNumber(newValue, 0.05, name);
396
398
  break;
397
399
  case 'use-mouse-wheel':
398
- this.useMouseWheel = newValue !== 'false';
400
+ this.useMouseWheel = parseBool(newValue, true);
399
401
  break;
400
402
  case 'mouse-wheel-sensitivity':
401
- this.mouseWheelSensitivity = parseVec2(newValue);
403
+ this.mouseWheelSensitivity = parseVec2(newValue, Vec2.ONE, name);
402
404
  break;
403
405
  case 'horizontal-scrollbar-visibility':
404
- this.horizontalScrollbarVisibility = parseEnum(newValue, visibilities, SCROLLBAR_VISIBILITY_SHOW_WHEN_REQUIRED);
406
+ this.horizontalScrollbarVisibility = parseEnum(newValue, visibilities, 'when-required', name);
405
407
  break;
406
408
  case 'vertical-scrollbar-visibility':
407
- this.verticalScrollbarVisibility = parseEnum(newValue, visibilities, SCROLLBAR_VISIBILITY_SHOW_WHEN_REQUIRED);
409
+ this.verticalScrollbarVisibility = parseEnum(newValue, visibilities, 'when-required', name);
408
410
  break;
409
411
  case 'viewport':
410
- this.viewport = newValue;
412
+ this.viewport = newValue ?? '';
411
413
  break;
412
414
  case 'content':
413
- this.content = newValue;
415
+ this.content = newValue ?? '';
414
416
  break;
415
417
  case 'horizontal-scrollbar':
416
- this.horizontalScrollbar = newValue;
418
+ this.horizontalScrollbar = newValue ?? '';
417
419
  break;
418
420
  case 'vertical-scrollbar':
419
- this.verticalScrollbar = newValue;
421
+ this.verticalScrollbar = newValue ?? '';
420
422
  break;
421
423
  }
422
424
  }
@@ -424,4 +426,10 @@ class ScrollViewComponentElement extends ComponentElement {
424
426
 
425
427
  customElements.define('pc-scrollview', ScrollViewComponentElement);
426
428
 
429
+ declare global {
430
+ interface HTMLElementTagNameMap {
431
+ 'pc-scrollview': ScrollViewComponentElement;
432
+ }
433
+ }
434
+
427
435
  export { ScrollViewComponentElement };
@@ -1,6 +1,7 @@
1
1
  import { SoundComponent } from 'playcanvas';
2
2
 
3
3
  import { ComponentElement } from './component';
4
+ import { parseBool, parseEnum, parseNumber } from '../parse';
4
5
 
5
6
  /**
6
7
  * The SoundComponentElement interface provides properties and methods for manipulating
@@ -46,8 +47,8 @@ class SoundComponentElement extends ComponentElement {
46
47
  * Gets the underlying PlayCanvas sound component.
47
48
  * @returns The sound component.
48
49
  */
49
- get component(): SoundComponent | null {
50
- return super.component as SoundComponent | null;
50
+ get component(): SoundComponent {
51
+ return super.component as SoundComponent;
51
52
  }
52
53
 
53
54
  /**
@@ -196,30 +197,30 @@ class SoundComponentElement extends ComponentElement {
196
197
  ];
197
198
  }
198
199
 
199
- attributeChangedCallback(name: string, _oldValue: string, newValue: string) {
200
+ attributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null) {
200
201
  super.attributeChangedCallback(name, _oldValue, newValue);
201
202
 
202
203
  switch (name) {
203
204
  case 'distance-model':
204
- this.distanceModel = newValue as 'exponential' | 'inverse' | 'linear';
205
+ this.distanceModel = parseEnum(newValue, ['exponential', 'inverse', 'linear'], 'linear', name);
205
206
  break;
206
207
  case 'max-distance':
207
- this.maxDistance = parseFloat(newValue);
208
+ this.maxDistance = parseNumber(newValue, 10000, name);
208
209
  break;
209
210
  case 'pitch':
210
- this.pitch = parseFloat(newValue);
211
+ this.pitch = parseNumber(newValue, 1, name);
211
212
  break;
212
213
  case 'positional':
213
- this.positional = this.hasAttribute('positional');
214
+ this.positional = parseBool(newValue, false);
214
215
  break;
215
216
  case 'ref-distance':
216
- this.refDistance = parseFloat(newValue);
217
+ this.refDistance = parseNumber(newValue, 1, name);
217
218
  break;
218
219
  case 'roll-off-factor':
219
- this.rollOffFactor = parseFloat(newValue);
220
+ this.rollOffFactor = parseNumber(newValue, 1, name);
220
221
  break;
221
222
  case 'volume':
222
- this.volume = parseFloat(newValue);
223
+ this.volume = parseNumber(newValue, 1, name);
223
224
  break;
224
225
  }
225
226
  }
@@ -227,4 +228,10 @@ class SoundComponentElement extends ComponentElement {
227
228
 
228
229
  customElements.define('pc-sounds', SoundComponentElement);
229
230
 
231
+ declare global {
232
+ interface HTMLElementTagNameMap {
233
+ 'pc-sounds': SoundComponentElement;
234
+ }
235
+ }
236
+
230
237
  export { SoundComponentElement };