@playcanvas/web-components 0.20.0 → 0.21.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 (100) hide show
  1. package/dist/app.d.cts +5 -113
  2. package/dist/app.d.ts +5 -113
  3. package/dist/asset-binding.d.cts +1 -0
  4. package/dist/asset-binding.d.ts +1 -0
  5. package/dist/components/anim-clip.d.cts +8 -10
  6. package/dist/components/anim-clip.d.ts +8 -10
  7. package/dist/components/anim-component.d.cts +5 -4
  8. package/dist/components/anim-component.d.ts +5 -4
  9. package/dist/components/audio-listener-component.d.cts +5 -4
  10. package/dist/components/audio-listener-component.d.ts +5 -4
  11. package/dist/components/button-component.d.cts +5 -4
  12. package/dist/components/button-component.d.ts +5 -4
  13. package/dist/components/camera-component.d.cts +5 -4
  14. package/dist/components/camera-component.d.ts +5 -4
  15. package/dist/components/collision-component.d.cts +5 -4
  16. package/dist/components/collision-component.d.ts +5 -4
  17. package/dist/components/component.d.cts +2 -2
  18. package/dist/components/component.d.ts +2 -2
  19. package/dist/components/element-component.d.cts +5 -4
  20. package/dist/components/element-component.d.ts +5 -4
  21. package/dist/components/gsplat-component.d.cts +5 -4
  22. package/dist/components/gsplat-component.d.ts +5 -4
  23. package/dist/components/joint-component.d.cts +5 -4
  24. package/dist/components/joint-component.d.ts +5 -4
  25. package/dist/components/layout-child-component.d.cts +5 -4
  26. package/dist/components/layout-child-component.d.ts +5 -4
  27. package/dist/components/layout-group-component.d.cts +5 -4
  28. package/dist/components/layout-group-component.d.ts +5 -4
  29. package/dist/components/light-component.d.cts +5 -4
  30. package/dist/components/light-component.d.ts +5 -4
  31. package/dist/components/particle-system-component.d.cts +22 -5
  32. package/dist/components/particle-system-component.d.ts +22 -5
  33. package/dist/components/render-component.d.cts +5 -4
  34. package/dist/components/render-component.d.ts +5 -4
  35. package/dist/components/rigid-body-component.d.cts +5 -4
  36. package/dist/components/rigid-body-component.d.ts +5 -4
  37. package/dist/components/screen-component.d.cts +5 -4
  38. package/dist/components/screen-component.d.ts +5 -4
  39. package/dist/components/script-component.d.cts +5 -4
  40. package/dist/components/script-component.d.ts +5 -4
  41. package/dist/components/scroll-view-component.d.cts +5 -4
  42. package/dist/components/scroll-view-component.d.ts +5 -4
  43. package/dist/components/scrollbar-component.d.cts +5 -4
  44. package/dist/components/scrollbar-component.d.ts +5 -4
  45. package/dist/components/sound-component.d.cts +5 -4
  46. package/dist/components/sound-component.d.ts +5 -4
  47. package/dist/custom-elements.json +38 -38
  48. package/dist/entity-reference.d.cts +13 -0
  49. package/dist/entity-reference.d.ts +13 -0
  50. package/dist/material.d.cts +8 -6
  51. package/dist/material.d.ts +8 -6
  52. package/dist/model.d.cts +8 -9
  53. package/dist/model.d.ts +8 -9
  54. package/dist/parse.d.cts +0 -8
  55. package/dist/parse.d.ts +0 -8
  56. package/dist/pointer-controller.d.cts +1 -0
  57. package/dist/pointer-controller.d.ts +1 -0
  58. package/dist/pwc.cjs +1360 -1186
  59. package/dist/pwc.cjs.map +1 -1
  60. package/dist/pwc.js +1360 -1186
  61. package/dist/pwc.js.map +1 -1
  62. package/dist/pwc.min.js +1 -1
  63. package/dist/pwc.min.js.map +1 -1
  64. package/dist/pwc.min.mjs +1 -1
  65. package/dist/pwc.min.mjs.map +1 -1
  66. package/dist/pwc.mjs +1361 -1187
  67. package/dist/pwc.mjs.map +1 -1
  68. package/dist/sky.d.cts +6 -7
  69. package/dist/sky.d.ts +6 -7
  70. package/dist/web-types.json +39 -39
  71. package/package.json +2 -2
  72. package/src/app.ts +16 -451
  73. package/src/asset-binding.ts +141 -0
  74. package/src/components/anim-clip.ts +22 -45
  75. package/src/components/anim-component.ts +10 -6
  76. package/src/components/audio-listener-component.ts +6 -5
  77. package/src/components/button-component.ts +8 -6
  78. package/src/components/camera-component.ts +6 -5
  79. package/src/components/collision-component.ts +6 -5
  80. package/src/components/component.ts +6 -4
  81. package/src/components/element-component.ts +6 -5
  82. package/src/components/gsplat-component.ts +6 -5
  83. package/src/components/joint-component.ts +8 -6
  84. package/src/components/layout-child-component.ts +6 -5
  85. package/src/components/layout-group-component.ts +6 -5
  86. package/src/components/light-component.ts +6 -5
  87. package/src/components/particle-system-component.ts +56 -30
  88. package/src/components/render-component.ts +6 -5
  89. package/src/components/rigid-body-component.ts +6 -5
  90. package/src/components/screen-component.ts +6 -5
  91. package/src/components/script-component.ts +8 -10
  92. package/src/components/scroll-view-component.ts +8 -6
  93. package/src/components/scrollbar-component.ts +8 -6
  94. package/src/components/sound-component.ts +6 -5
  95. package/src/entity-reference.ts +237 -0
  96. package/src/material.ts +25 -29
  97. package/src/model.ts +24 -48
  98. package/src/parse.ts +0 -232
  99. package/src/pointer-controller.ts +550 -0
  100. package/src/sky.ts +19 -30
package/src/parse.ts CHANGED
@@ -11,17 +11,8 @@
11
11
  * shared frozen constants (`Vec3.ZERO`, `Color.WHITE`) as defaults.
12
12
  * - `parseBool` and `parseTags` take no attribute name, because every value is valid for them and
13
13
  * so they never warn.
14
- *
15
- * `findEntityElement` and `getEntity` are the exceptions: they resolve a reference rather than
16
- * parsing a literal, and return `null` instead of falling back to a default. A reference
17
- * beginning with `#` is a document-wide selector (an element id, or any selector rooted in one);
18
- * anything else is an entity name, resolved lexically through the entity hierarchy first and
19
- * against the document after — never as a selector or an id. They also do not warn - what an
20
- * unresolved reference means depends on the element holding it - so elements report through
21
- * `resolveEntity`, which takes that meaning as parameters.
22
14
  */
23
15
 
24
- import type { Entity } from 'playcanvas';
25
16
  import { Color, Quat, Vec2, Vec3, Vec4 } from 'playcanvas';
26
17
 
27
18
  import { CSS_COLORS } from './colors';
@@ -327,226 +318,3 @@ export const parseVec4 = <T extends Vec4 | null>(
327
318
  }
328
319
  return new Vec4(components);
329
320
  };
330
-
331
- /**
332
- * Runs querySelector, absorbing the SyntaxError an unparseable selector throws - references are
333
- * arbitrary author text, so a lookup must fail to `null`, never throw.
334
- *
335
- * @param selector - The selector to query.
336
- * @returns The matched element, or `null`.
337
- */
338
- const query = (selector: string): Element | null => {
339
- try {
340
- return document.querySelector(selector);
341
- } catch {
342
- return null;
343
- }
344
- };
345
-
346
- /**
347
- * Runs a lookup against one scope, checking the scope element itself before its subtree — a
348
- * reference deep in a cloned prefab must be able to name the prefab's root. Absorbs the
349
- * SyntaxError of an invalid selector like {@link query}: escaping quotes and backslashes does not
350
- * make arbitrary text a valid CSS string (a reference containing a newline still throws), so a
351
- * lookup must fail to `null`, never throw.
352
- *
353
- * @param scope - The element whose inclusive subtree to search.
354
- * @param selector - The selector to query.
355
- * @returns The matched element, or `null`.
356
- */
357
- const queryScope = (scope: Element, selector: string): Element | null => {
358
- try {
359
- return scope.matches(selector) ? scope : scope.querySelector(selector);
360
- } catch {
361
- return null;
362
- }
363
- };
364
-
365
- /**
366
- * Reads the entity a resolved element is backing, through the `entity` accessor every
367
- * entity-fronting element exposes. `null` for no element, and for an element backing nothing.
368
- *
369
- * @param element - The element to read, or `null`.
370
- * @returns The backing entity, or `null`.
371
- */
372
- const entityOf = (element: Element | null): Entity | null => {
373
- return (element as { entity?: Entity } | null)?.entity ?? null;
374
- };
375
-
376
- /**
377
- * The elements that front an entity: what a bare name can resolve to, and the scopes of the
378
- * lexical name lookup.
379
- */
380
- const ENTITY_KINDS = ['pc-entity', 'pc-model', 'pc-node'] as const;
381
-
382
- /**
383
- * The entity-fronting elements as one selector, for the scope walk.
384
- */
385
- const ENTITY_SCOPES = ENTITY_KINDS.join(', ');
386
-
387
- /**
388
- * Resolves a reference string to the element it names. The grammar is closed — every reference
389
- * has exactly one interpretation:
390
- *
391
- * - A reference beginning with `#` is a document-wide CSS selector — an element id (`#body`), or
392
- * any selector rooted in one (`#hud pc-entity`). It is authoritative: the name lookup never
393
- * runs for it, so an unusually named entity cannot shadow it.
394
- * - Any other reference is the name of an entity-fronting element (`<pc-entity>`, `<pc-model>` or
395
- * `<pc-node>` — for a node, the glTF node name it binds), and nothing else. A bare reference is
396
- * never interpreted as a selector or an element id, so adding or renaming elements can never
397
- * change which form it takes.
398
- *
399
- * When `from` is supplied, a name resolves lexically first: the closest entity-fronting
400
- * ancestor's inclusive subtree, then each outer entity-fronting ancestor, then the containing
401
- * `<pc-app>`, then the document. This is what lets a `<template>` prefab reference its own
402
- * entities by name — every clone resolves within itself before a document-wide lookup could reach
403
- * an earlier clone — provided the prefab has a single entity-fronting root to be the enclosing
404
- * scope.
405
- *
406
- * Separate from {@link getEntity} so a caller reporting a failure can tell the causes apart
407
- * ({@link unresolvedCause} words them): nothing in the document matches the reference, or
408
- * something matches but is not backing an entity (yet, or ever).
409
- *
410
- * @param ref - The reference string to resolve.
411
- * @param from - The element resolving the reference, whose entity-fronting ancestors scope the
412
- * name lookup. Omitted, the name lookup is document-wide only.
413
- * @returns The matched element, or `null`.
414
- * @internal
415
- */
416
- export const findEntityElement = (ref: string, from?: Element): Element | null => {
417
- if (!ref) {
418
- return null;
419
- }
420
-
421
- // A '#' reference is document-wide and bypasses the name lookup entirely - an entity named
422
- // '#body' must never shadow the element whose id is 'body'.
423
- if (ref.startsWith('#')) {
424
- return query(ref);
425
- }
426
-
427
- // The name lands inside a quoted CSS string, so its quotes and backslashes are escaped -
428
- // a name like `say "hi"` must resolve, not turn the lookup into a SyntaxError.
429
- const escaped = ref.replace(/["\\]/g, '\\$&');
430
- const nameSelector = ENTITY_KINDS.map(kind => `${kind}[name="${escaped}"]`).join(', ');
431
-
432
- if (from) {
433
- let scope = from.parentElement?.closest(ENTITY_SCOPES);
434
- while (scope) {
435
- const element = queryScope(scope, nameSelector);
436
- if (element) {
437
- return element;
438
- }
439
- scope = scope.parentElement?.closest(ENTITY_SCOPES);
440
- }
441
-
442
- const app = from.parentElement?.closest('pc-app');
443
- if (app) {
444
- const element = queryScope(app, nameSelector);
445
- if (element) {
446
- return element;
447
- }
448
- }
449
- }
450
-
451
- return query(nameSelector);
452
- };
453
-
454
- /**
455
- * Resolves a reference string to the {@link Entity} backing an entity-fronting element
456
- * (`<pc-entity>`, `<pc-model>` or `<pc-node>`). The reference is a name — resolved lexically
457
- * through the entity hierarchy first when `from` is supplied — or a document-wide `#` selector
458
- * ({@link findEntityElement} details the grammar and order). Returns `null` if no matching
459
- * element (or backing entity) is found.
460
- *
461
- * @param ref - The reference string to resolve.
462
- * @param from - The element resolving the reference, whose entity-fronting ancestors scope the
463
- * name lookup. Omitted, the name lookup is document-wide only.
464
- * @returns The resolved entity, or `null`.
465
- * @internal
466
- */
467
- export const getEntity = (ref: string, from?: Element): Entity | null => {
468
- return entityOf(findEntityElement(ref, from));
469
- };
470
-
471
- /**
472
- * Describes why a non-empty reference did not resolve, for a warning. Three causes, because they
473
- * have three different fixes: nothing matches (usually a typo), the matched element is not backing
474
- * an entity yet (usually timing - a `pc-node` whose asset has not loaded - so resolving again
475
- * later can work), or the matched element can never back one (the reference points at the wrong
476
- * element, so only correcting it can). Capability is the `entity` accessor every entity-backing
477
- * element inherits from EntityBaseElement.
478
- *
479
- * @param element - The element the reference matched, or `null` when nothing did.
480
- * @returns The cause, phrased to follow `could not resolve ... -`.
481
- * @internal
482
- */
483
- export const unresolvedCause = (element: Element | null): string => {
484
- if (!element) {
485
- return 'nothing in the document matches it';
486
- }
487
- const tag = `<${element.tagName.toLowerCase()}>`;
488
- return 'entity' in element
489
- ? `${tag} matches it but is not backing an entity yet`
490
- : `${tag} matches it but cannot back an entity`;
491
- };
492
-
493
- /**
494
- * Builds the migration pointer for a bare reference that names nothing but matches the id of an
495
- * entity-fronting element - it was almost certainly meant as an id, so point at the form that
496
- * expresses it, escaped so the suggestion actually parses as a selector (an id like `a:b` must
497
- * be written `#a\:b`). Empty when the reference is already a `#` form, matches no id, or the id
498
- * belongs to an element that could never back an entity - suggesting it would only trade this
499
- * warning for the wrong-target one.
500
- *
501
- * @param ref - The unresolved reference.
502
- * @param prefix - Text the suggested form must carry in the caller's syntax (e.g. `entity:`).
503
- * @returns The advice sentence, or an empty string.
504
- * @internal
505
- */
506
- export const idHint = (ref: string, prefix = ''): string => {
507
- const match = !ref.startsWith('#') && document.getElementById(ref);
508
- return match && 'entity' in match
509
- ? `A bare reference is a name - write '${prefix}#${CSS.escape(ref)}' to reference the element with that id.`
510
- : '';
511
- };
512
-
513
- /**
514
- * Resolves a reference string to the {@link Entity} backing an entity-fronting element, scoped to
515
- * the resolving element ({@link findEntityElement} details the order) and warning when a
516
- * non-empty reference does not resolve - otherwise the reference fails silently, invisible
517
- * except through the behavior it should have driven. The message names which of the three causes
518
- * ({@link unresolvedCause}) it hit, and advises reassigning later only when that can work.
519
- *
520
- * An empty reference stays silent: it is the unset state of an optional attribute, and on some
521
- * elements (`pc-joint` `entity-b`, `pc-button` `image`) a documented value of its own.
522
- *
523
- * @param ref - The reference string to resolve.
524
- * @param from - The element resolving the reference; scopes the lookup and names the message.
525
- * @param attribute - The attribute being resolved, for the message.
526
- * @param consequence - What the unresolved reference means for the element, for the message.
527
- * @returns The resolved entity, or `null`.
528
- * @internal
529
- */
530
- export const resolveEntity = (ref: string, from: Element, attribute: string, consequence: string): Entity | null => {
531
- if (!ref) {
532
- return null;
533
- }
534
-
535
- const element = findEntityElement(ref, from);
536
- const entity = entityOf(element);
537
- if (!entity) {
538
- let advice = `Assign ${attribute} again once the entity exists.`;
539
- if (element && !('entity' in element)) {
540
- advice = `Point ${attribute} at a pc-entity, pc-model or pc-node instead.`;
541
- } else if (!element) {
542
- const hint = idHint(ref);
543
- if (hint) {
544
- advice = hint;
545
- }
546
- }
547
- console.warn(
548
- `${from.tagName.toLowerCase()} could not resolve ${attribute} '${ref}' - ${unresolvedCause(element)} - ${consequence}. ${advice}`
549
- );
550
- }
551
- return entity;
552
- };