@playcanvas/web-components 0.8.1 → 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 +23 -13
  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
package/src/entity.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { AppBase, Entity, Vec3 } from 'playcanvas';
2
2
 
3
3
  import { AsyncElement } from './async-element';
4
- import { parseVec3 } from './utils';
4
+ import { parseBool, parseVec3 } from './utils';
5
5
 
6
6
  /**
7
7
  * The EntityElement interface provides properties and methods for manipulating
@@ -45,76 +45,48 @@ class EntityElement extends AsyncElement {
45
45
  */
46
46
  private _listeners: { [key: string]: EventListener[] } = {};
47
47
 
48
+ /**
49
+ * The event types for which an inline `onpointer*` attribute is currently present.
50
+ */
51
+ private _inlineHandlerTypes = new Set<string>();
52
+
48
53
  /**
49
54
  * Whether the hierarchy has been built for this entity.
50
55
  */
51
56
  private _built = false;
52
57
 
58
+ private _entity: Entity | null = null;
59
+
53
60
  /**
54
- * The PlayCanvas entity instance.
61
+ * The PlayCanvas entity instance. Available once the element is ready — await
62
+ * {@link whenReady} or the element's `ready()` promise before accessing it.
63
+ * @returns The entity instance.
55
64
  */
56
- entity: Entity | null = null;
65
+ get entity(): Entity {
66
+ return this._entity!;
67
+ }
57
68
 
58
69
  createEntity(app: AppBase) {
59
70
  // Guard against double creation. When a subtree is inserted at runtime (e.g. cloning a
60
71
  // `<template>`), an ancestor's connectedCallback eagerly creates descendant entities; the
61
72
  // descendants' own connectedCallbacks would otherwise create them a second time.
62
- if (this.entity) {
73
+ if (this._entity) {
63
74
  return;
64
75
  }
65
76
 
66
77
  // Create a new entity
67
- this.entity = new Entity(this.getAttribute('name') || this._name, app);
68
-
69
- const enabled = this.getAttribute('enabled');
70
- if (enabled) {
71
- this.entity.enabled = enabled !== 'false';
72
- }
78
+ const entity = new Entity(this.getAttribute('name') || this._name, app);
79
+ this._entity = entity;
73
80
 
74
- const position = this.getAttribute('position');
75
- if (position) {
76
- this.entity.setLocalPosition(parseVec3(position));
77
- }
78
-
79
- const rotation = this.getAttribute('rotation');
80
- if (rotation) {
81
- this.entity.setLocalEulerAngles(parseVec3(rotation));
82
- }
83
-
84
- const scale = this.getAttribute('scale');
85
- if (scale) {
86
- this.entity.setLocalScale(parseVec3(scale));
87
- }
81
+ entity.enabled = parseBool(this.getAttribute('enabled'), true);
82
+ entity.setLocalPosition(parseVec3(this.getAttribute('position'), Vec3.ZERO, 'position'));
83
+ entity.setLocalEulerAngles(parseVec3(this.getAttribute('rotation'), Vec3.ZERO, 'rotation'));
84
+ entity.setLocalScale(parseVec3(this.getAttribute('scale'), Vec3.ONE, 'scale'));
88
85
 
89
86
  const tags = this.getAttribute('tags');
90
87
  if (tags) {
91
- this.entity.tags.add(tags.split(',').map(tag => tag.trim()));
88
+ entity.tags.add(tags.split(',').map(tag => tag.trim()));
92
89
  }
93
-
94
- // Handle pointer events
95
- const pointerEvents = [
96
- 'onpointerenter',
97
- 'onpointerleave',
98
- 'onpointerdown',
99
- 'onpointerup',
100
- 'onpointermove'
101
- ];
102
-
103
- pointerEvents.forEach((eventName) => {
104
- const handler = this.getAttribute(eventName);
105
- if (handler) {
106
- const eventType = eventName.substring(2); // remove 'on' prefix
107
- const eventHandler = (event: Event) => {
108
- try {
109
- /* eslint-disable-next-line no-new-func */
110
- new Function('event', handler).call(this, event);
111
- } catch (e) {
112
- console.error('Error in event handler:', e);
113
- }
114
- };
115
- this.addEventListener(eventType, eventHandler);
116
- }
117
- });
118
90
  }
119
91
 
120
92
  buildHierarchy(app: AppBase) {
@@ -159,12 +131,12 @@ class EntityElement extends AsyncElement {
159
131
  // Notify all children that their entities are about to become invalid
160
132
  const children = this.querySelectorAll('pc-entity');
161
133
  children.forEach((child) => {
162
- (child as EntityElement).entity = null;
134
+ (child as EntityElement)._entity = null;
163
135
  });
164
136
 
165
137
  // Destroy the entity
166
138
  this.entity.destroy();
167
- this.entity = null;
139
+ this._entity = null;
168
140
  this._built = false;
169
141
  }
170
142
  }
@@ -284,6 +256,31 @@ class EntityElement extends AsyncElement {
284
256
  return this._tags;
285
257
  }
286
258
 
259
+ /**
260
+ * Tracks whether an inline `onpointer*` attribute is present. The browser itself compiles and
261
+ * runs these attributes — they are standard `GlobalEventHandlers`, so setting one replaces
262
+ * the previous handler and removing it removes the handler, exactly like `onclick` on any
263
+ * HTML element. But because they bypass {@link addEventListener}, the connect/disconnect
264
+ * bookkeeping that lets the application lazily attach its canvas pointer handlers must be
265
+ * kept in sync here.
266
+ *
267
+ * @param name - The attribute name (e.g. 'onpointerdown').
268
+ * @param value - The attribute value, or `null` when the attribute has been removed.
269
+ */
270
+ private _updateInlineHandler(name: string, value: string | null) {
271
+ const type = name.substring(2);
272
+ const had = this._inlineHandlerTypes.has(type);
273
+ const has = value !== null;
274
+
275
+ if (has && !had) {
276
+ this._inlineHandlerTypes.add(type);
277
+ this.dispatchEvent(new CustomEvent(`${type}:connect`, { bubbles: true }));
278
+ } else if (!has && had) {
279
+ this._inlineHandlerTypes.delete(type);
280
+ this.dispatchEvent(new CustomEvent(`${type}:disconnect`, { bubbles: true }));
281
+ }
282
+ }
283
+
287
284
  static get observedAttributes() {
288
285
  return [
289
286
  'enabled',
@@ -303,19 +300,19 @@ class EntityElement extends AsyncElement {
303
300
  attributeChangedCallback(name: string, _oldValue: string, newValue: string) {
304
301
  switch (name) {
305
302
  case 'enabled':
306
- this.enabled = newValue !== 'false';
303
+ this.enabled = parseBool(newValue, true);
307
304
  break;
308
305
  case 'name':
309
306
  this.name = newValue;
310
307
  break;
311
308
  case 'position':
312
- this.position = parseVec3(newValue);
309
+ this.position = parseVec3(newValue, Vec3.ZERO, name);
313
310
  break;
314
311
  case 'rotation':
315
- this.rotation = parseVec3(newValue);
312
+ this.rotation = parseVec3(newValue, Vec3.ZERO, name);
316
313
  break;
317
314
  case 'scale':
318
- this.scale = parseVec3(newValue);
315
+ this.scale = parseVec3(newValue, Vec3.ONE, name);
319
316
  break;
320
317
  case 'tags':
321
318
  this.tags = newValue.split(',').map(tag => tag.trim());
@@ -325,20 +322,7 @@ class EntityElement extends AsyncElement {
325
322
  case 'onpointerdown':
326
323
  case 'onpointerup':
327
324
  case 'onpointermove':
328
- if (newValue) {
329
- const eventName = name.substring(2);
330
- // Use Function.prototype.bind to avoid new Function
331
- const handler = (event: Event) => {
332
- try {
333
- const handlerStr = this.getAttribute(eventName) || '';
334
- /* eslint-disable-next-line no-new-func */
335
- new Function('event', handlerStr).call(this, event);
336
- } catch (e) {
337
- console.error('Error in event handler:', e);
338
- }
339
- };
340
- this.addEventListener(eventName, handler);
341
- }
325
+ this._updateInlineHandler(name, newValue);
342
326
  break;
343
327
  }
344
328
  }
@@ -365,10 +349,16 @@ class EntityElement extends AsyncElement {
365
349
  }
366
350
 
367
351
  hasListeners(type: string): boolean {
368
- return Boolean(this._listeners[type]?.length);
352
+ return Boolean(this._listeners[type]?.length) || this._inlineHandlerTypes.has(type);
369
353
  }
370
354
  }
371
355
 
372
356
  customElements.define('pc-entity', EntityElement);
373
357
 
358
+ declare global {
359
+ interface HTMLElementTagNameMap {
360
+ 'pc-entity': EntityElement;
361
+ }
362
+ }
363
+
374
364
  export { EntityElement };
package/src/index.ts CHANGED
@@ -10,7 +10,7 @@
10
10
  /* eslint-disable import/order */
11
11
 
12
12
  // Note that order matters here (e.g. pc-entity must be defined before components)
13
- import { AsyncElement } from './async-element';
13
+ import { AsyncElement, whenReady } from './async-element';
14
14
  import { ModuleElement } from './module';
15
15
  import { AppElement } from './app';
16
16
  import { EntityElement } from './entity';
@@ -69,5 +69,8 @@ export {
69
69
  MaterialElement,
70
70
  ModelElement,
71
71
  SceneElement,
72
- SkyElement
72
+ SkyElement,
73
+ whenReady
73
74
  };
75
+
76
+ export type { AsyncElementTagName } from './async-element';
package/src/material.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { Color, StandardMaterial, Texture } from 'playcanvas';
2
2
 
3
+ import { AppElement } from './app';
3
4
  import { AssetElement } from './asset';
4
5
  import { parseColor } from './utils';
5
6
 
@@ -8,6 +9,10 @@ import { parseColor } from './utils';
8
9
  * {@link https://developer.playcanvas.com/user-manual/web-components/tags/pc-material/ | `<pc-material>`} elements.
9
10
  * The MaterialElement interface also inherits the properties and methods of the
10
11
  * {@link HTMLElement} interface.
12
+ *
13
+ * A `pc-material` must be a direct child of `pc-app` — elements placed elsewhere log a warning
14
+ * and never create a material. Elements inserted while the application is already running are
15
+ * created on insertion.
11
16
  */
12
17
  class MaterialElement extends HTMLElement {
13
18
  private _diffuse = new Color(1, 1, 1);
@@ -22,6 +27,28 @@ class MaterialElement extends HTMLElement {
22
27
 
23
28
  material: StandardMaterial | null = null;
24
29
 
30
+ async connectedCallback() {
31
+ const appElement = this.parentElement?.closest('pc-app') as AppElement | null ?? null;
32
+
33
+ // Materials must be direct children of pc-app (matches the boot query ':scope > pc-material')
34
+ if (!appElement || this.parentElement !== appElement) {
35
+ console.warn(`pc-material '${this.id}' must be a direct child of pc-app - material not created`);
36
+ return;
37
+ }
38
+
39
+ await appElement.ready();
40
+
41
+ // The element may have been removed or re-parented while waiting for the app
42
+ if (!this.isConnected || this.parentElement !== appElement) return;
43
+
44
+ // Materials present at startup are created by AppElement's boot; this branch handles
45
+ // elements inserted (or re-inserted) after the app is already running
46
+ if (!this.material) {
47
+ if (!appElement.app) return; // pc-app is re-connecting; its own boot will create this
48
+ this.createMaterial();
49
+ }
50
+ }
51
+
25
52
  createMaterial() {
26
53
  this.material = new StandardMaterial();
27
54
  this.material.glossInvert = false;
@@ -118,7 +145,7 @@ class MaterialElement extends HTMLElement {
118
145
  attributeChangedCallback(name: string, _oldValue: string, newValue: string) {
119
146
  switch (name) {
120
147
  case 'diffuse':
121
- this.diffuse = parseColor(newValue);
148
+ this.diffuse = parseColor(newValue, Color.WHITE, name);
122
149
  break;
123
150
  case 'diffuse-map':
124
151
  this.diffuseMap = newValue;
@@ -138,4 +165,10 @@ class MaterialElement extends HTMLElement {
138
165
 
139
166
  customElements.define('pc-material', MaterialElement);
140
167
 
168
+ declare global {
169
+ interface HTMLElementTagNameMap {
170
+ 'pc-material': MaterialElement;
171
+ }
172
+ }
173
+
141
174
  export { MaterialElement };
package/src/model.ts CHANGED
@@ -108,4 +108,10 @@ class ModelElement extends AsyncElement {
108
108
 
109
109
  customElements.define('pc-model', ModelElement);
110
110
 
111
+ declare global {
112
+ interface HTMLElementTagNameMap {
113
+ 'pc-model': ModelElement;
114
+ }
115
+ }
116
+
111
117
  export { ModelElement };
package/src/module.ts CHANGED
@@ -40,4 +40,10 @@ class ModuleElement extends HTMLElement {
40
40
 
41
41
  customElements.define('pc-module', ModuleElement);
42
42
 
43
+ declare global {
44
+ interface HTMLElementTagNameMap {
45
+ 'pc-module': ModuleElement;
46
+ }
47
+ }
48
+
43
49
  export { ModuleElement };
package/src/scene.ts CHANGED
@@ -2,7 +2,7 @@ import { Color, Scene, Vec3 } from 'playcanvas';
2
2
 
3
3
  import { AppElement } from './app';
4
4
  import { AsyncElement } from './async-element';
5
- import { parseColor, parseVec3 } from './utils';
5
+ import { parseColor, parseEnum, parseNumber, parseVec3 } from './utils';
6
6
 
7
7
  /**
8
8
  * The SceneElement interface provides properties and methods for manipulating
@@ -14,7 +14,7 @@ class SceneElement extends AsyncElement {
14
14
  /**
15
15
  * The fog type of the scene.
16
16
  */
17
- private _fog = 'none'; // possible values: 'none', 'linear', 'exp', 'exp2'
17
+ private _fog: 'none' | 'linear' | 'exp' | 'exp2' = 'none';
18
18
 
19
19
  /**
20
20
  * The color of the fog.
@@ -41,15 +41,21 @@ class SceneElement extends AsyncElement {
41
41
  */
42
42
  private _gravity = new Vec3(0, -9.81, 0);
43
43
 
44
+ private _scene: Scene | null = null;
45
+
44
46
  /**
45
- * The PlayCanvas scene instance.
47
+ * The PlayCanvas scene instance. Available once the element is ready — await
48
+ * {@link whenReady} or the element's `ready()` promise before accessing it.
49
+ * @returns The scene instance.
46
50
  */
47
- scene: Scene | null = null;
51
+ get scene(): Scene {
52
+ return this._scene!;
53
+ }
48
54
 
49
55
  async connectedCallback() {
50
56
  await this.closestApp?.ready();
51
57
 
52
- this.scene = this.closestApp!.app!.scene;
58
+ this._scene = this.closestApp!.app!.scene;
53
59
  this.updateSceneSettings();
54
60
 
55
61
  this._onReady();
@@ -69,7 +75,8 @@ class SceneElement extends AsyncElement {
69
75
  }
70
76
 
71
77
  /**
72
- * Sets the fog type of the scene.
78
+ * Sets the fog type of the scene. Can be `none`, `linear`, `exp` or `exp2`. Defaults to
79
+ * `none`.
73
80
  * @param value - The fog type.
74
81
  */
75
82
  set fog(value) {
@@ -190,22 +197,22 @@ class SceneElement extends AsyncElement {
190
197
  attributeChangedCallback(name: string, _oldValue: string, newValue: string) {
191
198
  switch (name) {
192
199
  case 'fog':
193
- this.fog = newValue;
200
+ this.fog = parseEnum(newValue, ['none', 'linear', 'exp', 'exp2'], 'none', name);
194
201
  break;
195
202
  case 'fog-color':
196
- this.fogColor = parseColor(newValue);
203
+ this.fogColor = parseColor(newValue, Color.WHITE, name);
197
204
  break;
198
205
  case 'fog-density':
199
- this.fogDensity = parseFloat(newValue);
206
+ this.fogDensity = parseNumber(newValue, 0, name);
200
207
  break;
201
208
  case 'fog-start':
202
- this.fogStart = parseFloat(newValue);
209
+ this.fogStart = parseNumber(newValue, 0, name);
203
210
  break;
204
211
  case 'fog-end':
205
- this.fogEnd = parseFloat(newValue);
212
+ this.fogEnd = parseNumber(newValue, 1000, name);
206
213
  break;
207
214
  case 'gravity':
208
- this.gravity = parseVec3(newValue);
215
+ this.gravity = parseVec3(newValue, new Vec3(0, -9.81, 0), name);
209
216
  break;
210
217
  // ... handle other attributes as well
211
218
  }
@@ -214,4 +221,10 @@ class SceneElement extends AsyncElement {
214
221
 
215
222
  customElements.define('pc-scene', SceneElement);
216
223
 
224
+ declare global {
225
+ interface HTMLElementTagNameMap {
226
+ 'pc-scene': SceneElement;
227
+ }
228
+ }
229
+
217
230
  export { SceneElement };
package/src/sky.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import { Asset, EnvLighting, LAYERID_SKYBOX, Quat, Scene, Texture, Vec3 } from 'playcanvas';
2
2
 
3
+ import { AppElement } from './app';
3
4
  import { AssetElement } from './asset';
4
5
  import { AsyncElement } from './async-element';
5
- import { parseVec3 } from './utils';
6
+ import { parseBool, parseEnum, parseNumber, parseVec3 } from './utils';
6
7
 
7
8
  /**
8
9
  * The SkyElement interface provides properties and methods for manipulating
@@ -28,6 +29,8 @@ class SkyElement extends AsyncElement {
28
29
 
29
30
  private _scene: Scene | null = null;
30
31
 
32
+ private _appElement: AppElement | null = null;
33
+
31
34
  connectedCallback() {
32
35
  this._loadSkybox();
33
36
  this._onReady();
@@ -35,6 +38,7 @@ class SkyElement extends AsyncElement {
35
38
 
36
39
  disconnectedCallback() {
37
40
  this._unloadSkybox();
41
+ this._appElement = null;
38
42
  }
39
43
 
40
44
  private _generateSkybox(asset: Asset) {
@@ -67,10 +71,12 @@ class SkyElement extends AsyncElement {
67
71
  private async _loadSkybox() {
68
72
  const appElement = await this.closestApp?.ready();
69
73
  const app = appElement?.app;
70
- if (!app) {
74
+ if (!appElement || !app) {
71
75
  return;
72
76
  }
73
77
 
78
+ this._appElement = appElement;
79
+
74
80
  const asset = AssetElement.get(this._asset);
75
81
  if (!asset) {
76
82
  return;
@@ -89,16 +95,22 @@ class SkyElement extends AsyncElement {
89
95
  }
90
96
 
91
97
  private _unloadSkybox() {
92
- if (!this._scene) return;
98
+ const scene = this._scene;
99
+ if (!scene) return;
100
+
101
+ this._scene = null;
102
+
103
+ // If the owning application has already been destroyed (removing a <pc-app>
104
+ // disconnects it before its children), the scene, graphics device and skybox
105
+ // textures have all been destroyed along with it — nothing left to clean up.
106
+ if (!this._appElement?.app) return;
93
107
 
94
- this._scene.skybox?.destroy();
108
+ scene.skybox?.destroy();
95
109
  // @ts-ignore
96
- this._scene.skybox = null;
97
- this._scene.envAtlas?.destroy();
110
+ scene.skybox = null;
111
+ scene.envAtlas?.destroy();
98
112
  // @ts-ignore
99
- this._scene.envAtlas = null;
100
-
101
- this._scene = null;
113
+ scene.envAtlas = null;
102
114
  }
103
115
 
104
116
  /**
@@ -264,25 +276,25 @@ class SkyElement extends AsyncElement {
264
276
  this.asset = newValue;
265
277
  break;
266
278
  case 'center':
267
- this.center = parseVec3(newValue);
279
+ this.center = parseVec3(newValue, new Vec3(0, 0.01, 0), name);
268
280
  break;
269
281
  case 'intensity':
270
- this.intensity = parseFloat(newValue);
282
+ this.intensity = parseNumber(newValue, 1, name);
271
283
  break;
272
284
  case 'level':
273
- this.level = parseInt(newValue, 10);
285
+ this.level = parseNumber(newValue, 0, name);
274
286
  break;
275
287
  case 'lighting':
276
- this.lighting = this.hasAttribute(name);
288
+ this.lighting = parseBool(newValue, false);
277
289
  break;
278
290
  case 'rotation':
279
- this.rotation = parseVec3(newValue);
291
+ this.rotation = parseVec3(newValue, Vec3.ZERO, name);
280
292
  break;
281
293
  case 'scale':
282
- this.scale = parseVec3(newValue);
294
+ this.scale = parseVec3(newValue, new Vec3(100, 100, 100), name);
283
295
  break;
284
296
  case 'type':
285
- this.type = newValue as 'box' | 'dome' | 'infinite' | 'none';
297
+ this.type = parseEnum(newValue, ['box', 'dome', 'infinite', 'none'], 'infinite', name);
286
298
  break;
287
299
  }
288
300
  }
@@ -290,4 +302,10 @@ class SkyElement extends AsyncElement {
290
302
 
291
303
  customElements.define('pc-sky', SkyElement);
292
304
 
305
+ declare global {
306
+ interface HTMLElementTagNameMap {
307
+ 'pc-sky': SkyElement;
308
+ }
309
+ }
310
+
293
311
  export { SkyElement };